Platformer movement (Flashback / Prince of Persia style)

Started by
3 comments, last by punkcoders 10 years, 7 months ago

I'm programming a pretty basic tile based platformer in Javascript and I'm struggling to figure out how to code the movement of entities correctly.

Originally the entities were directly influenced by key presses ie. pressing left would make the entity move one tile width to the left (Pressing SHIFT would make the entity sprint instead of walk) but this caused problems with the entity's animation and position if the entity began to sprint half way through moving.

I remember games like Flashback and Prince of Persia had a very distinct movement style where the entity would only begin to sprint when it reached the next tile. I tried to implement a system where the player would actually move onto the next tile instantly but the sprite would have an offset that would catch up to the entity eventually (and the entity would not process key presses until the sprite had caught up). This gave the right effect when moving left and right but it all started to fall apart when jumping / crouching / getting knocked back. Also I liked the way that (in Flashback) it was possible to press a button to draw your gun mid-step and the character would remember to do that when they reached the next tile.

Could anyone suggest a simpler way of achieving this kind of movement or point me to an existing example?

Advertisement

When the player presses a key you just need to start the character walking (or running). Not for one tile, just forever. You can do this by having the key presses not directly tied to movement. When you press the left key, for example, it would set a variable called "moveLeft" to true and then you can check this on an update loop and actually move the character.

Then look at the characters' position and check if the tile has changed. So you can store a variable, like "lastTile" and then compare it to "thisTile". If they are different, then call a function that will reevaluate the character state.

This function could check if the left/right keys are pressed, and if they are continue walking/running. If they are not pressed, then at this point you can safely stop the character from moving. You can also draw the character's gun at this point. You would just need a flag you previously set called "drawGunOnNextTile" or whatever, and the handle this when the tiles switch.

Hope that makes sense.

Both these games you described feature realistic animation.

Things like running, jumping and unholstering a weapon will require several frames to address the natural acceleration and the timing of movement.

How you'll approach this problem depends on how wide your tiles are in relation to your character. If the tiles span several "character widths", your character will be able to walk fractions of tiles in steps. If the tiles are sized to measure the same width as your character, things become simpler as each step reaches a new tile.

You can represent any sort of environment design with wide or small tiles, so it becomes a matter of choice.

First think of how many steps your character will need to get to full speed (it's generally two, you can try it for yourself by running from a standing position).

Then animate your character accelerating with that precise amount of steps - but just accelerating, he's not engaging in running yet, so the last frame of this 'acceleration' sequence should lead to the first frame of the 'running' sequence.

So consider you have this 'acceleration' animation sequence done.

You select which next animation sequence to play when this acceleration sequence finishes playing.

To decide which, consider if the player is still holding the movement key. If he is, then engage in the 'running' sequence. If he's not, then play the 'slowing down' sequence, which has the character doing one or two steps to come to a halt.

Note that the last frame of the 'acceleration' sequence should fit with the first frame of the 'running' sequence as well as the first frame of the 'slowing down' sequence, because they are both likelly to happen.

The above functionality enables you to "hit" the movement key if you want the character to take a few steps (he accelerates and then comes to a halt), and enables you to engage in running (he accelerates and continues on running). Like in the original games.

If you're looking for reference, there's none better than the original games:

http://jordanmechner.com/wp-content/uploads/2013/04/POP2-Bible.pdf (Prince of Persia 2 Bible, includes information on animation sequences and frames)

http://jordanmechner.com/wp-content/uploads/1989/10/popsource009.pdf (Prince of Persia 1 Source and Information)

http://www.gamedev.net/topic/645973-gdc-classic-game-postmortems/ (First link on the list is the POP presentation on GDC)

To program behaviors of games like princeofpersia-flashback-abe-etc you need a state machine. Each character is managed like a mini-application with a small sub-program for each action.

First have a look to the design pattern state (google is your friend). For characters you can make simple states with at least 2 events: start(), routine(). (i think it does not need stop, pause, resume, etc)

Create a CharacterStateManager motherclass ( with its events routine() and changestate() ). It needs a "frame-timer" variable to control the end of states. On every changeState call the frame-timer must be reset to 0. The routine call only one state routine at once. Each character is an instance of CharacterStateManager.

Then, for each action (most will be shared by all characters) make an abstract motherclass CharacterState with empty functions to make sure there won't be any call of undefined function. Then, each character will use one instance of each state class.

Examples:

- standing up state. on start() event set the frame of character standing up. on routine() event, wait for an action input (keypress for player, ia for non-player, or hit), and when key pressed, call changeState( TheNextState );

- crouching state. on start() event change height of hitBox .on routine() event, display the frames or crouching animation. When finished, call a changeState to te crouched state

- crouched state. on routine() event, wait the input for standing up (release key "down" for player, ia for non player)

- standing state. on start() event change height of hitBox. on routine() event, play in reverse the crouching animation frames and change height of hitbox, when finished, call a changeState to the standing up state.

- walking state. on routine() event, play animation. Each time character reach a new tile, chek the input (ia or keyboard or hit), if no change state then carry on walking.

- etc...

I developed a game like this a long time ago, was really more simple than flashback or abe, the states i used for all characters were: standing, walking on floor, walking on stairs up, walking stairs down, jumping, falling, knocked, speaking.

good work !

P.S. do not forget to manage your characters with an object pool, because javascript garbage collector is a pure crap you cannot trust on. So, do not subclass the CharacterStateManager, use a "behavior" index instead, and use it to reference global or static functions.

P.S.2 :

If you're not comfortable with OOP, you can do exactly the same with a procedural approach. I suspect the first pop-like were developed in C so were fully procedural.

So, each character and state methods are replaced by global functions ( walking_start(), walking_routine(), etc ), with an argument "object" (or a small table) replacing "this". For each state, just make a small table with global function references.

I personnaly prefer the procedural approach, it makes shorter code, but wrapped in a static class to avoid name conflicts.

This topic is closed to new replies.

Advertisement