World Fighter

Play online

Classic beat ’em up action. You must guide the planet and defeat the evil planets to save the universe!

Videos

Post Mortem

World Fighter, The Cosmic Warrior was my thirteenth game developed for the main 48 hour Ludum Dare game development competition.

Dylan, Joe, and myself got together at Panera on the Friday night before the competition for a Ludum Dare kickoff.  We speculated about what the theme would be.  In previous competitions, we could get an idea of what the final contenders would be based on voting in previous rounds.  However, those metrics are no longer available, so it was anyone’s guess.

My previous two games that I had developed over the past month were both collectible games.  Note Chomper was a 2.5D Pac-Man clone that I developed for the MiniLD #73.  Miner Madness was a platformer that I developed in GameMaker for GM48 where you avoid the bats and collect the gems.  I knew I wanted to develop something for this competition where you attack and blow things up.


One of the themes that caught my interest was “A Small World”.  As with some of my previous entries, such as One Gunman, I knew I could take the theme and make it the protagonist of the game.  I told our group that I was thinking that I could make a fighting game, with a character like Globey from Pee-Wee’s Playhouse as the main character.  He would fight other planets across the universe.

My original idea was a fighting game similar to Street Fighter II.  The title is a play on “Street Fighter, The World Warrior”.  At first, I thought about just switching the words “street” and “world”, but “The Street Warrior” really didn’t fit when I decided that the environment would be space, so I decided to go with “The Cosmic Warrior”.  I had never made a beat ’em up game, so I decided to make the game similar to classic arcade games like Final Fight or Double Dragon.

For the player’s character, I decided to make it green with blue for the facial features and hair.  I tried adding a nose to my character by modifying the mesh in Blender, but then it really didn’t look like planet so I kept the original sphere shape.  I think Joe was the one who suggested using moons for punching, which I think turned out well.  I modeled the planet character and animated the moon punching in Blender.  I tried keeping the planet and two moons as separate objects in Blender, but that caused problems when importing into Unity, so I combined the three meshes into one, with three bones in the armature.  I created an idle animation and a punching animation.  I assigned one capsule collider to the planet character, and then a sphere collider to the moon used for punching.  Unfortunately, this means that the moon “fist” collider has to be reassigned whenever the model is re-imported into Unity.  I haven’t found a good way around this yet.

The enemies are similar to the player’s character, except they have a different texture.  I tried making them look like Mars, with white hair to look like the northern ice cap of Mars.  I made it so that each enemy could be destroyed with one hit.  I had planned on having multiple enemies with varying levels of health, so that some would be more difficult to defeat than others.  I also hoped to have a boss planet character, that would need to be defeated in order to clear the level.  I ended up just having a counter for the total number of enemies and the player just needs to defeat all of the enemies to clear the level.  I also wanted to have life bars displayed for each of the enemies, but time ran out before I could add that feature.

The movements of the player and enemies were handled with Playmaker addon for Unity.  The enemies continually check to see if the player is a certain distance away.  Once the player is close enough, then the enemy will move to the player’s location.  When the enemy reaches the player’s location, it will start attacking.  After each attack, it will check to see if the player is still in range, and move toward the player again if the player has moved away.  Both the player and enemies bob up and down, which I think turned out well.  It gives a bit of liveliness to the characters.  I had to manually write the turning code myself, since the default rotation was not always in the direction that I wanted.  I always wanted the player to rotate with the front facing towards the camera, so I had to take that into consideration in my rotation code.

I used the Blender Cell Fracture plugin again for making the planets explode.  I put the explosion animation in a separate prefab.  When an enemy is defeated, the enemy GameObject is destroyed, then an enemy explosion prefab is instantiated which plays the death sound effect along with playing the cell fracture animation.  The one problem I still have with the Cell Fracture plugin is that you can’t define what the inner parts of the exploded object look like, so it just appears to be random parts of the texture.  There are lots of options for the plugin, so I probably just need to look into it some more.

I used Audacity again for the sound effects.  I didn’t try anything really experimental this time.  I used the pitch modification to lower my voice and added a little bit of an echo.  I used an envelope for the punch swipe sound.  The one thing that I find frustrating with Audacity is that I think it should make the folder of the file that you opened the default when saving or exporting the modified file, because it wastes a lot of time having to dig through the directory tree to find your sound effect folder each time.  However, it is a free tool so I can’t complain.  The Audacity source code is also on GitHub, so I could actually change this if I really wanted.

The music was composed in GarageBand on my MacBook Pro, as I have done in previous competitions.  Again, I used my regular process of making a couple of melodies, then I changed up the instruments and made slight modifications and mixed the melodies together.  I also made a slower version with fewer instruments for the title screen.

I made the starfield background using a tutorial that I found years ago when making my Earthball pinball game.  I changed it up a bit to suit my needs.  I left out the supernova stars to create a skybox background.  I learned that the skybox settings are hidden in the Window Lighting settings, and it is specific per scene.  I had to change the Environment Lighting Source to a solid color, since the starfield skybox source made everything too dark.  I put two stars down as a guide on the ground texture for the bounds for where the player can move.

The game world is composed of a number of “blocks”, similar to a street block.  Each block has three enemies, which are somewhat randomly placed.  There are two starport type objects, which I modeled and texture mapped in Blender at the last minute, which also form the bounding area of where the player can move.  I had envisioned that these would be destructible and produce items, similar to the trash cans in Final Fight.  The level could be improved by having an invisible wall that prevents the player from proceeding until all of the enemies on a block are defeated.  I have a case statement that does add an invisible wall before the first block and after the last block to prevent the player from falling off of the ground.

I am happy with the game that I made for this Ludum Dare competition, but I don’t feel like I learned or tried anything new.  There are definitely things that I want to fix and enhance in this game.  However, after three back-to-back game jams I’ve decided to take a break for a little while.  I think I want to try a new game engine or new modeling tool next time.

 

Released

Worker Bees

Play online

Description

Enemy bugs are attacking  the bee hive.  Spawn worker bees to attack the enemies and protect the hive.  Worker bees will orbit around the hive at a constant distance.  The bee meter in the upper right corner shows the amount of time remaining until another bee can be spawned.  How long will your bee hive last?

Screenshots

 

Released

Wipe Out

Level Select

Began working on improving the Level Select screen.  First, I needed a method to convert the numeric ranks to a character or string.  I really didn’t know where was the best place to put this method, so I included it as a static method in the LevelDefinition class, so that other classes won’t need a reference to a LevelDefinition object to get the string representing the rank (S, A, B, or C).  And yes, you can spell three letter dirty words using the rank letters.

Next, I got the vertical scrolling working on the level select screen.  Defined variables  to track the number of levels displayed on the screen, the offset level (minimum level displayed), and the currently selected index.  The selected level is the offset level plus the selected index, which is a derived value calculated in a method.  In the screenshot below, the offset level is 3, the selected index is 4, so the selected level is 7.  I may go back later and add another static method to convert the level numbers to more meaningful values, such as “1-1” for level 0, “1-2” for level 1, and “2-1” for level 10.  If the user presses down and the currently selected index is the maximum number of levels displayed on the screen, then the level offset is increased by one (unless the maximum number of levels are already displayed).  If the user presses up and the currently select index is zero, then the level offset is decreased by one (unless the level offset is already zero).  Simple up and down arrows are displayed when the minimum level index can be increased or decrased, letting the player know that there are more levels to be displayed.

 

Saving Data

I was able to get simple saving done (just strings) a few days ago, but this really didn’t actually save any of the game data.  So I went back and created a method in the PlayerRecords class which serializes all of the record data.  Basically, it just writes out one line for each level.  The line first contains a Y/N value indicating if the level was completed, then three pipe delimited values containing the integer value for the ranks achieved for that level.  Conversely, I created a parse data method which takes a string acquired by my file load method, and uses splits to read data out of each line and out of each pipe delimited value.  These values are then stored into the data arrays.  I also created a reset method, which clears all data by writing an empty string to the save data file, and then loads that data file.

Clearing Data

I also wanted to give the player the ability to delete all their records, in case they want to start fresh.  This was accomplished by calling the reset method when the Back button was pressed on the Level Select screen.  However, this made it too easy for the player to press Back and wipe all their data.  The player could have just wanted to go back to the title screen and didn’t know which button to press.  Therefore, I created a mini-state within the level select class which prompts the user to confirm if they really want to delete all the records.  The default is (obviously) “no”, so the user has to consciously press up to change the value to “yes” and then press the confirm button.  The one thing that confused me was that the selected index for the “yes” value was zero, since it was the choice on top and “no” has a value of one.  This goes completely against my programming instincts, where one is a positive or true value, and zero is a negative or false value.  The one exception being the return values from main in a C program, where zero is success and a positive value is an error return code.  This functionality could have been extracted out into its own Confirmation Dialog class, but I didn’t feel like taking the time to do the required setup to get that working, since it would not fit my standard Screen display model.  So instead, there is just a boolean in the Level Select class which determines if it should display the confirmation screen and process the events on the confirmation screen.  It’s too bad that I can’t use my menu code that I wrote in Ruby for TetraCity, because it is a very solid menu’ing system that I wrote.

 

So now it looks like I am almost completely done with the core functionality of the entire game.  The only thing that I know that needs to be changed is that when the user replays a level, a rank should only be overwritten if the user actually gets a better rank than the one currently achieved.  It should also let the player know if they have beaten one of their previous ranks.  Currently, the rank data for the level will be overwritten regardless.  I could add an options menu to change the sound volume and button layout, but I think there is very little value in doing that compared to the actual benefit of having those options.  If the sound is too loud, then that is the reason why television remote controls have volume controls.  Nobody ever really looks at credits screens, so I don’t see the point in making one.  None of the classic games ever had credit screens, aside from the credits that play at the end of the game.

The final two main tasks that remain to be completed are the improved graphics and finishing designing the remaining levels.  Each level requires the array data to be generated in Mappy, and then I have to manually add the rank requirement data for each stage.  Finally, I could add an ending screen which displays once the player completes all levels.