Hello world!
How can I make my code more like a library or a self-contained independent module/component? Here's a text scroller by me (my first published cart yay!). Currently you need to call three functions to use it:
function _init() scroller = init_scroller("lorem ipsum dolor sit amet, consectetur... ", 30, 5/30) end function _update() update_scroller() end function _draw() cls(0) draw_scroller(4, 60, 7) end |
I tried to write it more like an component but couldn't make it work. My idea was that init_scroller() would return "an object" which would contain everything. Then you'd call object.update() and object.draw() to use it and could create as many instances as needed. However my return object had just pointer to global functions and later instances overwrote earlier ones.
Can you point me to a simple example how to do components in PICO-8?
You can probably tell I'm coming from Java background ;) Are there any specific style guides or general conventions for PICO-8 Lua? I'm coding with VS Code, can't do it with the 128x128 window...
You can definitely make this simpler by using t() as a control variable for the scroll, which would then obviate the need for _init() and _update() parts of the process. Here's the code to do it that allows an x/y coord, a width, a speed, and the color:
function _draw() cls(1) txtscroll("0123456789",10,10,20,1/30,8) txtscroll("0123456789",10,20,40,2/30,11) txtscroll("abcdefghijklmnopqrstuvwxyz",10,80,80,1/30,11) txtscroll("abcdefghijklmnopqrstuvwxyz",40,50,60,-1/30,11) end function txtscroll(txt,x,y,w,spd,c) clip(x,y,w,5) local len=#txt*4+w local ox=(t()/spd)%len print(txt,x+w-ox,y,c) clip() end |
Here's what that looks like actually in use (and notice it allows for negative speeds to go backwards):
You could improve this further by adding code that detects glyphs to adjust the len variable, since glyphs take up 8 pixels, not 4.
To make your code into a component, speaking specifically about the scroller and leaving you to generalise to the more general case, a simiple way to do this is to use the numerical indexing of a table as a collection for multiple scroller data, and to use its named key-value pairs for functions.
(Edited: simplified example for clarity.)
function _init() scroller={ add=function(sentence,y,speed) local x=127 y=y or 60 speed=speed or 1 add(scroller,{t=sentence,x=x,y=y,speed=speed}) end } --table functions can be declared outside the table declaration too scroller.draw=function() for i=#scroller,1,-1 do s=scroller[i] print(s.t,s.x,s.y,6) s.x-=s.speed if (#s.t*4+s.x<=0)del(scroller,s) end end scroller.add("sentence 1") scroller.add("sentence 2",66) scroller.add("sentence 3",72,.5) end function _update() --at some point, new sentences --would be added during _update end function _draw() cls() scroller.draw() end |
(This doesn't follow your description of what you attempted, but I feel it covers the general component idea you were looking for.)
Other brief explanatory notes
Lines such as y=y or 60 are a Lua idiom which will mean that if y isn't passed as an argument and is therefore nil, it will instead be set to 60.
In the scroller.draw function, the iteration goes from the size of the table to 1 to make deletion easier.
In if (#s.t*4+s.x<=0)del(scroller,s) 4 is the width of a character. (If it was instead 8, it would cope with the glyph characters too, with a little extra longevity for strings which weren't replete with glyph characters.)
The previous more complex version:
You could instead use method syntax with a colon, which would just pass the object itself as the first parameter self:
In _init:
function scroller:draw() for i=#self,1,-1 do s=self[i] print(s.t,s.x,s.y,6) s.x-=s.speed if (#s.t*4+s.x<=0)del(self,s) end end |
And the changed call in _draw:
function _draw() cls() scroller:draw() end |
Then you can start looking at:
- objects https://www.lua.org/pil/16.html
- closures https://www.lua.org/pil/6.1.html
- metamethods https://www.lua.org/pil/13.html
- coroutines https://www.lua.org/pil/9.html
Also note MBoffin's comment "You could improve this further by adding code that detects glyphs to adjust the len variable, since glyphs take up 8 pixels, not 4."
I have omitted checking for glyphs for simplicity. Other things may also have been omitted because it's more a demonstration of using a table as a component of code than anything else.
Wow, thanks, both of you!!
@MBoffin t() and clip() were new to me, using print() like that with clip() is quite clever. My original solution was very much overengineered :)
@remcode thanks for the OO links and example - and a different kind of implementation!
I got PICO-8 by surprise as a part of the itch.io BLM bundle and it has been the best thing ever for the past week or so for me!
[Please log in to post a comment]