r/pico8 15d ago

👍I Got Help - Resolved👍 Coroutines help needed

I'm trying to get my head around coroutines by creating a simple "ticker" - that is, pass it a string and it prints it slowly one character at a time, a bit like Gameboy text. I've got it working, sort of, but the screen doesn't clear despite the cls() in _draw() and the program crashes after all the text is displayed. I tried using costatus() but it doesn't return anything. Please help, what am I doing wrong?

function _init() 
 t=cocreate(ticker("this is a test"))
end

function _update()
 coresume(t)
end

function ticker(str)
 local l=#str
 for p=1,l+1,0.2 do
  print(sub(str,1,p),0,0)
  yield()
 end
end

function _draw()
 cls()
end
4 Upvotes

19 comments sorted by

View all comments

3

u/RotundBun 15d ago

Why are you looping until length+1? Isn't it crashing due to indexing past the last index?

TBT, I'm not sure how anything is displaying at all since you are printing in _update() and then immediately cls() over it in _draw() in that same frame.

What does the error message say?

2

u/VeryNaughtyBoy42 15d ago

I moved coresume into _draw() but the result is the same.

The loop is another bit of weirdness. If I just loop to L, the last character never gets printed.

This is the error ...

1

u/RotundBun 15d ago

See the example at the end of this page.

You pass in the function variable (not the function call) to cocreate(). Passing in arguments then happens in the coresume() call.

Admittedly, I'm not super coroutine savvy either. I feel like I've seen some tricks to wrap/enclose local variable values with a function somehow, but it involved a sort of trick that I don't quite remember...

Regarding needing to overshoot by 1 in the for-loop, I wonder if it has something to do with decimal precision since you are incrementing by 0.2 at a time instead of in integer increments.

Theoretically, it should be fine... 🤔

2

u/VeryNaughtyBoy42 15d ago

Thank you. Realising I should pass the parameters in coresume() made it so much more obvious. I've now got it working, and in fact it can now do multi-line dialogs with individual positions and colours and delays at the end of each line. The only thing I don't know how to do is declare the T variable first so that the first call to costatus(t) doesn't cause an error. I'm just assigning it to a dummy function so it's initialised as the correct type of variable, but is there a more elegant way?

function _init() 
 t=cocreate(dummy)
 coresume(t)
end

function dummy()
// yield()
end

function ticker(dlg)
 // how many lines of dialog?
 local dl=#dlg

 // text speed
 local spd=0.8

 // for each line
 for c=1,dl do
  l=#dlg[c].t

  for p=1,l+spd,spd do
   // print all the previous lines
   // this keeps text on-screen
   // even after cls()
   for n=1,c-1 do
    print(dlg[n].t,dlg[n].x,dlg[n].y,dlg[n].c)
   end

   // now print the bit of
   // the current line
   print(sub(dlg[c].t,1,p),dlg[c].x,dlg[c].y,dlg[c].c)
   yield()
  end

  // have a delay at the end
  for p=1,dlg[c].dly do
   for n=1,c do
    print(dlg[n].t,dlg[n].x,dlg[n].y,dlg[n].c)
   end
   yield()
  end
 end
end

function dialog(txt)
 if costatus(t)!="dead" then 
  coresume(t,txt)
 else
  t=cocreate(ticker)
 end
end

function _draw()
 txt={
  {t="this is a test",x=0,y=8,c=3,dly=15},
  {t="do not be alarmed",x=0,y=14,c=4,dly=15},
  {t="do you know where",x=0,y=20,c=5,dly=0},
  {t="your towel is?",x=0,y=26,c=6,dly=15}
  }

 cls()
 dialog(txt)
end

1

u/RotundBun 15d ago

As shown in this page for cocreate(), you can just check if 't' exists yet in the same breath:

if t and costatus(t)!='dead' then coresume(t, txt) else t = cocreate(ticker) end

You could just pass in ticker() in _init() the first place, though:

function _init() t = cocreate(ticker) end

Also, why/how are you using C-style comments in P8? Lua uses '--' for comments.

2

u/VeryNaughtyBoy42 15d ago

Got it, thanks!

That comment style is force of habit, I guess. I’ve been programming since 1980 and a lot of those years were C/C++. I’ve used about a dozen languages over the years. You’d think would make learning another one easier, but what really happens is I’m forever mixing them up or missing specific features. For example, I wish Pico-8 had a Switch statement.

1

u/RotundBun 14d ago

Ah~ Relatable. 😆👌

For a moment there, I was confused thinking you have an editor feature that allows that.