Help with Collision Detection

Problem:
I don't know where I can call other:crush and set car.isColliding to false.

Thoughts:

car.isColliding :
Car:collisionReponse works great. But the documentation says I shouldn't handle any sprite manipulation so I'm avoiding doing so.

So I'm just setting isColliding = false. This stops everything else down the chain from moving which is great.
But I need to know when I'm not colliding with something too. And since car:collisionResonse only happens when I'm colliding with something setting my Car.isColliding = false seems impossible or at least very difficult.

I tried to use function Car:moveWithCollison() which does get called, but it also stops calling Car:collisionResponse so it seems one or the other... Yes I'm calling it in the update, but that's a self:moveWithCollison() which it seems to like. only when I use function does it freek out.

other:crash :
This releates to the above. Like I said the documentation for collisionResponse discurages doing anything with sprites in the function. So.... where do I do that?
It says try working with moveWithCollision, but I did that and it totally makes collisionReponse stop working.

Again I feeel trapped here. I don't know what to do? Can someone please take a look at the code below and tell me what that see?

import "CarBase"

local pd <const> = playdate
local gfx <const> = pd.graphics

class('Car').extends(gfx.sprite)

function Car(x,y,bit)
    DrillBit.super.init(self)

    self.imagetable = bit
    self.animation = gfx.animation.loop.new(100, self.imagetable,true)
    self.isColliding = false

    self:setRotation(90)
    self:setImage(self.animation:image(1))
    self:setCollideRect(0, 0,self:getSize())
    
    self:moveTo(x,y+92)
    self:add()
end

function Car:getIsColliding()
    return self.isColliding
end

function Car:GetCarBit(version)
    local bit = "images/animated/dbv1-table-65-62"

    if version >=2 then
        bit = "images/animated/dbv"..version.."-table-65-62"
    end

    return bitMic
end

function Car:collisionResponse(other)
    local response = gfx.sprite.kCollisionTypeOverlap
    
    if other.type == "rock" then
        if self:alphaCollision(other) then
          
            self.isColliding = true -- I'm setting true here, because I don't want to just collide with something, I need to no when the alphaCollision collides. So I set it here. and it tells everything else to stop moving too.
			-- Thing is where can I safely set it to false???? O.....o
			
            --other:crush() I was calling it here and it does seem to work, but it's a no no ?
        end
    end
    
    return response
end

function Car:update()
    Car.super.update(self)
    self:moveWithCollisions(self.x,self.y)
end

Update
Ended up going in a new direction. Still seems hacky though.

import "CarBase"

local pd <const> = playdate
local gfx <const> = pd.graphics

class('Car').extends(gfx.sprite)

function Car(x,y,bit)
    DrillBit.super.init(self)

    self.imagetable = bit
    self.animation = gfx.animation.loop.new(100, self.imagetable,true)
    self.isColliding = false
	self.type = "player"
    self:setRotation(90)
    self:setImage(self.animation:image(1))
    self:setCollideRect(0, 0,self:getSize())
    
    self:moveTo(x,y+92)
    self:add()
end

function Car:getIsColliding()
    return self.isColliding
end

function Car:GetCarBit(version)
    local bit = "images/animated/dbv1-table-65-62"

    if version >=2 then
        bit = "images/animated/dbv"..version.."-table-65-62"
    end

    return bitMic
end

function Car:collisionResponse(other)
    local response = gfx.sprite.kCollisionTypeOverlap
    return response
end

function Car:update()
    Car.super.update(self)
    self:moveWithCollisions(self.x,self.y)
	
	local collisions = gfx.sprite.allOverlappingSprites()
    
    if #collisions == 0 then
        self.isColliding = false
    else
        for c = 1, #collisions do
            local collisionPair = collisions[c]
            local player = nil
            local rocks = {}
            
            for cp = 1 , #collisionPair do
                if collisionPair[cp].type == "rock" then
                    rocks[c] = collisionPair[cp]
                end
    
                if collisionPair[cp].type == "player" then
                    player = collisionPair[cp]
                end
            end
    
            for r = 1, #rocks do
                if player:alphaCollision(rocks[r]) then
                    self.isColliding = true
                    print("Rock?",rocks[r].type)
                    rocks[r]:crush()
                end
            end
        end
    end
end
1 Like

Hi! Sorry for taking so long to respond!

I tried to use function Car:moveWithCollison() which does get called, but it also stops calling Car:collisionResponse so it seems one or the other... Yes I'm calling it in the update, but that's a self:moveWithCollison() which it seems to like. only when I use function does it freek out.

I am not sure I understand this part. Calling moveWithCollison() should trigger the collisionResponse() callback when necessary - are you not seeing that behavior? Or were you overriding the moveWithCollison method? (not something I would recommend doing!)

Looking at your examples, I like the second approach better, because as you mentioned you should not be doing sprite manipulation inside the collisionResponse callback. self:alphaCollision(other) is a function that can be very slow (as it has to check every pixel), and collisionResponse can be called very often so it should return as quickly as possible.

I think it would simplify things if you were to use the return values from your self:moveWithCollisions(self.x,self.y) call in your Car:update() function, particularly the third collisions return value. This would prevent the extra redundant work that is being done when you call allOverlappingSprites(), which should no longer be necessary.

Another optimization and simplification, if you don't need any logic in your Car:collisionResponse() function, would be to directly assign self.collisionResponse = gfx.sprite.kCollisionTypeOverlap in your Car init method, and remove the collisionResponse function altogether.

1 Like