supercurses [Lexaloffle Blog Feed]https://www.lexaloffle.com/bbs/?uid=75425 Referencing tables before they are created <p>Hello, considering the following:</p> <p>Trying to remake Vampire Survivors and a fun project<br /> I have a character class<br /> Characters have effects that are applied to a target. In this example my target = player<br /> I have a character that is an instance of that class. Let's call him &quot;Antonio&quot;<br /> I have a &quot;run&quot;, Antonio is copied into run.player<br /> I set player to be run.player</p> <p>My problem is that I have to initiate the character class and Antonio before I create &quot;player&quot;. But player is not yet created so player referenced on the character class is nil.</p> <p>I hope this makes sense, I have a workaround but it feels clunky and I'm wondering if there are other solutions.</p> <p>Here is my code before the workaround:</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> character = {} character.__index = character function character:new(name) local o = setmetatable({}, character) o.name = name o.x = 0 o.y = 0 o.sp_scale = 1 o.w = 16 o.h = 16 o.effects = effects o.original_invincibility_frames = 10 o.invincibility_frames = 0 o.max_health = 100 o.health = 20 o.recovery = 0 o.armor = 0 o.move_speed = 1 o.might = 1 o.weapon_projectile_speed = 0 o.weapon_duration = 0 o.weapon_area = 0 o.weapon_cooldown = 0 o.weapon_projectiles_amount = 0 o.revival = 0 o.magnet = 0 o.luck = 0 o.growth = 0 o.greed = 0 o.curse = 0 o.reroll = 0 o.skip = 0 o.banish = 0 return o end function character:set_effects(effects) self.effects = effects end function character:apply_effects(level) local effects = self.effects for _, effect in pairs(effects) do if level % effect.level_increment == 0 and level &lt;= effect.max_level_increment then local target = effect.target if effect.mode == &quot;percent&quot; then target[effect.stat] += (target[effect.stat] or 0) * effect.value else target[effect.stat] = (target[effect.stat] or 0) + effect.value end end end end antonio = character:new(&quot;antonio&quot;) antonio.recovery = 0.5 antonio:set_effects( { { description=&quot;Gains 10% Might every 2 Levels&quot;, stat = &quot;might&quot;, value = 1, target = player, -- here is the problem, player doesn't exist level_increment = 2, max_level_increment = 10, mode = &quot;percent&quot; }, { description=&quot;Gains 0.5 Recovery every 1 level&quot;, stat = &quot;recovery&quot;, value = 0.5, target = player, level_increment = 1, max_level_increment = 5 } } ) function _init() t = 0 run = {} run.player = {} run.level = 1 add(run.player, deepcopy(antonio)) player = run.player[1] end function _update() if t % 60 == 0 then player.health += player.recovery end if btnp(4) then run.level += 1 player:apply_effects(run.level) end t += 1 end function _draw() local y = 0 cls(0) for entry in all(run.player) do for k, v in pairs(entry) do if type(v) == &quot;number&quot; then print(k..&quot;:&quot;..v, 0, y) y += 8 end end end local y = 0 print(&quot;Level: &quot;..run.level, 240, y) end function deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do copy[deepcopy(orig_key)] = deepcopy(orig_value) end setmetatable(copy, getmetatable(orig)) else -- for numbers, strings, booleans, etc copy = orig end return copy 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 is my code with the workaround, in short, once player is created I go and apply player as the target of the effects: player:update_effects_target(player)</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>character = {} character.__index = character function character:new(name) local o = setmetatable({}, character) o.name = name o.x = 0 o.y = 0 o.sp_scale = 1 o.w = 16 o.h = 16 o.effects = effects o.original_invincibility_frames = 10 o.invincibility_frames = 0 o.max_health = 100 o.health = 20 o.recovery = 0 o.armor = 0 o.move_speed = 1 o.might = 1 o.weapon_projectile_speed = 0 o.weapon_duration = 0 o.weapon_area = 0 o.weapon_cooldown = 0 o.weapon_projectiles_amount = 0 o.revival = 0 o.magnet = 0 o.luck = 0 o.growth = 0 o.greed = 0 o.curse = 0 o.reroll = 0 o.skip = 0 o.banish = 0 return o end function character:set_effects(effects) self.effects = effects end function character:update_effects_target(target) for _, effect in pairs(self.effects) do effect.target = target end end function character:apply_effects(level) local effects = self.effects for _, effect in pairs(effects) do if level % effect.level_increment == 0 and level &lt;= effect.max_level_increment then local target = effect.target if effect.mode == &quot;percent&quot; then target[effect.stat] += (target[effect.stat] or 0) * effect.value else target[effect.stat] = (target[effect.stat] or 0) + effect.value end end end end antonio = character:new(&quot;antonio&quot;) antonio.recovery = 0.5 antonio:set_effects( { { description=&quot;Gains 10% Might every 2 Levels&quot;, stat = &quot;might&quot;, value = 1, target = player, -- here is the problem, player doesn't exist level_increment = 2, max_level_increment = 10, mode = &quot;percent&quot; }, { description=&quot;Gains 0.5 Recovery every 1 level&quot;, stat = &quot;recovery&quot;, value = 0.5, target = player, level_increment = 1, max_level_increment = 5 } } ) function _init() t = 0 run = {} run.player = {} run.level = 1 add(run.player, deepcopy(antonio)) player = run.player[1] player:update_effects_target(player) end function _update() if t % 60 == 0 then player.health += player.recovery end if btnp(4) then run.level += 1 player:apply_effects(run.level) end t += 1 end function _draw() local y = 0 cls(0) for entry in all(run.player) do for k, v in pairs(entry) do if type(v) == &quot;number&quot; then print(k..&quot;:&quot;..v, 0, y) y += 8 end end end local y = 0 print(&quot;Level: &quot;..run.level, 240, y) end function deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do copy[deepcopy(orig_key)] = deepcopy(orig_value) end setmetatable(copy, getmetatable(orig)) else -- for numbers, strings, booleans, etc copy = orig end return copy end</pre></div></td> <td background=/gfx/code_bg1.png width=16><div style="width:16px;display:block"></div></td> </tr></table></div></div> https://www.lexaloffle.com/bbs/?tid=141922 https://www.lexaloffle.com/bbs/?tid=141922 Wed, 24 Apr 2024 10:32:02 UTC Grid based partitioning for collision detection <p>Hello,</p> <p>For fun, I'm building a Vampire Survivors style game. There will be a lot of mobs on screen, so I've built a grid partitioning system and each weapon only checks for collisions with mobs nearby.</p> <p>The grid size is 30, so that's a 16 x 9 grid. </p> <p>My question is this, currently, I'm initialising the grid on every frame and re-populating all the mob positions into their grids.</p> <p>Should I move to initialising just once and updating mob positions in the grid on every frame? I'm not sure whether that will actually be quicker because I will have to delete the mob from one grid position and add it to another.</p> <p>Also, that seems hard to implement :-)</p> <p>Thanks in advance</p> <p>Russ</p> <img style="margin-bottom:16px" border=0 src="/media/75425/SCR-20240417-pabq.png" alt="" /> https://www.lexaloffle.com/bbs/?tid=141783 https://www.lexaloffle.com/bbs/?tid=141783 Wed, 17 Apr 2024 15:45:15 UTC Knuckle Dice v1.3 <img style="margin-bottom:16px" border=0 src="/media/75425/matrixv1_1_1.png" alt="" /> <p> <table><tr><td> <a href="/bbs/?pid=126787#p"> <img src="/bbs/thumbs/pico8_rikazogoye-3.png" style="height:256px"></a> </td><td width=10></td><td valign=top> <a href="/bbs/?pid=126787#p"> Knuckle Dice v1.3</a><br><br> by <a href="/bbs/?uid=75425"> supercurses</a> <br><br><br> <a href="/bbs/?pid=126787#p"> [Click to Play]</a> </td></tr></table> </p> <h1>Knuckle Dice v1.3</h1> <p>Knuckle Dice is an attempt to recreate Knuckle Bones from Cult of the Lamb. This is my first programming project ever so there's no AI yet - it's two player only to begin with.</p> <p>In the future I will try to add:</p> <ul> <li>CPU AI (DONE)</li> <li>I want to experiment with perfect information. In other words, remove the randomness and tell the player exactly what the opponent is about to play.</li> </ul> <p>Controls</p> <ul> <li>z to start/restart</li> <li>x to play a dice</li> </ul> <p>Rules/Game Logic</p> <ul> <li>Maximum 3 dice in one column</li> <li>Playing a die in a column that matches dice in the opposing player's column removes all instances of that dice</li> <li>When nine dice are played by either player the game ends</li> </ul> <p>Scoring</p> <ul> <li>You receive points equivalent to the die played multiplied by the number of instances of that dice. (e.g a 5 played twice in one column will give you twenty points - 2*(5+5)</li> <li>The player with the most points wins</li> </ul> <p>v1.1 Updates</p> <ul> <li>Changed GFX to more of a 1bit style</li> </ul> <p>v1.3 Updates</p> <ul> <li>Now it's a single player game with some rudimentary AI for P2</li> </ul> https://www.lexaloffle.com/bbs/?tid=51916 https://www.lexaloffle.com/bbs/?tid=51916 Wed, 08 Mar 2023 16:14:07 UTC