Page 1 of 1

Vertical Movement Platform - Glue

Posted: Fri Dec 09, 2022 4:41 pm
by brenus
Hi, everyone.

I'm making a platform game and there's a vertical movement platform. My problem is how you guys deal with vertical movement; the player doesn't distance himself from it.

What I'm doing is on the player:

I'm summing up the DeltaPlataformMovement (speedPlataform*dt) on the player's movement when he's on the platform. For example:

Code: Select all

player.physics.body:setY(player.physics.body:getY() + platform.deltaMovementPlatform)
Result (When the platform goes down the player is suspended in the air):

with player
Image

no player
Image

What I tried to improve: increase the fixture of the player; increase the gravity value; add body:applyForce(0, 1000) on the player <- none of them helped me.

I'm using only physics love2d vanilla. Thanks in advance for any insights.

Re: Vertical Movement Platform - Glue

Posted: Fri Dec 09, 2022 4:59 pm
by BrotSagtMist
Id say if there is a touch simply replace the player.

Re: Vertical Movement Platform - Glue

Posted: Fri Dec 09, 2022 4:59 pm
by darkfrei
1) Be sure that you update platform before update of player.
2) Why not hard placing as player.y = platform.y - player.height? (while standing on the platform)

(Update: you are right, must be minus height)

Re: Vertical Movement Platform - Glue

Posted: Fri Dec 09, 2022 6:53 pm
by brenus
BrotSagtMist wrote: Fri Dec 09, 2022 4:59 pm Id say if there is a touch simply replace the player.
I don't understand well, what is "touch simply"? (I'm beginner)

---
darkfrei wrote: Fri Dec 09, 2022 4:59 pm 1) Be sure that you update platform before update of player.
2) Why not hard placing as player.y = platform.y + player.height? (while standing on the platform)
1) I've tried to move the platform first, but I think the coordinates became from world:update(dt), not?

2) I've tried, but maybe I'm missing something (btw it's not - player.height no? because + is below the platform?). And this approach do I have to designate another collider only on the surface?

---

Maybe this code with a simple implementation from my game could be useful:

Code: Select all

local world
Player = {}
local Platform = {}
local deltaMovement = 0

WIDTH = love.graphics.getWidth()
HEIGHT = love.graphics.getHeight()

-- Player
local function jump()
    Player.physics.body:applyLinearImpulse(0, -2000)
end

local function move(dt)
    if Player.isMovementPlatformY then
        --Player.physics.body:setY(Platform.physics.body:getY() - 80)
        Player.physics.body:setY(Player.physics.body:getY() + deltaMovement)
    end
end


-- Platform
local function platformMove(dt)
    local _, py = Platform.physics.body:getPosition()
    deltaMovement = Platform.dir * 100 * dt
    Platform.physics.body:setY(py + deltaMovement)

    Platform.distActual = Platform.distActual + math.abs(deltaMovement)

    if Platform.distActual >= Platform.distLimit then
        Platform.dir = Platform.dir * -1
        Platform.distActual = 0
    end
end

function love.load()
    -- physics
    world = love.physics.newWorld(0, 1000, false)
    world:setCallbacks(beginContact, endContact, preSolve, postSolve)

    -- PLAYER
    Player.isJumping = false
    Player.isGrounded = true
    Player.isMovementPlatformY = false
    -- Physics
    Player.physics = {}
    Player.physics.body = love.physics.newBody(world, WIDTH/2, HEIGHT/2, "dynamic")
    Player.physics.body:setFixedRotation(true)

    Player.physics.shape = love.physics.newRectangleShape(40, 80)
    Player.physics.fixture = love.physics.newFixture(Player.physics.body,
        Player.physics.shape, 1)
    Player.physics.fixture:setUserData("Player")


    -- PLATFORM
    -- Physics
    Platform.physics = {}
    Platform.physics.body = love.physics.newBody(world, WIDTH/2, HEIGHT/2 + 100, "static")
    Platform.physics.shape = love.physics.newRectangleShape(100, 20)
    Platform.physics.fixture = love.physics.newFixture(Platform.physics.body,
                                Platform.physics.shape)
    Platform.dir = 1
    Platform.physics.fixture:setUserData("Platform")
    Platform.distActual = 0
    Platform.distLimit = 100

end

function love.update(dt)
    world:update(dt)
    platformMove(dt) -- Platform
    move(dt) -- Player
end

function love.draw()
    debug()
end

function beginContact(a, b, coll)
    if a:getUserData() > b:getUserData() then a, b = b, a end
    if (a:getUserData() == "Platform" and b:getUserData() == "Player") then
        Player.isJumping = false
        Player.isGrounded = true
        Player.isMovementPlatformY = true
    end
end

function endContact(a, b, coll)
    if a:getUserData() > b:getUserData() then a, b = b, a end
    if (a:getUserData() == "Platform" and b:getUserData() == "Player") then
        Player.isJumping = true
        Player.isGrounded = false
        Player.isMovementPlatformY = false
    end
end

function preSolve(a, b, coll)
    if a:getUserData() > b:getUserData() then a, b = b, a end
    if (a:getUserData() == "Platform" and b:getUserData() == "Player") then
        Player.isJumping = false
        Player.isGrounded = true
    end
end

function postSolve(a, b, coll, normalimpulse, tangentimpulse)

end

-- Keyboard
function love.keypressed(key)
    if key == "w" or key == "up" then
        jump()
    end
end

function debug()
    -- Debug
        for _, body in pairs(world:getBodies()) do
          for _, fixture in pairs(body:getFixtures()) do
              local shape = fixture:getShape()
              if shape:typeOf("CircleShape") then
                  local cx, cy = body:getWorldPoints(shape:getPoint())
                  love.graphics.circle("fill", cx, cy, shape:getRadius())
              elseif shape:typeOf("PolygonShape") then
                  love.graphics.polygon("fill", body:getWorldPoints(shape:getPoints()))
              else
                  love.graphics.line(body:getWorldPoints(shape:getPoints()))
              end
          end
        end
end


Re: Vertical Movement Platform - Glue

Posted: Fri Dec 09, 2022 8:41 pm
by pgimeno
A platform that accelerates faster than the player will always outrun the player's fall, that's just how the world works. If the platform's speed changes from 0 to a finite value without a transition, the acceleration is infinite, and that means the player is not supposed to catch up with the platform, i.e. the player will be suspended in air for a moment.

By the way, platforms are usually made kinematic. Static sounds like the wrong type.

Re: Vertical Movement Platform - Glue

Posted: Sun Dec 11, 2022 7:50 pm
by brenus
pgimeno wrote: Fri Dec 09, 2022 8:41 pm A platform that accelerates faster than the player will always outrun the player's fall, that's just how the world works. If the platform's speed changes from 0 to a finite value without a transition, the acceleration is infinite, and that means the player is not supposed to catch up with the platform, i.e. the player will be suspended in air for a moment.

By the way, platforms are usually made kinematic. Static sounds like the wrong type.
Thank you for your insights, and you're right I didn't know about the kinematic type.

About the vertical platform, I'm giving up for now because it's driving me crazy haha I'll think of another way to do that

Re: Vertical Movement Platform - Glue

Posted: Wed Dec 14, 2022 7:22 pm
by pgimeno
Here's an example of an object on a kinematic platform:

Code: Select all

local lp = love.physics
local lg = love.graphics

local platvel = 50

local world = lp.newWorld(0, 600)

local function newObject(body, shape)
  return {body = body, shape = shape, fixture = lp.newFixture(body, shape)}
end

local player = newObject(lp.newBody(world, 400, 300, "dynamic"),
  lp.newRectangleShape(40, 60))

local platform = newObject(lp.newBody(world, 400, 350, "kinematic"),
  lp.newRectangleShape(100, 10))

platform.body:setLinearVelocity(0, platvel)

function love.keypressed(k)
  if k == "escape" then return love.event.quit() end
end

function love.update(dt)
  world:update(dt)
  if platform.body:getY() > 450 then
    platform.body:setPosition(400, 450)
    platform.body:setLinearVelocity(0, -platvel)
  elseif platform.body:getY() < 350 then
    platform.body:setPosition(400, 350)
    platform.body:setLinearVelocity(0, platvel)
  end
end

function love.draw()
  lg.polygon("fill", player.body:getWorldPoints(player.shape:getPoints()))
  lg.polygon("fill", platform.body:getWorldPoints(platform.shape:getPoints()))
end