Problem with 2D physics

Questions about the LÖVE API, installing LÖVE and other support related questions go here.
Forum rules
Before you make a thread asking for help, read this.
Post Reply
Enderxell
Prole
Posts: 1
Joined: Mon Aug 19, 2024 1:22 pm

Problem with 2D physics

Post by Enderxell »

Hey, I got a problem. so I created a Virus class, and when it collides with the player it should only stick to it, not move around or anything. But my problem is, when the virus' collision body collides with the player's, it passes through any other collision body after, like as if it's collision body is disabled. I'm using Windfield as the physics module. Here's the code:

virus.lua -

Code: Select all

local Movement = require 'libraries/movement'

local Virus = {}
Virus.__index = Virus

function Virus.new(world, x, y, size, virusType)
    local self = setmetatable({}, Virus)
    self:init(world, x, y, size, virusType)
    return self
end

function Virus:init(world, x, y, size, virusType)
    self.collider = world:newCircleCollider(x, y, size)
    self.size = size
    self.virusType = virusType
    self.movement = Movement.new(2000, 150, 0.9)  -- Reduced speed and maxSpeed
    self.health = virusType == "Unstable" and 200 or 100
    self.damage = virusType == "Unstable" and 20 or 10
    self.attackRange = 100
    self.sticking = false
    self.offsetX = 0
    self.offsetY = 0
end

function Virus:update(dt, player)
    if self.sticking then
        self:stickToPlayer(player)
    else
        if self.virusType == "Passive" then
            return
        elseif self.virusType == "Hostile" then
            self:moveTowardsPlayer(player)
        elseif self.virusType == "Unstable" then
            if math.random() > 0.5 then
                self:moveTowardsPlayer(player)
            end
        end
    end
end

function Virus:moveTowardsPlayer(player)
    local px, py = player.collider:getPosition()
    local x, y = self.collider:getPosition()
    local distance = math.sqrt((px - x)^2 + (py - y)^2)

    if distance < self.attackRange then
        self.movement:moveTowards(self.collider, px, py)
    end
end

function Virus:stickToPlayer(player)
    local px, py = player.collider:getPosition()
    self.collider:setPosition(px + self.offsetX, py + self.offsetY)
    self.collider:setLinearVelocity(0, 0)  -- Ensure no force is applied
end

function Virus:draw()
    local x, y = self.collider:getPosition()
    love.graphics.circle("fill", x, y, self.size)
end

function Virus:checkCollisionWithPlayer(player)
    local px, py = player.collider:getPosition()
    local x, y = self.collider:getPosition()
    local distance = math.sqrt((px - x)^2 + (py - y)^2)

    if distance < self.size + player.size then
        self.sticking = true
        self.offsetX = x - px
        self.offsetY = y - py
        self.collider:setLinearVelocity(0, 0)  -- Stop the virus from moving
        self.collider:setCollisionClass('Virus')  -- Keep the collision class as 'Virus'
        self.collider:setPreSolve(function(collider_1, collider_2, contact)
            if (collider_1 == self.collider and collider_2 == player.collider) or 
               (collider_2 == self.collider and collider_1 == player.collider) then
                contact:setEnabled(false)  -- Disable collision response with the player
            end
        end)
    end
end

return Virus
movement.lua (required by virus.lua) -

Code: Select all

local Movement = {}
Movement.__index = Movement

function Movement.new(speed, maxSpeed, deceleration)
    local self = setmetatable({}, Movement)
    self.speed = speed
    self.maxSpeed = maxSpeed
    self.deceleration = deceleration
    return self
end

function Movement:handleInput(collider, controls)
    local fx, fy = 0, 0
    local vx, vy = collider:getLinearVelocity()
    local movementApplied = false

    if love.keyboard.isDown(controls.up) and vy > -self.maxSpeed then
        fy = -self.speed
        movementApplied = true
    elseif love.keyboard.isDown(controls.down) and vy < self.maxSpeed then
        fy = self.speed
        movementApplied = true
    end

    if love.keyboard.isDown(controls.left) and vx > -self.maxSpeed then
        fx = -self.speed
        movementApplied = true
    elseif love.keyboard.isDown(controls.right) and vx < self.maxSpeed then
        fx = self.speed
        movementApplied = true
    end

    if movementApplied then
        collider:applyForce(fx, fy)
    else
        self:applyDeceleration(collider, vx, vy)
    end
end

function Movement:applyDeceleration(collider, vx, vy)
    vx, vy = vx * self.deceleration, vy * self.deceleration

    if math.abs(vx) < 1 and math.abs(vy) < 1 then
        vx, vy = 0, 0
    end

    collider:setLinearVelocity(vx, vy)
end

function Movement:moveTowards(collider, targetX, targetY)
    local x, y = collider:getPosition()
    local angle = math.atan2(targetY - y, targetX - x)
    local fx = math.cos(angle) * self.speed
    local fy = math.sin(angle) * self.speed
    collider:applyForce(fx, fy)
end

return Movement
User avatar
dusoft
Party member
Posts: 635
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: Problem with 2D physics

Post by dusoft »

Windfield is outdated and abandoned (it's really fascinating how many people keep using it while the Github repo clearly says it's been archived). Even if your code is correct, windfield likely has bugs etc.

You might want to use breezefield as your replacement:
https://github.com/HDictus/breezefield

or just the LOVE physics module directly.
Post Reply

Who is online

Users browsing this forum: Google [Bot] and 2 guests