9
\$\begingroup\$

I am making a 2d platformer where the player can press a button, and restart the level, only their previous character will also run the level at the same time, like they are traveling back in time.

I know other games have done this before, and the way I have thought of doing it is to make the game character have a set of actions (Idle, Jumping, Walking Left etc.) and then detect changes in those actions and log them into a list along with the game time. So then when I need the character to run the level again on its own, I can just go through the list changing its actions at the right time.

Is this the best way to do it? Does anyone have any experience in this?

Thanks.

\$\endgroup\$
3
  • \$\begingroup\$ What you are looking for is more of a 'Replay' than time control. You might find some nice articles on ways to deal with this, but I still say the answer below is also a good start in this area. Keep in mind that things that are 'random' in the game will screw up replays for the 'ghost' character running it again if they can affect progress. \$\endgroup\$
    – James
    Commented Jan 6, 2011 at 0:25
  • 3
    \$\begingroup\$ Good point about the "random" parts. Be sure to use a random generator that generates its numbers based on a seed. Then save the seed with your replay and use the same seed when playing that replay. \$\endgroup\$
    – bummzack
    Commented Jan 6, 2011 at 7:49
  • \$\begingroup\$ How did you do this? What is your workaround? \$\endgroup\$
    – user80190
    Commented Mar 8, 2016 at 15:24

4 Answers 4

8
\$\begingroup\$

EDIT:

Please see @Bluescrn's answer to this question; he elaborates on weaknesses in replaying controls rather than movement vectors or position.

--

You're on the right track. Here's the approach I'd use:

Controllers

Create a Controller class which receives keyboard input and passes it on to your character. However, also have a Controller record exactly when the significant keys (e.g. arrows, jump, etc) were pressed and when they were released. It would store up this sort of information:

actions[0].milliseconds = 400     actions[0].action = right pressed
actions[1].milliseconds = 1000    actions[1].action = jump pressed
actions[2].milliseconds = 1300    actions[2].action = jump released
actions[3].milliseconds = 2500    actions[3].action = jump pressed
actions[4].milliseconds = 3000    actions[4].action = jump released
actions[5].milliseconds = 5330    actions[5].action = right released

A Controller has two modes:

  1. Record: Receives keyboard input. Records input in the list. Hands the character input based on keyboard state.
  2. Replay: Ignores keyboard input. Advances through the list according to milliseconds elapsed since the level began. Hands the character input based on the recorded keyboard state at the current moment.

Characters

When your Character object is constructed, it creates a fresh Controller for itself. The Character can be in one of two modes at any time:

  1. Active: There is only ever one active Character and it is the one you control. When the Character is in Active mode, its Controller is in Record mode. By default when a Character is constructed it is in Active mode.
  2. Ghost: This is the one that replays your past actions. When a Character enters Ghost mode, it changes its appearance and sets its Controller to Replay mode.

Levels

A freshly started level

When you start the level, create a single Character. Now the level begins and the player does his thing.

When time resets

When the level resets, do three things:

  1. Tell the current Active Character to enter Ghost mode.
  2. Create a new Character.
  3. Call all Characters to Reset themselves. This will place them back at the starting position with no movement, etc. They will in turn tell their Controllers to reset to millisecond 0 with no keys pressed.

Then the level begins and the player does his thing.

\$\endgroup\$
1
  • \$\begingroup\$ This is perfectly clear. Thanks a lot. I kinda had the right idea, but I was going to make a central system to log movement, but having each character log its own movement is a much easier way to go about it. Thanks. \$\endgroup\$ Commented Jan 5, 2011 at 17:14
8
\$\begingroup\$

If you are replaying recorded inputs, consider the implications of any moving/destructible/interactive objects in the world, which may have moved or changed state when the actions are replayed

Also, replaying inputs will not work precisely if your game uses a variable timestep. You may want to consider a fixed-timestep game update (with interpolation for variable framerate rendering)?

\$\endgroup\$
1
  • 1
    \$\begingroup\$ +10 if I could. Great considerations. Replaying either movement vectors or position would be superior to replaying input, depending on the desired effect. Tens of milliseconds of inaccuracy between frames is probably easier to account for when working with movement and position than it is with input. \$\endgroup\$ Commented Jan 6, 2011 at 9:04
4
\$\begingroup\$

There are a lot of topics that cover game recording/replay systems/etc which should probably be the keystone of your past runthroughs.

Here's one: How to design a replay system

\$\endgroup\$
0
\$\begingroup\$

Recording the keyboard input might not be that useful in your case. You can however generate a spline with a timeline. You can even rewind time if your tricky with the forces that you need to apply

\$\endgroup\$

You must log in to answer this question.

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