[SOLVED] Applying velocity (on X-axis) to a physics body
Posted: Tue Apr 02, 2019 8:24 am
Hello everyone!
I'm working on a 2D platformer that uses box2d physics (I believe that's what LÖVE is using right?) and I'm trying to apply velocity to my Physics body object (in this case my player object). What I want is to create a platformer that moves around in a similar fashion to Mario from NES (but not necessarily a carbon copy).
I have implemented velocity from an older project where the player object doesn't use a physics body that you can see here:
I've managed to implement a method of movement that works in my platformer project (that uses physics) but I'm having problems figuring out a way to make velocity work with my physics implementation in my platformer.
My current platformer project:
Player.lua
main.lua
platform.lua
Please keep in mind I'm a little bit unfamiliar exactly how box2d physics works but I think I believe I'm starting to grasp it. Please let me know if there's any other information that you need to know!
edit: got my player object to move by using:
Has to figure out instead why my object only uses "Acceleration" in my prototype
I'm working on a 2D platformer that uses box2d physics (I believe that's what LÖVE is using right?) and I'm trying to apply velocity to my Physics body object (in this case my player object). What I want is to create a platformer that moves around in a similar fashion to Mario from NES (but not necessarily a carbon copy).
I have implemented velocity from an older project where the player object doesn't use a physics body that you can see here:
Code: Select all
local isLeftHeld
local isRightHeld
-- Velocity cap as to how fast the Player can move
local maxVelocity
-- If the Player isn't touching a key, do nothing
isLeftHeld = false
isRightHeld = false
-- Players intial velocity
baseVelocity = -800
-- Player table with variables
Player = {}
Player.Sprite = love.graphics.newImage("player.png")
Player.posX = love.graphics.getWidth() * 0.5
Player.posY = love.graphics.getHeight() - 80
Player.Orientation = 0
Player.scaleX = 1
Player.scaleY = 1
Player.originX = math.ceil(Player.Sprite:getWidth() * 0.5)
Player.originY = 0
Player.Width = Player.Sprite:getWidth()
Player.Height = Player.Sprite:getHeight()
Player.Velocity = 0
Player.maxVelocity = 4.25
Player.Direction = 1
Player.clampLeft = 42
Player.clampRight = love.graphics.getWidth() - 42
function Player:load(arg)
end
function Player:update(dt)
-- Move left if key is down and set direction to left
if isLeftHeld == true then
self.Velocity = baseVelocity
self.Direction = 1
elseif isRightHeld == true then
-- Move right if key is down and set direction to right
self.Velocity = baseVelocity
self.Direction = -1
else
-- Slow down if nothing is happening
self.Velocity = self.Velocity * 0.94
end
-- Update movement
self.posX = self.posX + (self.Velocity * dt) * self.Direction
-- Cap the Players velocity to maximum velocity allowed
if self.Velocity > self.maxVelocity then
self.Velocity = self.maxVelocity
end
-- Prevents the player from moving outside to the left
if self.posX < self.clampLeft then
self.posX = self.clampLeft
elseif self.posX > self.clampRight then
self.posX = self.clampRight
end
end
function Player:draw()
-- Draw the player
love.graphics.draw(self.Sprite,
self.posX,
self.posY,
self.Orientation,
self.scaleX,
self.scaleY,
self.originX,
self.originY)
end
function Player:keypressed(key)
-- If the player is pressing the key, it's true
if key == 'left' then
isLeftHeld = true
end
if key == 'right' then
isRightHeld = true
end
end
function Player:keyreleased(key)
-- If the player isn't pressing the key, it's false
if key == 'left' then
isLeftHeld = false
end
if key == 'right' then
isRightHeld = false
end
end
return Player
I've managed to implement a method of movement that works in my platformer project (that uses physics) but I'm having problems figuring out a way to make velocity work with my physics implementation in my platformer.
My current platformer project:
Player.lua
Code: Select all
love.graphics.setDefaultFilter("nearest")
local isLeftHeld
local isRightHeld
baseVelocity = -800
-- Player Table --
Player = {}
-- Sprite Variables --
Player.Sprite = love.graphics.newImage("tempChar.png")
Player.spritePreJump = love.graphics.newImage("spritePreJump.png")
Player.spriteJumping = love.graphics.newImage("spriteJumping.png")
Player.spriteLanding = love.graphics.newImage("spriteLanding.png")
Player.posX = love.graphics.getWidth() * 0.5
Player.posY = 300--love.graphics.getHeight() * 0.5
Player.Body = love.physics.newBody(physicsWorld,
Player.posX,
Player.posY,
"dynamic")
Player.Shape = love.physics.newRectangleShape(34, 70)
Player.Fixture = love.physics.newFixture(Player.Body, Player.Shape)
Player.Radians = 0 -- Rotation
Player.scaleX = 3
Player.scaleY = 3
Player.originX = Player.Sprite:getWidth() * 0.5
Player.originY = Player.Sprite:getHeight() * 0.5
Player.Width = Player.Sprite:getWidth()
Player.Height = Player.Sprite:getHeight()
Player.Speed = 425 -- Temporary variable, may change to a Velocity setup instead
Player.clampLeft = 16
Player.clampRight = 784
Player.impulseX = 0
Player.impulseY = -1250
--Player.isJumping = false
--Player.reachedMaxHeight = false
Player.isGrounded = false
Player.Direction = 3
Player.currentDirection = Player.Direction
Player.lookingLeft = false
Player.lookingRight = true
Player.velocityX = 0
--Player.velocityY = 0
Player.Acceleration = 100
Player.maxSpeed = 600
Player.Friction = 20
function Player:update(dt)
self.Body:getX(self.posX + self.velocityX)
self.velocityX = self.velocityX * (1 - math.min(dt * self.Friction, 1))
if love.keyboard.isDown("left", "a") and self.velocityX > -self.maxSpeed then
self.Body:setX(Player.Body:getX() - self.velocityX - self.Acceleration * dt)
self.currentDirection = -self.Direction
elseif love.keyboard.isDown("right", "d") and self.velocityX < self.maxSpeed then
self.Body:setX(Player.Body:getX() + self.velocityX + self.Acceleration * dt)
self.currentDirection = self.Direction
end
if self.Body:getX() <= self.clampLeft then
self.Body:setX(self.clampLeft)
elseif self.Body:getX() >= self.clampRight then
self.Body:setX(self.clampRight)
end
if self.isGrounded == true then
self.Sprite = self.Sprite
else
self.Sprite = self.spriteLanding
end
print("Player Direction: "..self.currentDirection)
end
function Player:draw()
love.graphics.draw(self.Sprite,
self.Body:getX(),
self.Body:getY(),
self.Radians,
self.currentDirection,
self.scaleY,
self.originX,
self.originY)
end
function Player:keypressed(key)
if key == 'up' and self.isGrounded == true then
print("Jumping")
self.Body:applyLinearImpulse(self.impulseX, self.impulseY)
end
if key == 'left' then
isLeftHeld = true
end
if key == 'right' then
isRightHeld = true
end
end
function Player:keyreleased(key)
if key == 'left' then
isLeftHeld = false
self.currentDirection = -self.Direction
lookingLeft = true
lookingRight = false
end
if key == 'right' then
isRightHeld = false
self.currentDirection = self.Direction
lookingLeft = false
lookingRight = true
end
end
return Player
Code: Select all
Platforms = require "platform"
function love.load()
physicsWorld = love.physics.newWorld(0, 780) -- Move this to a Game Manager
physicsWorld:setCallbacks(beginContact, endContact, preSolve, postSolve)
Player = require "Player"
Platforms:spawnPlatform(0, 550, 800, 30)
end
function love.update(dt)
physicsWorld:update(dt)
Player:update(dt)
end
function love.draw()
--love.graphics.print("Sprite: "..Player.Sprite, 10, 10)
Player:draw()
Platforms:draw()
if love.keyboard.isDown("c") then
for _, body in pairs(physicsWorld: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
end
-- Closes down the game window when pressing ESC
function love.keypressed(key)
Player:keypressed(key)
if key == 'escape' then
love.event.quit()
end
end
function love.keyreleased(key)
Player:keyreleased(key)
end
function beginContact(a, b, coll) -- put this in a game manager?
Player.isGrounded = true
end
function endContact(a, b, coll) -- put this in a game manager?
Player.isGrounded = false
end
Code: Select all
Platforms = {}
--Platforms:spawnPlatform(0, 550, 800, 30)
function Platforms:update(dt)
end
function Platforms:draw()
for i,p in ipairs(Platforms) do
love.graphics.rectangle("line",
p.platformBody:getX(),
p.platformBody:getY(),
p.platformWidth,
p.platformHeight)
end
end
function Platforms:spawnPlatform(x, y, width, height)
local Platform = {}
Platform.platformBody = love.physics.newBody(physicsWorld, x, y, "static")
Platform.platformShape = love.physics.newRectangleShape(width * 0.5,
height * 0.5,
width,
height)
Platform.platformFixture = love.physics.newFixture(Platform.platformBody,
Platform.platformShape)
Platform.platformWidth = width
Platform.platformHeight = height
table.insert(Platforms, Platform)
end
return Platforms
Please keep in mind I'm a little bit unfamiliar exactly how box2d physics works but I think I believe I'm starting to grasp it. Please let me know if there's any other information that you need to know!
edit: got my player object to move by using:
Code: Select all
self.Body:applyForce((self.velocityX - self.Acceleration *dt), 0)