Character Keeps Double-Jumping Past the Limit. HELP!

General discussion about LÖVE, Lua, game development, puns, and unicorns.
Post Reply
User avatar
PixelHero
Prole
Posts: 45
Joined: Sat Apr 16, 2022 3:16 am

Character Keeps Double-Jumping Past the Limit. HELP!

Post by PixelHero »

Code: Select all

local Class = require 'lib.hump.class'
local Entity = require 'entities.entity'

local player = Class{
  __includes = Entity
}

function player:init(world, x, y)
  self.img = love.graphics.newImage('/assets/character_block.png')

  Entity.init(self, world, x, y, self.img:getWidth(), self.img:getHeight())

  -- player values
    self.xVelocity = 0 -- current velocity on x, y axes
    self.yVelocity = 0
    self.acc = 100 -- acceleration of player
    self.maxSpeed = 600 -- the top speed
    self.friction = 20 -- slow player down - could toggle this situationally to create icy or slick platforms
    self.gravity = 80 -- towards the bottom
    
    self.isJumping = false -- in the process of jumping?
    self.doubleJumps = 3
    self.isGrounded = false -- on the ground?
    self.hasReachedMax = false  -- is this as high as player can go?
    self.jumpAcc = 500 -- how fast does player accelerate towards the top
    self.jumpMaxSpeed = 11 -- speed limit while jumping

    self.world:add(self, self:getRect())
end

function player:collisionFilter(other)
  local x, y, w, h = self.world:getRect(other)
  local playerBottom = self.y + self.h
  local otherBottom = y + h

  if playerBottom <= y then -- bottom of player collides with top of platform.
    return 'slide'
  end
end

function player:update(dt)
  local prevX, prevY = self.x, self.y

    -- Apply Friction
    self.xVelocity = self.xVelocity * (1 - math.min(dt * self.friction, 1))
    self.yVelocity = self.yVelocity * (1 - math.min(dt * self.friction, 1))

    -- Apply gravity
    self.yVelocity = self.yVelocity + self.gravity * dt

	if love.keyboard.isDown("a") and self.xVelocity > -self.maxSpeed then
		self.xVelocity = self.xVelocity - self.acc * dt
	elseif love.keyboard.isDown("d") and self.xVelocity < self.maxSpeed then
		self.xVelocity = self.xVelocity + self.acc * dt
	end

    -- The Jump code gets a lttle bit crazy.  Bare with me.
    if love.keyboard.isDown("w") then
        if -self.yVelocity < self.jumpMaxSpeed and not self.hasReachedMax then
            self.yVelocity = self.yVelocity - self.jumpAcc * dt
        elseif math.abs(self.yVelocity) > self.jumpMaxSpeed then
            self.hasReachedMax = true
        end

    self.isGrounded = false -- no longer in contact with the ground

    end

-- double-jump script
    function love.keyreleased(key)
        if key == 'w' then
            function love.keypressed(key)
                if key == 'w' and self.doubleJumps > 0 and self.doubleJumps ~= 0 then
                    self.yVelocity = self.yVelocity - self.jumpAcc * dt
                    self.doubleJumps = self.doubleJumps - 1
                end
            end
        end
    end

  -- store the location the player will arrive at should
  local goalX = self.x + self.xVelocity
  local goalY = self.y + self.yVelocity

  -- move player while testing for collisions
  self.x, self.y, collisions, len = self.world:move(self, goalX, goalY, self.collisionFilter)

  -- loop through those collisions to see if anything important is happening
  for i, coll in ipairs(collisions) do
    if coll.touch.y > goalY then  -- touched below intended target.
      self.hasReachedMax = true
      self.isGrounded = false
    elseif coll.normal.y < 0 then
      self.hasReachedMax = false
      self.isGrounded = true
      self.doubleJumps = 3
    end
  end
end

function player:draw()
  love.graphics.draw(self.img, self.x, self.y)
end

return player
I have no idea what is happening, but something is, because I can rapid-click 'w' and double-jump off the screen. If anyone has an idea, please help me.
Dragons are great.
User avatar
darkfrei
Party member
Posts: 1204
Joined: Sat Feb 08, 2020 11:09 pm

Re: Character Keeps Double-Jumping Past the Limit. HELP!

Post by darkfrei »

Why you have

Code: Select all

    if love.keyboard.isDown("w") then
        if -self.yVelocity < self.jumpMaxSpeed and not self.hasReachedMax then
            self.yVelocity = self.yVelocity - self.jumpAcc * dt
        elseif math.abs(self.yVelocity) > self.jumpMaxSpeed then
            self.hasReachedMax = true
        end
        self.isGrounded = false -- no longer in contact with the ground
    end
and

Code: Select all

    function love.keyreleased(key)
        if key == 'w' then
            function love.keypressed(key)
                if key == 'w' and self.doubleJumps > 0 and self.doubleJumps ~= 0 then
                    self.yVelocity = self.yVelocity - self.jumpAcc * dt
                    self.doubleJumps = self.doubleJumps - 1
                end
            end
        end
    end
and not just one of them?

And why function love.keypressed(key) is in the function love.keyreleased(key)?
:awesome: in Lua we Löve
:awesome: Platformer Guide
:awesome: freebies
User avatar
PixelHero
Prole
Posts: 45
Joined: Sat Apr 16, 2022 3:16 am

Re: Character Keeps Double-Jumping Past the Limit. HELP!

Post by PixelHero »

darkfrei wrote: Tue Apr 19, 2022 11:25 am Why you have

Code: Select all

    if love.keyboard.isDown("w") then
        if -self.yVelocity < self.jumpMaxSpeed and not self.hasReachedMax then
            self.yVelocity = self.yVelocity - self.jumpAcc * dt
        elseif math.abs(self.yVelocity) > self.jumpMaxSpeed then
            self.hasReachedMax = true
        end
        self.isGrounded = false -- no longer in contact with the ground
    end
and

Code: Select all

    function love.keyreleased(key)
        if key == 'w' then
            function love.keypressed(key)
                if key == 'w' and self.doubleJumps > 0 and self.doubleJumps ~= 0 then
                    self.yVelocity = self.yVelocity - self.jumpAcc * dt
                    self.doubleJumps = self.doubleJumps - 1
                end
            end
        end
    end
and not just one of them?
This is because I didn't know how to do them together.
And why function love.keypressed(key) is in the function love.keyreleased(key)?
Because I needed to check to see if the key had been released.
Dragons are great.
MrFariator
Party member
Posts: 559
Joined: Wed Oct 05, 2016 11:53 am

Re: Character Keeps Double-Jumping Past the Limit. HELP!

Post by MrFariator »

Reading this thread and your other thread about cursors, it seems you have a misunderstanding about how you're supposed to use love.keypressed and love.keyreleased callbacks. You only really need to define them once, and only once*. If you define love.keypressed twice, then the one that gets executed later becomes the active one. Lua basically goes "oh, we have this callback defined - but here it's defined again. Lets replace the one we're currently using with this new one."

*You could redefine them when changing between different game states (eq. menus and gameplay using different versions of the callback), but for now it might be better to focus on keeping things simple.

So, an exercise would be to fix your code so that instead of this:

Code: Select all

function player:update(dt) 
    -- ...
    -- love.keyreleased gets redefined every time player:update() runs!
    function love.keyreleased(key)
        if key == 'w' then
            -- love.keypressed gets redefined every time love.keyreleased runs!
            function love.keypressed(key)
                if key == 'w' and self.doubleJumps > 0 and self.doubleJumps ~= 0 then
                    self.yVelocity = self.yVelocity - self.jumpAcc * dt
                    self.doubleJumps = self.doubleJumps - 1
                end
            end
        end
    end
    -- ...
end
Do this:

Code: Select all

function player:update(dt) 
    -- ...
end

function love.keyreleased(key)
    if key == 'w' then
        -- do something
    end
end

function love.keypressed(key)
    -- put the logic about pressing "escape" here too, while at it
    if key == 'w' then
        -- do something
    end
end
As for your actual problem, it appears to me the culprit of your issues is here:

Code: Select all

if love.keyboard.isDown("w") then
    if -self.yVelocity < self.jumpMaxSpeed and not self.hasReachedMax then
        self.yVelocity = self.yVelocity - self.jumpAcc * dt
    elseif math.abs(self.yVelocity) > self.jumpMaxSpeed then
        self.hasReachedMax = true
    end
end
Seems to me that while you keep track of how many double jumps player can do with your love.keypressed callbacks, the above code in charge of handling the jump velocities doesn't care for it. Any time the "w" key is held down, player's velocity will be changed (so long the apex of your jumps isn't reached?), allowing you to rapid-tap the button and gain infinite height. So, you'll have to make the said code account for how many jumps player still has available, if any.
PixelHero wrote: Tue Apr 19, 2022 1:15 pm
And why function love.keypressed(key) is in the function love.keyreleased(key)?
Because I needed to check to see if the key had been released.
In your player:update() function, you can check for the key release with:

Code: Select all

if not love.keyboard.isDown("w") then
  -- the "w" key is not down!
end
So you could do something like

Code: Select all

if love.keyboard.isDown("w") then
  -- jump code
  if not self.jumpPressed then
    -- pressed!
    self.jumpPressed = true
    -- ...stuff that happens when you press the button
  else
    -- holding!
    -- ...stuff that happens when you hold the button
  end
else
  -- stuff that happens when jump is not held
  if self.jumpPressed then
    -- released button!
    self.jumpPressed = false
    -- ...stuff that happens when you release the button
  end
end
You can facilitate the same behavior with love.keypressed and love.keyreleased callbacks, which I'd personally recommend. I'll leave that for you to implement (should you go down that route) as a learning exercise.
User avatar
PixelHero
Prole
Posts: 45
Joined: Sat Apr 16, 2022 3:16 am

Re: Character Keeps Double-Jumping Past the Limit. HELP!

Post by PixelHero »

I changed to a new tutorial, with new code. However, I did implement this stuff. Thanks!!!
Dragons are great.
Post Reply

Who is online

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