Ninja Caves - Update One
Since March, I have been building a platformer game for my son (now six years old), inspired by Crystal Caves, using GameMaker Studio 2.
I have documented my progress in the following articles, including the rationale for the project.
I have continued to make good progress and have now completed the following features, which can also be reviewed in my backlog.
- Level Objects, including walls, doors, ladders, fires, etc.
- Collectable Objects, including coins, crystals, abilities.
- Obstacle Objects, including water, lava, spikes, spinning saw.
- Destructible Objects, specifically crates.
- Story Objects, specifically signposts.
- Player Movement, including keyboard/mouse and controller support.
- Player Animations, including idle, run, jump, fall, crouch, climb, glide, hit, death.
- Player Weapons, specifically ninja stars.
- Player Health, including health bar.
- Player Special Abilities, including speed, jump and glide.
- Enemy Types, including customisable attributes.
- Enemy Movement, including keyboard/mouse and controller.
- Enemy Animations, including idle, run, jump, fall, hit, death.
- Enemy Types, including customisable attributes.
- Enemy Weapons, specifically ninja stars.
- Lighting System, immitting light from a specific source.
- Particle System, specifically lava particles.
- Transition System, animating specific events.
- Save Game System, persisting level, coins and kills.
- Tile Sets, specifically jungle and caves.
- Music and Sound Effects.
- Menu and Ending Systems.
The video below highlights these features in action across the first three levels, which start in the jungle, before entering the caves.
The majority of the game will occur in the caves (I am thinking ten levels), with each level challenging the player with unique obstacles, supported by specific abilities.
The game has three basic objectives, collect the coins, find the crystal, progress through the level. The ninja enemies can be defeated using ninja stars, but this is not a requirement.
The video below shows the game running on an Apple iPad Pro (Apple iOS 14.6), including Bluetooth controller support.
It is worth noting that Apple iOS assigns the controller to slot 1 (not the default slot 0), which caused me some initial issues, as I had naively hardcoded slot 0 throughout my code.
As part of the most recent release, I also did a lot of clean-up across my codebase, which is available for review (and reuse) on GitHub.
I am particularly pleased with my lighting system, which uses a simple surface overlay and cutout object to deliver the illusion of light immitting from a specific source. The code assigned to the draw event can be found below.
/// @desc Draw Lighting
// Surface Overlay
if (surface_exists(lighting_surface) == false) {
lighting_surface = surface_create(room_width, room_height);
}
surface_set_target(lighting_surface);
draw_clear_alpha(c_black, tansparency); // Set Room Colour
// Lighting Cutout
with(oLightingCutout) {
var wobble_amount_x = image_xscale + random_range(-wobble, wobble);
var wobble_amount_y = image_yscale + random_range(-wobble, wobble);
gpu_set_blendmode(bm_subtract);
draw_sprite_ext(sprite_index, image_index, x, y, wobble_amount_x, wobble_amount_y, 0, c_white, 1); // Default Cutout Lighting
gpu_set_blendmode(bm_add);
draw_sprite_ext(sprite_index, image_index, x, y, wobble_amount_x, wobble_amount_y, 0, colour, intensity); // Custom Cutout Lighting
gpu_set_blendmode(bm_normal);
}
The code is split into two parts, the first creates the surface overlay and applies transparency based on a room variable. The second leverages a blend mode to remove the surface overlay for the “oLightingcutout” object.
It should be noted that the surface overlay must be the power of two (e.g. 1024, 2048, 4096) to ensure compatibility with Apple iOS/iPadOS devices.
The image below shows the “oLightingCutout” objects applied to the room.
In a future release, I intend to transition my player object (oPlayer) to a finite state machine, which is a method of programming that uses sequential “states” to perform tasks in a logical form. This approach will hopefully streamline the player object, which has become cumbersome due to the number of animations.
The main challenge I have faced is balancing the difficulty, recognising the target audience (a six-year-old). I hope to make the game challenging, but still fun for someone playing their first 2D platformer.
I will continue to post periodic development updates. The game videos, backlog and source code can be found linked below.
Assuming the game maintains a reasonable level of quality, I plan to publish for PC, macOS, Linux, iPadOS, and AppleTV (controller support required).