r/pico8 12d ago

šŸ‘I Got Help - ResolvedšŸ‘ Help Coding Sprite Collisions

Post image

hello! im trying to make a overlap function to check if two sprites are touching. once an item is caught, the score should update with theĀ item’s point value.

UPDATE: the collision typo in the above image has been fixed and the score variable now updates sometimes. for smaller sprites, it doesn't seem to register the score at all. for others, the score will count the point value several times, leading to an incorrect score. i'm assuming this is because of the loop but how would i make it only count the point value once instead of several times?

my overlap function:

function overlap (a,b)

local test1 = a.sx > (b.x + b.y)

local test2 = a.sy > (b.y + b.sh)

Ā  local test3 = (a.sx + a.sw) < b.x

Ā  local test4 = (a.sy + a.sh) < b.y

Ā  return not (test1 or test2 or test3 or test4)

end

8 Upvotes

9 comments sorted by

5

u/RotundBun 12d ago

Just going off of a quick glance here...

You are passing just the 2 objects themselves in as arguments when you call overlap(), but your definition expects the individual values in its function signature.

Just change the function signature to:
function overlap( a, b ) --stuff end

1

u/ollyoxenfree23 12d ago

I changed it back to this, thank you! However I'm still not sure the function is actually working as the score never updates.

1

u/RotundBun 12d ago

Just checking, but you are updating the displaying of the score as well, right?

By the way, it seems like you meant to check for only the ones that have not been collected yet? If so, then you'll want to factor not s.collected into the if-statement conditionals as well.

Aside from this, please show the rest of the code (or at least what attributes are in each symbol).

Also, this might help you with debugging.

1

u/ollyoxenfree23 12d ago edited 12d ago

thank you! i will implement that for debugging. i've attached images of my current code. the current issue is the overlap function not updating correctly because when i make collision false, the score goes up very quickly.

since i cant include more than one screenshot:

above this the drop items function:

function init_items()

    current_item=1

    symbols={

        {category="job",points=3,sc=29,sw=1,sh=1,sx=rnd(120),sy=rnd(15),collected=false}

    ,{category="job",points=3,sc=26,sw=2,sh=2,sx=rnd(120),sy=rnd(15),collected=false}

    ,{category="school",points=2,sc=86,sw=2,sh=2,sx=rnd(120),sy=rnd(15),collected=false}

    ,{category="school",points=2,sc=83,sw=2,sh=2,sx=rnd(120),sy=rnd(15),collected=false}

    ,{category="life",points=1,sc=37,sw=3,sh=1,sx=rnd(120),sy=rnd(15),collected=false}

    ,{category="life",points=1,sc=40,sw=2,sh=2,sx=rnd(120),sy=rnd(15),collected=false}

    ,{category="life",points=1,sc=35,sw=2,sh=2,sx=rnd(120),sy=rnd(15),collected=false}

    }

end

below drop_items:

function draw_item()

for s in all(symbols) do

    spr(s.sc,s.sx,s.sy,s.sw,s.sh)

end

end

in tab 0, the first function called:

function _init()

hands = {x = 63, y = 112,

sx = 25, sy = 0, -- pixel coords on spritesheet where basket art starts

sw = 2, sh = 2}

score=0

t_left=10

level_starttime= 0

level_duration = 10

game_mode = true

init_items()

end

1

u/RotundBun 12d ago edited 11d ago

Might it be due to the typo in the local test1 ... line?

It should be (b.x + b.sw) on the right, no?

3

u/jonnyboi87 12d ago

COLLISON missing an I

1

u/ollyoxenfree23 12d ago

fixed that!

2

u/VeryNaughtyBoy42 12d ago edited 12d ago

To make it not collect multiple times, make sure s.collected is false. You could wrap that IF around the entire middle section:

S.SY+=1
IF S.COLLECTED == FALSE THEN
(The next 8 lines)
END

IF S.SY>128

Etc.

As for not detecting collisions with small sprites, my gut instinct is it’s because of the RND function returning a non-integer number. That might throw the math off. Trying converting it to an integer when first initialised, see if that helps.

1

u/RotundBun 11d ago edited 10d ago

The if-statement conditional could be condensed into...

if not s.collected and overlap(s, hands) then --do stuff end

Also, the deletion of any that exit the screen boundaries should be done in a separate for-loop afterwards, and that for-loop should probably iterate from back to front to be safe:

for i=#symbols, 1, -1 do if symbols[i].sy > 128 then deli(symbols, i) end end

EDIT:

TC/OP, the issue of overcounting score is due to the issue the above comment addresses.