The first original game I designed and executed was a Top-Down 2D zombie shooter. It's a round-based survival game that creates more and more zombies until the player is overwhelmed and inevitably dies; there is no winning, much like real life. The notable features of this build is the implementation of the A* pathfinding algorithm to develop dynamic AI that could traverse the level while responding to the player's position, the random assignment of pre-made rooms, random placement of powerups, and tracking collisions between the player and enemy sprites.
The above image depicts the layout of the map. Each room is randomly chosen each time the player completes a round. The process is not procedural, though, as the rooms are pre-made and swapped around to ensure that a round stays fresh as the game progresses. Each of the blocks hanging from each room are zombie spawn points. Zombies are then spawned randomly throughout the map at intervals and in amounts based on the round -- the higher the round, the more zombies in smaller intervals.
When the game first starts, the screen shrinks and blinks "Wave /d" where /d is the round number. In the top left the number of zombies left in the round can be seen (though it is not set until the black border recedes to the edges of the screen again), and in the bottom right corner the player's ammo for the equipped weapon is displayed. The pistol has infinite ammo because it seemed wrong to force a player that can't defend themselves from physical attacks into a fist fight, though the player does have the option to melee, with the knife dealing a 1 hit K.O. In the background, the sprites and colliders for the previous round (save for the first) are removed and new ones are randomly generated. The effect of the black border obscures this from the player's view.
Here we can see the simple player surrounded by a world of hurt. But he's actually pretty resilient. With a quick trigger finger they could probably shoot their way out of this. As the round progresses, the player sprints from room to room shooting zombies in their wake. However, while the map is cyclic and the player is faster than their pursuers, zombies can come from anywhere, and all it takes is a single slip-up to become zombie-chow. It's easy to be overwhelmed, and the player can't simply run through the zombies either. The zombie consists of two colliders: one that serves as its physical body and one that serves as its area of attack. The one that serves at the physical body prevents the player from simple passing through the zombie, and the area of attack serves to detect when the player has come into range, allowing the zombie to begin its attack while still moving. The zombies use the A* pathfinding algorithm on an unweighted graph, using the colliders associated with the walls and obstacles in each room to render certain parts of the graph un-visitable. This gives the illusion of zombies walking around objects when they're actually following a path that is within the interior of the map. I should note that the A* pathfinding algorithm implemented is not of my own creation, and is a free plugin within Unity. I attempted to write a similar script, but couldn't beat the speed of the plugin and voted to use the free plugin in the interest of making the game run smoother. I do manipulate the script to respond to specific colliders and define boolean flags that illicit the appropriate response from the enemy controller.
The UI above is what the screen looks like before any work is done; initially, it is covered in a black screen until the character is placed at the starting position. The UI feature in the top right represents a time limit on power-up pickups from within the game. The position of the bar is configured such that the most recently picked up power-up appears at the top, and as the power-up runs out, the most recently picked up power-up, if there is one, is shifted one position above where it previously was situated. The bottom left shows the player's health: it uses a slider component that responds to the health field in the player controller. On collision with an attack, the player's health is modified and then the slider is set to the player's health, thus dynamically changing the value of the slider based on an event-driven system.
If you want to see my repository for this project, follow this link:
Comments