slainte [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=38916 Using _𝘦𝘯𝘷 in PICO-8 <h3>Understanding ENVIRONMENTS</h3> <p>Inherited from native LUA, _𝘦𝘯𝘷 (NOTE: type it in PUNY FONT, won't work otherwise! For External editors, write it in CAPS _ENV so it transfers as PUNY FONT inside PICO-8) can be a tricky feature to understand and use (abuse?). There's been some talking around this subject and as I am actually using it heavily in my coding style (very OOP I'm afraid...) I thought I could share some knowledge around it.</p> <p>If we take the information directly from <a href="https://www.lua.org/manual/5.3/manual.html#2.2">LUA's manual</a> what we are told is the following:</p> <hr /> <p><em>As will be discussed in &sect;3.2 and &sect;3.3.3, any reference to a free name (that is, a name not bound to any declaration) var is syntactically translated to _ENV.var. Moreover, every chunk is compiled in the scope of an external local variable named _ENV (see &sect;3.3.2), so _ENV itself is never a free name in a chunk.</em></p> <p><em>Despite the existence of this external _ENV variable and the translation of free names, _ENV is a completely regular name. In particular, you can define new variables and parameters with that name. Each reference to a free name uses the _ENV that is visible at that point in the program, following the usual visibility rules of Lua (see &sect;3.5).</em></p> <p><em>Any table used as the value of _ENV is called an environment.</em></p> <hr /> <p>Cryptic right? Let's try to distil the information... </p> <p>Let's start with understanding what's a <strong>free name</strong>. Any declared identifier that does not correspond to a given scope, f.e. GLOBAL variable definitions, API defined symbols (identifiers, functions, etc) and so on, is considered a <strong>free name</strong> OK... so this starts to get us somewhere! Any time we are using a global scope variable name or an API function call, internally LUA's interpreter is actually converting that to _𝘦𝘯𝘷.identifier. These tables used as values for _𝘦𝘯𝘷 are usually called <strong>ENVIRONMENTS</strong>.</p> <p>Let's move into the next part: _𝘦𝘯𝘷 itself is just a local identifier in your current scope, and like any other identifier you can assign anything to it. In particular, you can overwrite the automatically created _𝘦𝘯𝘷 in your current scope, which will always be the GLOBAL ENVIRONMENT, and point it to any table, and from that point on, any <strong>free name</strong> will be looked for inside that table and not in the _𝘦𝘯𝘷 scope originally received . </p> <p>Everytime a scope is defined in the LUA execution context, the GLOBAL ENVIRONMENT (on isolated scopes, like function scopes) or the currently active environment (inside language scope constructs) is injected as a local external variable _𝘦𝘯𝘷. That means every function scope, any language scope construct (do ... end, if ... end, etc)</p> <p>Great! So that's all there is to know about _𝘦𝘯𝘷... but how can we use this to our benefit? Let's find out!</p> <h3>Using ENVIRONMENTS</h3> <p>The core and simplest use-case for <strong>ENVIRONMENTS</strong> is mimicking <strong>WITH</strong> language constructs. It's quite typical that you have a table in your game holding all the information of the player... it's position, health level, sprite index, and many others probably. There's almost for sure some place in your code that handles the initialization of the player and that probably looks something similar to this:</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>player={} player.x=10 player.y=20 player.lives=3 player.sp=1 -- many more here potentially...</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>Depending on how many times you need to access the player table you can actually consume a big number of tokens (1 per each access to player). When you have more than 3 (the general cost of redeclaring _𝘦𝘯𝘷) or 4 (the cost if you require a scope definition for it) you can benefit from not needing to repeat PLAYER for every access like this:</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>player={} do local _𝘦𝘯𝘷=player x=10 y=20 lives=3 sp=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>The use of the DO ... END block in there prevents that we override _𝘦𝘯𝘷 for all our code, and that this applies only to the lines we want it to apply.</p> <p>This technique is particularly useful if you use an OOP approach where you pass around SELF as a self-reference to table methods and will reduce drastically the need to repeatedly use SELF everywhere:</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>player={ x=10, y=20, lives=3, sp=1, dead=false, hit=function(self) local _𝘦𝘯𝘷=self if not dead then lives-=1 if (lives==0) dead=true sp=2 -- dead sprite end end } ?player.lives player:hit() ?player.lives</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>You can even reduce the need for the override this way (thank you <a href="https://www.lexaloffle.com/bbs/?uid=29645"> @thisismypassword</a> for the contribution):</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>player={ x=10, y=20, lives=3, sp=1, dead=false, hit=function(_𝘦𝘯𝘷) if not dead then lives-=1 if (lives==0) dead=true sp=2 -- dead sprite 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>In a sense, this is very similar to <strong>WITH</strong> language constructs in other programming languages like Object Oriented BASIC or PASCAL. The benefit: reduce token count and char count. But don't just jump blindly into using this, get to the end of this post and understand the associated drawbacks!</p> <h3>Drawbacks of using ENVIRONMENTS in PICO-8</h3> <p>The main drawback for using an overriden ENVIRONMENT is loosing access to the GLOBAL ENVIRONMENT once we replace _𝘦𝘯𝘷 in a particular scope. When that happens, we stop seeing global variables and all API and base PICO-8 definitions, so we won't be able to call any function, use glyph symbols or access global vars. Luckily, METATABLES can help us here taking advantage of <strong>__INDEX</strong> metamethod.</p> <p>METATABLES can be defined as a PROTOTYPE for other tables, and apart from defining elements to inherit in ohter tables, they can also define the BEHAVIOUR of these tables using METAMETHODS. Those are a quite advanced feature in LUA and I won't cover them in this post but for <strong>__INDEX</strong> that is going to be our solution for keeping our access to the global scope even if we have overriden our ENVIRONMENT (at a small performance cost...)</p> <p><strong>__INDEX</strong> METAMETHOD defines the behaviour of a table when we try to access an element that is not defined in it. Try this code to have a clear example of what it does:</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>d=4 mytable={ a=1, b=2, c=3, } setmetatable(mytable, { __index=function(tbl,key) stop(&quot;accessing non existent key &quot;..key..&quot;\nin table &quot;..tostr(tbl,true)) end }) ?mytable.a ?mytable.b ?mytable.c ?mytable.d</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p><strong>__INDEX</strong> can be defined as a function or as a TABLE that will be where the missing identifier will be searched for... and there's our solution, just redefine <strong>__INDEX</strong> as _𝘦𝘯𝘷 and our problem is solved:</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> d=4 mytable={ a=1, b=2, c=3, } setmetatable(mytable,{__index=_𝘦𝘯𝘷}) ?mytable.a ?mytable.b ?mytable.c ?mytable.d</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>If we apply this approach to our previous example we can do things like this:</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>player=setmetatable({ init=function(_𝘦𝘯𝘷) x=10 y=20 lives=3 sp=1 w=2 h=2 fliph=false flipv=false dead=false end, draw=function(_𝘦𝘯𝘷) cls() spr(sp,x,y,w,h,fliph,flipv) end, update=function(_𝘦𝘯𝘷) if btnp(⬅️) then if (x&gt;0) x-=1 fliph=true elseif btnp(➑️) then if (x&lt;128-8*w) x+=1 fliph=false end end, hit=function(_𝘦𝘯𝘷) if not dead then lives-=1 if (lives==0) dead=true sp=2 -- dead sprite end end },{__index=_𝘦𝘯𝘷})</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>That's a very basic OOP-like approach to have entities inside your games, that expose entity:update() and entity:draw() methods you can call in your game loop (like having a list of entities in a table and iterate it calling update() and draw() for each entity inside your _update() and _draw() functions).</p> <p>__INDEX will also come to the rescue when working inside functions to prevent losing global access... as functions themselves don't have metamethods you can &quot;trick&quot; things if you set _𝘦𝘯𝘷 to a table that has __INDEX set and leverage the lookup to it:</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>tbl=setmetatable({a=1},{__index=_𝘦𝘯𝘷}) b=2 function doit(_𝘦𝘯𝘷) ?&quot;tbl.a=&gt;&quot;..a ?&quot;global b=&gt;&quot;..b end doit(tbl)</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <p>There is another effect that loosing access to the GLOBAL ENVIRONMENT generates, and this one is not fixed by __INDEX. Any new <strong>free name</strong> we create will be created inside the active ENVIRONMENT, so we won't be able to create any new GLOBAL variable from within the scopes affected by the override. If you need to be able to access the global space, one easy option is have a global variable pointing to the GLOBAL ENVIRONMENT in your code. Natively, LUA has _G environment available everywhere, but this one is not present in PICO-8, so you will need to create your own.</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>-- used by __index access _g=_𝘦𝘯𝘷 mytable=setmetatable({ a=0,b=0,c=0, init=function(_𝘦𝘯𝘷) a,b,c=1,2,3 newvar=25 -- this is created in mytable _g[&quot;initialized&quot;]=true -- this is created in GLOBAL ENVIRONMENT end },{__index=_𝘦𝘯𝘷}) mytable:init() function _draw() -- outside table scopes (no __index access) local _g,_𝘦𝘯𝘷=_𝘦𝘯𝘷,mytable if _g.initialized and _g.btnp()&gt;0 then a+=1 b+=1 c+=1 end cls() ?tostr(initialized)..&quot;:&quot;..mytable.newvar..&quot;, &quot;..mytable.a..&quot;, &quot;..mytable.b..&quot;, &quot;..mytable.c end </pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> <h3>Other uses</h3> <p>There's many more uses you can find for using ENVIRONMENTS... shadowing and extending the GLOBAL ENVIRONMENT, some Strategy Pattern approach (f.e. having several tables with alternate strategies extending the global scope and switching between them...). Don't be afraid to experiment! The basics are all here, the limits are yours to find!</p> https://www.lexaloffle.com/bbs/?tid=49047 https://www.lexaloffle.com/bbs/?tid=49047 Thu, 25 Aug 2022 20:12:35 UTC Aztec - LOWREZJAM 2022 <p>I leave here in the forums a copy of my entry to lowrezjam 2022, Aztec. Code ended up being really messy and there's a lot of things to fix/improve post-jam, but I thought it would be a nice addition to the BBS. It's multicart (has a loader companion) as I needed a bit of extra space in the main cartridge to fit everything.</p> <p> <table><tr><td> <a href="/bbs/?pid=115799#p"> <img src="/bbs/thumbs/pico8_aztec-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=115799#p"> aztec</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=115799#p"> [Click to Play]</a> </td></tr></table> </p> <p>Tonatiuh, the Sun God is angry! The High Priest Tonauac has decided to invoke the Tanatiuh Cualo, the ritual that will eat the Sun God and placate his wrath, but to achieve it he needs the Jewel skulls to be placed in their right places in Tenochtitlan's Templo Mayor.</p> <p>While he prepares for the ritual, he sends you, the Aztec prince Guatemoc, into the temple to search for the sacred skulls and place them in their pedestals. Beware the traps and misteries that protect the sacred grounds of the Temple!</p> <p>Code, SFX &amp; Art by SlainteES<br /> Music &amp; SFx by: VavMusicMagic</p> <p>Find this game on itch: <a href="https://slaintees.itch.io/aztec">https://slaintees.itch.io/aztec</a></p> <p>Issues and bugs to fix:</p> <ul> <li>Jumping whlie climbing continuously reattach you to the ladder if pressing a directional button</li> <li>Some issues with &quot;top of a ladder&quot; state detection can cause you to drop from the top of a ladder</li> <li>Some performance issues randomly due to suboptimal collision detection</li> <li>If dying mid-air ocassionally the game does not make you land before actually dying (rare to happen)</li> <li>Minor sync issues detecting activable objects (particularly Obsidian mirrors, that can be activated a bit earlier than they should)</li> <li>Some more (yes... those again...) ladder issues can end up pushing you inside walls... 1 bugreport so far, but a nasty one... (Really... who decided ladders are cool?)</li> </ul> <p>Fixed Issues:</p> <ul> <li>Reset DX velocity to 0 before respawn, you could &quot;move&quot; while respawning because it was not set to 0</li> </ul> https://www.lexaloffle.com/bbs/?tid=48907 https://www.lexaloffle.com/bbs/?tid=48907 Mon, 15 Aug 2022 17:14:53 UTC XOR <p> <table><tr><td> <a href="/bbs/?pid=109635#p"> <img src="/bbs/thumbs/pico8_xor-13.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=109635#p"> xor</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=109635#p"> [Click to Play]</a> </td></tr></table> </p> <h1>XOR Must Be Revealed</h1> <p>His many faces are scattered through 15 levels. Acquiring all the faces on any level will enhance your knowledge of Xor.</p> <p>Beware Xor controls his world and doesn't give up his personality easily</p> <p>Rediscover this classic from 1987, originally released by Astral Software under Logotron. This is still a very early WIP (first playable alpha actually), a few levels can be played but still missing levels, sound and probably some graphical polishing. The game will provide the original 15 levels and several extra ones once complete and ideally (if sticking to plan...) a level editor so you can create your own levels and puzzles.</p> <p>Take control of Magus and Questor and beat all the levels in Xor's world by picking all his many faces and exiting through the door. Switch between Magus and Questor with X and see a level map with Z. You can quit a level if you get stuck from the map screen.</p> <p>Experiment and unravel the strange rules that govern Xor's Domain!</p> <h2>Status</h2> <p><strong>This is an early Alpha</strong> Any feedback appreciated!</p> <ul> <li>15 levels implemented</li> <li>Forcefields, Fish, Chicken, H-Bombs, V-Bombs, Fat Dolls, Switches and BMUS implemented, though levels with BMUS have not been tested that much... expect failures</li> <li>ingame press πŸ…ΎοΈ to see the map</li> <li>Switch shields with ❎</li> <li>Quit level (f.e. when unsolvable...) holding ❎ in the map view</li> <li>Some basic SFX</li> </ul> <h2>Bugs</h2> <ul> <li>Teleporting does not center correctly on shield after the move : FIXED (for real this time I hope...)</li> <li>Teleports not correctly reset between levels : FIXED</li> <li>Explossives missbehaviour, they should not exploed when used to detonate others : FIXED</li> <li>Moving explossives missbehaviour, failed to explode afer las update : FIXED</li> </ul> <h2>Pending</h2> <ul> <li>Big rewrite to save compressed space... hard limit there... got it down to 95%</li> <li>Full SFX and Music</li> <li>Level access logic (10-&gt;11, 12-&gt;13, 14-&gt;15)</li> <li>End level letters for the Decoder</li> <li>Password unblock for free level access</li> <li>Extra levels (extra levels pack and Prospector in the mines of Xor extra levels) probably requires multicart</li> <li>Level Editor</li> <li>CARTDATA handling with best scores per level and controlling level access</li> <li>Probably splitting into 2 carts if including editor...</li> <li>A way to share new levels (probably stored in spr/map area on the second cart with serial)</li> </ul> https://www.lexaloffle.com/bbs/?tid=47231 https://www.lexaloffle.com/bbs/?tid=47231 Sun, 03 Apr 2022 20:04:02 UTC LZW Compress/Decompress <p>I've been doing some experiments with LZW compress/decompress lately to retake some work on my Isometric engine so I could manage bigger tilesets (compress on string or memory, spr bank switching, etc). Reasonably happy on how this is working... it's a straight forward LZW with 256 dictionary size and 16 root symbols (a.k.a. 16 colour indexes). Works quite well for moderately big images but fares quite badly the moment it runs out of dictionary entries as dictionary is not optimized but generated dynamically both in compression and decompression and it potentially wastes entries with low re-usability or even foldable into later entries (f.e. long single colour runs that would do better on RLE)</p> <p>Unsure if this will help anyone as there's already other compression solutions through the bbs, but here it goes in case you feel like it can be useful.</p> <p>See the code for info on how to use it, the compression generates a small header (2 bytes for width/height) and the compressed string. The decompression can use pset/sset/mset or an internal pxset function that can write screen-format blocks at arbitrary memory addresses (lower performance than native funcs if you are writing to spr,map or screen though).</p> <p>The cart shows 3 32x32 sprites (512b) displayed with SPR and compressed-&gt;decompressed with LZW equivs along compression ratios info.</p> <p> <table><tr><td> <a href="/bbs/?pid=96541#p"> <img src="/bbs/thumbs/pico8_lzw_experiment-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=96541#p"> lzw_experiment</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=96541#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=44398 https://www.lexaloffle.com/bbs/?tid=44398 Fri, 27 Aug 2021 20:59:58 UTC Golden Star Sheriff [LOWREZJAM 2021] <p>This is my entry for LOWREZJAM 2021, still incomplete and it will be mostly a POC of a complete game.</p> <p> <table><tr><td> <a href="/bbs/?pid=95998#p"> <img src="/bbs/thumbs/pico8_golden_star_jam-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=95998#p"> golden_star_jam</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=95998#p"> [Click to Play]</a> </td></tr></table> </p> <p>The game is a tribute to the Natsume's SNES classic &quot;Wild Guns&quot; and is inspired by the gameplay in that game.</p> <p>In &quot;Golden Star Sheriff&quot; as the new sheriff in Dodge City your duty is to chase and get rid of a big band of thieves that have taken over the city and it's sorrounding areas.</p> <p>Current state of the game (JAM Version) is going to be a tweaked version of the full game as there's been not enough time to have multiple levels in place, so it will take place only in the first level, Dodge City streets, chasing for &quot;Perro Loco&quot;, the lowest ranking bandit chief in the band. The game is tweaked so you can play several times the phase with increased odds rather than actually advancing phases... </p> <p>Gameplay:</p> <p>Move with cursor keys, shoot with X and roll with Z or C while moving left or right. A gamepad is highly recommended for this game.</p> <p>While pressing the fire button you will enter &quot;free aim&quot; mode and will hold your position while sending out a barriage of bullets! </p> <p>When you find yourself in a tight spot, roll out of danger... bullets won't be able to catch you while rolling! But... be very cautions as rolling is a reflex action and you cannot control where you will be landing!</p> <p>Note: The code just grew dirtier and messier the closer to the submission date... plenty of junk both in code and the cart (sprites, sound and such)... also it is my usual convoluted extreme OOP approach, you have been warned ;)</p> <p>CHANGELOG:</p> <p>Moved Health icon from a red cross to a heart, complying to Red Cross mandates<br /> Adjusted targetting speed, player bullet speed and power-ups bonuses to balance things up a bit<br /> Implemented rolling coyote time to facilitate rolling/dodge activation</p> <p>Fixed a bug that was not updating Z for the bandits and they ended up incorrectly sorted at drawing time, also changed the health power-up icon to comply to Red Cross restrictions prohibiting red crosses depiction for this kind of stuff, not it is a nice heart</p> https://www.lexaloffle.com/bbs/?tid=44230 https://www.lexaloffle.com/bbs/?tid=44230 Sat, 14 Aug 2021 15:36:13 UTC Crazy Scribe's Adventure WIP <p>So I decided to go for a platformer... my first in PICO8. Building it on top of my OOP game model (which maybe was not that good an idea...) so it is a code nightmare. Already at version 4 with a few discarded prototypes in the middle and for sure require some cleanup and refactoring... but kind of works and it would be great to start getting feedback.<br /> Torches are an application of an old experiment, it's been a while I wanted to include them in some project (and for sure require fine tunning, as they are map cannot scroll as they are poke'd in place with additive blitting)</p> <p>Still a very early WIP, no screen boundary control so if you fall off an edge you will fall forever :)</p> <p>I am parking this for a while but I will come back to it very soon, I relly like where this is going</p> <p> <table><tr><td> <a href="/bbs/?pid=95329#p"> <img src="/bbs/thumbs/pico8_crazy_scribes_adventure-5.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=95329#p"> crazy_scribes_adventure</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=95329#p"> [Click to Play]</a> </td></tr></table> </p> <p>move with ⬅️/➑️ ⬆️/⬇️<br /> hold ⬇️ to crawl<br /> jump with ❎<br /> drop from a platform with ❎ when crawling<br /> activate action menu (currently Psalm selection) with πŸ…ΎοΈ (just the visuals, non-functional)</p> <p>Last changes:</p> <ul> <li>Added Coyote time (maybe it's a bit too gracious...)</li> <li>reduced the scribe's speed to make it more reasonable (now it is like he lives at 30FPS on 60FPS world)</li> <li>var-heigt jumps</li> <li>vertical speed adjusted when hitting the ceiling</li> <li>debug cannot be toggled in anymore (still there, but key was repurposed)</li> <li>added bats (not yet fully operational, they don't &quot;attack&quot;</li> </ul> https://www.lexaloffle.com/bbs/?tid=43960 https://www.lexaloffle.com/bbs/?tid=43960 Tue, 27 Jul 2021 07:09:40 UTC Fantasy Tactics - LOWREZJAM version <p> <table><tr><td> <a href="/bbs/?pid=80838#p"> <img src="/bbs/thumbs/pico8_fantasytactics-10.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=80838#p"> fantasytactics</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=80838#p"> [Click to Play]</a> </td></tr></table> </p> <img style="margin-bottom:16px" border=0 src="/media/38916/FantasyTacticsLogo.png" alt="" /> <p>So LOWREZJAM 2020 comes to an end... I finally submitted a playable project but with a lot of unfinished features. For a start there is no AI, In the remaining time I would not have been able to add a proper &quot;smart&quot; AI so I prefered to leave the game as 2p game only (or for those wanting to challenge themselves balttle yourself!). Sound is totally missing... I will be welcoming sfx and track contributions... that area is not my best. You can check it also in it's <a href="https://slaintees.itch.io/fantasy-tactics">itch.io page</a></p> <h2>Future plans</h2> <p>At this resolution (mode 3, 64x64) and with the constraints in time for the JAM I &quot;abandoned&quot; that cart and started focusing on rewriting things on a 128x128 more organized cart (keeping all the good things in this one) so expect to keep hearing from Fantasy Tactics HD ;)</p> <h2>Game mechanics:</h2> <p>This is a simplified &quot;tactics&quot; game (Final Fantasy Tactics, Tactics Ogre and so many more...). There's two opposing sides, <strong>The Kingdom</strong> and <strong>The Undead</strong> and the objective is wipe out all the opposing forces. Every turn a unit can <strong>MOVE</strong> and perform an <strong>ACTION</strong>. </p> <h3>Moving</h3> <p>Activate a unit with ❎ and it's move area will be displayed in <strong>RED</strong>. That area is calculated based on the <strong>MOVE</strong> trait of the unit but considering units cannot go trhough other units, rocks or trees, that you cannot end your move in water (but you can jump across 1 tile of water) and that you cannot jump up more than a height difference of 2. Press ❎ again to select where you want to move or πŸ…ΎοΈ to cancel the action and release the unit.<br /> Press ❎ on an empty tile to get the <strong>TURN MENU</strong> that helps you find units that have not yet moved and allows also to end the turn inmediately</p> <h3>Actions</h3> <p>After moving, the <strong>ACTION MENU</strong> will show up with the available actions. After selecting ATTACK or to cast a <strong>SPELL</strong> a <strong>TARGETTING AREA</strong> will be displayed in <strong>GREEN</strong>. Any potential target in the area is tracked and you can iterate through them with the cursor keys to pick the target you want. If the unit is carrying <strong>POTIONS</strong> and it has lost some <strong>HIT POINTS</strong> it can drink one of them to restore up to 3HP. <strong>SUPPORT</strong> spells automatically succeed and apply to the targetted unit. You can cancel your orders with πŸ…ΎοΈ.</p> <h3>Combat</h3> <p>ATTACK and OFFENSIVE spells initiate a combat roll. Combat is <strong>DICE</strong> based. The attacking and the defending units roll a number of dice and depending on the results the combat is resolved.<br /> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_16.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_16"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_16.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_16"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_16" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> </p> <ul> <li>BASIC ATTACK: The roll is <strong>ATTACK</strong> vs <strong>DEFENSE</strong> traits. <strong>HIT</strong> symbol is <strong>SWORD</strong>, <strong>DEF</strong> symbol is <strong>SHIELD</strong></li> <li>SPELL ATTACK: The roll is &quot;SPELL LEVEL&quot; vs <strong>DEFENSE</strong> trait. <strong>HIT</strong> symbol depends on the spell, <strong>DEF</strong> symbol is <strong>SHIELD</strong></li> </ul> <p>The combat result is the defending unit looses as many <strong>HIT POINTS</strong> as the count of <strong>HIT</strong> minus <strong>DEF</strong> symbols</p> <h2>The Units</h2> <h3>The Kingdom</h3> <ul> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_5.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_5"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_5.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_5"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_5" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Archers: Fast moving, attack at a distance, carry a potion</li> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_1.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_1"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_1.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_1"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_1" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Halberdiers: Sturdy and with a long reach, carry a potion</li> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_2.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_2"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_2.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_2"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_2" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Axemen: Strong attack, carry a potion</li> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_11.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_11"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_11.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_11"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_11" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Priests: Weak attack, SUPPORT spell <strong>HEAL</strong> (+4HP)</li> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_4.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_4"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_4.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_4"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_4" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Wizards: Weak attack and defense, OFFENSIVE spell <strong>FIREBALL</strong> (LV 4, HIT symbol <strong>FIREBALL</strong>)</li> </ul> <h3>The Undead</h3> <ul> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_6.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_6"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_6.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_6"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_6" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Lancers: Avg attack, low defense, long reach</li> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_7.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_7"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_7.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_7"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_7" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Swordmen: Avg attack and defense</li> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_8.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_8"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_8.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_8"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_8" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Reapers: Strong attack, low defense</li> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_9.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_9"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_9.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_9"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_9" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Necromancer: Low attack and defense, SUPPORT spell <strong>MEND</strong> (+4HP)</li> <li> <table><tr><td width=0> <img src="https://www.lexaloffle.com/bbs/gfxc/38916_10.png" width=0 height=0> </td> <td valign=bottom> <a style="cursor:pointer;font-size:8pt" onclick=' var el = document.getElementById("gfxcode_38916_10"); if (el.style.display == "none") el.style.display = ""; else el.style.display = "none"; microAjax("https://www.lexaloffle.com/bbs/gfxc/38916_10.txt", function (retdata){ var el = document.getElementById("gfxcode_38916_10"); el.innerHTML = retdata; el.focus(); el.select(); } ); '> [0x0]</a> </td></tr> <tr><td colspan=2> <textarea rows=3 class=lexinput id="gfxcode_38916_10" style="width:640px;background-color:#fed;display:none;overflow:hidden; font-size:6pt;"></textarea> </td> </tr> </table> Lych: Sturdy wraith with strong attack and defense, OFFENSIVE spell <strong>MIASMA</strong> (LV 4, HIT symbol <strong>SKULL</strong>)</li> </ul> https://www.lexaloffle.com/bbs/?tid=39240 https://www.lexaloffle.com/bbs/?tid=39240 Sun, 16 Aug 2020 11:17:37 UTC Fantasy Tactics <p>I am working on a project for <a href="https://itch.io/jam/lowrezjam-2020">URL LOWREZJAM 2020</a> and I think it is time to present it here to get some comments maybe. </p> <p>The cart is quite far from being playable but as there's been some expectation around it I've dediced to keep the wip cart here so ppl can comment and try it. Don't expect too much out of it, still very early</p> <p><strong> CART UPDATED </strong><br /> Updated with a bugfix... using potions broke unit release</p> <p> <table><tr><td> <a href="/bbs/?pid=80443#p"> <img src="/bbs/thumbs/pico8_fantasytactics-8.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=80443#p"> fantasytactics</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=80443#p"> [Click to Play]</a> </td></tr></table> </p> <p>It's going to be a &quot;tactics&quot; like game (tactics ogre, final fantasy tactics...). Still plenty of work to do and not sure if I will be able to put everything up for the Jam but for sure I am gonna keep working on this to a point it becomes a playable game. For now working on 2 carts... the game itself and the editor and probably I will release the editor/isometric renderer on it's own cart in case someone wants to experiment with it once it's kind of &quot;complete&quot;</p> <p>Project is in MODE 3 as the jam is 64x64 and I am using some odd sizes around (my general sprite/object box is 10x16) even though I am adding full support to custom sprite sizes for the renderer itself.</p> <p><img style="margin-bottom:16px" border=0 src="/media/38916/fantasy_tactics_001.png" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/38916/fantasy_tactics_editor_3.gif" alt="" /></p> <img style="margin-bottom:16px" border=0 src="/media/38916/fantasy_tactics_editor_4.gif" alt="" /> <p>At the current version it moves 20x20 tiles at 85-90% cpu at 60FPS but I think I can bring that down a bit... There's a few optimizations like truncate tile rendering when outside the clipping boundaries (some hidden blitting is already in place but need to push that a bit further)</p> <p>Some images on how it has evolved to the current state:</p> <p><img style="margin-bottom:16px" border=0 src="/media/38916/lowrezjam_0.gif" alt="" /> <img style="margin-bottom:16px" border=0 src="/media/38916/lowrezjam_6.gif" alt="" /></p> <img style="margin-bottom:16px" border=0 src="/media/38916/fantasy_tactics_editor_0.gif" alt="" /> <p>Hope you like the idea, comments appreciated.</p> https://www.lexaloffle.com/bbs/?tid=39134 https://www.lexaloffle.com/bbs/?tid=39134 Fri, 07 Aug 2020 07:29:58 UTC Uploaded cart gives out syntax issues <p>I've tried to upload several times a new version for a cart but seems something breaks that cart in particular... everything runs fine locally (windows machine) but the uploade version gives a syntax error in an odd place (inside one px9 generated string)</p> <p>I saved the cart a few times but results are the same... any idea on the reason and a potential fix?</p> <p>cart is <table><tr><td> <a href="/bbs/?pid=80075#p"> <img src="/bbs/thumbs/pico8_deflektor-17.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=80075#p"> deflektor</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=80075#p"> [Click to Play]</a> </td></tr></table> (and a few of the previous ones... 14+) In terms of changes against version 13 there's a few extra lines and some extra bin data in the map area. Not htting any of the limits (compressed at 98%,7253 tokens, 48153 chars)</p> https://www.lexaloffle.com/bbs/?tid=39012 https://www.lexaloffle.com/bbs/?tid=39012 Wed, 29 Jul 2020 07:26:25 UTC OOP Mouse snippet <p>Probably everyone has one of these... sharing in case you don't and need a quick wrapper around the mouse support.<br /> The library implements an OOP like MOUSE object that supports 2 buttons and provides the following methods:</p> <ul> <li>enable() : Enables mouse suport</li> <li>disable() : Disables mouse support </li> <li>pressed(&lt;num&gt;) : true/false if button number &lt;num&gt; is pressed in current frame</li> <li>clicked(&lt;num&gt;) : true/false if button number &lt;num&gt; is pressed in current frame but was not in the previous</li> <li>released(&lt;num&gt;) : true/false if button number &lt;num&gt; is not pressed but was in the previous frame</li> <li>inside(minx,miny,maxx,maxy) : true/false if mouse is inside the defined rect boundaries</li> </ul> <p>Would be quite easy to extend, mouse cursor can be set to any spritesheet index and would be easy to handle animated cursors, bigger cursors and such...</p> <p>The demo cart shows how it behaves... pressing buttons changes background color, clicking and releasing draw some points on the screen (in green hues for btn 1, blue hues for btn 2.. brighter for click, darker for release)</p> <p> <table><tr><td> <a href="/bbs/?pid=79605#p"> <img src="/bbs/thumbs/pico8_mousedemo-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=79605#p"> mousedemo</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=79605#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=38902 https://www.lexaloffle.com/bbs/?tid=38902 Sun, 19 Jul 2020 14:16:24 UTC Not a bug I guess but very annoying <p>Took me a while to debug and identify why this was happening...</p> <p>I was taking advantage of RESET to clear clipping and palette and as a side-effect RND() started to misbehave returning always the exact same number. I guess that RESET also sets a fixed srand seed and that's why the pseudo-randoms go stale... Probably worth documenting that RESET also does that or if this was unintentional fix it...</p> https://www.lexaloffle.com/bbs/?tid=38833 https://www.lexaloffle.com/bbs/?tid=38833 Wed, 15 Jul 2020 18:58:46 UTC Particle Experiments <p>Will post here my experiments with particle effects...</p> <h2>Experiment 1: Fireworks... basic explosions</h2> <p>version 1: very basic approach<br /> <table><tr><td> <a href="/bbs/?pid=67561#p"> <img src="/bbs/thumbs/pico8_fireworkstest-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=67561#p"> fireworkstest</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=67561#p"> [Click to Play]</a> </td></tr></table> </p> <p>version 2: added gravity pull and callback update/draw for particles to operate multiple particle types (f.e. rocket and spark in the test)<br /> <table><tr><td> <a href="/bbs/?pid=67630#p"> <img src="/bbs/thumbs/pico8_fireworkstest-3.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=67630#p"> fireworkstest</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=67630#p"> [Click to Play]</a> </td></tr></table> </p> <h2>Experiment 2: Additive blit particle fire</h2> <p>version 1:<br /> <table><tr><td> <a href="/bbs/?pid=67630#p"> <img src="/bbs/thumbs/pico8_particlefiretest-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=67630#p"> particlefiretest</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=67630#p"> [Click to Play]</a> </td></tr></table> </p> <p>version 2: Supporting sprite-based blendop palettes (for now only partial additive palette included), next goal blit optimization<br /> <table><tr><td> <a href="/bbs/?pid=67630#p"> <img src="/bbs/thumbs/pico8_particlefiretest-1.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=67630#p"> particlefiretest</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=67630#p"> [Click to Play]</a> </td></tr></table> </p> <p>version 3: PEEK/POKE BLIT without great results... per-pixel blendops still kill it, updated color and added some toying controls<br /> <table><tr><td> <a href="/bbs/?pid=67630#p"> <img src="/bbs/thumbs/pico8_particlefiretest-2.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=67630#p"> particlefiretest</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=67630#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=35337 https://www.lexaloffle.com/bbs/?tid=35337 Fri, 13 Sep 2019 19:17:33 UTC led7segment <p>While starting work on my little deflektor project I decided to have classic 7 segment led style numbers, my first iteration (the one currently in the game...) is based on sprites but I wanted something a bit more versatile. This is a basic line drawing small library to handle 7 segment led like any digit length display. It should be fairly easy to define a text set and draw 7 segment text desplays (just need a table with the segment mapping for every letter and put up a wrapping function that receives a text and not a number)</p> <p>It supports background displaying of segments (&quot;off&quot; segments), color configuration and segment width configuration. The cart includes the library and a very basic demo on what it can do</p> <p>I might be working on reducing token size a bit (library itself is around 300 tokens) and I think there's some salvageable space there, but don't count on it for now</p> <p>Hope it helps someone out needing a 7 segment style display</p> <p> <table><tr><td> <a href="/bbs/?pid=66679#p"> <img src="/bbs/thumbs/pico8_led7segment-0.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=66679#p"> led7segment</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=66679#p"> [Click to Play]</a> </td></tr></table> </p> https://www.lexaloffle.com/bbs/?tid=35075 https://www.lexaloffle.com/bbs/?tid=35075 Wed, 14 Aug 2019 18:49:27 UTC Deflektor v0.5.5 <p>I've invested some time working on a demake for one of my favourite games from the 8-bit era, Deflektor (by Costa Panayi). Your goal is to guide a laser to the receiver on each of the levels, access to it is blocked until you destroy all pods on the level. Laser overloads when it hits mines or if the emitter gets feedback.</p> <p> <table><tr><td> <a href="/bbs/?pid=66564#p"> <img src="/bbs/thumbs/pico8_deflektor-18.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=66564#p"> deflektor</a><br><br> by <a href="/bbs/?uid=38916"> slainte</a> <br><br><br> <a href="/bbs/?pid=66564#p"> [Click to Play]</a> </td></tr></table> </p> <p>HOW TO PLAY (you can go through this tutorial in the game itself)</p> <img style="margin-bottom:16px" border=0 src="/media/38916/deflektor_2.gif" alt="" /> <p>CHANGELOG V0.5.5</p> <ul> <li>1 MORE LEVEL (now totalling 8)</li> </ul> <p>CHANGELOG V0.5.4</p> <ul> <li>1 MORE LEVELS (now totalling 7)</li> </ul> <p>CHANGELOG V0.5.3</p> <ul> <li>2 MORE LEVELS (now totalling 6)</li> <li>ADDED safety pre-check so levels don't start on full-reflection or overload status</li> </ul> <p>CHANGELOG V0.5.2</p> <ul> <li>FIXED tutorial can be run multiple times</li> </ul> <p>CHANGELOG V0.5.1</p> <ul> <li>FIXED bug duplicating player cursor entity...</li> <li>FIXEX tutorial scrambled if you play before running it</li> </ul> <p>CHANGELOG V0.5</p> <ul> <li>Massive rewrite (almost 80% of it is new...)</li> <li>ADDED a few more levels</li> <li>REMOVED editor mode... it is now it's own cart... was too big</li> <li>ADDED Tutorial, Intro screen, proper game over and End Game sequence</li> <li>FIXED a few nasty reflection bugs for the laser beam</li> </ul> <p>CHANGELOG V0.3.5<br /> <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <ul> <li>FIXED bug with negative angle reflections not causing overload</li> <li>ADDED some more basic FX</li> <li>EDITOR MODE early version (reqs. mouse)</li> <li>ADDED laser loading phase at start level/new live</li> <li>ADDED end level scoring</li> <li>WIP bgmusic (in the cart but not playing, unsure if it will stay)<br /> </div></div></div></li> </ul> <p>CHNAGELOG V0.3.1<br /> <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <ul> <li>FIXED bug in map loading that made optical fiber to crash (main reason to re-release)</li> <li>ADDED some basic SFX</li> <li>FIXED optical fiber pair coloring</li> <li>some minor token salvaging and code clean-up<br /> </div></div></div></li> </ul> <p>CHANGELOG V0.3<br /> <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <ul> <li>FIXED extra greediness in beam capture at mirror centers causing odd reflexions</li> <li>FIXED color error on initial rise for the overload meter</li> <li>MASSIVE spr sorting to allow for a reasonable leveldata format</li> <li>Level is loaded from data (level info will live in 0x1000 to 0x1FFF unused shared map/spr space)</li> <li>Crude leveldata persister as a prototype for leveleditor mode (unsure if editor will be a separate cart)<br /> </div></div></div></li> </ul> <p>CHANGELOG V0.2<br /> <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <ul> <li>Optical fiber interaction</li> <li>Laser grid scatter interaction</li> <li>Level can be completed</li> <li>Interaction with the receiver (connected status to end level)</li> <li>Removed displaying laser point debugging</li> <li>FIXED metal wall reflexion failing for some situations<br /> </div></div></div></li> </ul> <p>CHANGELOG V0.1<br /> <div><div><input type="button" value=" Show " onClick="if (this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display != '') { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = ''; this.innerText = ''; this.value = ' Hide '; } else { this.parentNode.parentNode.getElementsByTagName('div')[1].getElementsByTagName('div')[0].style.display = 'none'; this.innerText = ''; this.value = ' Show '; }"></div><div><div style="display: none;"></p> <ul> <li>Basic intro page</li> <li>Beam generation and reflection</li> <li>Player movement</li> <li>Mirror interaction and auto-rotation</li> <li>Beam interaction with mirrors, walls, mines and pods</li> <li>Full HUD control</li> <li>Crude live / energy / overload management</li> <li>Scoring</li> <li>Hardcoded level mapping<br /> </div></div></div></li> </ul> <p>PENDING</p> <ul> <li>MUSIC: title music from the original and maybe a bg loop while playing</li> <li>SOUNDS: laser connection sound</li> <li>VISUALS &amp; GAMEPLAY: <ul> <li>live lost sequence</li> <li>level transition</li> <li>extra detail in end game sequence</li> <li>gremlins from the original game... unsure if I will be adding those</li> <li>a few more levels... the plan is get around 20-30 levels in place</li> </ul></li> <li>CODING: even if I refactored a lot, there's still quite some junk... could be I do some more</li> </ul> https://www.lexaloffle.com/bbs/?tid=35031 https://www.lexaloffle.com/bbs/?tid=35031 Sun, 11 Aug 2019 19:31:18 UTC