travisvroman.com archives

This site contains archived posts made before July 2022. If you're looking for the live site, you can find it here.

24 Hour Game Dev Challenge: Bull Shift!

Sat Apr 27 2019

It's been a while since I have created and actually published a game. The last one I did was released in 2014, which was just a simple Flappy Bird clone called StupidDuck. Having the itch to release a game of my own again, I decided to set myself up with a challenge - to complete a game in 24 hours.

The challenge was to develop an entire game in less than 24 hours total time. To clarify, this means 24 hours of development time, not one calendar day.

The game is based around an idea I roughly came up with almost 10 years ago. It involves a farmer named Jethro, who must rescue and protect his cattle during an alien invasion. The game would be a sokoban-style game, which involves the player moving cattle on a tile-based screen to a series of goal tiles. The game would be called Bull Shift, which is a play on words about moving cattle around the screen.

The original game concept involved powerups, level obstacles and cut-scenes which followed a story as the user progressed through the game. I was aware from the onset of the project that the scope was too large to be done in 24 hours, so I decided to go for the minimum viable product instead and build from there. Basically, a simple, straightforward sokoban game. It should also be mentioned that the idea for the game was finished before development began, so this was not part of the time spent developing. Application publishing to the Google Play store was also not part of this, as there is an application process which takes time.

I also decided I would make the project open source, so I kept it on GitHub as I worked. The project is available here.

It is also available on Goole Play:

Breakdown of Progress by Hour

Hour 1

This first hour was spent performing setup tasks like project scaffolding, seting up HTML/CSS and a basic JavaScript file. This also featured the inclusion of PIXIJS library, used for rendering, and basic game loop setup.

Hour 2 

In this hour, most of the time was spent setting up some basic structure for the game. This included the setup of a game "class" in JavaScript as well as setup basic messaging. Messaging systems are a powerful way to avoid tight coupling in code and to enforce separation of concerns.

Hour 3

More uninteresting architectural items were done here, including the setup GameObjects and some public "interfaces" for them. GameObjects are objects which exist in the world and provide a transform, but do not perform any logic or display on their own. Those items come next.

Hour 4

Even more architectural works was done, this time for the setup of Components and interfaces for them. Components are objects which have self-contained logic and concerns, which are then attached to GameObjects. In this case, they are stood up via factories which take in configuration. Components are a great way to separate concerns further. Some components are renderable and are aware of how to render themselves whereas some might not render but define behaviors.

Hour 5

In hour 5, a lot of work was done to setup basic levels, which hold game objects. I also began support for configuration file loading and implemented more component factories. There isn't much more to report here.

Game Configuration
Game Configuration

Hour 6

At this point I decided to make a slight change in the game's technology stack. This is usually a bad idea mid-stream, but in this case I felt it was warranted. Basically, I got tired of the headaches of trying to implement "classes" in Javascript. As a result, I converted the entire project to TypeScript, which is a superset of JavaScript which provides strong typing and a more clear class structure for the code. I use TypeScript at work a lot for browser game development, and it really is the way to go for implementing clean code quickly. It ultimately transpiles to JavaScript anyway.

Hour 7

Finished up the conversion to TypeScript. At this point I also added SpriteComponent, which renders a sprite to the screen. I also began source control at this point, as I figured the project was far enough along to warrant it. So, I created the GitHub repo and checked in code for the first time. The project is available at https://github.com/travisvroman/bullshift.

TypeScript conversion complete! A screen shot showing components on screen.
TypeScript conversion complete! A screen shot showing components on screen.

Hour 8

At this point I decided to create a BaseGameObjectComponent class, which is an abstract game object component base class which handles a few things all components will need (configuration loading and name assigning for example). I also fixed a few bugs found in the messaging system.

Hour 9 and 10

Created AnimatedSprites, which inherit from sprites but allow animations through sprite sheets. This class took 2 hours to implement because it took a while to troubleshoot some issues I was having with the update loop.

Animated sprites added.
Animated sprites added.

Hour 11

At this point I realized I needed a centralized way to handle assets. So, I added an AssetLoader and AssetManager to streamline this process. I then tied it into components which used assets.

Hours 12-13

At this point I was ready to actually start working on the game. The first thing I needed was a TileMap, so I began its implementation. I also created some "better" assets to test with, which were closer to what would be used in release (as opposed to the placeholder assets I'd been using up to this point). I also added a lot of documentation comments, because my aim for this project was to have parts of the code be reusable. I also added message broadcasting.

I realized that I was past halfway point now, and started to think about which features to cut. Immediately level obstacles and powerups were first on the list. I figured I could always add them later, but only after the basic game was complete.

Tile map support added.
Tile map support added.

Hour 14

Added the ability to unsubscribe to messages. This is needed as objects which are subscribed are destroyed, as the message system should not be trying to send them messages still. Also added a spawn component (which listens for messages).

Hour 15

More tweaking/addition of assets. Also updated the tile map. Not much more to report here.

Hour 16

Got multi-level loading working, including the ability to switch back and forth between them. Also fixed bugs with object and component destruction. Tied a temporary UI control to switch levels for resting purposes.

Hour 17

Added tweening of player movement. Sokoban Controller component added, which tracks game state and manages objects it needs to know about (such as the player). TileMap checks added for bounds.

Player and controller component added.
Player and controller component added.

Hour 18

Added crates, which represent the objects pushed around by the player. Player is now able to push them about and they collide correctly with walls and other crates.

Collision detection and crate moving is now working.
Collision detection and crate moving is now working.

Hour 19

Added goals, which overlay the tile position where the crates should be pushed. Also began adding screen fade logic.

Hour 20

Added keyboard input handler to expedite play testing and debugging. Fixed some bugs with screen fades. Also added TextComponent to get text on the screen. Added a move counter to the play screen, which tracks the number of moves the player has made.

Hour 21

Added UI elements to the play screen. Also added a summary screen. Tweaked previous UI controls. At this point, it's getting down to the wire. Many plans I had to polish items are having to be put aside.

Hour 22

Added audio, support, including support for music and sound effects. Also added UI controls to mute SFX or music independently.

UI and sound effects added.
UI and sound effects added.

Hour 23

Added title screen. Added an options menu and ability to select level. This also includes the ability to restart the current level and return to the title screen.

Hour 24

Added the remaining levels. Performed some minor tweaks to the UI and user experience with the remaining time.

At this point, the game is done! Everything that is needed to have a minimum viable product is in.

I completed the challenge and met my goal. 

The game is available on Google Play here:

Still To Do

Even though I completed my goal, there are still a few things I'd like to implement in an update to the game. When I make these updates, they will be in a fork of the project and released separately so that the original game can still be viewed. Some of the items I'd like to add are:

Things I Would Have Done Differently

If I were to attempt this again, I'd do a few things differently.

Use an Existing Game Engine

As can be seen from the above recap, I spent a lot of time implementing a game engine. Granted, I used Pixi under the hood, which turned out to be a good decision, but all the architecture took me hours that I could have spent on the visual aspects of the game, or not having to cut features instead.

One positive from this, though, is that I do have reusable code that I can leverage in future projects. So from that perspective it is not a total loss.

Pick the Correct Tech Stack from the Beginning

Switching to TypeScript mid-stream took about an hour cumulative that could have been spent elsewhere. Before I started the project, I was considering TypeScript, but opted for JavaScript because it wouldn't require any build setups which are required by TypeScript. I could have done the entire thing in JavaScript even still, but I think in this case I should have started with TypeScript to begin with.

Pick a Project with a Smaller Scope

The scope of this project was too large for a 24-hour project. I pretty much knew before even starting it that features were going to be cut. While this is a normal occurrance in game development (or any development, really) I had to cut out quite a lot more than I originally wanted to in order to make it fit in the time allotment. Granted, some of this was due to the tech stack, but otherwise a smaller, more focused game idea might have been a better way to go.

Conclusion

All in all, I am okay with the game as a whole. I would have liked to polish it a lot more and add some additional features and better graphics. This project provided some valuable lessons learned, though, and I am okay with the game as-is for it having been done in 24 hours. It's the fastest I have ever developed a game and actually shipped it.