Log In  

Cart #apa64_scroller2-0 | 2020-07-02 | Code ▽ | Embed ▽ | No License

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...

P#78797 2020-07-02 17:10

3

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.

P#78801 2020-07-02 18:49 ( Edited 2020-07-02 19:15)
1

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:

scroller.add was previously defined to allow tables of sentence information to be sent to it, but in my opinion this detracted from the clarity of showing the use of the scroller table as a component; I have therefore changed it above. This is the version of scroller.add I last had up (not the original version, but that was just quickly programmed).

 scroller={
  add=function(a,b,c)
   if (type(a)=="string")a={{a,b,c}}

   if type(a)=="table" then
    for i=1,#a do
     if type(a[i])=="table" and type(a[i][1])=="string" then
      local t,x,y,speed
      t,x=a[i][1],127
      y=a[i][2] or 60
      speed=a[i][3] or 1
      add(scroller,{t=t,x=x,y=y,speed=speed})
     end
    end
   end
  end
 }

Previous note read: (I have added some type checking for the arguments to make scroller.add a little more versatile in what it accepts - I wanted it to accept a table of sub-tables too - which makes the scroller.add function look more complicated than it is - its essence is to take its arguments and use them in the line add(scroller,{t=t,x=x,y=y,speed=speed}) - the rest I hope is reasonably self-explanatory.)

-- end of previously posted material


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:


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.

P#78822 2020-07-03 05:32 ( Edited 2020-07-04 11:31)

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!

P#78888 2020-07-04 11:37 ( Edited 2020-07-04 11:38)

[Please log in to post a comment]