Hi, everyone. I made a very simplistic scene manager for you all to use, its somewhat compressed as well. here's an example:
Basically, this scene manager allows you to create init, update and draw for each scene (as well as anything else you want to cook up, of course).
HOW TO USE
to make a new scene, use the command 'nscn' inside of your init function. for example: nscn({init=function() end, update=function() end, draw=function() end})
to grab the current scene thats running so you can modify it or its variables, you can simply create a local variable called 'self'.
local this=scn['self']()
(or local this=scn.self())
to switch to a scene, you'll need to comment the ID of that scene so you don't lose track. I recommend you have a function that launches at the init() of your game that creates all of your scenes for you.
command to load a scene: scn_mng.go(id) where id is the scene number you want to run.
Finally, you need to put the 2 commands inside draw() and update(). in update(), put scn_mng.update() and in draw put scn_mng.draw()
code snippit:
--scene manager --shooting★ scn = {self=function() return scn[scn_mng.r] end} scn_mng = { go=function(s) scn_mng.r = s scn[s].init() end, draw=function() scn[scn_mng.r].draw() end, update=function() scn[scn_mng.r].update() end } function nscn(d) local a={ init=d.init or function() end, update=d.update or function() end, draw=d.draw or function() end } add(scn, a) end |
code example (used in cart above)
--sample function create_scenes() --scene 1 nscn({ init=function() --create a local var called --this and set it to self --scene local this=scn['self']() --create particles this.particles = {} for i=0,16 do local a={rnd(127),rnd(127),rnd(2)} add(this.particles, a) end --create a timer to switch --to scene 2 with this.timer=0 end, update=function() --create a local var called --this and set it to self --scene local this=scn['self']() this.timer+=1 if this.timer==120 then this.timer=0 --switch to scene 2 scn_mng.go(2) end end, draw=function() --create a local var called --this and set it to self --scene local this=scn['self']() --draw particles for i=1,#this.particles do pset(this.particles[i][1], this.particles[i][2], 7) this.particles[i][1]+=this.particles[i][3] this.particles[i][2]+=this.particles[i][3] end end }) --scene 2 nscn({ init=function() --create a local var called --this and set it to self --scene local this=scn['self']() this.timer=0 end, update=function() --create a local var called --this and set it to self --scene local this=scn['self']() this.timer+=1 if this.timer==120 then this.timer=0 --switch back to scene 1 scn_mng.go(1) end end, draw=function() cls(1) end }) end function _init() --create scenes create_scenes() scn_mng.go(1) end function _update() scn_mng.update() end function _draw() cls() scn_mng.draw() print('running scene '..scn_mng.r, 0, 0, 7) end |
So this is nice.
However, I saw you posting similar systems on Twitter and I wanted to bring up something you might not be considering. In the lower right corner Pico-8 will track how many 'Tokens' your code is using. The concept of a Token is a bit nebulous but basically every time you type an operator, a command, a function, a variable you spend at least a Token. When you hit 8192 Tokens, it's game over. You can't put any more code in your cart. In fact, your code won't even run until you can somehow go below that limit again. Note that this is not the same as the length of the code. Shorter variable names or compression won't save Tokens.
When doing bigger projects in Pico-8, being efficient with Tokens will be a very high priority. Every bigger project is bound to hit that limit. Your efficiency will translate directly into being able to implement more features.
OOP is a highly token-inefficient way of coding.
player_x = 1 -- is 3 Tokens
player.x = 1 -- is 4 Tokens
Every single time you access a property of an object it costs you an additional Token. So every time you use objects, you should ask yourself: "Does this absolutly HAVE to be an object? What am I actually GAINING from this being an object?".
Your sample code with the scene manager is 299 Tokens.
This is a whole racing game made in 387 Tokens
https://twitter.com/p01/status/1091498849049427969
And the code below is your sample rewritten. It has no scene maner and no OOP. But it still uses the same function pointer trick you applied and it's not that much harder to use. It's 163 Tokens.
I'm not bringing this up to dunk on your system. I'm sure it has its place. And maybe you already know all of this and you had your reasons. I wanted just to make sure you're not wasting your time developing systems that end up causing you more problems than they solve.
Cheers man, keep it up!
function init_1() _drw=draw_1 _upd=update_1 particles = {} for i=0,16 do local a={rnd(127),rnd(127),rnd(2)} add(particles, a) end timer=0 scn_num=1 end function update_1() timer+=1 if timer==120 then timer=0 init_2() end end function draw_1() cls() for i=1,#particles do pset(particles[i][1],particles[i][2],7) particles[i][1]+=particles[i][3] particles[i][2]+=particles[i][3] end end function init_2() _drw=draw_2 _upd=update_2 timer=0 scn_num=2 end function update_2() timer+=1 if timer==120 then timer=0 init_1() end end function draw_2() cls(1) end function _init() --create scenes init_1() end function _update() _upd() end function _draw() _drw() print('running scene '..scn_num, 0, 0, 7) end |
Krystman,
Thank you for that info. All the more reason to love pico8 as its going to force me to optimize more! Loving the token system, and I'll start paying attention to it more <3
Cheers!
function scene(act, int, upd) if act == 'new' then return {int=int, upd=upd} end if act == 'go' then int.int() scn = int end end function upd_scn() if not scn then return end scn.upd() end |
Krystman
thanks for telling me about tokens! I made this update here that only uses 41 tokens. <3
sample:
function scenes() scene1=scene('new', --init function() scene1.f=0 end, --update/draw function() print(scene1.f) scene1.f+=1 end) end function _init() scenes() scene('go', scene1) end function _draw() upd_scn() end |
----EDIT----
even more optimized now <3 same setup just different execution
function scene(a, b, c) if a == 'new' then return {b, c} end if a == 'go' then if c != true then b[1]() end scn=b end end function upd_scn() if not scn then return end scn[2]() end |
this one uses 44 tokens and looks cleaner.
compressed:
function scene(a, b, c) if a == 'new' then return {b, c} end if a == 'go' then if c != true then b[1]() end s=b end end function upd_scn() if not s then return end s[2]() end |
[Please log in to post a comment]