AmazingChest [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=26548 Emitter Demo <p> <table><tr><td> <a href="/bbs/?pid=46841#p"> <img src="/bbs/thumbs/pico46853.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=46841#p"> Emitter Demo</a><br><br> by <a href="/bbs/?uid=26548"> AmazingChest</a> <br><br><br> <a href="/bbs/?pid=46841#p"> [Click to Play]</a> </td></tr></table> </p> <p>This is my second experiment with PICO-8, this time making a flexible and customizable particle emitter system. In this demo I've pre-made several different emitters that you can view by pressing (left) or (right).</p> <p>Particles are only rendered as lines, but there are a lot of options to control how they look and behave. It took a while to figure out how to handle colliding with the edges of the screen such that it was accurate no matter how fast the particles were traveling or how long their trails were. Here's just the particle update function to see what's going on:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> function particle:update() if self.age &lt; self.lifespan then if self.jitter &gt; 0 then local curr_jitter = rnd(self.jitter)-self.jitter/2 local curr_angle = atan2(self.dx,self.dy) local curr_mag = sqrt(self.dx^2+self.dy^2) self.dx = cos(curr_angle+curr_jitter)*curr_mag self.dy = sin(curr_angle+curr_jitter)*curr_mag end self.dx = (self.dx+self.xgrav)*self.drag self.dy = (self.dy+self.ygrav)*self.drag local next_x = self.x+self.dx local next_y = self.y+self.dy local line_pts = {{self.x, self.y}} line_pts.segments = 0 while self.collide do -- left collision if next_x &lt; 0 and btwn(self.y+((next_y-self.y)*self.x/(self.x-next_x)),0,screen) then self.y += (next_y-self.y)*self.x/(self.x-next_x) self.x = 0 self.dx *= -self.bounce next_x *= -self.bounce -- right collision elseif next_x &gt; screen and btwn(self.y+((next_y-self.y)*(screen-self.x)/(next_x-self.x)),0,screen) then self.y += (next_y-self.y)*(screen-self.x)/(next_x-self.x) self.x = screen self.dx *= -self.bounce next_x = screen-(next_x-screen)*self.bounce -- top collision elseif next_y &lt; 0 and btwn(self.x+((next_x-self.x)*self.y/(self.y-next_y)),0,screen) then self.x += (next_x-self.x)*self.y/(self.y-next_y) self.y = 0 self.dy *= -self.bounce next_y *= -self.bounce -- bottom collision elseif next_y &gt; screen and btwn(self.x+((next_x-self.x)*(screen-self.y)/(next_y-self.y)),0,screen) then self.x += (next_x-self.x)*(screen-self.y)/(next_y-self.y) self.y = screen self.dy *= -self.bounce next_y = screen-(next_y-screen)*self.bounce else -- no collision break end add(line_pts, {self.x, self.y}) line_pts.segments += 1 end self.x = next_x self.y = next_y add(line_pts, {self.x, self.y}) line_pts.segments += 1 add(self.lines, line_pts) elseif self.maxlength &gt;= 1 then self.maxlength -= 1 end -- trim the lines while #self.lines &gt; self.maxlength do del(self.lines, self.lines[1]) end -- get older self.age += 1 end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>With this code a particle can bounce multiple times in a single frame.</p> <p>Anyway, if this is useful at all feel free to steal it, or just check out the demo.</p> <p>edit: You can now press (x) to toggle performance info.<br /> edit2: Improved readability of performance info and fixed bug where the particle:draw() function was being called on &quot;dead&quot; particles.</p> https://www.lexaloffle.com/bbs/?tid=30346 https://www.lexaloffle.com/bbs/?tid=30346 Wed, 29 Nov 2017 17:52:56 UTC Fastest way to loop through a table? <p>Let's say I have a table called 'objects' that contains all of the objects in my scene. I want to loop through it and call each object's update function. The order in which the objects are updated doesn't matter. Of the following examples:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> -- example 1 for obj in all(objects) do obj:update() end -- example 2 for _,obj in pairs(objects) obj:update() end -- example 3 for i in pairs(objects) objects[i]:update() end -- example 4 foreach(objects, function(obj) obj:update() end) </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>which is the fastest?</p> <p>Thanks.</p> https://www.lexaloffle.com/bbs/?tid=30300 https://www.lexaloffle.com/bbs/?tid=30300 Tue, 21 Nov 2017 16:37:24 UTC Dot Party <p> <table><tr><td> <a href="/bbs/?pid=46540#p"> <img src="/bbs/thumbs/pico46571.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=46540#p"> Dot Party</a><br><br> by <a href="/bbs/?uid=26548"> AmazingChest</a> <br><br><br> <a href="/bbs/?pid=46540#p"> [Click to Play]</a> </td></tr></table> </p> <p>My first cart with PICO-8, Dot Party is a very simplistic implementation of a particle system using OOP techniques. I'm an hobbyist programmer and I've never used Lua before so this was mainly a learning experience figuring out how to make and use &quot;classes&quot; in PICO-8.</p> <p>I'm not sure if my implementation is the best way (or even good), but here's the breakdown:</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> dot = { x = 64, y = 64, size = 15, shrink = 0.2 } function dot:new(o) local o = o or {} setmetatable(o, self) self.__index = self return o end function dot:update() self.x -= (self.x-64)/128 self.y -= (self.y-64)/128 self.size -= self.shrink end function dot:draw() circfill(self.x, self.y, self.size, self.size) end function dot:exists() return self.size &gt; 0 end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>This is the &quot;dot&quot; class and its members. It's got a constructor and various functions to update, draw, and return its status.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> function spawn_dot(t) add(t, dot:new { x = rnd(128), y = rnd(128), size = 1+rnd(15), shrink = 0.2+rnd(0.3) }) end function update_all(t) local d = {} for _,o in pairs(t) do if o:exists() then o:update() else add(d, o) end end for _,o in pairs(d) do del(t, o) end end function draw_all(t) for _,o in pairs(t) do o:draw() end end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Here we have a function that spawns a new dot and functions to update and draw tables of instanced objects. They assume these objects contain certain functions that they call for each.</p> <div> <div class=scrollable_with_touch style="width:100%; max-width:800px; overflow:auto; margin-bottom:12px"> <table style="width:100%" cellspacing=0 cellpadding=0> <tr><td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> <td background=/gfx/code_bg0.png> <div style="font-family : courier; color: #000000; display:absolute; padding-left:10px; padding-top:4px; padding-bottom:4px; "> <pre> function _init() dots = {} end function _update() update_all(dots) spawn_dot(dots) end function _draw() cls() draw_all(dots) end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>And here's the game loop, which looks nice and neat thanks to our functions.</p> <p>This is certainly more abstracted than it needs to be, but again I'm just trying to learn. If there's something that I could be doing better I'd definitely like to know. I'm really enjoying using PICO-8 so far.</p> <p>edit1: Updated the code to use foreach() where I could instead of for in all() because I've heard it's faster. Saved a couple tokens too at the expense of a few more chars.</p> <p>edit2: Updated to use the pairs() iterator function because I found it to be the fastest method in my own tests. One thing to keep in mind is that pairs() does not iterate in a particular order, but for this it didn't seem to matter.</p> <p>edit3: Removed recycling to simplify the code and I don't think it made a performance difference anyway.</p> <p>edit4: Fixed bug in update_all() where deleting dots inside the loop caused the next dot to get skipped entirely. Also realized that pairs() does iterate in order when dealing with a sequenced table, so that's nice.</p> https://www.lexaloffle.com/bbs/?tid=30296 https://www.lexaloffle.com/bbs/?tid=30296 Tue, 21 Nov 2017 03:47:08 UTC