The core select screen, featuring the game's 24 equippable cores

Video Demonstration (URL: https://www.youtube.com/watch?v=3WEqctaFW_4)

Using cores to solve puzzles and bypass hazards to collect rewards

Using cores to defeat enemies guarding key collectibles

A snippet of the Core_defs class, displaying information for each core, and their parameters that affect the player's abilities and attributes

A snippet of the system in which the player takes damage on a timer-based system, as opposed to only on the frame of initial contact

Core Mechanic

Core Mechanic is a 2D action/puzzle platformer designed and coded entirely by myself. In this game, you play as a robot that can be equipped with various “cores”, which are fittingly Core Mechanic’s core mechanic.

In this completed prototype, there are 24 cores for the player to choose from. There are 12 “passive cores” that grant the robot new abilities, stat upgrades, and equipment, and 12 “active cores” that let the robot perform certain actions such as weapon attacks or inverting their own gravity.

The game evolved into a personal passion project, and it was programmed entirely in Lua, using the LÖVE2D framework.

Design

Many design principles came into play while developing Core Mechanic, particularly the balancing of the game’s many cores and the design of the level.

For the cores, much effort was put into the idea of making sure the cores were as balanced as possible, as each took up an equal 1 of 8 slots. For example, the core LockBreaker() can effectively let the player skip the entire level if they wish, which sounds extremely unbalanced, but the tradeoff would be that the player would take a large hit to their overall level score if they did so, having likely skipped over all the keys, enemies, and collectibles.

Another example of core balancing was the AutoTurret() core, which is the only core that gives the player passive damage towards enemies. From the start, this core was far too powerful, and was nerfed considerably throughout development. The turret’s pellets only do decimal damage, and I further added a “negative” synergy with the ElectricBlast() core, where using it would also temporarily confuse the AutoTurret AI and cause it to shoot randomly for a few seconds.

Finally, the level design was a large undertaking, as it had to be possible with any combination of the 24 cores. As a result, the three keys which are required to progress (without LockBreaker) could not be gated behind small areas, acid, lasers, spikes, etc. To combat this, the keys were simply guarded by enemies, so that even if the player had no cores, they could still defeat or avoid the enemies to reach them.

The many other puzzles for coins had a lot more freedom; some required a specific core or cores to collect, but others would have multiple solutions. In testing, I found that the player could 100% complete the level with as few as five cores, but doing so is certainly difficult.

Coding

Core Mechanic was my first completely solo project on something of this scale, and throughout its month-long development, I often had to think outside the box.

One key aspect of the code was the game state system, where the game had a “base state” class with constructor functions for starting, exiting, updating, and rendering, with every possible state of gameplay being a child class of that base state. This includes of course the gameplay state, but also the core selection, the preview mode, and all of the game’s several menus.

Another aspect was the handling of the game’s cores. I did not want 24 separate classes with repetitive code for every single core, and I was able to handle all of them in effectively 3 or 4. A “Core” parent class, a “Core_defs” class (pictured) which defines the parameters of each core, and a “CoreHandler” which handles the equipping of cores onto the player character. For active cores, the longer functions were kept in the Player class, for the sake of readability and simplicity of Core_defs, as well as the fact that at its essence, cores are effectively just variable changes and functions within the Player class.

One final aspect worth noting was collision. I was working within the constraints of Box2D, which caused difficulty at times. Due to errors that would occur if an object was moved (or removed) at the same frame as a collision event, I ended up handling damage to both the player and enemies in its own sort of system. Using a checkDamage function, the game would check if the player touched an enemy or hazard, then use a series of timers to check for the first tick of damage (usually a frame or two after initial impact), then another separate timer for more damage on prolonged contact. The idea for one of the cores, iFrameBooster(), actually came from this, giving the player more leeway in taking damage.

For a much more detailed analysis of the design and coding decisions that went into the cores and the game as a whole, you can view the README file in the game’s primary folder.

Credits / How to Play

Art and audio assets were obtained via public domain and creative commons sources online. For a full list of credits, please view “credits.txt” in the primary folder of the game project, which is linked on this page. To play the game itself, install LÖVE2D and click the “playgame.bat” in the main folder.

Role
Creator, Designer, Programmer
Date
October 2021
URL
drive.google.com/file/d/1y4e0Ep6DSl_TnjKUsjR8QfHVC95DUsvQ/view