Eejan Rizzler And The Order Of Drip
Project Type:
Pac-Man Clone
Role:
Gameplay Developer
Language:
C++
Engine:
FLECS, DX11, Gateware
Date:
October 2023
Named after our graphics engineer (Najee), Eejan is a PacMan clone made using FLECS in C++, Gateware, and a DX11 renderer I partially developed prior to the project as the basis for the game’s engine. In this project I served as team lead and a gameplay developer. As the lead I was responsible for task delegation through JIRA and maintaining group productivity. As a gameplay developer I was responsible for the vast majority of systems, including: collision, player movement, enemy AI, and more!
Game collision is achieved by querying all game objects for the “Collidable” tag and then placing them into an array at game start.
Collidables include the walls, ghosts, pellets, and specials. (The player is considered a collidable as well, but is not copied every frame in the next step).
Every frame, each instance of a collidable’s OBB is copied into the SHAPE struct and a soft collision test is applied.
If a collision is suspected - based on the distance between the player and object versus the player’s bounds - a more in depth collision check is performed.
If a collision is found then the CollidedWith tag is added to the player and test object.
From there, the test object will perform some action, such as ghosts consuming the player or walls limiting player movement.
Collision
Player movement was designed to prevent diagonal movement and mimic old school computer games’ directional hierarchy.
If the player is able to move in a direction (there is no wall collision) and an input has not been registered yet (represented by the bool “keyFound”) then the input value is added to the applicable axis with respects to direction (left = -1, right = 1).
From there, all other inputs are filtered out from highest priority to lowest in the following order: left, right, up, down.
After filtration, the player’s x or z-axis is adjusted by a clamped value (-1 to 1) with respects to time. The clamped value was used in case two keys of the same direction are pressed at the same frame.
Player Movement
Ghost AI is simple and follows a few rules. Utilizing a hidden node system, ghosts will move from node to node in a random direction. Ghosts will never go back the direction they came from. If they’re currently headed left on the screen they will not go right. At a fork they will either choose to go up, down, or continue left. When the player “eats” the ghost they will return to their home node and resume their random patrol.
Enemy AI
Ghost AI is initialized by setting the ghost’s home node.
This is where they will return when “eaten” by the player.
The home node is set to the travel node within 0.1f units of the ghosts’ initial position.
By setting the current and target node to the home, the ghost will see they are at the home node and begin searching for their next node to travel to.
Movement
While patrolling, if the ghost reaches the target node, their last node visited and current node are updated.
This is used to prevent back tracking by the ghost.
When the current node becomes the target node, a new target node is searched for.
At game initialization each travel node determines their adjacent travel nodes.
The ghost generates a random number, and checks if the corresponding adjacent node is traversable. If the adjacent node is traversable it is set as the new target node.
Ghosts move around the game board at a speed that is adjusted by game level.
Ghost movement is calculated via linear interpolation.
Ghosts can also utilize the left and right board exits to teleport to either side of the map, just like the player.
Collision events involving the player first check if the player is “powered up”.
If the player is not powered up, then a life is lost or the game is ended.
The player and ghosts are returned to their home nodes, and the on screen text is updated.
Collision With Player
If the player is powered up, the player’s score is adjusted, and the ghost is moved to their home node.