Nothing new on the game front, but, after I wrapped up my Ludum Dare 41 entry a few weeks ago, I decided I should take some time and refine/refactor the handful of utility scripts that I find myself always reusing when I make games. Tonight's efforts revolved around refinements to a few of my 2D Projectile functions. There's nothing mind blowing here, but, if you find yourself doing the same thing more than once, you ought to make a reusable function for it
Trace Projectile - Given a projectile's initial position and rotation, create a list of Vector3 of points that trace out the projectile's trajectory -- Useful for rendering flight paths with a LineRenderer component.
Sooooo... I decided to participate in my first Ludum Dare this weekend. Over the last 48 hours, I've created a brand new game: Tri-Angle
Download it for Android --> https://play.google.com/store/apps/details?id=com....
Play it on Itch.io --> https://fussenkuh.itch.io/tri-angle
All told, it took me around 24 hours to create the game an (sadly) another 5-6 hours just getting everything wrapped up (screen shots, uploads, etc.)
50m? 150m? 300m? How far can you fling the Happy Little Triangle (H.L.T.)?
- Hurl your H.L.T through the danger zone!
- Boost to never before seen distances!
- Enjoy new unique layouts every time you play!
How far can you fling?
Lack of motivation to tackle any substantial task today, I decided to spend a few hours investigating what it might take to make my water cannon look a little bit more watery.
Prior to today, my cannon basically shot projectiles that had simple trail renderers on them. Things kinda sorta looked decent when you fired a bunch in the same basic spot, but, once you started moving the cannon, instead of a stream of water, you saw a bunch of individual shots of water with long tails.
Today's work involved hacking around with the Unity LineRenderer. Unfortunately, it's a bit cumbersome to work with. To render a line, you basically need to give it an array of Vector3 every frame. It'll then connect the dots. Additionally, each LineRenderer can only draw one contiguous line. Need a few streams of water? You need a few LineRenderer gameObjects.
This led me to create a WaterManager class. When the Water Cannon is fired, a projectile is fired. This projectile registers itself with the WaterManager. When the projectile dies, it unregisters itself. In turn, each frame the water manager scans through the list of all the projectiles it knows about. Projectiles that are 'close enough' to each other get all their positions lumped into a Vector3 array. This process ultimately produces a list of Vector3 arrays (one array for each clump of projectiles). Each array of Vector3 then gets assigned to a LineRenderer object.
The results? Something that looks like a constant stream of water... Well, really more like a stream of silly string. But, something that looks better than what I had before. Additionally, when the middle of that stream of water hits an object or when the projectiles in that stream get too far apart from each other, the stream dynamically breaks into two (or more) streams.
Ultimately, it's still not perfect and, if nothing else, can probably be refactored to be a bit more efficient. But, for now, I'm calling it an improvement.
Go ahead. Shoot those fancy new Red Cubes with something more powerful than a water cannon and see what happens. Ever play Asteroids? Because you ought to have played Asteroids. Then maybe you'd realize that sometimes destroying things is gonna just make things worse before they get better...
That's right, folks, your shots will technically kill 'em, but, in the process, you'll release a new batch of smaller Red Cubes to contend with. Unleashing the pushing power of that Water Cannon or the concussion wave of those Force Grenades is probably your safer option. Push those pesky Red Cubes off the level and save yourself a headache.
Today's highlights include:
The below GIF is a window into "Level 2" (clever name, that!) Basically, I just wanted to try making a hole in the middle of the play field with various enemy spawners while limiting the Player's weapons to only things that can push the enemies around. In other words, the only way you can win is if you knock the enemies off the edges of the play field.
This update also marks Box Shooter v0.5.2. Grab the ALPHA now, from Google Play.
Today's efforts revolved around fleshing out the enemy navigation system I started yesterday. To that end, we now have a dynamics NavMesh that reacts to physics obstacles and, to a bit of my surprise, the enemies pretty much avoid everything that I've dropped near them. The Destination --> Agent --> Physics Enemy technique I talked about yesterday is working far better than I figured it would. #Win.
Tonight started with a bit more cleanup work on the weapon/reload side of things. Though, I still see some much needed refactoring in my future, for now, the system is at least working reliably. That meant it was time to start investigating adding a bit of movement AI...
Currently, my enemies simply lumber slowly down the Z-axis toward the player in what's basically a straight line. Ideally, I want holes and obstacles and such in my levels and I want the enemies to navigate around those items. Unity's NavMesh agent *almost* gives me what I want. It's great at path finding and will even move along that path. However, it doesn't really allow for interaction with the physics system. But, I'll be damned if I'm going to let that stop me.
What I'm showing off tonight is the simple start to my movement solution. The Yellow Ball is the enemy I want to control with physics (yes, the stuttering in his movement is intentional). The White Box is the agent traversing my NavMesh and the Green Box that I'm moving around manually is the agent's destination. The goals are simple: The enemy attempts to 'physics' its way toward the agent. The agent will wait around for the enemy to get 'close enough' to it an then it'll start moving toward the destination. If the enemy falls too far behind the agent, the agent will stop and wait for him.
In my simple testing, this idea seems like it'll work nicely for my basic needs. That said, I'm going to have to add logic like warping the agent back close to the enemy if the enemy gets blasted waaaay far away from the enemy. And, I'm sure I'm going to have to do some additional tweaking once I actually have obstacles to account for, but, thus far, I think this idea has some promise.
A wise man once told me "shit or stop complaining about shitting." Or, something like that. Since Box Shooter's inception, I was worried about being able to generate enough compelling levels to make a game. So, over the last week, I decided to both stop attempting to shit and complaining about it.
Instead, I've branched my game into something new. You'll still be shooting stuff, but, instead of Major Mayhem inspired levels, I've simplified my life and opted to generate levels revolving around needing to kill enemies as they slowly (or quickly) lumber toward you. The player will have an even wider variety of weapons to choose from. I have a decent set of ideas that'll hopefully allow me to flesh out this concept and provide more variety than my Major Mayhem inspired concept. More importantly, I actually feel like I'll have a much better shot at accomplishing my new set of goals. And, if not, well, I'll just branch again!
With the above announcement out of the way, tonight's specific work revolved around refactoring some of my weapon internals that handle reloading, making some basic physics tweaks, and making enemy targeting a bit more forgiving. Now it's time to test stuff out on the small screen of my phone. If all goes well, I'll be able to start focusing on new and interesting gameplay concepts!
Soooooo, about my lack of math/physics skills. While I still don't claim to have retained too much from my college math and physics courses, it turns out that I can correctly implement formula if they're given to me. What I can't apparently do is actually take the output from the formula and actually apply it correctly to my player.
A fresh mind this morning equated to quickly identifying the problem. The angle I'm calculating is used to rotate around the X-axis. To properly align my weapon, I also need to rotate around Y-axis. I was accomplishing the Y-axis rotation by simply taking advantage of Unity's Transform.LookAt() function to simply 'LookAt' the target. I was 'smart' enough to know I needed to zero out the elevation of the target to match my gun's elevation before rotating along the Y-axis. However, my hazy mind from late last night was taking 'zero out' too literally: I was simply setting the target's Y elevation to 0 instead of to the gun's elevation. As a result, the LookAt() call was rotating around both the Y and X axis. When I then applied my calculated X-axis rotation, I was always coming up short.
In other words, I was doing something stupid. Just goes to show you that sleep is, indeed, important.
With that stupidity out of the way, I updated my pistol and machine gun to use the new ballistic solution calculations. Granted, thanks to their velocity, they still basically shoot exactly how they were shooting before the update. I also threw together a quick prototype grenade launcher. It's much easier to see the ballistics in action when I fire off a few rounds of it.
Oh, and there's now explosive barrels. Because, why not?
Was hoping to tweak my weapons' ballistics tonight. My current system just assigns an arbitrary muzzle velocity to every weapon and removes gravity from projectiles. It works, but, it basically makes it impossible to create something like a grenade launcher; something that ought to have a low muzzle velocity forcing you to fire in a pretty arc to hit distant targets.
Enter 'Projectile Motion Equations.' Specifically, my goal was to figure out what angle I need to fire a projectile at given (1) the projectile's speed (2) the range to the target and (3) the altitude of the target. Wikipedia has a nice entry on the topic and a nifty formula that I ought to be able to use.
Specifically, I was looking at the "Angle [theta] required to hit coordinate" formula.
To cut a frustrating story short, I have myself some ballistic calculations using this formula, but, the calculations fail to actually hit their target. The formula has a + and - option. If I use the + option, all my shots overshoot by 2-3 units. If I use the - option, all my shots undershoot by a 1/2 unit or so. WTF, ballistics formula?!?!
At this point, I'm too tired to care any more. I have to assume that the formula is correct and that I'm just failing to do something properly in my translation. Either that, or I have a rigidbody setting screwed up. Hopefully, a fresh mind will show me an obvious problem to correct tomorrow.
Tonight, I made a bomb. Not a fancy throwin' bomb. Or a fancy 'flying through the air' bomb. But, a 'I sit on the ground and blow up when I get shot' bomb. Even better, its explosion blows up enemies around it.
Thanks to the generic 'destructible object' and 'hit' interfaces I've created, it was rather straightforward to tailor the pieces to bring the bomb into this world. Once created, I plopped a few of them in a couple of my level segments and pushed a build to my phone to confirm that, yes indeed, EXPLOSIONS, even ugly looking ones, make everything better.
Put a little bit of thought into creating a few different enemy kinds today. Meet the current crew:
Yep, got some real complicated names right there. I'm sure the above enemy stats will be tweaked (or completely revamped), but, now I have a small handful of actual enemy variants to use while testing level segment concepts.
Speaking of Level Segments, the new segment I've been testing with (1) demonstrates at least one example of each of my new enemy types and (2) has a new enemy activation concept implemented. You can now set triggers that will activate a new group of enemies. In my example segment, I have it configured to activate a new batch of enemies after you kill one of the originally deployed 'Heavy Circle" enemies.
Spoiler Alert: It's not actually my wedding. But, it's a friend's wedding that'll be taking up most of my day. But, before that kicks off, I had a wee bit 'o time to try implementing some stuff. In the short time I had, I decided to start creating a 2nd type of enemy... which is really just like my 1st enemy, only he has more hit points and is a different color. More than anything, creating this 2nd enemy basically confirmed that it'll be fairly easy to swap enemy types in my level segments. The level segments will have baked-in values defining when and how the enemy moves and fires. But, at run time, I'll be able to actually choose what type of enemy to spawn.
Moving forward, this might allow me to cheat a bit and reuse level segments in different ways. Early levels might spawn easier enemy types while later levels can spawn more difficult enemy types.
Today I started work on testing the level segment creation process. Unfortunately, I fear segment generation is going to be a rather long and tedious process :/ while the workflow is fairly straightforward, it's still rather time consuming since everything is hand generated.
I'm trying not to be a Debbie Downer, but even if I figure on a small 5 segments per level, that's still 50 segments for a 10 level game... Which isn't a very long adventure.
Things just got a bit more deadly: The player is no longer invincible. Three hits will now kill ya. But, thinking ahead, I figure I'm going to want to offer the player an option to revive. So, keeping with my Player State Machine motif, there are now "Player Knocked Out" and "Player Dead" states. When the player loses all his hit points, he'll be 'knocked out' Currently, this causes a quick and dirty GUI to pop up asking if you'd be interested in reviving. Also, as of right now, you can revive as many times as you'd like. If the player chooses to revive, he'll be restored back to the proper state in the Player State Machine to continue the fight.
So, to quote Metallica quoting The Misfits Die. Die. Die, My Darling...
As noted in my last post, I made some changes to my hit detection system to account for different round types. Unfortunately, due to the lack of nested prefabs in Unity, that also meant that I had to individually tweak every enemy that was baked into every one of my level segments. Moreover, if I ever wanted to change values associated with those enemies again, I'd have to individually tweak them... again. Sucks to that!
So, tonight, I rejiggered the way those enemies. Turns out, the 'fix' was trivial. Each enemy consists of a parent and 3 children: Start Position, End Position and Entity (the actual thing that moves and shoots). Rather than having 'Entity' be a fixed child of the enemy, I simply changed it to be a prefab instantiated by the enemy.
Now, if I need to tweak the stats (health, weapon type, color, etc.) of a particular enemy type, I just need to tweak the prefab. Granted, if I want to change the enemy type associated with any particular enemy in any particular level segment, I have to still manually track down that enemy in that level segment prefab and swap out it's enemy type prefab. But, that's a whole heck of a lot less annoying than my previous setup.
Up to this point, the hit detection on the enemies has been very basic. Essentially, on collision, a hit point is removed from the enemy and when the enemy's life hits zero, it's destroyed. Considering I want different weapons that do different damage with possible different effects, I need something a bit more beefy.
The solution turned out to be quite simple: Harvest some scripts from the Dual Stick Shooter (DSS) prototype that NoStyleGuy and I were working on last year. I'm now reusing a couple Hit and Round interfaces defined in DSS to accomplish exactly what I want. I also ported over the EffectsManager from DSS to decouple all of my hit, death, etc. effects from my objects.
Sadly, since Unity doesn't have a concept of Nested Prefabs, and since all of my enemies need to be baked into the level segments they live in, I needed to spend a decent chunk of time updating every instance of my enemies by hand rather than being able to change a single enemy prefab to make this update. I'm going to have to come up with an easier scheme to update/tweak these values moving forward. But, oh well. For now, brute force got the job done.
On the positive side, the ease in which I was able to reuse some of the DSS code makes me smile. It shows that, while DSS might be on hold (or dead) we made a lot of useful (and reusable) thing that will continue to pay dividends in future endeavors.
Not much time to dedicate to Game Dev this weekend. But, I managed to sneak in a few hours today. I believe I've wrapped up the integration of the new player control scheme. Behaviors (shooting, moving, etc.) are now fully being managed by a Unity Animation Sate Machine and the rest of the game has been updated to use said state machine.
This means v0.5.1 is being uploaded to the Play Store ALPHA channel as I type!
Instead of trying to reignite work on Box Shooter tonight, I got to spend the evening as Extended Family IT Guy! (tm)
The Symptom: Can't get on the Internet
The More Detailed Symptoms: Windows 10 reports that it's connected to the Internet and everything is normal. However, Chrome and Edge won't load pages and eventually lock up. Try doing a 'ping' and you're greeted with (1) not a successful ping (2) not the standard 'ping timeout' but (3) "General Failure" Ooooooooooooooh... that's for the useful, detailed feedback, fellas! WTF??!?! My phone is working flawlessly on the WiFi connection and the router admin page reports no oddities.
Queue "IT Googling" Montage... After trying all sorts of different suggestions to clear/reset various Windows Networking Stack things, I try to do the more logical thing and boot into Safe Mode. How do you boot into Safe Mode in Windows 10? Simple, boot into normal Windows and then, from normal windows, try resetting while holding down Shift. Either that or go into the settings menus and choose some special 'restart' command. WTF?!? I have to be in normal Windows mode just to get into Safe Mode?!?!? What the f**k happened to spamming F8 while the computer loads? What if my computer is so f**ked up that I can't even get into normal Windows successfully? Oh, and also, the 'hold shift' while choosing restart from the Start Menu did jack s**t for me. I could only get the 'special' setting menu option to work.
Anywho, eventually got into Safe Mode and networking works perfectly. Hmmm... what would be causing things not to work in normal mode? I bet it's that stupid Mcafee bulls**t. Lets get rid of that. Try to add/remove programs that s**t... Mcafee uninstaller locks up and pretty much makes the computer useless. Time to reboot. Reboot complete... s**t, can't boot right back into Safe Mode. Gotta jump through the Safe Mode s**t steps again to get that going. Woot, back in Safe Mode. Try to uninstall Mcafee again. Uninstaller starts working, but, then freezes. But, hey this time the computer isn't a jacked up. Time to search the web... "How to really uninstall Mcafee Windows 10" Directly from the Mcafee website: If a normal uninstall doesn't work, download <this app> and run it. WTF?!?!? You know your software is such a piece of s**t that it can't even uninstall itself correctly and you needed to write another f**king piece of software to remove your piece of s**t?!?!? Brilliant!!
Downloaded the 'real' uninstaller. Ran it. Looking like it's going to lock up too... thankfully, nope. Its just slow as balls. Finally, after a final reboot the f**king piece of s**t virus known as Mcafee Security Center appears to be wiped clean from the system. What's better? The Internet just works again! Praise The Flying Spaghetti Monster!
So, in conclusion: No Box Shooter work tonight. Too pissed off at technology. Also, f**k Mcafee and its f**king piece of s**t uninstalling capabilities. May it burn in hell while being f**ked by some f**king demon.
Thus ends the latest tale of Extended Family IT Guy (tm)...
Unlike last night, tonight, Visual Studio decided to not be stupid. With a fully functional IDE, I set off to reimagine my player control scheme. Over time, my prototype control script turned into a bunch of spaghetti cluttered up with a bunch of booleans, 'if' check and finicky timing issues . Adding anything new was becoming more and more of a hassle.
Since the controls I'm dealing with are basically a clearly defined state machine, why not just use a freaking state machine? Enter Unity's Animation State Machine, stage left. As you can see in the screenshot, at the moment, I have 4 main states the player can be in and, right now, I have things configured up to allow the player to transition to any state from any state. This will probably change in the future. All transitions are based on the values of two variables: shooting & moving.
The beauty of this new setup is that I've now forced myself to handle player input processing in very distinct and discrete ways. If you're in the 'Shooting From Cover' state, I have an exact set of actions the player can do and, thus, a simple set of code associated with that state. No more error-prone spaghetti logic for me! Moreover, I should have more foolproof control over transition animations from one state to the next thanks to the clearly defined Start/Exit state functions. This will (hopefully) clean up many of my timing issues.
With the basics laid out, I started migrating actual logic into the new state machine. Thus far, I've succeeded in adding logic to allow actions in and transitions to/from the 'Behind Cover' and "Shooting From Cover' states. Basically, the player can pop out of cover, shoot and return to cover. Hopefully, filling out the remaining states will be as straightforward as these first two.
So, I was hoping to start tackling the rework of my player input mechanism tonight. Basically, I have a bunch of spaghetti code to shoot, move, etc and it just keeps getting uglier as I add more things. That's an obvious sign that it's time to refactor.
Unfortunately, upon waking up my computer I was greeted with a Windows 10 "It's time to reboot and install a whole bunch of s**t" message. So, that whole process ate up a bunch of my time. Okay, we'll just start game dev a little later. Launch Unity, launch Visual Studio, get going on the rework... aaaaaaand, the computer is running slower than I do in a 5K race (if you've seen me 'run', you know that's damn slow). Not only that, but, I'm experiencing a lot of lovely VS doesn't want to recognize any of your Unity classes making intelisense useless moments which I only know how to 'fix' by killing and restarting VS... aaaaaaaaand waiting.
Those facts mixed with feeling like butt, and I've decided it's probably best to just put the computer down for the night and get some sleep. Maybe it (and I) will feel better tomorrow.
Decided to start tackling another large task today: Implementing a better player weapon and weapon swapping system. The basics for defining new weapons are off to a good start and a very basic prototype UI is in place to test swapping between the Player's Pistol and Machine Gun. Now everything just needs to be refined, and refined some more.
Didn't have a whole lot of time to work on the project today. So, rather than diving into anything major, I took a moment to make my Components in the Unity Inspector look a bit better. In doing so, I learned a few new things:
Today revolved around two major tasks:
First, lets state the obvious: Everyone else is Streaking, why shouldn't I? Even though I've been working on my latest game for several weeks and even though @FunkyJive and @NoStyleGuy have been pestering me to write something, I've neglected to resume Streaking. That neglect ends tonight (or this morning, or whatever)! We'll see how it lasts ;-)
Tonight's battle revolved around Unity's Timeline feature. A few days ago, I figured out how to hack it sufficiently to use it as a way to activate my enemies at the appropriate time. Tonight, I felt compelled to actually attempt to extend the Playable API to write my own custom Timeline track controller. Why?, you ask. Because, it would be cool if I had an easier way to script my enemy movements and actions in a semi-straightforward drag-and-drop way. My current enemy control mechanisms work but they're kind of a pain to fine tune. I'm hoping time spent trying to understand how one extends Timeline will make my life easier.
I still don't fully understand all the details of what I'm doing, but, after studying the examples in the Default Playables asset (free from Unity Technologies) I've constructed an extension that will basically let me send arbitrary 'messages' to an enemy. At the moment, I can command them to FIRE, POP OUT OF COVER, and RETURN TO COVER. The duration of the message bars in Timeline dictate how long the enemy will take to do each command. Adding new 'messages' ought to also be fairly easy.
It's still fairly basic, but, even in its early state, it already is looking like using this tool is going to save me time in the long run.