top of page
skullspider.png
skullspider.png
title.png
skullspider.png
skullspider.png

Overview

This was a small Ghouls and Ghosts / Metroidvania clone intended for html5 release.  I was putting it together for fun when other priorities took over.  I still have a soft spot for the mechanics and world design however so hope to go back to it one day.

This is the story, all about how

my death got flipped turned upside down

I'd like to animate just shamble there

as I tell you how

I became a skeleton

walking around in fresh air...

The story is that of a sleepy skeleton named James Boned.  James is rudely awoken when a maniacal necromancer awakens all the dead in the kingdom.  The more recently dead are under the necromancer's thrall and quickly set about eating brains and terrorising the living so that the necromancer can conquer the world.

James doesn't care about this.  He just wants to go back to sleep by breaking the necromancer's curse.  Coincidentally this will save all the living as well.

ghouls-n-ghosts.jpg
coin.png
woods_midground.png
woods_canopy_big.png
woods_background.png
chest.png

Gameplay

The original Ghouls and Ghosts was well loved, but also a brutal challenge designed to drain coins in an arcade setting.  The core of Boned was more forgiving, although it retained the perfectionism and precision needed from GnG.  The metagame was to complete a chapter playing as a character, reaching the Necromancer's tower.  Upon doing so, another chapter and character was unlocked.  The player had to complete four chapters (with any character) to unlock the fifth and final chapter of the Necromancer's tower.  

Each character had unique gameplay design, best used in their own chapter but also applicable in the other chapters.  The game was a huge secret hunt, planned to feature hidden endings, chapters and characters in addition to the base game.  Only by finding all the secrets could the player 100% everything and see all content.  Yes, it was hardcore.

Gravestones were the save points of each level, also allowing the player to recover lost body parts and switch character to any of those already unlocked.

enemy_cherufe.png
graves.png
enemy_evileye.png
player_james.png

James Boned

  • Initial playable character

  • Throws his arm as a returning 'bonerang'

  • Can jump, hillslide and push blocks

  • If injured, is reduced to just his skull until he finds a gravestone

player_mike.png

Mike Jackson

  • Pumpkin headed skeleton

  • Breathes fire as an attack

  • Can detach his head on purpose and roll through small gaps - his body waits behind unless hit

WIP

Ethel Dice

  • Ethereal ghost in a funerary urn

  • Limited abilities while in the urn but can leave it in ghost form and drift through physical objects

  • Cannot stray too far from the urn, which is dragged after her ghost form and can still be broken

WIP

Jemima Boned

  • James' younger sister

  • Carries a sack of deadly bombs, just as dangerous to the player as the enemies

  • Cannot stray too far from the urn, which is dragged after her ghost form and can still be broken

Secret Hunting

All levels would be static and hand made without any procedural element.  The idea would is to include fixed secret areas for the player to remember so that when they unlock a new character, the previous level content becomes more valuable since there are many more nooks and crannies for the player to go back over and discover secrets within.

AI System

Enemy AI would be built from a series of AI Actions which would be placed by the designer in a state machine frontend layout.  Changing the action configuration would result in radically different enemy behaviour without large amounts of hard core.  The goal here is to allow the gameplay designer to create multiple experimental AI behaviours and eventually use only the ones which follow the core design principal of producing the most emergent gameplay when combined with other enemy types and level obstacles.  In terms of which actions to implement from code, the idea is to always produce the simplest and most versatile actions possible, leaving the experimentation and gameplay construction up to gameplay design.

state_machine.png

This is an example of a bare boned AI setup.  It's made from two action types (Idle and Jump) and a single condition (Hit Wall?).  The enemy simply jumps left every two seconds until it bumps into a wall.  Once it does so, it jumps right until it hits another.  It has no knowledge of the player or any other gameplay element and is relatively harmless.

  • Actions can be configured by the designer within the frontend

    • Jump can be given different forces for X/Y​

    • Negative X means 'jump left' while positive is 'jump right'

  • The Idle action has a single configuration for how long to wait​

    • This would also be linked into the animation to loop an idle anim while the enemy is in this state​

  • Not shown are the interrupting parts of the state machine​

    • When the enemy is injured, a special series of actions and conditions takes over, interrupting anything else the enemy is doing​

  • A more aggressive variant of this same enemy could have higher jumps or reduced idle times

This system is designed to allow the addition of new actions which have a low cost of implementation but allow the design team to get creative in how they are used.  Below is a list of potential actions that could be implemented as a initial set.

Walk

Force X

Duration Min, Max

WhichAnimation

Enemy faces and walks according to the value specified in force X.  Left or right is specified by the force being either negative or positive.  The enemy will continue walking until they reach the elapsed amount of time - which is either Duration Min or a random value between Duration Min and Max if the Max value is specified.  If the Min value is negative, the enemy will walk forever unless something interrupts the action.  This action also specifies the enemy animation walk loop using WhichAnimation, the speed of which is multiplied the relative force (velocity).

Enemy does nothing for a period of time randomly set between Wait Min and Wait Max. If these values are the same or Max is not specified then there is no randomisation.  The animation used is defined by the designer in Wait - this allows multiple loops to be set up whereby the enemy might use a simple idle animation most of the time, but occasionally enter a special 'idle tic' every now and again after a randomised delay.

Idle

WhichAnimation

Wait Min, Max

Enemy applies the X and Y force to itself in a jump in the direction in which it is facing.  If it hits an obstacle or wall while airborne, it's current X force is inverted, making it bounce off.  The animations correspond to A = prepare, B =airborne and C = land.

Jump

Force X, Y

WhichAnimation A,B,C

Enemy applies the X and Y force to itself in the direction in which it is facing.  This ignores gravity.  It uses the same duration min/max as the walk action.  As usual, the designer specifies the animation to be used during this action.  Note that how long this action takes to complete depends on a number of factors - the game physics, distribution of platforms and so on.

Fly

Force X, Y

Duration Min, Max

WhichAnimation

ShootForward

Force X, Y

BurstAmount

BurstDelay Min, Max

ProjectileObject

Enemy fires a BurstAmount of ProjectileObject's in the direction they are facing, with a delay of BurstDelay between each shot.  Giving it a Y force component causes the projectile(s) to react to gravity and use a parabolic arc.

Finally, the AI system needs conditionals in order to be complete.  These activate under certain circumstances and either trigger actions, interrupting others or modifying ongoing actions.

PainDrop

Damage Threshold

WhichAnimation

Duration Min, Max

Whenever the enemy receives at least DamageThreshold points of damage, this condition activates.  It triggers WhichAnimation and causes the enemy to drop to the floor using the base game physics.  After a Duration the enemy will advance to the next action after this one in its state machine.

The designer attaches a Collider object to the enemy which registers whenever it it intersected by another entity of the specified DetectType. When or if this occurs any current state is interrupted.  An example usage would be to make an enemy use two different walk actions - a slow one for calm mode and a fast one if the player is in front of them.

DetectOther

DetectType

Collider

The idea of this condition is for an enemy to change its behaviour when reaching the edge of a platform.  If the FlipDirection flag is used and the enemy is using a move action, that X component will simply be reversed.  If however there are other actions connected to this condition then those will be followed.  For example, this could be used to make and enemy jump when reaching a platform edge. or just turn round and go back.

DetectEdge

FlipDirection?

Conclusion 

There's a lot I like about this concept, beyond the creepy characters and theme, the base system is a rock solid foundation upon which to construct a platforming adventure.  It's a cleaner variant of one that I've used various times to make similar systems design driven games.  The hard part it always convincing the team that 'now' is a good time to implement features that aren't needed yet.  In my experience, 'later' is always worse - you're closer to deadline and the feature when implemented won't benefit from as much playtesting because the deadline is coming in fast.

Modular, systems based design of features will always beat the 'let's do one feature after another' approach in my book.

zombie.png
bottom of page