Java Project

Block & Key
2D-Platformer Game

This project was a larger assignment involving project management where it was important to maintain proper documentation throughout the development of the program. I'm pretty proud of what I've done anyway though as I coded the game in almost pure raw Java. I ended up using the Lightweight Java Game Library for rendering .png files to the screen, but all of the actual game logic uses just normal Java code with a tiny bit of multithreading.

Level 1 of the game. No pits or spikes and only two enemies to try an acclimate the player to the controls of the game in a non-punishing way.

Level 2 of the game. Introduces spikes that kill the player instantly on contact.

Level 3 of the game. I attempt to more fully utilize the space for this level and encourage more precise jump inputs by the player to avoid taking damage.

Level 4 of the game. A more advanced version of level 2, with spikes but also several bat enemies and forcing the player to use either the improved jump height or speed from one of the two powerup items in order to reach the key.

Level 5 of the game. A final gauntlet of precise jump challenges to get through to the end without dying. The game closes upon completion of this level.

The first bit of multithreading I came up with for this project. The JumpLimiter Java class has two primary purposes. First, It uses java's TimerTask implementation to place a delay between toggling a boolean value to determine whether a "jump" input by the player actually causes the player to jump or not. This prevents the player from "flying" by jumping repeatedly. The second purpose is increasing the players height in small but rapid increments and checking with each iteration against a different boolean value to see if the player has collided with a block and breaking out of the jump loop if this value is true. This prevents the player from jumping through blocks.

My detectBlockCollision() method initializes a boolean value as false, then checks player positioning against an arraylist of all the block positions in the current level. If the player is within or against the bounds of any of the blocks the boolean is toggled to true and if the player is clipping into the block they are shifted to the left or right of the block depending on which side of the block they're closer to. Finally, after checking against every block in the list the boolean value is returned so it can be used for other game logic such as the previous JumpLimiter example.

Here's a snippet of handling for damage collision with enemies. Enemy types are stored in an enumeration and since the spike obstacles are technically treated as an enemy this code differentiates between collision with a spike and collision with any other enemy. Spikes simply lower player health by 3 which is enough to instantly defeat the player and push them back to the start of the current level. For other enemies it lowers player health by 1 and instantiates InvulnTime and DamageFlicker objects to handle player invulnerability time between the player taking damage and the player sprite flickering in response to that damage respectively.

Here you can see the simple logic involved with the invulnerability period between being able to take damage. Upon generation of an object of this class in response to taking damage, a boolean value for determining if the player should be able to take damage is checked and if true is toggled to false then a TimeTask starts to wait one second before toggling the flag back to true.

The DamageFlicker class works similarly to the previous InvulnTime class, but it uses a repeating scheduled task to rapidly toggle a boolean that alters the sprite for the player to create a flickering visual effect to indicate to the player that they have received damage. The final short sleep and boolean setting call is a failsafe to ensure that after the while loop ends the player's sprite is set back to the "not damaged" state.