4
\$\begingroup\$

I'm trying to make a cinematic platformer, in the veins of the first two Oddworld games, Flashback, Prince of Persia, Blackthorne and so on. This article describes very well how this kind of movement should work:

(...) The algorithm is then as follows:

  1. Create a copy of the character where he’d like to move to (e.g., if moving one tile to the right, make a copy where every tile of the character is shifted 1 tile to the right)
  2. Check that copy for intersection with the background and other characters.
  3. If an intersection is found, the character’s movement is blocked. React accordingly.
  4. Otherwise, the path is clear. Move character there, optionally playing an animation so the transition looks smooth.

This kind of movement is very ill-suited for traditional arc-shaped jumps – so games in this genre often have no jump at all (Toki Tori, Lode Runner), or only allow vertical or horizontal jumps (Prince of Persia, Flashback), which are nothing but special cases of linear movement.

Eventhough the idea seems very clear to me, the actual implementation of it raises a lot of questions in my mind. For some of them I feel I have very complicated solutions, while I have no idea how to solve others.

For starters, the basic mechanism for moving: if the player presses right, the character will enter a "walking right". While on that state, the character will move from the starting tile until the next one, even if the player releases the right key; if the player is still pressing the key when the character reaches the next tile, the same thing will happen. However how exactly should that movement inbetween tiles work? Should it be just a regular speed being applied to the character's x position? What should that speed be in order to assure that the character will stop in the precise location in the next tile? And should that speed work with the update's delta time?

Another thing that has me at a loss is how much of the sprite's positioning has to be done by the actual x,y positioning and how much should be done inside the sprite. For example, in the case of a running jump, which is, as noted, a special case of linear movement, should there just be empty space below the character (and position the sprite by its bottom) or should the y position be adjusted accordingly?

I'd really appreciate some help with implementing this kind of platformer. That article above is the only thing I've found that sheds any light on how to do it, and I'm struggling to figured out the rest on my own.

\$\endgroup\$

2 Answers 2

5
\$\begingroup\$

I've tried to copy the movement/controls for an Oddworld-style game before.

Here is some of the code for the state machine: https://gist.github.com/tomdalling/5201751

Here is a video of the movement: http://www.youtube.com/watch?v=Ni2hE-bCZTA

However how exactly should that movement inbetween tiles work?

See the StandingMove state. In my code, the player always has a discreet x/y coordinate on the grid, which doesn't change during animation. Let's say the grid is 16x16 pixels, then the "walk right" animation will be 32 pixels wide, because it covers two horizontal cells. Once the animation is finished, the x coordinate is updated to x += 1. The "move left" is a little different, because it does x -= 1 before the animation runs, but it's basically the same thing.

Should it be just a regular speed being applied to the character's x position?

Because the x/y doesn't change, the speed is completely controlled by the length of the animation. The StandingMove state checks if the animation is finished before it returns to the StandingIdle state:

if(p->_anim.isFinished())
    return &p->_s_StandingIdle;

should there just be empty space below the character (and position the sprite by its bottom) or should the y position be adjusted accordingly?

I just took the empty space approach. This is the sprite sheet for the ledge grabbing/climbing animations:

jumping and climbing animation sprite sheet

You can tell from the image that the y coordinate is on the ground during jumping/climbing. Once the player is actually on top of the ledge at the end of the LedgeClimbUp state, the y coordinate gets updated with y += 3.

\$\endgroup\$
6
  • \$\begingroup\$ +1, this is fantastic, thank you! Clearest explanation I've seen so far! How would you handle collision with another moving object (Goomba, bullet, etc) here? Do you have a per-pixel collision mask for each animation or does it simply not happen in your game and if it would, you'd use a different approach? \$\endgroup\$ Mar 20, 2013 at 10:30
  • 1
    \$\begingroup\$ @Jan I didn't get as far as collision, but I would probably do per-pixel collision using the alpha channel in the animations. \$\endgroup\$ Mar 21, 2013 at 0:19
  • \$\begingroup\$ I see, thank you! I don't understand why this isn't getting more upvotes :-) \$\endgroup\$ Mar 21, 2013 at 12:41
  • \$\begingroup\$ Very nice solution. I've actually asked around about this and I got a different solution from someone at TIGSource. I'll post it as an answer here too, might be helpful too. \$\endgroup\$
    – Vexille
    Mar 24, 2013 at 16:39
  • \$\begingroup\$ @TomDalling: any chance you could restore the video? \$\endgroup\$ Apr 20, 2021 at 12:46
1
\$\begingroup\$

Here's a different approach, taken by electrolyte, from the TIGSource forums. He was making this platformer project (some footage here).

Here's some of his explanation:

The way my platformer worked was to send a 'sequence' request to a function. So for example, I might press the right key and this tells the sequencer function that the player is trying to walk right, so start the 'Walk Right' sequence.

Inside the 'Walk Right' sequence not only do you have the animation information, but you also move the character a set and precise amount of pixels to it's next grid space. This loop isn't broken until it's completed.

Next up, once the sequence is completed you need to see what the user is pressing or not pressing and react to that. This in essence is how you can create fluid animations.

Example:

1up presses right key, start ' Walk Right' sequence.

'Walk Right' sequence is completed, see what keys 1up is pressing

1up is now pressing left key, start 'Turn Right to Left' sequence

'Turn Right to Left' sequence finished and 1up is still pressing left key so start 'Walk Left' sequence

and so on

The problem starts when you have to capture every combination and call a sequence / animation! How you do this is up to how you want to programme it, but I recommend just jotting down on paper some of the combinations to start with and then add more and more. In flash I used a pretty dirty Switch statement which worked well.

And regarding movement, I was thinking maybe interpolating the player's position between one tile to another, but he had this to say:

So the movement is still handled as you would a normal platform game. I would stay away from tween engines :D

Simply work on X and Y, so to walk right, x + 1. Then make sure your 'Walk Right' sequence loops say 16 times ... which is the pixel width of the grid and you know that in the loop it will move exactly to the next grid position! Of course tailor that number to your requirements.

Also what's really handy is if you then set the animation frames to 16 frame cycles (the width of grid squares), each time you add 1 to the X you can move forward a frame in animation.

In terms of jumping, that really was handled like a traditional platform game, so some Y inertia, but split the jump into sections, so "jump up", "Falling down", "Landing" etc. That way at the end of the jump up sequence you can check for hanging onto stuff etc.

The only thing that should be noted with this approach is that ideally, you need a fixed timestep in your updates. I think the "Constant Game Speed with Maximum FPS" solution in this article would work pretty well.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .