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
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.
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.
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.
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.
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.
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.
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.
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).
More tweaking/addition of assets. Also updated the tile map. Not much more to report here.
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.
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.
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.
Added goals, which overlay the tile position where the crates should be pushed. Also began adding screen fade logic.
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.
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.
Added audio, support, including support for music and sound effects. Also added UI controls to mute SFX or music independently.
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.
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:
- Add more visual variety to the levels, especially tile sets. There are three worlds (hence the level scheme 1-1, 1-2, 2-1, 2-2, etc.) Each of these should have a unique tile set.
- Add character animations (including cattle). Ideally, I'd like animations to be added for the player, including for each direction the player faces. Think of a classic RPG, when you face left, a left animation plays. When you face up, a different animation plays.
- Add cut scenes/story back into the game. I feel like this is an important bit that would add a lot to the game.
- Polish the user interface and add UI animations for a cleaner look.
- Have a configurable user interface, including the ability to move the user controls to the other side of the screen. This was suggested by my wife and is a good call!
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
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.
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.