juxipolo

LD33

LD33 Post-Mortem

Lich Rising – compo entry

[I’d put an image of the game here, but WordPress doesn’t give me that option…]

Lich Rising is probably best described as an RTS tower defense in reverse built by someone who hasn’t played an RTS in a long time. It was developed solo in 48 hours with C# and Monogame. The details and download link are through the link above, the rest of this post will be a quick post-mortem from my experience creating the game. I’ll to talk about what went well, challenges I encountered, and the design process.

Some background on me, I’ve been developing games for years, but only came to LD in the last year. I’ve got a lot of experience and boiler plate for working with C#/Monogame, so the platform choice was obvious.

I wasn’t real excited about the theme selection this time around. The idea for this game was the only real feasible and interesting idea I came up with. This one just didn’t hook me. The final result is fairly similar to my initial pitch. Since I wasn’t super excited, to keep things interesting I pushed in new personal directions for art and code style.

Art Style

I’m quite pleased with how the art style turned out. I settled on the direction very quickly and the results are appealing for how simple the core style was to create content for. It might be difficult to tell, but there’s no real 3D in the scene. The style creates a good illusion and it looks better than if all the sprites were laid down from straight overhead. Each object in the scene is comprised of several planes parallel to the camera with varying heights from the ground. I think the key to it working well is the bright solid colors, no borders, mostly angular geometry, and little anti-aliasing. The effect gives a good illusion of a more detailed 3D model for a very low time cost.

I implemented it with a 2D camera by offsetting planes from the center of the camera based on height. I’m more comfortable working with a 2d camera, so I went that route instead of 3D. 3D obviously would have been the better choice given more time to experiment.

Towards the end of the weekend, I added several new models to the scene in just a few minutes, and the characters took maybe half an hour each. Some of my janky animations break the effect if you pay attention, but not severely with all the other action.

Early on, I also made the decision to use bright and unusual colors for the monsters and props, and drab colors for the humans. I think that helped add visual interest and convey what was going on when there were a lot of things on screen. The coffins were a bit of a challenge. I knew I wanted to make it clear you were raising the enemies you killed. They also needed to be findable and targetable by the player. A grave or cross might not have been easy to see in battle, and I suspected a dead body on the ground wouldn’t look good with the art style. A coffin seemed like the best choice.

In retrospect, I am a little disappointed in the ground texture, I wanted something that conveyed camera movement, but the result doesn’t look as good as I had hoped. I also wanted to go back and change the tower to be octagonal. It stands out as particularly not angular with everything else in the scene.

Development

The style of game and art style pushed my game logic outside my comfort zone. Most of the games I’ve built before this have either been turn based, or built on top of simulations that are still compartmentalized. Most of my code library has been built for integers and discrete grids. That didn’t seem feasible with this game, so I had to get comfortable with floats and vectors pretty quickly. For most game code that wasn’t a problem outside of a few hooks in my library. The two biggest problems – collisions and pathfinding – came at the tail end of the first night.

Leveraging the grid-based pathing code I’ve used before was impractical. I didn’t have anything resembling a useful quadtree or navmesh, and six hours in is a bad time to realize how important that was. The original plan was to build several windy trails through the woods. I considered a system of waypoints or possibly directional slopes to funnel units into the players home base, but that fell apart as soon as a unit encountered a player unit and gets led off-path. I also briefly considered something like hugging the right wall to sidestep obstacles. That was probably closer to feasible, but still a lot of work and still not great. Additionally, even simple collisions require more than comparing each object to each other object and look for overlaps. Not even having a reliable quadtree available, let alone geometrical collision system, was a major problem.

Luckily, the two biggest problems had a single LD-style solution. I constrained collisions to mostly happen in a single direction, removed most obstacles, and used the simplest collision model. By confining the space vertically, it let me divide the world into vertical slices that could reduce the search space for any given collision (it isn’t quite that simple, objects can exist in multiple slices, but it reduces the algorithms complexity by a significant factor). That same tool was also later reused for fast access to what’s on screen and what’s under the mouse pointer.

Each character on the map used a relatively simple state machine, with only some small variation between player controlled units and AI controlled one. The collision handling was managed in the state machine for simplicity, and is slightly interesting. On the tick for each unit, a first pass collision check is done against friendly units. If friendly units overlap, they apply a small force against each other so they spread out a little. Then a stronger force is applied towards their state goal (nearest unit or the player base). Finally, the unit checks for collisions with props in the scene where it’s planning to go. If there is a collision, the prop pushes back outward from the center of the prop, and then that final normalized movement is applied to the unit.

I had to make a choice in how to build the map. I could build a simple map editor and place objects by hand, or I could generate the map procedurally. In the end, I chose to place all the props and spawn locations procedurally for several reasons.

  1. Because of the issues with collisions there weren’t going to be complex path layouts
  2. I was worried I might need to change the map size over time (and I did), which would likely mean rebuilding the map
  3. Spending time to build a tool that then takes more time to use sounded like a lot of time total

Gameplay and Controls

The original goal was to have a single unit that would raise the dead, have direct RTS-ish control over the main character an their minions, and defend against waves of humans. Everything else I expected to would figure out along the way, and that worked out okay *this time*.

I sort of wanted to have the player work from a graveyard in the middle of a map with paths coming in from various directions, and obstacles like fences, trees, and graves. Technical limitations meant that probably wasn’t feasible, so I had to improvise. It was early enough in that I could still make large changes. I took some time to really think on it and work on some rendering and animation. It would have been easy to give up at that point. What helped the most was thinking about the subsystems I knew I would need and challenging myself to find a way to implement them quickly. If I built a simple collision system around circles intersecting, could I change the game to fit that restriction? If units only knew how to walk in a straight line and bounce off obstacles, could I change the game to fit that restriction? The answer was obviously yes.

So after making sure the game was feasible, implementing the collision system, unit state machine, and basic mouse controls, I had a mostly empty playing field early on Saturday. I still wasn’t totally clear on the goal of the game. Defending against waves can be fun if there is variety, but I wanted something more. I didn’t want it to just be a tower defense, and having a clear goal and end state can keep a player engaged. Taking the fight back to the humans seemed like a good idea from a theme perspective, maybe you attack a castle or village. That seemed like a lot of time. So thinking about limitations, what if I restricted it to just a tower as a representation of that? That could work, so then we had a goal.

So with that I had a barebones game. As I went, I took time to occasionally play around with the systems and imagine what I could add with a little more than a day left. I zoomed the camera out so you could better see and manage units, I made the map taller so it felt less like a corridor and gave some options for going around the edges. I spent some time on the controls.

I chose to have the spell casting be a two step process because I was thinking I might implement other spells where the location mattered more. Something like a corpse explosion or summoning a healing corpse flower turret thing. It wasn’t intentional, but it does have the side effect of adding more to do minute-to-minute, which is nice. I went with the cooldown time mechanic for spell casting because it was a safe choice. If I wanted to switch to like mana or something else, I would probably still have a short cooldown. After a bit of playing the game, the cooldown felt alright, so I left it pretty much untouched to focus on other things.

I then implemented some more thematic units, animations, projectiles. and wave spawning. Along the way, I noticed the map felt empty. Enemies trudged on a linear path, so the top and bottom were somewhat wasted. I had planned on adding random objects to the center of the map, but that would just mean sometimes the humans would look silly walking straight into objects. I also realized you could just send a unit along the back side and chip away at the human tower. Putting turrets in the middle as an obstacle was a logical solution.

I actually found myself with some time after implementing what felt like a decent mix of units. I could have added more units, I could have worked on the spell system, or I could have improved the progression. Those would have been nice, but a tutorial system was probably the best use of time. The controls weren’t going to be immediately obvious from within the game, and for an LD game there is a lot going on in this one. Tutorials and basic usability aren’t very sexy, but as quickly as people jump between LD games, it’s more important than many devs expect. A giant text dump or click through dialog is only somewhat better than nothing, so I definitely wanted some interactivity to it. It’s just a linear series of steps, and it was pretty easy to add a hook to progress the tutorial on certain basic actions. This was also a good opportunity to not just convey the necessary information, but give the game some flavor.

One of the last gameplay changes I made was to coffins. After a few waves, if you weren’t really keeping up with the spells, you would have a pile of coffins in the middle of the path of the enemies. This meant enemies could get stuck on the coffins and become easy targets, and you had all the coffins you could ever ask for. Removing collisions from the coffins was the first thing I tried, but the coffins looked a little weird when every unit was just stepping over them. I could have had a drop rate for coffins, but I felt something would need to happen to the enemies that didn’t turn into coffins. Luckily, I had a bit of a eureka moment. Making the coffins targetable by enemies was surprisingly easy to implement, and meant coffins weren’t a limitless resource and would never really get in the way of the enemies.

Sound

I’ve never been particularly musically inclined, but I wanted to push myself and include music this time. I had allocated about two hours for it, and had a looping track, but it obviously didn’t make it. I didn’t think it fit the game well. I was worried it was too distracting, and didn’t want a situation where music is worse than silence. I probably spent too long getting set up for it, I’l have to make sure I have a workflow figured out in advance next time.

I recorded quite a few sound effects, but only used 4 and really needed some more in places. I spent most of the time focusing on the battle sounds. I recorded a few dozen, trimmed that to 12, and then pulled the ones that weren’t speech after hearing them in game. Even playing with distortion and how often they’re played, the sound effects didn’t sound right in battle.

I also recorded a set of responses when you select a unit. I got as far as compiling them in, but then forgot to hook them up. Whoops.

In retrospect, I needed a few sound effects for a few other events. When a spell recharges would be really useful, and spell casting might be nice. Something when the Lich or altar is under attack would also have been good.

What went well

  • I was really happy with how the art style turned out. If I want to implement another top down game, there’s a real good chance I go this direction again.
  • I’m really surprised how much I got done. I didn’t really think I would get all the units in I did.
  • There was a point in dealing with collisions and pathfinding that I considered scrapping the whole thing, but I’m glad I pushed through.

Needs improvment

  • The controls weren’t great. Even after playing for a while I occasionally hit the wrong button, which is never a good sign. I did some research into control schemes, but I didn’t find one that made sense to really clone. I also forgot to add screen-edge mouse scrolling for the map. I meant to come back to that.
  • Audio ate a lot of time, with very little to show for it. I need more practice with music, it would have been nice. I also recorded three dialog bits that I forgot to add to the game, and that’s just embarrassing.

In retrospect

  • One lane of enemies is maybe too straightforward. I wish I had thought to break up the spawns into lanes. It would have added some variety and a use for the map edges. It would have been very easy to implement, but I just didn’t think about it in time.
  • Unity is good at several of the things I struggled with. It wouldn’t have been a good time to start from scratch on a new platform, but it’s worth thinking about for the future.

Future

This post-mortem is really sealing the project. I don’t have a strong desire to polish this up an publish it somewhere. I learned a lot and it was a bunch of fun, but I have a long list of other projects in process.

LD34

LD 34: Colony XG-29 Postmortem

Colony XG-29 is a strategy and resource management game where you take on managing a fledging human colony on an outer rim planet. It was developed solo in 72 hours using C# and Monogame.

 

Details and download link

Here I’d like to talk about the design process, what went well, and challenges I encountered.

I am quite verbose. So to save your scroll wheel on the main page, everything is below the fold.

Theme

I’m pretty bad at predicting the final theme. Like the last LD, I had barely thought about either of these themes in advance. It took around 2 seconds to rule out two button controls. Then it took around 2 hours of brainstorming to settle on a direction for growing, which was too much time.

Initial Designs

“Why not both?”

I did come into the LD hoping to make something turn based and mechanic heavy. That probably meant either a TBS or a card game. I don’t know what happened, but I must have had an aneurysm because for some reason I thought “why not both?”.

The original design idea was to grow a colony of settlers using cards to place buildings and perform actions. I didn’t have a really good sense for how the game would play out. I think I was expecting the cards to be a secondary mechanic for the turn based unit and building management.

One of the first major decisions was setting. A space colony seemed to make a little more sense than a historic or fantasy setting. Having some sort of abstract stockpile of things that could be used on demand didn’t seem to fit those settings.

crop1

Development

“Hexes are future-y”

I have written a lot of engine and other game code over the years with C# and Monogame/XNA. Other than my core engine, I pulled in some of the card rendering and basic interaction code I used in mini-LD 60 (but then ended up rewriting a lot of it). I also have a bunch of code to support a hex grid with structures, rendering, and camera controls. Going into the LD, I didn’t really want to reuse the hex rendering logic since I’ve used it for several projects and it’s a bit of a beast, but hexes are future-y and fit the theme. Eventually I was also able to crib some of the tutorial system from LD 33.

That all makes it sound like I just had smash a bunch of bits together and call it a day, but I definitely wrote more new code this LD than any previous one. Wiring up the hex grid rendering code to the point where it showed terrain took almost all of Friday evening, if that’s any indication.

I wasn’t really sure how you would select or generate cards. I knew I wanted some sort of pack opening mechanic integrated somehow. While trying to think about how it would work during normal gameplay, I hit upon the initial drafting mechanic. It fit really nicely with the theme as like selecting supplies for a space ship. As soon as I had terrain rendering, I switched gears and implemented the card rendering and built out the initial card drafting screen because it made a good simple test.

crop2

After hooking up some basic cards on the map and the resource system, I started to get an inkling that I was just building a turn based, single player, Offworld Trading Company. I really wanted to differentiate the game. I had originally thought about military units fighting off aliens as sort of being a primary component of the game, but wrote it off for time as things were dragging on. The game needed something more, so I put in the aliens and built up the combat and AI. Supporting direct unit control for player units was going to take too much time. Instead I was planning on having turret-based defenses, but once I had the units in it was easier to just drop one in as owned by the player with some small AI tweaks. I had the units pop back to your deck when idle because I didn’t know what else to do with them. With that hooked up, I never felt like I needed to circle back to add defense turrets. Automating the units after placement gave the game more movement, kept it from dragging with micromanagement, and meant you didn’t have to fill the board with a giant turret ring.

I knew I needed a way to get more cards from very early on. I wired up the black market, and set up a system for card pack vendors. That system really highlighted just how few cards there were. You’d open a pack, and get the same cards every time. The problem was that I was already behind schedule. The goal I’ve had with LDs is to have a complete and playable game Saturday night. That leaves Sunday for testing, audio, UI polishing, balance, etc. I didn’t hit that point until Sunday afternoon and the last four hours of the compo window was a mad dash of building a bunch of cards to fill in packs and blank spots in the economy.

This game continues my tradition of terrible names created at the literal last seconds :)

crop3

Compo -> Jam

“Making a better game won out”

It was and incredibly frantic weekend, and I didn’t have time for audio, but I did it! I made a compo game on time! One little problem. I hadn’t actually played the game. It ran and the features mostly worked, but I had ran out of time before playing it with all the debug cheats off. After some food, some errands, and some relaxing, I reevaluated what I had made. It was technically a complete game, but it wasn’t fun.

I had to make a tough call. I had created a game within the compo restraints, but I was very disappointed with it. I had taken Monday off as an LD recovery day, so I had flexibility. In the end, making a better game won out.

“Why does this tiny colony need this many hospitals?”

There were a lot of problems with the compo version.

  • You very quickly had more resources than you knew what to do with – This is still a problem to some extent, but it was worse in the initial version. You could not practically spend your resources fast enough. To address this, I created reusable cards like the DarkNet Channel to act as money sinks, and created disasters to eat chunks of your reserves. I strongly considered adding resource caps that you needed to expand, but ran out of time.
  • You had to wait too long for population to grow and the last 200 citizens took ages – I added in the random chance for colonists to arrive, and added the Offworld Shuttle as both a population pump an money sink. I also magnified the effect of happiness, which hadn’t increased population enough in the late game
  • You constantly had a ton of dead cards in your hand – one of the problems is that if you bought a pack of cards, you got all of them. If you wanted a specific card, you’d get several duds as well. I added in the resell mechanic, the direct vendor purchase, and the recycling card to help keep your hands small.
  • The aliens were only a thread because you had so many useless cards in your deck you had to skip to get to a military unit – I strengthened some of the aliens, and increased the costs of the military units
  • Buildings could go anywhere. There was no reason to not just plonk buildings down wherever – I wish I had time for more of these, but I added the Network Hub and changed to Vidplex to change based on the surrounding buildings.
  • There wasn’t enough variety – Originally the only event you could get was the black market. I added random disasters, colonists, and the direct sale screens as alternatives. I did make a handful of new cards as well, but I didn’t want to flood the game with slight variations on the same cards, they needed to be unique.
  • You spent more time reading tooltips than looking at the card – I improved some of the card-mouse interactions, and specifically added the hover effect that pops cards in hand forward.
  • Happiness was pointless after a few dozen turns, you really had to let a shortage get out of hand to offset the happiness from buildings – this took a lot of thinking. Futzing with the formulas would either make the early game too difficult, or it was confusing. Eventually I settled on the adding the health mechanic. After a certain grace period, the illness value periodically starts ticking up by one, and every turn the population goes down by the illness number. That doesn’t make a ton of sense if you stop to think about it (why does this tiny colony need this many hospitals?), but it solves several problems. It can have significant detrimental effects if you don’t deal with it, health buildings are a resource sink, and it acts as a sort of ticking clock beyond the aliens.
  • You didn’t know when the aliens were coming, so you had to play zoomed out and constantly scan around for alien movement to deploy your units – I added the notification queue so you can see them coming.

At final count, I had 7 units, 24 buildings, and 38 cards. For as much time as I spent on them that feels like such a small number.

What went well?

I really feel like I nailed the content workflows this time. I figured out a way to skip one step to import content with monogame, but I also saved tons of time ignoring the XML-driven content system I’ve used in past games. Instead I focused on generating all the card rules and text in code. I’ve picked up great C# techniques since the last LD that were really clutch. The last time I tried game data via code, it meant constructors with tons of parameters and/or lots of switch statements and special cases all over, but now I can make this so succinct. This is all it took to get a card in game:

code

That’s so much simpler than the XML deserialization nonsense I had been dealing with, and delegates make special cases so much cleaner.

I took good advantage of C#’s async feature. It was very convenient for the card playing logic. It made it really easy to create a code flow like click -> wait for animation to complete -> prompt for a cell on the map -> actually play the card. No need for a bunch of state variables or deep callback chains, it’s all one code path. (FYI: If you’re thinking of going down this route with Monogame, by default your tasks may land on a second thread, which can cause unexpected race conditions. You can fix this by rolling your own SynchronizationContext)

I found a bug in my engine that has been there for probably ~5 years. This is an improvement over last LD, where I ran into a lot of issues with the control layout and interaction code that led to significant rewrites afterwards.

What went poorly?

“I should have known better.”

I should have known better. Mini-LD 60 was a card game, and it ate so much time. Building a turn based strategy game on top of that was madness from the very beginning. I never had time to stop and consider how much work I had set myself up to do, I just kept going. Not submitting for compo was disappointing, and this was ultimately the cause.

Even with an extra day, I didn’t really have enough time for audio. I just couldn’t prioritize it over making the game playable and intuitive. Making music was out of the question, but some simple sound effects would go a long way. In retrospect, I probably could have reused some old audio with the jam rules, but wiring it up and mixing it still takes some time.

Cards have a rarity that impacts how often you see them in packs, but you basically can’t tell and it doesn’t matter. Every pack has a rare, but since there are so few, they’re sometimes practically more common than other common cards.

There isn’t much of a reason to explore once you’ve found the three basic resources.

Future plans

After the extra day of balancing, I’m super chuffed about this game. I’ve played through it a few times after submission just for fun, which I haven’t done for an LD game in a while. I’ve got tons of ideas for cards and mechanics. I really do want to see this thing through. Art will be a very large challenge, though. Programmer art is not a cohesive style. I’m thinking about clean and solid colors, maybe something like this?

future mockup

[looks like I didn’t put a shadow under that smokestack… whoops]

 

 

 

LD35

//SHIFT/haxe Postmortem

 

//SHIFT/haxe is an overhead shooter with vector-style graphics, where you can shift between various shapes to destroy waves of enemies. The game contains many procedural elements, including enemy bosses.

It was developed solo in 48 hours for LD35 using C#, Mongame, and SFXR.

Click on the image, or here to play and rate.

This post will be a postmortem of the development of the game. I am very verbose, so everything is hidden below the fold.

Theme

Looking back over the last 5 LDs, I’ve only had a strong vision for a theme once. I’ll have a few strong ideas for other finalist themes, but then really have to stretch once one is picked. I didn’t have a hard time coming up with ideas for shapeshift, I just had a difficult time finding something I really wanted to make. A few other final themes sparked some ideas I was excited for, but this theme just left me cold. I was sorely tempted to ditch it entirely, but stuck to it because I can always revisit those later.

The final gameplay is very similar to what I envisioned. I did imagine there would be an overworld connecting various “servers” with multiple arenas that would have a boss that unlocked a new shape, but I dropped the overworld portion fairly quickly to keep scope down. I wasn’t really intending for it to be as much of a bullet-hell shooter as it can be, but I’m not sure what I would have done differently to change that.

I designed the gameplay and art style first, knowing what I have worked on in the past. From there, that are style really dictated the digital-computer setting.

5

Development

I hedged my bets in design to design a game that could leverage the things I had done for LD 33. I had come up with a rendering and collision system. I reasoned that I would be able to leverage that code for an overhead shooter.

The art style in that game was a simple fake-3d overhead perspective. Using a series of 2d rotated image layers offset to give the illusion of 3d makes it very easy to import a new object with a high quality 3d appearance. I had also created a circular collision system on that game meant to limit the number of collision checks between objects.

As it turns out, I reused maybe a dozen lines of code. The player and enemy ships didn’t benefit from the 3d, but it meant I could still get some nice 3d looking effects fairly easily. That only took about 3 lines of very simple code, and a little bit of overhead throughout. I never needed to implement the whole collision system, and a little profiling makes me think I over-engineered it back then.

I started by creating arenas, and specifically drawing the arena walls. I knew I wanted arenas with shape, and while I could have hand placed where each line was drawn, I really wanted to automate the process so I could have variety. Weirdly that code was some of the more complicated and time consuming on the project. Basically the code iterates around a grid of solid and walkable cells that defines the shape. When it hits a wall, it steps around the edge and builds a list of corners. It tracks every edge it steps over in the process so it doesn’t build multiple overlapping walls. Having a system like that allowed me to later add many arenas fairly quickly and I leveraged the code for the end of level teleporter effect.

3

Next up was the camera. It’s easy to overlook the camera in LD because it’s subtle and it isn’t obvious what a good camera adds to the game. A locked overhead perspective with the player at the center doesn’t feel great in an enclosed space. Especially with bullets that don’t have a max range, it would have felt like a lot of the screen was going to waste. I also didn’t want a locked view that fills the screen, since that would make the arenas feel small. The game projects a point a certain distance in front of the player towards the mouse and centers the view around that. That doesn’t work great around the edges, so I constrained that centering point to keep more of the arena on screen at the edges.

On Saturday I started making enemies. I didn’t really have a specific plan, I just wanted to make sure there was a good variety. Just changing the enemy sprite didn’t feel like it was enough. I wanted to make sure they each behaved differently. Enemies and the player share some base movement, firing, and rotation code. On top of that, enemies make a movement and firing plan via something like a frame-step co-routine. While that executes, each frame they are just constrained by the world’s physics to make sure they keep a reasonable speed check for collisions. When that plan completes they create a new movement plan with a little randomness. Each enemy AI is fairly simple, but the unique behavior adds a lot of depth. The circle moves towards the player on the X or Y axis. The arrow slowly turns to face the player and then fires and rushes in. The W shape strafes left or right and fires 4 bullets at a time. The big green one moves on the X or Y axis randomly, slowly turns to the player, and fires a stream of bullets.

Level variety was important to me, so I planned ahead with things like the dynamic wall construction so that I could slot in multiple maps with minimal overhead. I originally considered procedurally generating levels, but I was worried that the levels would feel very strange or sometimes be impossible. I also considered a level editor, but the maps were simple enough that that felt like overkill. Instead I built an importer that opened all the images stored in a specific folder. It read the images pixel by pixel, and built the collision grid from that. Certain colors on the image translated to map features. I’d experimented with something similar a few months back in a very limited fashion. I think this worked out very well technically, though my level design wasn’t great on a few of the maps.

Procedural Boss Generation

At that point I had most of the trappings of a game, but it needed a feature to really stand out. Just fighting waves of enemies felt too repetitive. I had been toying around with the idea of bosses, but I wasn’t sure if I could pull it off. I started in seriously late on Saturday. The idea was that I could create one master enemy that created a set of enemies that it would control. First, the boss decided randomly whether it was primarily wide or tall, then it determined whether it would be symmetrical left to right and/or front to back. With those variables, it created a virtual grid around the center piece at 0,0. Then it picked either a row or a column and appended a piece to either end of that row or column. If it is symmetrical, it adds pieces to mirror the placed piece. Each piece it adds has a different frequency and difficulty cost, and it stops when it places enough pieces to meet a difficulty threshold.

4

Once the boss is created, the single boss center piece controls the behavior and total HP. All of the sub-pieces just try to stay in formation and fire occasionally / on command. When the boss is created it also sets a few attributes based on difficulty and randomness. It picks a max speed, and determines what behaviors it will follow (using the same basic enemy co-routine framework). If the boss is wide it tends to strafe more, and if it’s tall it tends to charge more. After a few levels it occasionally stops and fires all weapons or teleports around the map. The results are fairly satisfying. Sometimes you get a real dumb looking boss, but sometimes you get something really awesome. The emergent behavior that comes from the boss trying to move around obstacles is also pretty cool, and (unintentionally) fits the theme well.

Scheduling this project was a bit interesting. The game is fairly safe and well established territory, and there was very little chance of not having a complete-feeling game at the end. As opposed to dedicating Sunday to polish, I polished as I went and triaged features up until the last hour. I constantly asked myself what is the most important feature I could add. That meant some key elements were postponed until late, but that let me be very flexible. For example, the menu to change your shapes out was added late, because I knew I could hard code the shapes to keys if needed. I could instead prioritize the boss system, which is something I would have been very afraid to add late, but turned out to be the highlight of the game.

Audio

I started creating sound effects with SFXR and wiring them in on Sunday, only to discover that the sound system was silently failing. I hadn’t worked on any game audio since I got this computer, and hadn’t tried playing sound during warm-up. Whoops. There wasn’t an obvious fix, so I just cut audio all together and worked on other things. After some other cleanup and polish I circled back because it was too important to the game. I still don’t know why it’s not playing, but I swapped out the monogame audio pipeline for the windows media one built into .Net. It’s really meant more for playing things like application alert sounds and beeps though, not game audio. It has a lot of issues, but it’s key feature is actually working. I wanted to include music in game as well, but just am not confident enough in my music making skills.

6

What went well

Procedural boss generation turned out way better than expected. You get some wacky bosses, and they’re fun and feel different. If I had known how well that would have turned out, I would have made this a boss rush game.

Enemies were easily identifiable, felt unique, and worked well together to create challenging scenarios.

Could have gone better

I mentioned audio already – I should have tested that during the warm-up

The upgrade system isn’t great. It doesn’t really keep up with the difficulty ramp up, several of the shapes aren’t very useful.

The only reason to not just hold down the trigger is to quiet the sound effect. I was debating healing by not firing, but was worried that would slow down the game.

The gamepad doesn’t work on the weapon configuration screen. I just couldn’t think of a simple way to implement it in time.

Not enough balance time. There were some tiny tweaks that would have been great if I had done more testing.

  • I scaled back enemy HP, but enemies still feel bullet-spongy.
  • The red enemy is a little frustrating because of the bullet lag – I should have made them continue in the same direction until they hit a wall instead of strafing randomly so you could better predict their movement
  • Game ramps up difficulty a little too fast – I doubt many people will unlock all the weapons.
  • The flamethrower mode needed longer range to be useful
  • The shield mode should have lasted until the shield wore out instead of using a timer
  • The little enemies are more of a threat than the bosses – I should have put in a spawn cap for the enemies that spawn in during boss levels and tapered off the normal level spawns more.
  • Several levels are just bad. The maze-like normal level and the wide boss level are probably the worst. Without better obstacle avoidance and pathfinding, enemies get stuck in corners and can’t reach the player. Also, the exit placement should probably have always been in the center so you don’t need to truck across the board for it.
  • Continue button should have probably been relabeled to better fit the theme.

Future plans

I don’t think I’m going to polish this up and ship it on some platform, but I’m on the fence on that. I do see a lot of potential in expanding it as a boss rush game, but I’m not sure what I’d want the upgrade system to look like. I won’t really touch it until after the voting period, so I can sit on that.

LD36

Legacy in Ice – Player’s Guide

 

I just put out a polished up post-compo build of my LD 36 game, and I thought it would be good to put together a little player’s guide to go with it. Point and click adventure games can be frustrating if you aren’t on the same wavelength as the developer, and everyone has a lot of games to play so I figured some hints might prevent you from getting stuck.

You can grab Legacy of Ice here, if you want to check it out.

Click the link below for the players guide.

Select text to reveal the hint. Each hint for a puzzle gives you more clues to solving it. To prevent spoilers, try to figure out one hint to a puzzle before revealing the next one.

 

General tips:

  1. Click on things multiple times to investigate them further
  2. Click the white bookmark in the upper left to open your inventory. Click an item to select it, then click where you want to use the item

How do I get into the mine?

  1. The chief of security on the second floor should be able to help you
  2. But he’s not going to fix that door anytime soon
  3. You’ll need to use an item on the door to replace the handle

How can I help the chief of security?

  1. You’ll need to replace the handle
  2. A bent piece of metal could probably be wedged in
  3. Use the angle bracket on the door

How do I get the shiny thing?

  1. It’s pretty high up there, but maybe if you gave it a good thwack
  2. A slingshot would do nicely
  3. If you pick up the divining rod and the rubber tube, that would work as a makeshift slingshot
  4. Use the slingshot on the squirrels nest

How do I get down the elevator?

  1. The robot is pretty stubborn, you’ll have to convince him to leave his post
  2. A fake disaster won’t get him to leave, but a real one might
  3. If the light on the dock were to break, you could convince him to fix that instead of clean
  4. Drop an icicle in the breaker box to fry the lights
  5. You can grab an icicle off the far side of the dorm building

How do I break through the wall?

  1. It’s pretty solid, you’ll need a power tool
  2. The grumpy miner was fiddling with something that might help
  3. The security chief might have an idea
  4. Give the grumpy miner the mail from the dock and he’ll forget all about his drill
  5. Use the drill on the wall

What do I do with the lone tree?

  1. What’s that thing at it’s base
  2. If might need to dig through the roots
  3. Use a shovel on the tangled roots
  4. There was a shovel back on the path to the dock

How do I turn this thing off?

  1. Each pedestal moves some of the sliders in a consistent pattern. Each slider only moves left and right. If you walk away, it will reset on it’s own
  2. Weren’t there some numbers written on the rock wall in the previous room?
  3. The numbers form a simple combination, with 1 on the left and 4 on the right
  4. Move the sliders such that the first and last are on the far right, the second is in the second position, and the third is on the left
  5. When all sliders are reset to the left, click the first pedestal twice, the second once, and the third 3 times

If anyone knows how to make proper spoiler text in wordpress, I’m all ears :)

LD 40

Triage Towers - Devlog / Postmoretem / Thing

For LD40, I recorded a ton of video about my dev process. Like a whole bunch. Like way more than anyone would think is reasonable. I've finally cleaned up and uploaded the potentially interesting bits to youtube. So if you want to watch entirely too much video about creating a Ludum Dare game, then I have you covered!

If you didn't play it during the rating period, Triage Towers is the game I'm talking about. If you want to spend an hour playing a simulation game about building a hospital, I've uploaded a more complete post-compo version with a lot of new features and things to build.

(I'm having trouble not embedding videos via youtube links - sorry for making you copy and paste URLs :disappointed: )

  • Day 0 - Initial ideas and brainstorming: https://youtu.be/DsghbC89b-M
  • Day 1 - Making progress, challenges along the way: https://youtu.be/HbFClGAHFzA
  • Day 2 - Deadlines, madness, and exhaustion: https://youtu.be/AP0PnJUb68g
  • Post-Weekend** - Post compo review: the good, the bad, and the other: https://youtu.be/i24rvy3elnw
  • Post-compo Update - Game updates and final thoughts: https://youtu.be/WYSr7R8Ipws

** - While not in chronological order, the post compo one is probably the best place to start and maybe the most interesting, as I give an overview of the game:

https://youtu.be/i24rvy3elnw

Ludum Dare 49

Post Mortem: 50 Crowns for 50 Kings

This is a post-mortem for my jam submission for LD49. Click here to check it out.

So this definitely isn't the best looking LD game I've ever made, it's quite unwieldy, and rough around the edges. However, I think it is one of my more interesting boondoggles. This post mortem is likewise a bit of a boondoggle - just fair warning, this is going to be a long read.

4.png

I've had the title "50 Crowns for 50 Kings" written down in my notes for a long time. A world where the united states failed to form and split into 50 independent nations could be interesting. How would that world shake out? Maybe that's the kernel of a novel, or maybe that's a video game.

The LD theme (unstable) seemed like a reasonable fit for this world. It's an unstable political situation.

As a video game, something like a grand strategy game would make some sense, but I'm not usually one for the obvious route. Some people might like the idea of conquering America as Delaware or Wyoming, but that doesn't really excite me. I already build a game a bit like that during LD 38. Perhaps instead you aren't playing as a one of 50 little kingdoms yourself, but are influencing their actions.

So that was the initial idea for this game. There are 50 warring state that act as simple automatons which fight each other. You would play as a European power in a turn based game that is not about conquering all the territory, but rather manipulating the states. You don't control troops, you control diplomats and spies, and are choosing where to invest. Perhaps you would have additional special actions that could have major impacts on what was going on.

If I had known how complicated this game would be, I probably wouldn't have tried to build it during Ludum Dare. I was aiming to complete it in the compo window, but only barely was able to barely finish it within 72 hours. In retrospect, this should have been impossible.

Friday Night

I had built an interactive region map system for LD38, but that had been a tedious process. I knew I would need even more regions on the US map, so I needed a new system. To create the US map, I started with satellite images, then divided it into regions and painted each region a different color than it's neighbors.

map regions.png Ugly, but the code doesn't care

The game then loads that image and scans it, creating regions on a grid based on neighboring pixels of the same color. Since I wanted some of the states to have multiple of these regions, I created a second map that grouped every region into real-world state boundaries. Running the same clustering algorithm on that image and cross referencing the two helped set up the initial board state.

I had planned to do something similar to create the visuals for the map. I would use a satellite image and extract each pixel to a tile in a tileset. That could allow for some detail like rivers and mountains. Once I had the current low res image in place, I never had the time to circle back to try that. I did eventually go back in and flatten the colors in the playable region. There is so much happening on the map already that the extra colors proved to be very distracting to play.

I expected delineating 50 different countries would be difficult. I settled on drawing the borders using one or two color patterns, and shading inside the borders of each territory. I started by making an image of the different lines, each one pixel wide. The top pixel of each line would be parsed and used for the inner shading. I started with a set of solid colors, then doubling that and painting in alternating colors that were mostly neutral, then adding a few combinations that looked good to differentiate further.

borders.png Each vertical line is a state border on the map (plus a few neutral lines for special cases)

Still, if two similar borders were next to each other, the results didn't look great, so I assigned each state a border, and then used a fixed random seed to shuffle the ordering. I tried a few random seeds until I found one that minimized adjacent borders of similar colors.

Saturday

The first major challenge was to design "simple automotons" for the states. It sounds simple on paper, and I think it's fairly intuitive, but it is probably the most complicated logic in the game.

I knew there would need to be some sort of system of military strength and combat, and some sort of system of resources to feed that military. I really had to fight the urge to add additional complexity and realism to the basic systems like that.

The player was going to see a lot of combat and needed to be able to parse combat results quickly. The solution was to just have a single number of troops per region, and no randomness to combat. There would be no differentiation for different types of armies/cavalry/artillery or anything like that. Simple modifiers could then be added on top of that, but as long as the number remain small, it's fairly easy to predict outcomes.

Similarly the economy would be made of just three simple things. Taxes, food, and guns. Cities would generate tax revenue, and larger cities would generate much more. Food is needed to sustain an army. 1 unit of food would feed 1 soldier each turn. 1 gun created by factories would add an additional soldier. Guns would be less common and more expensive than food, so there's a benefit to keeping troops alive.

That sounds simple enough, but then I had to make an AI to use that system in a way that feels reasonable.

Each turn, the AI collects resources and pays it's debts. It distributes all of the food it has to feed it's troops. If it doesn't have enough food, it trades money for food. If it has extra food, it instead sells that food for extra cash. If there still isn't enough food, troops randomly disband for each food they're short by.

econ.png This probably isn't enough to explain the system in game, but it's about all I had time for

Then the AI determines the threat of all neighboring territories. For each region it controls it checks that regions neighbors and marks the magnitude of the possible attack that each region faces. For all of the regions which are under threat, it tries to shore up those borders by purchasing troops. Each gun resource that it has can create a soldier, which is placed randomly, but weighted in favor of the regions under heaviest threats. If the state doesn't have enough gun resources, they buy them.

Now the AI starts to think about attacking. It searches all enemy neighboring regions, and scores them based on what resources they have and how many troops they have relative to possible attack launching points. They select one region as their potential juicy target for the turn, and one of their bordering regions to be the spearhead for a potential attack. If they have leftover money at this point, they buy additional soldiers and place them on the spearhead. They won't spend all their money recruiting troops to attack, however. If they are under threat, they will spend whatever it takes to shore up defenses, but for attacking they are a bit more conservative. Each king is assigned a target reserve randomly at the beginning of the game. They will only spend money above and beyond that threshold to pay for aggression. This helps insulate them against future threats, and randomizing gives each game a little more variability.

The AI kings do that at the start of the round. Then players take their turn. When you click next turn, each king will look at their juicy target, and decide if they will attack. They count the number of troops they can attack with from their spearhead (minus one to stay behind), and compare that with the troops in the enemy territory plus any fort bonuses. I opted to make the AI a little hesitant, so the more overwhelming the attack, the more likely they will be to attack. That way things aren't entirely predictable, but you can have a pretty good idea. Assuming the attacker won, they distribute all the troops between the two regions similar to how they would be recruited. The order the kings go in could matter here, so the kings take their turns sorted by the number of soldiers they have. Larger countries go first, which is useful as that means they can make an attack and another neighbor can swoop in and steal it out from under them. This makes the Kings seem more aggressive and dynamic.

The kings serve their purpose reasonably well, acting as mostly intuitive automatons, even if the player doesn't fully realize everything going on behind the scenes. They aren't always the smartest, but when there are 50 AIs interacting, it's pretty easy to overlook a quirk here or there. The one thing this system doesn't do is allow for the AI to fail an attack or do something like skirmish without committing all of their troops. I'm not sure that's really too important, though. Importantly, it allows for a reasonable number of places for one of the players to interact with these underlying systems.

That all probably sounded pretty straightforward now that I'm describing it, but it took a lot of brain crunching to come up with that system. Figuring that all out and getting it all working took basically a whole day on top of rendering the map. By Saturday night I was able to watch the AIs fight each other automatically. I was pleased to see that given enough time, someone would eventually take over. Without having any way for the player to interact with it, it was fairly neat to see the AI go at each other.

Sunday

One thing I noticed from testing the system out was that it would take a long time for someone to conquer the states. Much longer than I want an LD game to run. Having the game stop after some number of turns and the winner based on score seemed like an explainable approach. I was really hoping to have something like a newspaper headline each turn to indicate some world event, eventually culminating in a world war, perhaps with a bit of randomness on when that came. Having world events would be a nice bit of flavor and world building. Unfortunately there just wasn't time. The telegram you get on the last turn came from this idea.

Early on I figured players would take turns placing diplomats and spies, and take actions based on where you placed them. I wasn't really sure what the diplomat and spy tokens would do, or how you would select those extra actions. I thought cards would probably be involved, but perhaps there would be a heavier focus on the tokens having basic abilities that could be selected. I opted to move the idea for basic actions to cards to simplify the turn structure and reduce repetition.

I wanted there to be something like a relationship system between the player and each of the kings. Something like the suzerain system of the Civ games. Placing diplomats would improve your relationship, and perhaps some of the extra actions would require a certain relationship level. I debated having the spy tokens act as a counter to the diplomats and reduce standing, but that didn't seem very fun. I also ended up having the diplomats generate additional funds for the kings where they were placed as I noticed most of the kings were generally always strapped for cash, and there should be some benefit if every player is courting them.

So I built a system of influence for the kings. Each king has a "swagger" which indicates how much influence the players have to generate to become an ally. This represents kings with larger kingdoms being more aloof and self-important, where some smaller nations are much more interested in what Europe has to offer. The first player to max out influence becomes the king's "key" ally. That doesn't quite have the impact I expected, but that status does double the score the king provides the player. You can see this system in action in the kingdom detail popup. Visualizing this system so that it could be self explanatory was important, so it had a bit of extra attention for something buried in an info bubble.

relationship.png

As I was coding the other systems, I had written down a decent number of ideas for actions. I've been trying not to make card-based games for a while if I can help it, but cards are a powerful tool and I have a lot of support code for them. They really did seem like the best option here. It's an intuitive metaphor, allows you to explain complex interactions, and makes every turn have different options available.

So with that, I had the basic turn structure for players. Players take turns putting out tokens, then play cards that affect areas where your tokens were placed. I don't think I got all of those basic systems in place until well after the original compo deadline.

The primary problem with all of these systems is that they are so predicated on having AI players to compete against. It wasn't enough to build the "automaton" AI for the kings, the other players needed to place their tokens on the board and play cards. If I had realized how much work I was signing myself up for, I would definitely have built this game differently. Luckily, the player AI was not quite as complicated as the kings.

Distributing the diplomats and spies is actually two separate problems, which just adds a little cherry on top. The players try to distribute their diplomats to different kings each turn. They look at all the possible regions and score them for much impact a single diplomat would have. (it might be buggy, but) they score regions where they could become the key ally highly, and regions where they already have an investment higher than regions where they don't. If the diplomat won't really do anything because they're capped out or almost capped out and can't take the key ally slot, that regions is rated lower. Spies also look at all the possible regions and similarly position based on a weighted score, scoring areas where there are multiple nearby diplomats highly, and kingdoms with a lot of total other-player influence higher.

Since I've built card games a few times, I had a decent idea of how to structure the AI for the card play, at least. Each card has a little async function running through the series of steps needed to resolve the card. The same function runs whether the player is human or AI, but each time the card requires a selection, the card provides a heuristic function to the selection which is used to calculate how to rate various selections. For humans, the player interactively makes a selection or cancels, but AI players use the heuristic to score all the possible regions and pick a positive score randomly based on the weight. That means each card actually has it's own little self-contained AI for how to make a good selection. Each turn, the AI basically just shuffles their hand and tries to play each card it can. This isn't particularly effective, but it can also crunch numbers better than a human and still appears to be somewhat competent. So the overall code flow wasn't tricky, but building out all of those little mini heuristic functions really ate up some time.

heist code.png Each card looks something like this

Monday

Once all these systems were together and there were enough cards to make it interesting, it was an absolute mad dash to the finish line for the 72 hour jam. I lifted the dialog system from a previous game and slapped it in place as a tutorial. I also used that to create a quick and dirty final score screen. I built out a series of lenses to visualize the various types of data on the map. I put together the intro text and menu selector. I built the message console so you wouldn't miss the important details that happened.

I did tack on a couple very quick features that I thought were cool. I made every European power slightly asymmetrical. Once the game was over, I set up a "one more turn" option. I added in a hard mode, which gives the AI additional money and cards each turn. I also added in an observer mode, mostly because I enjoyed watching the AI just duke it out on it's own. If I had time to actually balance the game, that probably would have been useful.

That was exhausting. I barely got everything in place in time, and what I did get there was fairly rough.

What went well?

Having a real world connection to the places in the game is very effective, and it's easy to add your own real-world knowledge of the states. It really helps generate stories, even without player intervention. Before I added any real player interaction and the states could just attack each other, I let the game run for a bit with just the states. I thought Manhattan would be well positioned to take over New England and sweep into the midwest, but instead Pennsylvania, New York, and Manhattan Island all smashed into each other, and then New Jersey swept in and cleaned up the pieces. From there the New Jersey Empire snowballed through New England and started into Ohio. Meanwhile in the west, San Francisco slowly conquered the rest of California and was slowly taking over the west coast. Ultimately San Francisco floundered without enough food to sustain a western advance. By the time New Jersey arrived, San Francisco could barely maintain it's troops around the Rockies. Using states in a game like this is almost a cheat code for storytelling to an American audience.

Beyond that, the pitch for the game is fairly strong. I probably need to refine it, but this is the sort of pitch that a wide audience could latch onto.

What went poorly?

The game was definitely over-scoped. I didn't really account for the complexity of the AI systems. Everything else in this section can be traced back to that.

The art style of the game is a mess. It isn't really an art style as much as a lack of an art style. I would have liked to see boardgame visuals like I created for LD38. It really would have taken a lot more time than I actually had, so it's probably for the best, but it isn't great.

Beyond the art style, the graphic design has some problems. It is quite difficult to parse through the information in the various lenses. Often the lenses don't have all the information you need to make a decision, so you have to swap back and forth. For example if you want to use the card that lets you form an alliance, you have to cross reference the relationship between kings, as well as see your player relationships to the various kings and check where your diplomats are.

The game system isn't intuitive enough, and also isn't explained well enough. I think the player relationships might be okay because there's a nice graphical display that responds to your actions, but several players understandably couldn't figure out the economy. A really good table or visualization or two might help to explain it for the curious, but could also be very tricky to implement.

There are a few smaller systems that don't quite come together. I ended up implementing as many of the card ideas as I could, but some don't really work. Forging an alliance is a bit tricky, and a sneak attack is quite difficult to actually pull off. There is a system of treaties which ends up permeating a lot of things, but the impact to the LD version of the game is quite minimal.

In combination with those previous issues, the turn structure is not smooth. I think I expected that you would play out your diplomats/spies for the turn without too much regard for the cards in your hand, but really the cards in your hand dictate where you should place your tokens. Trying to figure out where to place a token optimally involves multiple rounds of cross referencing and planning. It's complicated, but there are a lot of combinations and unknowns in planning, and not a huge payoff if you get it right.

What's next?

This game seems to have enough legs to continue development on. I'm not sure how far I will take it, but there is enough here to warrant some additional exploration.

I wanted to make the European nations more unique, and would probably give each at least a unique card, or possibly some more asymmetry.

I'd definitely redo all the art and make it look more like a board game.

I'm tempted to add multiplayer, primarily as a learning opportunity for future projects. I think the game is structured in a way that would make multiplayer "easy", but I could definitely be wrong.

I expect a lot of time will need to go into improving the player experience. I'm still not sure the best way to visualize all the different things the player needs to know, and maybe there are improvements that could be made to the core game loop.