merwok [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=41031 the true guide to objects, prototypes and metatables <p>people often ask about object orientation (OOP) and inheritance, but can get confusing or incomplete guides. I want to help everyone understand how prototypes work!</p> <p>lua does support object-oriented programming (but does not require it), based on prototype inheritance &mdash; not classes.<br /> metatables are part of this but also often misunderstood. this is a complete explainer that I wrote on discord and keep not putting here in a clean way. so I am putting it here as it is!</p> <p>so what is a prototype?</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>goblin={ sp=42, } function goblin:new(x,y) local obj={x=x, y=y} return setmetatable(obj, {__index=self}) end function goblin:draw() spr(self.sp,self.x,self.y) end gob1=goblin:new(40,40) gob2=goblin:new(60,70)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>alright so this is like 6 different things working together.</p> <p>1) table with methods: <code>goblin</code> is a table with property <code>sp</code> and methods <code>new</code> and <code>draw</code> (a method is a function attached to an object)</p> <p>calling <code>goblin:new(40,40)</code> is the same as <code>goblin.new(self,40,40)</code>; self is &laquo;the object we are working on&raquo;; defining <code>function goblin:draw()</code> is the same as <code>function goblin.draw(self)</code> and the same as <code>goblin={sp=42, draw=function(self) spr(...) end, somethingelse=true}</code></p> <p>there is a difference between the two methods in my example: when we call <code>goblin:new</code>, the <code>self</code> param inside it will be the <code>goblin</code> table itself (the prototype), but when we have <code>gob1:draw()</code> then self inside draw will refer to gob1.</p> <p>2) metatables. there are special methods that lua uses to implement operators (<code>+</code>, <code>/</code>, <code>..</code>, etc). the method for addition for example is <code>__add</code> (we call these metamethods). if I want to be able to do <code>vector1 + vector2</code>for my custom vector tables for example, I need to define a method named <code>__add</code> but I can&rsquo;t do it in the <code>vector</code> prototype table, lua will not look it there; it is required to define these metamethods in a table&rsquo;s metatable. (the metatable is similar to a class in other object-oriented languages: it is the template, or the definition, or the model for many tables.) so that&rsquo;s what happens in <code>goblin:new</code>: I define a metatable with one metamethod and set it on my goblin object.</p> <p>3) prototype. these are great! if I have 50 goblins on screen and they have different health and coordinates but the same properties for sprite, width, height, etc, and the same methods for update, attack, draw, etc, I would like to define all the shared things in one place, then have custom things in each goblin table. that&rsquo;s what a prototype is for! here in <code>goblin</code> example we have <code>sp</code> and <code>draw</code> shared, and in a specific goblin table (it starts as <code>obj</code> on line 6, then it&rsquo;s <code>gob1</code> or <code>gob2</code> in my example) we have specific data like x and y.<br /> much more info on this really useful site: <a href="https://gameprogrammingpatterns.com/prototype.html">https://gameprogrammingpatterns.com/prototype.html</a></p> <p>alright so how do I say &laquo;gob1 and gob2 should delegate to goblin prototype for some properties&raquo;? I define a metatable with an <code>__index</code> property. it is called by lua when I do <code>gob1.sp</code> and <code>sp</code> is not found inside <code>gob1</code>. it can be a function (can be useful to have a dynamic property that&rsquo;s computed from other properties) or another table: the prototype!<br /> more: <a href="https://www.lua.org/pil/13.4.1.html">https://www.lua.org/pil/13.4.1.html</a></p> <p>now this is the cool thing with prototype-based object-oriented language that you don&rsquo;t have in such a nice way with class-based OO languages<br /> what if I want 40 goblins on screen and 10 archer goblins? these should have a different sprite and different attack method.</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>archer=goblin:new() archer.sp=52 function archer:attack(target) --use the bow end arcgob1=archer:new(20,50) arcgob2=archer:new(40,70)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>look at this from bottom to top:</p> <ul> <li><code>arcgob1.x</code> will be 20, <code>y</code> 50</li> <li>arcgob1&rsquo;s and arcgob2&rsquo;s prototype is <code>archer</code>, because when we call <code>archer:new</code>, <code>self</code> on line 6 of my first code block points to <code>archer</code></li> <li><code>arcgob1.sp</code> is 52 (the value comes from the prototype)</li> <li><code>arcgob1:attack(hero)</code> will use our <code>archer:attack</code> method.</li> <li><code>arcgob1:draw()</code> will use <code>goblin:draw</code>! archer itself is a table that has goblin for prototype<br /> <code>draw</code> is not found in arcgob1, look at its prototype archer, not found, look at its prototype goblin, found! call it with <code>self</code> pointing to arcgob1.</li> </ul> <p>result:</p> <img style="margin-bottom:16px" border=0 src="/media/41031/goblins.png" alt="" /> <p>the confusion is that we often see code like this to explain prototypes (or &laquo;class&raquo;, but lua doesn&rsquo;t have classes):</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>goblin={sp=42} function goblin:new(obj) setmetatable(obj, self) self.__index=self return obj 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>why do we need to add <code>goblin.__index = goblin</code>?? it&rsquo;s its own prototype? but it&rsquo;s a metatable? both?!<br /> the thing is, we don&rsquo;t need that. a metatable is only strictly required to implement metamethods to define what operators do. when we want a prototype, <code>{__index=proto}</code> is the metatable, and proto the prototype. clarity at last!)</p> <p>hope this helps! please ask follow-up questions if needed, try to implement your own cart and share it!</p> https://www.lexaloffle.com/bbs/?tid=141946 https://www.lexaloffle.com/bbs/?tid=141946 Thu, 25 Apr 2024 16:35:23 UTC Splore shows html entities in game titles <p>Looking at lucky draw and the game with bbs thread title <code>&quot;Fit&quot; Santa</code> (<a href="https://www.lexaloffle.com/bbs/?pid=fit_santa_00-1">https://www.lexaloffle.com/bbs/?pid=fit_santa_00-1</a>) was displayed with &amp; quot ; (can&rsquo;t type it here even in backticks!)</p> https://www.lexaloffle.com/bbs/?tid=46152 https://www.lexaloffle.com/bbs/?tid=46152 Thu, 13 Jan 2022 16:36:18 UTC Add function to list directories <p>In game code, calling <code>ls()</code> only returns names of cart files.</p> <p>To make it possible to write local game launchers and other mini-splores, it would be nice to have a way to get directories too (some of us are hoarders and have to organize carts).</p> <p>Ideas:</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>ls() -- same as now ls(0x2) -- get directories only ls(0x3) -- (maybe) get other kinds of files -- (for art tools and such, to build dialogs instead of -i / stdin / drag n drop) -- or ls() -- unchanged lsdir() -- new -- will also need `cd(path)` to go there and list carts, or `ls(path)`</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Thanks for considering this!</p> https://www.lexaloffle.com/bbs/?tid=46143 https://www.lexaloffle.com/bbs/?tid=46143 Wed, 12 Jan 2022 22:32:19 UTC Feature request: export cart label <p>Would be useful to have an export option (in the console and in the command-line interface) to get the label image as a PNG, to print labels for physical carts or for emulation frontend metadata for example. Could be 'export game.label.png', using the same resolution as GIFs.</p> https://www.lexaloffle.com/bbs/?tid=44603 https://www.lexaloffle.com/bbs/?tid=44603 Mon, 13 Sep 2021 00:37:12 UTC Feature: save P8 cart as PNG from command-line <p>To ease the workflow of developing with p8 file, then saving as PNG for sharing, it would be really useful to have a command-line switch to save as PNG (combined with the positional parameter that loads a cart), for example: pico8 game.p8 -save game.png</p> <p>This would behave like 'SAVE game.png' in the console, adding the .p8 string in the middle, but not prompting for overwrite confirmation (goal is headless/automatic conversion, like -export &mdash; of course errors are possible if the cart doesn&rsquo;t respect limits).</p> <p>Rationale: I find myself working with both P8 and PNG carts for the same game/project, using the P8 file as authoritative version (limits don&rsquo;t prevent saving + compatible with all text tools) and also saving as PNG to see what the label looks like and share it when desired. It is cumbersome to work with the P8, save, save as png, confirm overwrite, then have to remember to load the P8 to avoid that the next save saves PNG then have to overwrite the P8. I would prefer to consider the PNG form a compiled form that I don&rsquo;t edit, and avoid human mistakes by saving it using a command line or makefile.</p> <p>Another use case from Sam Hocevar on discord: he wanted to convert P8 to PNG to study the compression algo, and had to resort to export to JS, extract cart data, serialise it, save in blank cart, which is quite convoluted.</p> https://www.lexaloffle.com/bbs/?tid=38271 https://www.lexaloffle.com/bbs/?tid=38271 Wed, 03 Jun 2020 17:55:09 UTC Splore feature request: save cart locally <p>Hi! It would be convenient to have an option in the cart submenu to save a file from BSS to local carts, for systems that are not always connected.</p> <p>For the carts that only have numerical IDs or generated names, it would be great to have a new RENAME command in the console :)</p> https://www.lexaloffle.com/bbs/?tid=38182 https://www.lexaloffle.com/bbs/?tid=38182 Thu, 28 May 2020 23:25:28 UTC Editor tab title preview skips line if all-caps <p>In the code editor, add a new tab with the first line being a comment line containing only puny caps and spaces, then add a second comment line with regular text. Hover over the tab, the title preview shows the second comment instead of the first. Bug doesn&rsquo;t happen if the title mixes cases (&quot;--UI helpers&quot; is ok).</p> https://www.lexaloffle.com/bbs/?tid=38114 https://www.lexaloffle.com/bbs/?tid=38114 Mon, 25 May 2020 03:13:02 UTC Website should have one canonical domain <p>I wondered why I was not logged in when opening some links, but I was logged in in other tabs.<br /> Found out that the website answers to both lexaloffle.com and www.lexaloffe.com, but logged in status is not shared.</p> <p>Possible solutions:</p> <ul> <li>change cookies to be valid for both variants</li> <li>pick one variant as canonical and redirect transparently</li> </ul> <p>Thanks!</p> https://www.lexaloffle.com/bbs/?tid=37926 https://www.lexaloffle.com/bbs/?tid=37926 Wed, 13 May 2020 15:20:10 UTC Featured carts on top of carts category are not real links <p>Hello! On the Carts category page <a href="https://www.lexaloffle.com/bbs/?cat=7&amp;sub=2">https://www.lexaloffle.com/bbs/?cat=7&amp;sub=2</a> , the three featured carts at the top are not real links (a elements), but divs with a custom JavaScript handler. This does not work with all the tools that know about links: ctrl+click to open in a new tab, middle click, long press on mobile, bookmark link, contextual menu, search links in page, etc. Please consider changing this!</p> https://www.lexaloffle.com/bbs/?tid=36056 https://www.lexaloffle.com/bbs/?tid=36056 Fri, 29 Nov 2019 19:17:26 UTC