Log In  

Cart #playback_a-0 | 2022-01-18 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
6
TO LOAD THIS CART in immediate mode, type load #playback_a


VVhat's new ?
(01-17-22)
✅ New BTN() can now be called with no arguments, returns numeric of all buttons, thanks to @SmellyFishstiks.
✅ Beefed up the documentation and usage instructions.


This program will let you record and playback keystrokes, including saving your code with those compressed keystrokes in very small code indeed.

First off, the record and playback routine is 436-characters total, so this entire method is pretty small at that. Add about 46-characters for each of the functions record() and play() and you're home free !

Further I did not make this game. It is JELPI, written by @zep, a demo game which is included when you purchase Pico-8.

What I have written are two primary functions. One to record keystrokes as you play the game and transfer them to the clipboard as new source code - and the other is to simply play them back as you have listed.

This replaces the btn() function with my own. Include the 3-functions that + typing at the top of your code: _b0=btn and you are perfectly done. Nothing whatsoever else is needed. See the code below on usage:

_b0=btn
function record()
  _bm=1_bp=1_bt=0_bd=""
end
function playback()
  _bm=2_bp=1_bt=0
end
function btn(p)local b=_b0()if _bm==1then if b!=_bl then if _bd>""then _bd=_bd.._bt..","else _bd=""_bt=0_bp=1end _bl=b _bd=_bd..b..","_bt=0else _bt+=1end if _b0()==15then printh("btnpb={"..sub(_bd,1,#_bd-1).."}\n","@clip")stop()end return _b0(p)elseif _bm==2then if _bt>0then _bt-=1else _bs=btnpb[_bp]_bt=btnpb[_bp+1]_bp+=2if _bt==nil then _bm=0end end if p==nil then return _bs elseif band(_bs,2^p)>0then return true else return false end else return _b0(p)end end

. . .

(( The beginning of your code, _init() or what have you ))

When you choose RECORD, you can play the game as normal with no changes to your sourcecode. Every keystroke is recorded through a new version of BTN() as you can see. To stop recording at any time by press all 4-arrow keys at the same time, this will also stop the cart and return back to the editor. Then you can choose a line of your source code and press CTRL+V to paste the new button set you just used to play your game. It might appear like this:

btnpb={0,84,2,109,18,31,2,29,0,74,2,49,0,49,2,29,0,14,1,84,0,19,2,14,0,44,2,9,18,3,22,19,6,9,38,24,6,14,2,24,0,39,1,169,17,23,0,79,2,184,0,34,2,9,18,31,2,89,0,79,16,15,0,84,1,69,0,4,16,11,18,3,2,14,0,49,2,164,18,51,2,109,18,19,2,59,0,104,1,29,0,54,2,4,0,139,2,9,22,23,38,39,6,4,2,9,0,59,2,139,34,159,0,4,16,3,18,31,0,49,1,9,17,71,1,24,0,24,16,23,0,34,1,34,0,49,1,29,0,49,1,14,0,79,1,19,0,79,16,19,17,3,1,9,0,39,1,54,0,34,2,114,18,15,2,154,18,27,2,104,18,39,2,4,0,14,1,39,0,24,2,14,0,79,2,14,0,39,16,15,0,89,2,54,18,27,2,14,0,44,2,209,18,39,2,79,0,9,1,74,0,29,2,9,0,44,16,15,0,59,2,94,18,27,2,74,0,49,16,23,0,59,2,124,18,51,2,49,18,15,2,39,0,24,1,24,17,27,1,9,0,59,2,9,18,27,2,9,0,19,1,9,0,69,15}

Then select PLAYBACK after the btnpb= definition and run your cart again. You will see all of your keystrokes played back exactly as you did them with exact timing and everything. When the end of your keystrokes is reached, game input returns to normal and you can continue playing your game right where it was left off.

There is slight compression in here in that it counts the number of cycles you repeat a keystroke or series of keystrokes. So it doesn't just record 30-numbers for 30-frames of data, that would make the data too big. In fact to play this entire demo game of JELPI above from beginning to end took only 265-numbers or true 687-characters of space.

There are more details and instructions in the cart listed above, examine them for additional assistance.

And that's it ! Choose RECORD first and play the game as well as you can. When done recording press all 4-arrow keys together. Return to your code and Press CTRL+V to paste the new btnpb (button playback) string. Then select the PLAYBACK function instead of record, run the code, and sit back and watch it.

If you want to, paste your own Pico-8 cart playing back your own movements for the game, to show everyone else how well you can play it.

If greater compression over raw numbers is desired, (6-bit characters for instance), I can certainly write that for you and increase the btn() function in size slightly with higher compression in the data table.

Thanks to @Cadaeib65 for getting my brain spinning on this.

Hope This Helps !

P#105249 2022-01-17 21:47 ( Edited 2022-02-26 07:05)

why isnt this playable

P#105258 2022-01-17 21:55
1

Brobgonal cause that's the point.
Also this is sick! I would love to make a TAS for my game and watch it back or something hahaha

P#105259 2022-01-17 21:57
:: dw817
1

Hi @brobgonal. That is the point. It is the first time to be able to take over the controls of Pico-8 and play them back as someone can record them, in this case what you see above is me playing the level.

If you own Pico-8, you can play this game from your DEMO folder. Failing that @zep did post the original JELPI found HERE:

https://www.lexaloffle.com/bbs/?tid=1810

P#105260 2022-01-17 22:05
:: dw817

Hi @SmellyFishstiks. Thanks ! I was beginning to wonder if what I wrote would not be understood.

And yes you can take those few functions, put them in your code, record a speedrun, press the 4-arrow keys to exit. Choose a line of your code to paste the playback string.

Select playback() post the new cart in your same or different thread, and you are all set. Let me know too ! So far I've only seen my playback code for JELPI.

Truly @zep should already have this feature of record and playback built-in. This, rewind, frame forward, frame backward, cheat search, save state, and load state.

P#105261 2022-01-17 22:09 ( Edited 2022-01-17 22:09)

Ya I'll have to see if it works on other carts, I'm not sure that a feature builtin to pico like this would be what I want but ya it's fun to play with.

P#105264 2022-01-17 22:18
:: dw817

Yes, please let me know, @SmellyFishstiks. I want this to work properly all the way around. I know there are some Pico-8 games people really do want to speedrun, and hopefully this tool will help in that endeavor.

P#105265 2022-01-17 22:22

this is sick!

P#105268 2022-01-17 22:35
:: dw817
2

Thanks, @SandwichBlam. I'm hoping someone posts a CELESTE or modified CELESTE speedrun cart with it. I think that would be interesting to see - and would verify my program is working 100% correctly.

P#105269 2022-01-17 22:39 ( Edited 2022-01-17 23:01)
1

This is like handing your little brother the controller because he wants to play but it isn't plugged in so he just watches you play thinking he's playing

P#105272 2022-01-17 23:10
:: dw817

Ah, pretty well, Scrub. I was thinking of flashing a green or red light or something in the corner showing recording or playback, but that might interfere with gameplay.

If it's truly desired, I can add it.

I wrote this so it would help others post a speedrun of their favorite games. Or maybe even nail down a particularly tricky bug that only appears one way.

You record up to that point where it crashes, post your recorded keystrokes. Then give that text or cart to someone where it dies and they can easily track and trace the problem by watching the playback.

As mentioned, adding this ability inside Pico-8 I think would be beneficial and increase interest in using it over other more limited free Fantasy Consoles.

P#105274 2022-01-17 23:44

hmmm I tried it with my game to start like this:

-- [[ game playback recorder
 --written by dw817 (01-17-22)
 --standard ⌂ pico-8 license

 function record()
   _bm=1_bp=1_bt=0_bd=""
 end

 function playback()
   _bm=2_bp=1_bt=0
 end

 _b0=btn
 btnpb={0,29,2,95,3,4,1,74,3,9,2,113,0,453,4112,23,2,89,0,17,1,44,0,41,6,5,7,14,15}

 --record()

 -- call btn() as normal
 function btn(p)local b=_b0()if _bm==1then if b!=_bl then if _bd>""then _bd=_bd.._bt..","else _bd=""_bt=0_bp=1end _bl=b _bd=_bd..b..","_bt=0else _bt+=1end if _b0()==15then printh("btnpb={"..sub(_bd,1,#_bd-1).."}\n","@clip")stop()end return _b0(p)elseif _bm==2then if _bt>0then _bt-=1else _bs=btnpb[_bp]_bt=btnpb[_bp+1]_bp+=2if _bt==nil then _bm=0end end if band(_bs,2^p)>0then return true else return false end else return _b0(p)end end
 --]]
 playback()

And at first I wasn't realizing why it wouldn't end recording when I pressed down ⬅️➡️⬆️⬇️,
Then I realized that you have to have a btn() call I guess which doesn't get ran when the player dies.
But after I figured that out I put my btnpb in and it keeps on giving me this error:

runtime error line 31 tab 0
 function btn(p)local b=_b0()if _bm==1then if b!=_bl then if _bd>""then _bd=_bd.._bt..","else _bd=""_bt=0_bp=1end _bl=b _bd=_bd..b..","_bt=0else _bt+=1end if _b0()==15then printh("btnpb={"..sub(_bd,1,#_bd-1).."}\n","@clip")stop()end return _b0(p)elseif _bm==2then if _bt>0then _bt-=1else _bs=btnpb[_bp]_bt=btnpb[_bp+1]_bp+=2if _bt==nil then _bm=0end end if band(_bs,2^p)>0then return true else return false end else return _b0(p)end end
attempt to perform arithmetic on local 'p' (a nil value)
at line 0 (tab 0)

where p is nil.. so ya It's really cool but man I just don't know how to use it.

(this was in the bottom of init. though I tried elsewhere and got the same issue)

P#105282 2022-01-18 01:24 ( Edited 2022-01-18 01:26)

ya when printing out p the first one is always nil..
OH wait, this is cause I have a btn call somewhere that's just nil or something isn't it

if btn()~=3 and (btn(0) or btn(1)) or a.drilling then
  a.ifmove = true
  a.mt += 1
 end

ya I have this. is there anyway you could make a failsafe if a btn() call doesn't have any arguments and is just for getting the bit field?

function btn(p) if p then local b=_b0()if _bm==1then if b!=_bl then if _bd>""then _bd=_bd.._bt..","else _bd=""_bt=0_bp=1end _bl=b _bd=_bd..b..","_bt=0else _bt+=1end if _b0()==15then printh("btnpb={"..sub(_bd,1,#_bd-1).."}\n","@clip")stop()end return _b0(p)elseif _bm==2then if _bt>0then _bt-=1else _bs=btnpb[_bp]_bt=btnpb[_bp+1]_bp+=2if _bt==nil then _bm=0end end if band(_bs,2^p)>0then return true else return false end else return _b0(p)end end end

maybe not the best way but something like that?

P#105283 2022-01-18 01:29 ( Edited 2022-01-18 01:32)
:: dw817

Hi @SmellyFishstiks:

Can you post the entirety of the code, please ? Full cart. I'll see what I can do to get it working and recording/playing back correctly. And yes I likely need to write a function for BTNP() as well.

Currently my record/playback engine only works with BTN(), not BTNP() nor any mouse functions.

P#105284 2022-01-18 01:31

ya I was editing my msgs to not spam, it was a lose btn() check but like ya could there be a failsafe?
When I added that failsafe it works now

P#105285 2022-01-18 01:32 ( Edited 2022-01-18 01:33)
:: dw817

I think I understand, @SmellyFishstiks. You want to be able to call btn() with no arguments and it returns the correct value instead of TRUE or FALSE.

Let me examine my code.

P#105286 2022-01-18 01:36

ya I want to use btn() by it's self to get just the state of the buttons, I use this as a cheap way to make sure you aren't pressing left and right at the same time.
And I'm sure I'm not the only one that has used this either

P#105287 2022-01-18 01:38 ( Edited 2022-01-18 01:38)
:: dw817

OK, rather than change all the code, @SmellyFishstiks, replace this single line into yours to see if this fixes it:

function btn(p)local b=_b0()if _bm==1then if b!=_bl then if _bd>""then _bd=_bd.._bt..","else _bd=""_bt=0_bp=1end _bl=b _bd=_bd..b..","_bt=0else _bt+=1end if _b0()==15then printh("btnpb={"..sub(_bd,1,#_bd-1).."}\n","@clip")stop()end return _b0(p)elseif _bm==2then if _bt>0then _bt-=1else _bs=btnpb[_bp]_bt=btnpb[_bp+1]_bp+=2if _bt==nil then _bm=0end end if p==nil then return _bs elseif band(_bs,2^p)>0then return true else return false end else return _b0(p)end end

If it does, I'll update the master.
Master cart updated.

P#105288 2022-01-18 01:42 ( Edited 2022-01-18 02:38)

It seems to work, Though after watching this I see as well that the rng state could mess things up (ex the clouds.)... would have to save the seed you started recording on and srand at the start..
But for replaying stuff this works great, Will love to use it if I have enough tokens left to record runs and stuff.

P#105289 2022-01-18 01:59
:: dw817
1

Owow I love your Rescue Bird, @SmellyFishstiks. That is neat. I am totally in the field I want to be. Helping out game programmers with useful functions and utilities. :)

As for tokens, hmm ... I could write a function that waits until you press CTRL+V and then PASTES the playback script from the clipboard directly into the array - skipping adding it to the source-code, if you think that will help.

. . .

Let me update the main engine with this new function.

P#105291 2022-01-18 02:20 ( Edited 2022-01-18 02:21)

ya new version works. once I actually have stuff to do in my game it'll get interesting.. But ya cool tool thanks for making it

P#105294 2022-01-18 02:44
:: dw817
1

You are very welcome, @SmellyFishstiks. I hope you other guys and gals find it useful too. I'm - already working on something else. :)

Write if you have any questions or comments about this Playback project.

P#105296 2022-01-18 02:47

Oh my god thank you so much @dw817 ! I will ask you again later when I have PICO-8. Do you have a discord or smth that we could use to not flood this place ? By the way I don't think the game I want to TAS has any RNG.

P#105300 2022-01-18 05:47
:: dw817

I'm glad you like it, @Cadaeib65. :) Something overdue for Pico-8 I guess ...

I was on discord at one point. Understand I'm never a leader. I always try to follow - if the path is not too difficult. If you yourself open a Discord I will accept your invite - but I won't open one personally myself.

Or you can reach me on my Writer's page by creating an account there for messaging. Click dw817 on this page to see the link. Click that link, let the page come up, then click at the top right, "Sign Up!" Once logged in you can send and receive private mail. I read, write, and reply to messages on that site daily as it's my home on the internet.

That's the best I can do.

P#105302 2022-01-18 06:33 ( Edited 2022-01-18 06:46)

There is is pico-tas discord I discovered recently @dw817 https://discord.gg/JWvDMda2

P#105507 2022-01-22 11:35
:: dw817

Received invite, @Cadaeib65. Thanks !

P#105525 2022-01-22 20:59

I like your colour taste. The game is not only properly programmed(I guess) but also looks fantastic.

P#105575 2022-01-24 19:30
:: dw817

Hi, @WallacePrio. Thank you however this game is not mine. It is from @zep, our lord and master of Pico-8.

What I wrote here is a way to record your movements and play them back in any Pico-8 cart, especially for use in Speedrunning. That is all.

P#105581 2022-01-24 22:34

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2022-05-21 21:08:53 | 0.203s | Q:56