After spending virtually every waking moment from Feb through the end of April on my (last) class for my Masters degree, I'm finally back to game development.
Actually, there was a little thing called Ludum Dare 41 in there too. Check out my game: https://ldjam.com/events/ludum-dare/41/flatformer
But now, I'm finally back to my own games. I'm going to put Space Roguelike in Space on hold for a bit while I actually finish a game. Why? Because I realized that I had bitten off a bit more than I could chew. I still think that I can technically create all the systems and components I need, but I don't know if I have the skills or inclination to make a compelling and balanced roguelike.
So without further adieu, I'm starting a new (but actually old) game!
Yea, okay, I worked on this exact concept about a year ago, but it was really hacked together, and I never really got out of (or even into) the prototype state. I went back to the codebase, and realized that (for a number of reasons) it's unusable, so I'm starting fresh. My goal is to release this game by 'the end of the summer', whatever that means. Wish me luck!
I changed my steering implementation to not always snap the sprite's orientation to the velocity vector. This was causing issues where slight bumps (asteroids, lasers) were making the agents freak out. Instead, now the sprite is on a separate game object that can turn independently from the 'engine', and always tries to face the player. It's a little unnatural to see a rigid vessel like a spaceship having decoupled movement and 'vision', but I rationalize it as the invaders have developed advanced thrust-vectoring engines that let them essentially hover and turn on a time.
Oh, I also changed the orientation to landscape, which gives me quite a lot more screen real estate, which was sorely needed.
Added some more steering behaviors. The first one was a "path follow" which actually isn't so much a steering behavior, as a planner for the Seek behavior.
Next was "Cohesion" which is the opposite of Separation: it induces entities to stay together. This is added to the 3 red dudes in the following video. Notice how they 'try' to stay together, while the other main groups spread out.
Started working on some basic steering behaviors for enemy AI:
I kinda already started this with the missile (seeking and obstacle avoidance), but they were totally coupled to the missile class. Tonight, I pulled them out into a generic architecture. In addition to updating Seek and Avoid, I added Separation, which keeps enemies separated.
Unfortunately, the separation kinda overrides the avoidance, so they are quite prone to colliding with the asteroids. This is a known issue and limitation of steering behaviors. Usually it is solved with weights and/or priorities, but it always ends up requiring tedious balancing of parameters to get it to 'feel' right. I'll have to cross that bridge eventually.
First things first: Ever since I added the post-processing effects, my GIFs are wayy to big (10-15MBs) for sharing. Even cutting the FPS down to 10 doesn't help much. So I'm going with Streamable videos. I'm curious what other people think of this, or what their preferred formats are.
Moving to the actual work I accomplished today:
Added a nifty shield-hit effect:
Added some missiles!:
Didn't post for the last couple days, but I actually have been busy! I added some post processing effects that make the game look ... better? I hope. The lens distortion is probably over-done, but I think it fits well with the circular nature of the game.
I also added the basics of a combat system: shields block normal blasters, but ion-type weapons defeat shields:
Spent a very small amount of time determining the actual 'leaf' nodes in the room graph. These will be useful for determining start and end positions on a map, as well as placing more difficult rooms with better loot because they're off the beaten path.
To implement, I actually had to make a whole new data structure. Before, I had a collection of Rooms and a separate collection of Edges. Now, I additionally have a collection of RoomNodes that have references to their neighbors (kind of replaces edges). A leaf node is any RoomNode that has exactly 1 neighbor.
I am not doing anything with this knowledge yet, but here I added some square gizmos that identify leaf nodes in the scene view:
Not a very productive day.
I managed to clean up some stuff I broke while making the A* hallways. To make those work, I had to change the definition of what was Passable in the grid from Floors, to empty space. Next, i changed the definition of Neighbors to only be the 4 cardinal directions since I don't really want diagonal corridors (they look weird).
All of this epically broke the Player's ability to actually move, so I did some refactoring to make those parts configurable, and now everything is working.
Better than nothing!
I added the ability to connect rooms that aren't vertically or horizontally aligned.
My initial thought was to make crude 'L' shaped hallways, but I realized that they would almost always intersect some other room/hallway, and I didn't want that.
My second thought was to use pathfinding to actually generate the hallway, and I got it about 99% working. Unfortunately, I'm not sold on how the results actually look.
Here are some pics (note: new A* hallways are in brown for illustrative purposes)
This third one exhibits the issue that keeps this only a 99% solution. The 2 rooms with brown doorways, but no connected path, are supposed to be connected, but no path can be found because of the 'courtyard' formed south of the left room.
I'm already picking where to start the hallways by choosing a spot on the wall of each room that has an open-air tile next to it, but that isn't enough.
I think my 2 easiest options are:
Finally, and I almost forgot, I don't really like the aesthetic of the winding hallways anyway. They'd fit great in a dungeon setting, but not so much in a space station. Might have to go back to the drawing board...
Added some doors between rooms. Okay, not actual doors that can be opened and closed, but I carved open hallways between rooms.
I haven't covered the case that 2 rooms are neither vertically or horizontally aligned. So for now, they are inaccessible, so that's next.
Been stumped by my overly-complicated combat system lately, so I decided to take a break and start some proc-gen.
This is just a really simple algorithm that randomly places some rectangles with rigidbodies, lets the physics engine separate them, and then rasterizes the result to the tile grid. It's a start!
Was on a ski trip with my in-laws from Thursday till tonight. However, I managed to get some gamedev in on the plane ride back.
Nothing worth making a GIF of, but I made it so normal attacks will NOT trigger the defender's damage reaction if they miss. This was working for the projectile a couple updates ago, but I made it more generic for any attack,.
I also added logic so the grappling hook will trigger the OnArrival behavior of the defender when it performs the final 'kick out'. This means, if you grapple an enemy right on top of a trap, it will actually take damage.
Not a lot of motivation today. Watched the Spartans hang on to beat a shitty Iowa team by 3. Not very inspiring.
However, I managed to add a little feature. Previously, it was possible to grappling-hook anything; including traps, which I want to limit. Now, there is a flag in the base Entity class, 'moveable', which is considered when trying to grapple. Of course, the Trap wasn't actually inheriting from Entity, I had to change that.
No GIF because I can't show something not working. Also, I'm lazy. Goodnight
Updated the grappling hook to calculate the nearest non-blocked tile and 'kick' (that's what I picture in my head at least. No actual animation) the defender to that position.
It's lacking the "OnArrival" behavior when the defender reaches its final destination. This would trigger the traps attack, for example.
Started some very basic work on the grappling hook today:
The obvious flaw right now is that it pulls the enemy onto the attackers tile. This technically is allowed in my combat system, but I don't want to encourage it. In fact, I may make it impossible for 2 entities to occupy the same tile, with the exception of traps.
To fix this part of the hook, I'll have to deduce the proper nearest point to the attacker to make the destination point for the victim. That shouldn't be too hard, but I'm honestly not sure what it should look like. If the victim isn't going to get pulled to center of the attacker, where should the grappling hook start? Should it have 3 points (attacker's position, destination tile, victim's position)? Or should I just fudge it somehow?
I was absolutely not feeling like doing gamdev after work and class tonight. I actually played video games (Rocket League) for 2 hours instead of doing gamedev, which is rare for me recently.
By 10pm I finally got the motivation to do some gamedev. I wanted to add a 'grappling hook' ability that will pull an entity right in front of the attacker. This will be a utility move for melee classes for closing the distance to ranged enemies. However, when I sat down to implement it, I realized it should be loosely based on my 'push' ability which I haven't kept up to day since the AbilityVisualization and ability UI system reworks. I spent about 30m updating it to a barely functional level (didn't actually implement a visualization, but the ability still 'waits' for all the enemies to move before completing). And then I lost motivation, and am going to bed. 30m is better than 0m!
Added something I've been meaning to get to: missing! Now attacks actually have the concept of not always hitting! For now, its a straight 50/50 RNG roll, but eventually it will be configurable per the ability, and might be modified by things like Entity accuracy, blind state, or target's evasiveness.
Implementing it required giving all AbilityVisualizations the concept of 'missing' as well. The only one I've gotten around to implementing is the ProjectileVisualization. Now, it actually goes past the intended target if it misses! It doesn't do anything fancy like detecting walls, so it looks kinda silly, but that can be refined later.
Once again, my group project has been sucking my mojo away from gamedev, but I managed to be decently productive for ~2hrs of time.
The Player and the Blob were duplicating a lot of code for things like: monitoring when an ability finished, updating passive traits every turn, updating their combat component every turn. I refactored that into a base class, and now they're only different in logical ways.
Generalized the StunTrait that gets applied by certain attacks to be any PassiveTrait via another ScriptableObject hierarchy. Technically, I could make an attack that gives the enemy the passive ActionRegen trait upon hitting, neat!
Here is a GIF of the Grenade ability imparting a 3 turn 'blind' state. Blind will eventually have some effect on combat (lower accuracy?) but for now it doesn't actually do anything:
Tonight, I added quite a bit of infrastructure to support "states". These will be various conditions that can affect an entity such as stun, rooted, and blind. This is implemented by a bitmask. Next, I added a PassiveTrait for stun that makes it easy for Abilities to apply a stun that lasts 3 turns and then removes itself. Whlie stunned, an entity basically forfeits it's turn. Finally, I added some UI to the EntityCanvas to visualize the current states.
My night class has been cramping my gamedev style, but I managed to add a little feature tonight: kill streaks.
Pretty straight forward: kill any entity on your turn, increment the kill streak. Don't kill anything, streak resets. The neat thing, if you can call it that, is that the kill streak is a ResourcePool, just like HP or Action Points. This means it can become a dependency of certain attacks ('have a kill streak of 2+') and I can optionally make some abilities 'consume' the kill streak. Not that I've actually used those ideas anywhere yet.
I might end up not using the yellow UI meter to visualize the kill streak; it's probably overkill. I think putting a simple # on the abilities that require a certain KillStreak might work. But it's good for debugging at least.
joined 2,227 days ago