Page 1 of 1

How to detect collisions for something that has multiple instances?

Posted: Thu Jul 04, 2024 6:12 am
by COMRADECHOnKy
Hello. I have been making a simple shooter game where the player has a gun and there are enemies. But I have run into a problem, I have made the collision system for the player and enemy just fine and the enemy damages the player and it dies when it collides with the player and

I want to do the same thing for the bullets and the enemy where the enemy will die after the bullet collides with it but it has multiple instances and I cant find a solution to it.

Bullet code:

Code: Select all

require("enemy")

image = love.graphics.newImage("bullet.png")

function bullet()
    return{ 
        x = 0,
        y = 0,
        width = 5,
        height = 5,
        speed = 150,
        direction = 0,
        delete = false,

        load = function (self,gun_x,gun_y,gun_direction)
            self.x = gun_x
            self.y = gun_y
            self.direction = gun_direction
        end,

        update = function (self,enem,dt)
            self.x = self.x + math.cos(self.direction) * self.speed * dt
            self.y = self.y + math.sin(self.direction) * self.speed * dt

            if self.x > love.graphics.getWidth() then
                self.delete = true
            end
            if self.y > love.graphics.getHeight() then
                self.delete = true
            end

            half_enemy_width,half_enemy_height = enem.width / 2
            ,enem.height / 2

            enemy_center_x = half_enemy_width + enem.x
            enemy_center_y = half_enemy_height + enem.y

            self_half_width = self.width / 2
            self_half_height = self.height / 2

            if math.abs(self_half_width + self.x - enemy_center_x) < math.abs(self_half_width + half_enemy_width) and
            math.abs(self_half_width + self.y - enemy_center_y) < math.abs(self_half_height + half_enemy_height) then
                self.delete = true
            end
        end,

        draw = function (self)
            love.graphics.rectangle("fill",self.x,self.y,self.width,self.height)
        end
    }
end
gun code:

Code: Select all

require("player")
require("bullet")
require("enemy")

gun = {
    x = 100,
    y = 50,
    angle,
    image = love.graphics.newImage("simple_m4.png")
}

bullet_list = {}
bullet_delete_list = {}

function gun:load()
end

function gun:update(dt)

    local mouse_x,mouse_y = love.mouse.getPosition()
    gun.angle = math.atan2(mouse_y - gun.y,mouse_x - gun.x)
    --bullet.direction = gun.angle    

    gun.x = player.x + (player.image:getHeight() / 2)
    gun.y = player.y + (player.image:getHeight() / 2)


    if love.mouse.isDown(1) then
        local new_bullet = bullet()
        new_bullet:load(gun.x,gun.y,gun.angle)
        table.insert(bullet_list,new_bullet)
    end

    for _, b in ipairs(bullet_list) do
        b:update(enem,dt)
    end
    for i = #bullet_list,1,-1 do
        if bullet_list[1].delete == true then
            table.remove(bullet_list,i)
        end
    end
end

function gun:draw()
    love.graphics.push()

    love.graphics.translate(gun.x,gun.y)
    love.graphics.rotate(gun.angle)

    love.graphics.draw(gun.image,-gun.image:getWidth() / 2,-gun.image:getHeight() / 2)

    love.graphics.pop()

    for i, b in ipairs(bullet_list) do
        b:draw()
    end
end

Code: Select all

enem = {}

function enemy()
    return {
        x = 0,
        y = 0,
        spd = 1000,
        width = 20,
        height = 20,
        spawned = true,
        hp = 4000,
        dead = false,

        update = function (self,player_x,player_y)
            enem.x = self.x
            enem.y = self.y
            enem.width = self.width
            enem.height = self.height

            local direction_X,direction_Y = player_x - self.x,player_y - self.y

            self.x = self.x + (direction_X / self.spd)
            self.y = self.y + (direction_Y / self.spd)

        end,

        checkCollision = function (self,player)
            half_player_width,half_player_height = player.image:getWidth() / 2
            ,player.image:getHeight() / 2

            player_center_x = half_player_width + player.x
            player_center_y = half_player_height + player.y

            self_half_width = self.width / 2
            self_half_height = self.height / 2

            if math.abs(self_half_width + self.x - player_center_x) < math.abs(self_half_width + half_player_width) and
            math.abs(self_half_width + self.y - player_center_y) < math.abs(self_half_height + half_player_height) then
                self.dead = true
                player.hp = player.hp - 1
            end
        end,

        drawEnemy = function (self)
            love.graphics.rectangle("fill",self.x,self.y,self.width,self.height)
        end
    }
end

Re: How to detect collisions for something that has multiple instances?

Posted: Thu Jul 04, 2024 12:03 pm
by dusoft
You need to compare each bullet instance with another object (enemy/player). Make a table of bullets fired and their positions, compare with a player. You might hit a block here with bullets being faster than your detection, but search the forum it has been discussed.

Re: How to detect collisions for something that has multiple instances?

Posted: Thu Jul 04, 2024 5:51 pm
by COMRADECHOnKy
dusoft wrote: Thu Jul 04, 2024 12:03 pm You need to compare each bullet instance with another object (enemy/player). Make a table of bullets fired and their positions, compare with a player. You might hit a block here with bullets being faster than your detection, but search the forum it has been discussed.
wow man, thank you so much. That's is pretty smart way to do that. I now have an idea of what to do.

Re: How to detect collisions for something that has multiple instances?

Posted: Sat Jul 06, 2024 2:17 am
by RNavega
COMRADECHOnKy wrote: Thu Jul 04, 2024 6:12 am

Code: Select all

function bullet()
    return{ 
        ...

        load = function (self,gun_x,gun_y,gun_direction)
            self.x = gun_x
            self.y = gun_y
            self.direction = gun_direction
        end
        
        ...
        }
end
Hi. While you're probably never going to run into problems with this, if I'm not mistaken, each time the bullet() function is called, the load etc functions will be instantiated, generating more garbage in memory, using up more memory that has to be cleared later by the garbage collector.
The solution to this is to declare the load etc functions before the bullet() function and as local functions (eg "local function _load(...)"), and then just assign references inside the bullet() function: {x = ..., y = ..., load = _load}.
This way the bullet tables only hold references to the same functions, not references to new instances of the functions per bullet.