how to record and play game input?

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
glitchapp
Party member
Posts: 235
Joined: Tue Oct 05, 2021 10:34 am
Contact:

how to record and play game input?

Post by glitchapp »

Hi,

I did not find a thread on this topic and I wonder what is the most efficient way to solve this problem:

I would like to be able to record keyboard input so that it can be used it to show recorded gameplay, demos or to use it to create game tutorials.

My keyboard includes this functionality like many gaming keyboards and I would like to implement it in a game. is there any library for this?

In summary I want to know how to:

Record game input

Play recorded game input.

Thank you!
User avatar
darkfrei
Party member
Posts: 1169
Joined: Sat Feb 08, 2020 11:09 pm

Re: how to record and play game input?

Post by darkfrei »

Store inputs as

Code: Select all

timings = {
  {time = 14.631, scancode = "a", duration= 3.14},
  {time = 21.07, scancode = "d", duration= 0.087},
}
Update:

Code: Select all

pressed = pressedList
if timing.time > time and timing.time+timing.duration  < time then
  pressed[scancode] = true
elseif pressed[scancode] and timing.time+timing.duration > time then
  pressed[scancode] = false
end
And be sure that your dt by recording and by playing are the same.
Last edited by darkfrei on Fri Jun 24, 2022 9:28 am, edited 2 times in total.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
glitchapp
Party member
Posts: 235
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: how to record and play game input?

Post by glitchapp »

thanks darkfrei, oh really is it so easy? I expected something more complicated.

I will test what's the output of timings after doing that thank you!
User avatar
darkfrei
Party member
Posts: 1169
Joined: Sat Feb 08, 2020 11:09 pm

Re: how to record and play game input?

Post by darkfrei »

Maybe it will be better to go to the ticks, where the dt is always 1/60 second, then you are need several saved tables:

Code: Select all

Replay.keypressed = {
  {tick = 17, scancode = "a"},
  ...
}

Replay.keyreleased = {
  {tick = 24, scancode = "a"},
  ...
}

Replay.mousemoved = {
  {tick = 24, x=317, y=137},
}
By the update just keep the actual reading elements of lists and save to your isDown[scancode] all player inputs until the next tick.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
glitchapp
Party member
Posts: 235
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: how to record and play game input?

Post by glitchapp »

Thanks darkfrei, it is not as complicated as I thought but it is also not too simple so I will keep all of this respond in my folder and I will attempt it in the future, if I succeed I will post it here.
User avatar
BrotSagtMist
Party member
Posts: 607
Joined: Fri Aug 06, 2021 10:30 pm

Re: how to record and play game input?

Post by BrotSagtMist »

If you have, say a complicated 2D jump n run, this wont be accurate enough to replay a map.
Youre better of saving the positions of everything on the screen for every frame.
obey
glitchapp
Party member
Posts: 235
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: how to record and play game input?

Post by glitchapp »

No it is for a puzzle game and I think it would work, but thanks to pointing it out so that I know it needs to be adapted for other type of games.
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: how to record and play game input?

Post by pgimeno »

Depending on how your game is made, it can be super simple or it can require a lot of data acquisition for replaying it later.

Even for a puzzle game, for example, if it has smooth transitions, that introduces a timing element. If the keyboard is disabled during certain intervals (e.g. during a transition), then timing can become critical, say if you press a key at a moment very close to the time when the key is enabled. That can make a difference when replaying: depending on the dt during the replay, the keypress can be accepted or rejected. So, in that case, going for a more general approach where also dt per frame is recorded would guarantee the ability to replay it later and obtain the same results. It's not necessary to save every object as BrotSagMist said, that's overkill; just dt and input events, and if you use love.timer functions, that too.

Roughly, it would consist of this. If you use love.keypressed/keyreleased/textinput, you need to record the call with all the parameters that you use, together with their timestamp. The timestamp would be a variable updated by love.update(). If you use joystick callbacks, same thing. In love.update, you would capture the individual dt's to later reconstruct the timestamp.

At the time of replaying, you would ignore actual events and only call the callbacks with the recorded events. In love.update, you would ignore the incoming dt and use the saved one instead.

The more I think about it, the more it seems to me that it's worth writing a library for it that you can use in your game transparently, by monkey-patching Löve functions.
glitchapp
Party member
Posts: 235
Joined: Tue Oct 05, 2021 10:34 am
Contact:

Re: how to record and play game input?

Post by glitchapp »

Oh writing a library for it that others can use would be fantastic! I'm glad I touched on a topic that would be of interest for others.

The game does not have smooth transitions and it is the same game I started working on at the beginning of this year and managed to get working thanks to the help of darkfrei.

You can find the main thread for the game here:viewtopic.php?f=4&t=92580&p=246339&hili ... ts#p246339 and the offical website here: https://glitchapp.codeberg.page/
Xugro
Party member
Posts: 110
Joined: Wed Sep 29, 2010 8:14 pm

Re: how to record and play game input?

Post by Xugro »

pgimeno wrote: Fri Jun 24, 2022 2:02 pmRoughly, it would consist of this. If you use love.keypressed/keyreleased/textinput, you need to record the call with all the parameters that you use, together with their timestamp. The timestamp would be a variable updated by love.update(). If you use joystick callbacks, same thing. In love.update, you would capture the individual dt's to later reconstruct the timestamp.

At the time of replaying, you would ignore actual events and only call the callbacks with the recorded events. In love.update, you would ignore the incoming dt and use the saved one instead.
Is there a problem with the speed of the playback? I am not sure.

Let's assume you have a fast pc and record your game with 60 fps. Then you send the recording to me. I have a slow pc and can only run the game with 30 fps. Since the playback would use the recorded dt's and my slow pc takes twice as long to recalculate everything, I would see the playback with half the original speed - wouldn't I? And I don't see where a timestamp would fix this problem.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 39 guests