Deylinia

Ludum Dare 46

Cacophony Hotfix #1

Hello!

We have been continuing development on Cacophony our roguelike dungeon crawler game made for Ludum Dare 46, in this time one of the priorites we had was fixing the many bugs and UI issues that we ran out of time to do during the game jam!

Our first patch is now live on itch.io and is playable in your browser

Fixes include:

-Better (see: actually visible) icons for equipment slots in the inventory

-Shops now refresh when you enter a new floor

-Items can now be purchased from shops by clicking the entire slot, not just the item sprite.

-There is now a floor counter so you can see how deep into the dungeon you make it

-Armor and weapons now properly grant stats

We hope you'll give the game another try or maybe your first try if you haven't played it yet!

Let us know what you think we plan to continue development on this game for a while longer so any and all feedback is greatly appreciated!

Remember to open your inventory and equip the sword when you start ;)

Starting on tuesday I plan to post a daily series of posts detailing our experience and development through ludum dare check it out if you are interested.

DONE.PNG

Play Cacophony in your browser now!

My First Ludum Dare Part 1

Hello! This was my first game jam and really the most complete game I have ever been able to make so I wanted to write about the experience a bit! I'll be making a new post every day detailing what happened throughout our Ludum Dare weekend!

If you'd like to try our game you can do so here make sure to leave feedback if you do!

we're looking to learn as much as we can from this experience thank you!

Introduction

We had messed around making some small projects before but they weren’t very impressive or complete (perhaps I will make a few posts on past projects at some point).

Game development is something I have been interested in for years. It is actually one of the reasons why I began programming when I was younger, but I was never able to fully sink my teeth into it.

I thought Ludum Dare would be my chance to finally do that.

Preparation

The way Ludum Dare works is the week before the Jam starts there are 4 days of voting for themes. The first three days will each have a unique list of themes and then on day four the most popular themes from days 1-3 will be chosen and voted on.

We took some time during the voting week to get together and discuss our ideas for possible games we could make relating to the themes so that on the day of the jam we could get to work as fast as possible.

Some of the highlights from these discussions were:

  1. 1 minute to prepare: PvE Auto-battler like Teamfight Tactics / Dota Underlords where each round your economy, levels, and pieces reset. Then, you have to choose how to spend your money before the round starts.
  2. Side effects: Each action you take slowly closes the side of the game screen in on you, when it gets too small you lose.
  3. Outdated Technology: You’re a master swordsman who has just been attacked by a group with guns for the first time ever, so now it is a stealth game.
  4. Momentum: Dynasty warrior type beat em up, every enemy you kill increases the speed of the game.

These were our favorite ideas for the other themes that even though we didn’t get to pursue this weekend we may look into making in the future!

In the end, the theme ended up being “Keep It Alive” which admittedly was not our first choice or one we had discussed much, but we were determined to do the best with it regardless.

Expectations

Going in, I wasn’t sure what to expect of myself, my team, and the game jam itself. I had never finished a game over the course of years of trying to. As a team, we had only made a halfway functional tower defense game over the course of a month so I wasn’t sure how we would fare on such a limited time frame and with the stress of that deadline hanging over our heads.

The only goal I had for our team and myself was that this time we complete a game. I believe this is a crucial skill to develop in and of itself and it was something that I had never accomplished.

Because of this, I had wanted to sway the team towards creating a very simple game that we could feasibly complete within the time frame. In my mind, the simpler the game idea and mechanics the better.

That is not how it turned out.

The Day Of The Jam

So the time has come for the theme to be revealed and we’re less than enthused about the “Keep It Alive” theme, but we had to get to work regardless of that.

Now this is where things went a bit off the rails.

We had decided we would make a roguelike RPG with a few survival mechanics as our game jam entry.

Remember when I said I wanted to do simple? Well, we threw that idea away almost immediately.

This decision still baffles me because instead of sticking with the plan of a simple game we could complete, we somehow made the decision to make a more complex game than anything we had attempted prior.

In any case, it was time to get to work.

Development

There are a few key factors to a roguelike game

Procedurally generated maps
Permanent death
Loot

Many of the older games in this genre also have a tendency to use grid-based movement and turn-based combat along with random item generation to make the loot more interesting.

The first and arguably most important thing we would have to accomplish to make this work was the procedural generation of maps.

So I began coding our GridGenerator script which would handle all of our map generation. I would say this is where I spent at least half of my time during this game jam.

In the end? We made it work well enough to make it one of the features we received a good deal of positive feedback on.

Next Post I will go over how we accomplished our map generation and some of the challenges faced along the way.

space.PNG

Cacophony: The Ballad of the Celestial Goblin-King is a procedurally-generated roguelike dungeon crawler created in 72 hours for Ludum Dare.

You can try the game in your browser here.

My First Ludum Dare Part 2 - Map Generation

This is going to be a bit more of a technical dive on the map generation in Cacophony.

I got a bit carried away so this post is a bit long but I hope its informative!

Map Generation

Procedural generation of maps is arguably one of the most iconic properties of roguelike games, because of this we had to make sure we got it right. As I had some experience creating a similar script in a previous unity project this task fell on me.

So I got to work.

The generation in our game is based on the methodology from a popular roguelike tutorial using a python library called libtcod. The basic process followed by this tutorial is as follows:

  1. Fill the specified area with walls
  2. Carve rooms out of this area by deleting walls and placing floors in rectangles
  3. Connect the current room with hallways
  4. Determine what type of room has been generated and place the proper extra characteristics within the room
  5. Repeat for the specified number of rooms

There was, however a few issues with using this tutorial namely:

  1. This tutorial is meant for python, not C# and especially not Unity
  2. This tutorial represented every wall with the same “Sprite” (really a character in most cases)
  3. While I am sure they get to it eventually, the section I read did not have different types of rooms generated

traditionalRogue.png         More traditional roguelike couresty of my co-developer Scott

ourMap.png One of our generated maps

Our Implementation

There are 3 main classes involved in the generation of maps in our game

GridGenerator.cs – Handles the generation aspect

MapInfo.cs – This is a scriptural object that contains variables used to generate the map, stores information such as the x and y bounds, the current tileset, and the list of enemies to be spawned in this map

Map.cs – This class contains static dictionaries used to reference the different tile layers using their (x,y) coordinate as a key. This class is responsible for populating these dictionaries after the game has been loaded.

If you’re interested in seeing the code in full for these classes click here

There is also a Rect class that handles some aspects of the room generation, but I don’t feel this is a good implementation in its current form and would recommend against our current setup.

GridGenerator.cs

For the most part, this class follows the tutorial linked above to a tee. Below is some of the code that had to be handmade to have our display work properly. Essentially all this does is place the proper sprites on the edges of the room so that they can visually look better than just having a flat wall sprite.

gridgen.png

It’s game jam code, go easy on me

Further down, in the GenerateMap() function we have another slight deviation from the tutorial script. We wanted to generate different types of rooms so we could have stores, traps, exits to a further floor, etc. The counter is basically a hacky way of making sure that we always generate one and only one kitchen, store, and exit.

the room variable is the room we are currently generating, this function will be called after the room has been carved out and hallways generated.

roomGen.png

I can’t explain why the usage of that counter – switch statement combo feels wrong but it does…

The functions being called on the room object belong to the Rect class, I am not sure is the best way to break up this code but it’s what we came up with in the time allotted.

I’ll only show a few examples so you can get an idea, because this is most likely the messiest code in the entire project.

diffRooms.png

Believe it or not, this is some of the better code from this section

Now, if you’re reading this in hopes to learn how to do some map generation please do not copy and paste this code, it is ugly ugly ugly and one of the first things I will be refactoring but it got the job done for the time we had.

MapInfo.cs

MapInfo is a Scriptable Object class, if you don’t know what that means I spent my first post on this blog talking about them! Alternatively, you can go straight to the resources I learned from this excellent blog post by Daniel Ilett.

To sum it up real quickly scriptable objects are a Unity class that are very good for storing data independent of game objects and with very easy serialization.

Here’s what our usage of them looks like:

mapinfo.png

The entirety of this class

The first section of variables lines 9-15 contains some general information about the map that will be useful to players,enemies and the grid generator.

All of the variables here are pretty self explanatory, the tiles and enemies are fed into the grid generator so that it knows what tiles to use and the boundaries determine where the map starts and stops generating.

What this allows us to do is create a Unity asset entirely in the editor for each different tileset and set the enemies and dimensions in there without changing any code at all!

unity.png

An example of what this object looks like in the Unity inspector

This is one of the better design choices we made during the jam as it allowed our map generation to be flexible even for our team members who did not know how to code.

Map.cs

This is the class that glues this whole thing together to work in our project.

It contains two dictionaries with every relevant tile that we can then access using the tiles (x,y) coordinates. This is how we handle movement, combat, and interaction with special objects.

What this class does is quite simple but the implementation can seem a bit confusing.

getTiles.png Thank God for stackoverflow

What happens is the tilemap object has a collider that scales when a tile is placed, we use this to get the x,y bounds of an this object and then we iterate every x,y position in world space and create a MapTile object (This is a data class that I will likely rewrite soon) and store it in the dictionary.

Most of the time when we reference this dictionary we are checking whether the requested tile is a floor or a wall.

Wrapping Up

All in all, I don’t think this seems like the most complex take on map generation I have ever seen and it is really a stringing together of different tutorials until we had something manageable. But it worked well for our game and most importantly we were able to get it done in the time frame we had.

This is a section of the code I spent a lot of Ludum Dare working on, and as we continue to develop the game I have no doubts this will continue to be the case.

Yes you read that right, we are going to continue developing Cacophony because we’re all having so much fun working on it.

The first update will release the same day Ludum Dare voting ends May 12th.

space.PNG

Cacophony: The Ballad of the Celestial Goblin-King is a procedurally-generated roguelike dungeon crawler created in 72 hours for Ludum Dare.

The first update to Cacophony will be released May 12th.

You can try the game in your browser here.

My First Ludum Dare Part 3 - Trials and Tribulations

As I am sure many other developers did, we ran into more than our fair share of bugs along the way while developing Cacophony. Some of which turned out to be straight forward fixes that were right under my nose, others which were a bit more elusive.

Let’s take a look at a few of the notable ones.

Walls that aren’t walls

In my previous post I wrote about how the map generation works for our game.

Long story short: We fill a square with walls, remove walls in rectangles to make rooms, remove walls to make hallways between these rooms. This is from my understanding a tried and true methodology for procedural generation of dungeons in roguelike games.

This is where A LOT of my programming time during Ludum Dare was spent and this bug in particular cause me a large quantity of grief.

Here’s what went down:

In our game, we have side and corner tiles for the wall to make the dungeon rooms look more natural and appealing. This is a feature we wrote from scratch on top of the generation provided by more text-based tutorials.

image-7.png

This alone was just some simple math, if we know the coordinates of the 4 corners of the room its easy enough to figure out where these tiles should go.

So while this was working we’d run into issues where when a room was not a corner like seen above, but more like the layout shown below, tiles in the green boxes would still visually appear to be walls but would logically act as floor tiles.

image-8.png

Maybe some of you can already see where this bug is going, but I could not. I looked through the code and everywhere when we set the logical tile to a floor tile we updated the visual tile so what was going on?

I debugged this for hours upon hours on Saturday morning with no luck, it had gotten to the point Sunday night I was content shipping it this way and just saying there are some visual errors in the game.

Then, in a passing sentence one of my co-developers Scott said something along the lines of “It looks like it’s just placing the walls on top of the hallways” and as soon as I heard that everything in my brain clicked into place.

What was happening was a problem with the order in which operations were happening. The hallways were getting created, which updated our logical tileset but afterward the visual corners and edge walls were being added. When the visual edges and corners are added, we weren’t changing the logical tiles because in my mind they were already walls we were just updating the visual cues.

A bug that had my pulling my hair out and accepting defeat, solved in seconds by Scott’s passing thought.

Classic.

Prefabs updating out of the game

This is probably one of the weirdest bugs I have ever seen in Unity, and this will serve as an example of why you should listen when people say there is a proper way to do things.

When maps are generated we also spawn a couple of NPCs in the dungeon. Namely, two shopkeepers one for gear, and one for food. Naturally, when we spawn these NPCs because our entire map is randomly generated we will have to place them in their respective rooms.

This should be a very simple operation but it wasn’t working both NPCs were being spawned at 0,0 and never moving.

So, a few Debug.Log statements later and we can clearly see the function responsible for moving them being called, and we can even see that the debug log is printing the position where they are supposed to be as their current position. Cue the confusion.

What was actually happening was that all of this code was accessing the prefab file stored in the editor, and not the active game object we had just instantiated using that prefab. Weird right?

The issue turned out to be how we were accessing the prefab we wanted to spawn.

image-9.png

What had tipped me off that this may be a problem was actually a random message directed to somebody else in the Unity discord. What did that message say? “There is no reason to ever use Resources.Load” and from there, I knew that even if it didn’t solve my problem it couldn’t hurt to remove this line of code and access the prefab in a safer way.

And like magic this actually solved our problem. What originally had confused me more than almost any other bug I had seen previously was as accessing prefabs the same way I did in every other script.

Programming, am I right? I suppose a lack of sleep and mounting stress will make you write bad code.

Our biggest challenge

More so than any of the bugs we encountered and map generation in totality by far the biggest challenge we faced during Ludum Dare was attempting an implementation of A* path-finding.

This was a daunting task but one that would have to be overcome in order for us to have a functional roguelike game, there’s not much challenge in a bunch of enemies that stand still is there?

The last time I had thought about A* was in my last college semester Algorithms class and even then I had a very hard time wrapping my head around it.

So without much planning or research I dove right in at a naive implementation of my own making which failed miserably. After a few hours were wasted on this effort Scott did some research on A* and prepared a presentation to explain the algorithm to me.

The details are hazy on me still so please do not take this as an A* guide there are much better resources out there but my understanding is essentially A* checks the possible moves it could make from its current position, then rates them based on their distance from the objective. From here it consistently makes the best decision currently available to it then moving in that direction.

From here, Scott, Ryan our artist, and myself got in discord and began to pair program our way to success with the guidance of Scott’s research and presentation.

Ultimately, this was a process that took us until almost 5am on Saturday night (Sunday morning?) but what was important that we succeeded and the game would not die by a lack of path-finding.

screeny.PNG

Cacophony: The Ballad of the Celestial Goblin-King is a procedurally-generated roguelike dungeon crawler created in 72 hours for Ludum Dare.

The first update to Cacophony will be released May 12th.

You can try the game in your browser here.

Cacophony v.02

Hey everyone! How's your Post-Ludum Dare been going? We decided since this was our first game project we got somewhat off the ground to continue iterating upon it and add some features many of which were suggested by people from this community!

Cacophony is a roguelike dungeon crawler and you can find it here

Our First Update

Content / Features

Boss Fight #1

Are you ready to challenge the Skeleton King?

skullservantanimation.png

The first boss fight is something I really wanted to get done in the Ludum Dare period of the game but unfortunately did not have enough time to do so.

But now he has been added and he has some challenging mechanics as well as our first dive into making a small “cinematic” for revealing him. This part of the update was a ton of fun to work on.

Scaling Difficulty

Previously, you could delve into the depths of our dungeon with little to no increase in challenge. In fact, the game would seemingly get easier as you would be acquiring gear while the monsters power level remained static.

This has now changed.

We have made it so that as you go deeper into our infinite dungeon the monsters will become more powerful until eventually you succumb to death. This mechanic will be the subject of ongoing iteration and balancing for the rest of Cacophony’s development.

Mini-map

image.png

We have also added a mini-map feature to the game! This is pretty self explanatory. The mini-map will be revealed as you explore it and marks points of interest you have discovered as well as your current location.

In the future we plan to make the map expandable for a more detailed view and we will continue to upgrade the visual design of it.

In this screenshot you can also see we’ve added an indicator for what floor you’re currently on! Let us know how far into the dungeon you can get! The current record is floor 63, though this was before the scaling difficulty.

QoL and General Improvements

Animations and Player Feedback

We’ve now added rotation animations to every sprite in our game. This should help to make the game feel more alive and visually polished. You can also see when a character takes damage they flash red for a brief moment to indicate this is happening.

Animations and feedback are another sections of the game where we will be continuously working to improve the look and feel of Cacophony.

Selling / Removing Items

image-1.png

You can now sell items at shops or destroy items from your inventory. When selling items you will receive 50% of the items purchase price as gold.

Future iteration for this feature will include better visual design, as well as confirmation messages so you don’t accidentally sell anything you planned on keeping.

Our Own Item Sprites

We’ve added our own unique item sprites now as well. Previously the Item sprites were one of the few assets that we did not create ourselves and now we have removed everything that was not made by us with the exception of the gold coin icon.

Bug Fixes

• Lots of path-finding bug fixes included. Enemies can now round corners, and will get stuck less often

• Enemies will no longer attempt to occupy the same tile as another enemy

• Map changing now works better and more smoothly, including transitions from randomly generated maps to hand-drawn maps.

• Fixed Armor/Weapons not applying stats properly in some cases

• Shops now refresh their stock every time a new map is generated

Conclusion

That’s about what we have been working on the past two weeks! It feels like a lot has been added or generally made better for Cacophony during this time and we’re still having a ton of fun working on this project. Up next we will decide what direction to take v.03 and where Cacophony will go in the future!

Thank you for playing Cacophony and for reading this. A lot of these changes were inspired by feedback given to use here on the Ludum Dare site so thank you to everyone who took the time to contribute and play our game.

Play Cacophony in browser now!

Ludum Dare 50

Foster The Bleeples

My second Ludum Dare in the bag!

FOSTERTHEBEEPLBES.jpg

What a fun time, we decided to make a semi-idle pet simulation game where you try to keep a small creature known as a Bleeple alive.

This game was a ton of fun to make and was a perfect game jam idea! We were able to get a lot done in the time frame of Ludum Dare. At the end of the day there was just ONE feature I really wanted to add to the game that didn't make the cut in time.

I'd say that's pretty good for a game jam!

Anyways, check out the game and let me know what you think! If you leave a rating/comment I'll do the same on your game. I'm hyped to see what everyone made!