Help with jumping

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.
User avatar
Gunroar:Cannon()
Party member
Posts: 1085
Joined: Thu Dec 10, 2020 1:57 am

Help with jumping

Post by Gunroar:Cannon() »

Hello all,

please help me. My jumps from here feel stiff and when the jump button is released the player falls straight down instead of falling downnin an arc.

The jump code for a quick glance is something like:

Code: Select all


function Player:__init__(...)
    ...
    
    self.jumpAcceleration = 300
    self.runAccel = 500
    self.brakeAccel = 1000
    self.maxVx = 200
    self.maxVy = 200
    
    self.weight = 750
    self.gravity = 0
    self.initGravity = 400
    self._initGravity = self.initGravity
    
    ...
end

function Player:updateGravity(dt)
    if not self.gravity or self.gravity==0 then
        self.gravity = self.initGravity
    end

    self.gravity = self.gravity+self.weight*dt
    local gravity = self.gravity
    self.vy = self.vy + gravity*dt
    
    if self.onGround then
        self.gravity = self.initGravity
    end
    
end

function Player:jump()
    
    if 1 then
        self.stats.jumpsPeformed = self.stats.jumpsPeformed+1
        self.sprite:switch("jumping")
        media.sfx.player_jumped:play()
        self.jumping = true
        self.vy = self.vy-self.jumpAcceleration
        
        --create Puff when jumping off wall
        if self.wallOnSide then
            self:createPuff(5,7)
        end
        
        --stops player from flying prematurely
        if not self.canFly then
            self.canJump =  false
        end
    end
end

funtion Player:update(dt)
    ...
    self:updateGravity(dt)
    ...
    
    if (self.Ljoystick:getYDir()*-1 > 0 or IM:isDown("Jump")) and self.canJump then
            self:jump()
    end
    
    --including this though not really used for gravity but who knows...
    self:changeVelocityByKeys(dt)


   ...

    self:checkLimits()

    local x,y = 0,0
    local vx=self.vx
    local vx, vy = self.x+vx*dt,self.y+self.vy*dt
    
 
    if not self.passive then
       --collision check
        local mx, my = self:move(vx,vy,dt)
        self.x, self.y = mx,my
    end
end


function Player:checkLimits()
    local maxVx,maxVy = self.maxVx, self.maxVy

    if true then
        
        if self.vy>0 then
            self.oldOnGround = false
        end
 
    
        if math.abs(self.vx)>maxVx then
            self.vx = maxVx*self:getDir(self.vx)
        end
    
        if self.vy>0 and self.onGround then
            self.vy = 0
        end
    
        if math.abs(self.vy)>maxVy then
            self.vy = maxVy*self:getDir(self.vy)
        end
    end
end

function Player:getDir(n)
    if n > 0 then return 1 elseif n < 0 then return -1
    else return 0 end
end


function Player:changeVelocityByKeys(dt, dir, dirY)
    self.isJumpingOrFlying = false

    if not self.active then return end

    local vx, vy = self.vx, self.vy

    if dir then
        dir, dirY = dir, dirY
    else
        dir, dirY = self.Ljoystick:getPos()
    end
    
    if not self.isBot and self.real then
        if (IM:isDown("Left")) then
            dir = -1
        elseif (IM:isDown("Right")) then
            dir = 1
        elseif love.keyboard.isDown("right") then error("Something bad happened in controls") end
    end
    
  
    if self.shot then
        vx = vx/2
    end
  
 
  
    if dir<0 then
        vx = (vx - 1 * (vx > 0 and self.brakeAccel or self.runAccel)) * (dir*-1)
    elseif dir>0 then
        vx = (vx + 1 * (vx < 0 and self.brakeAccel or self.runAccel)) * dir
    else
        local brake = dt * (vx < 0 and self.brakeAccel or -self.brakeAccel)
        if math.abs(brake) > math.abs(vx) then--or self.shot then
            vx = 0
        else
            if (150)>math.abs(brake) then
                vx = vx + brake
            --friction??? Buggy sometimes
            if math.floor(math.abs(vx))>0 then
                vx = vx - self:getDir(vx)*(frr or 150)*dt
            end
            end
        end
    end

    if self.vx>self.maxVx then
        self.vx = self.maxVx
    end
    
    --flying is fine for me
    if dirY>0 and self.fly then
        self.gravity = self.gravity-500*dir
    end
    
    if dirY<0 and self.fly then
        self.gravity = self.gravity+500*dirY*-1
    end
 
    self.vx, self.vy = vx, vy
end

_badjump.png
_badjump.png (30.85 KiB) Viewed 5609 times
_goodjump.png
_goodjump.png (34.63 KiB) Viewed 5609 times
Last edited by Gunroar:Cannon() on Sun Sep 12, 2021 1:12 pm, edited 2 times in total.
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Help with jumpin

Post by pgimeno »

So the problem is with the horizontal velocity of the player, but the snippet you've posted lacks any mention to vx. How do you expect us to help?

Also why do you change gravity? Gravity is a constant.
User avatar
Gunroar:Cannon()
Party member
Posts: 1085
Joined: Thu Dec 10, 2020 1:57 am

Re: Help with jumpin

Post by Gunroar:Cannon() »

pgimeno wrote: Sun Sep 12, 2021 11:28 am So the problem is with the horizontal velocity of the player, but the snippet you've posted lacks any mention to vx. How do you expect us to help?
Sorry, was typing it on a low battery life. Device died while I was editing, just got the minimum info out. Edited post with more code.
Edit: more reasonable code
Also why do you change gravity? Gravity is a constant.
:cry: That's the implementation I used. Any ideas on a complete revamp is welcome but I think I've tried that before. Let's just say my gravity variable is a state of the mind...? :?
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
darkfrei
Party member
Posts: 1169
Joined: Sat Feb 08, 2020 11:09 pm

Re: Help with jumping

Post by darkfrei »

Code: Select all

if state == flying then -- free falling
  vx=vx -- no changing :)
  vy=vy+dt*g
else
-- input controls code here
end
x=x+dt*vx
y=y+dt*vy
--collision code here, check if not more flying 
Last edited by darkfrei on Mon Sep 13, 2021 4:23 am, edited 1 time in total.
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Help with jumping

Post by pgimeno »

Applying gravity should be something like:

Code: Select all

function Player:updateGravity(dt)
    self.vy = self.vy + self.initGravity * dt
end
(assuming the player can have different gravity from others, otherwise just the global gravity, but physically gravity affects all of us in mostly the same way unless e.g. one of us is in space, or the game is one of those which toggle gravity, or there's some character that has "moon gravity" as a game mechanic or something weird like that)

In fact I wonder if your problem is that the gravity increases as the jump progresses and that makes the fall faster.

I've made your code work by adding this prologue:

Code: Select all

local function nop() end

local Player = {
  Ljoystick = {};
  canJump = true;
  jumping = false;
  weight = 10;
  vx = 0;
  vy = 0;
  x = 400;
  y = 300;
  onGround = true;
  real = true;
  isBot = false;
  active = true;
  fly = false;
  stats = {jumpsPeformed = 0}; -- sic
  sprite = {switch = nop};
}

function Player.Ljoystick:getYDir()
  return 0
end

function Player.Ljoystick:getPos()
  return 0, 0
end

function Player:move(x,y,dt)
  return x, y
end

local IM = {}

function IM:isDown(s)
  if s == "Jump" then s = "space" else s = s:lower() end
  return love.keyboard.isScancodeDown(s)
end

local media = {sfx = {player_jumped = {play = nop}}}
And this epilogue:

Code: Select all

Player:__init__()

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

function love.update(dt)
  Player:update(dt)
  if Player.jumping then Player.onGround = false end
end

function love.draw()
  love.graphics.rectangle("fill", Player.x, Player.y, 10, 10)
end
And then commented out all the `...` and fixed the `funtion` typo. Of course there's no collision, so the player falls indefinitely on the first jump.

I don't see the effect that you describe though. There's a problem that the vertical speed limit is very low, as low as the horizontal speed limit, and that makes the player go diagonally at 45°, but not vertically as you say. Can you try it and tell me if you still see the problem with it? And if you do, can you explain the problem better than with those drawings? And if not, you're on your own looking for the problem somewhere else, because that snippet seems to work.

Edit: Oh wait, you mean you want your player to preserve the inertia while jumping? Something like this?

Code: Select all

    -- add this at the top of changeVelocityByKeys:
    if not self.onGround then return end
LuisLJLV
Prole
Posts: 5
Joined: Tue Sep 07, 2021 8:08 pm

Re: Help with jumping

Post by LuisLJLV »

You want the friction of the character to be less when the player is not on Ground(?
User avatar
Gunroar:Cannon()
Party member
Posts: 1085
Joined: Thu Dec 10, 2020 1:57 am

Re: Help with jumping

Post by Gunroar:Cannon() »

LuisLJLV wrote: Mon Sep 13, 2021 3:20 am You want the friction of the character to be less when the player is not on Ground(?
Yeah, I tried friction in air but that was caused some buggy problems for me, like the player moved wierdly. It is a known solution that can work which I read about in one article though. (two friction values for ground and air).
pgimeno wrote: Sun Sep 12, 2021 10:11 pm A lot
(What's the difference between scanCodeDown and keyDown?)

Wow, thanks for your time :ultrahappy: but...
Edit: Oh wait, you mean you want your player to preserve the inertia while jumping? Something like this?

Code: Select all

    -- add this at the top of changeVelocityByKeys:
    if not self.onGround then return end
...Yes, I did mean like that. I guess my fault for thinking the drawings would do most of the talking typing.
It worked but that made the player unable to control their direction when in air. Besides that it's a nice simple solution.
darkfrei wrote: Sun Sep 12, 2021 10:02 pm

Code: Select all

if state == flying then -- free falling
  vx=vx -- no changing :)
  vy=vy+dt*g
else
-- input controls code here
end
x=x+dt*vx
y=y+dt*vy
--collision code here, check if not more flying 
Strangely I was a bit skeptical about this one but it was the one that worked :rofl:

Thanks all, solved :P
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
User avatar
pgimeno
Party member
Posts: 3544
Joined: Sun Oct 18, 2015 2:58 pm

Re: Help with jumping

Post by pgimeno »

I forgot to answer this...
Gunroar:Cannon() wrote: Fri Sep 17, 2021 2:33 pm (What's the difference between scanCodeDown and keyDown?)
For alphanumeric keys, isDown returns the character printed in the key, whose position depends on the language of the keyboard. This is specially bad for French keyboards, where the top row starts with AZERT instead of QWERT, the middle row with QSDFG instead of ASDFG, and the bottom row with WXCVB instead of ZXCVB. So, the French keyboard equivalent of the famous WASD is ZQSD; the W is in the bottom row instead of above the S, and the A is on the top instead of to the left of the S. French people can't (comfortably) play a game with WASD controls if you use isDown.

isScancodeDown, on the other hand, works by key positions, with the key names being the letter that is in that position in a U.S. keyboard; therefore, if you press the Z in a French keyboard, isScancodeDown("w") will be true, and French people can play your game comfortably.

If you want characters because you're using text, love.textinput is perfect because it recognizes all characters, including accent keys in a Spanish keyboard like mine, for example, which isDown and love.keypressed don't handle. So there's barely any reason to use isDown or the first parameter of love.keypressed, which are there just for legacy reasons. I only use it out of laziness when the only keys I'm handling are e.g. arrows or the space bar, because these don't change between keyboards. Or for my one-liner quit-with-esc for simple programs:

Code: Select all

function love.keypressed(k) return k == "escape" and love.event.quit() end
The only real use I can think of, is to display the keys in a game with re-definable controls. It would be confusing to tell a French that the controls are defined as WASD when the keys that work for him are ZQSD.
grump
Party member
Posts: 947
Joined: Sat Jul 22, 2017 7:43 pm

Re: Help with jumping

Post by grump »

pgimeno wrote: Mon Sep 20, 2021 2:00 pm The only real use I can think of, is to display the keys in a game with re-definable controls. It would be confusing to tell a French that the controls are defined as WASD when the keys that work for him are ZQSD.
See also https://love2d.org/wiki/love.keyboard.g ... omScancode

It's one super common mistake a lot of hobbyists are making, and it's often a game-breaking mistake. WASD on French layout is a good example, or even worse with a lot more people affected: when your game has 2 actions and they're hardcoded to Z and X. Like, half of the games made for game jams are basically unplayable if you don't change your keyboard layout settings because of this.
User avatar
Gunroar:Cannon()
Party member
Posts: 1085
Joined: Thu Dec 10, 2020 1:57 am

Re: Help with jumping

Post by Gunroar:Cannon() »

Okay, thnx. So I can use getKeyFromScancode and getScancodeFromKey to still display the correct controls in settings, is that correct?
The risk I took was calculated,
but man, am I bad at math.

-How to be saved and born again :huh:
Post Reply

Who is online

Users browsing this forum: Ahrefs [Bot], Semrush [Bot] and 53 guests