I am a newbie at coding in love and am trying to make a semi-basic platformer as my first project. I wanted to code the ability to use a 'short hop', pushing the jump button down for a shorter time in order to do a shorter jump. Is this possible, and if so could you explain to me how to do it? I have defined both the short and long jump's velocities already. This in an excerpt from my current main.lua file and I am using love 0.8.0 currently, though plan to upgrade if necessary.
Current code:
if love.keyboard.isDown("up") then
player:jump()
end
What I have unsuccesfully tried:
if love.keyboard.isDown("up") > love.timer.getMicroTime(0.5) then
player:jump()
end
Thank you in advance for your replies!
How to time keypresses
Forum rules
Before you make a thread asking for help, read this.
Before you make a thread asking for help, read this.
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: How to time keypresses
Hi and welcome to the forums!
First, love.timer.getMicroTime doesn't accept parameters, so that's wrong.
Second, it's strongly recommended to use the latest löve version, unless your computer's specs can't run it (mostly due to the gpu being old).
In any case, there are a few ways to accomplish what you want; here's how i'd do it (I tried to use functions as they worked in 0.8):
This may be overcomplicating things a bit, with all keys having 4 "virtual" states, but it does keep track of how long the keys were held down, and you can use that information for whatever you want; also, detecting release may also be important since that should be what stops the ascent of your player.
Edit: Fixed a mistake in my code...
First, love.timer.getMicroTime doesn't accept parameters, so that's wrong.
Second, it's strongly recommended to use the latest löve version, unless your computer's specs can't run it (mostly due to the gpu being old).
In any case, there are a few ways to accomplish what you want; here's how i'd do it (I tried to use functions as they worked in 0.8):
Code: Select all
-- This will hold the states for each key.
-- state can be 0,1,2,3 with meanings: depressed, pressed, held and released
-- held is the time the button was held down
local keys = {}
keys.up = {state = 0, held = 0}
keys.down = {state = 0, held = 0}
keys.left = {state = 0, held = 0}
keys.right = {state = 0, held = 0}
function love.load()
-- Turn off key repeat; in 0.8 it was Löve's own doing, but after, it delegated it to the OS;
-- i always code my own, so i disable this anyways.
love.keyboard.setKeyRepeat(0)
end
-- This gets called by Löve whenever a key is pressed, but only at that moment.
-- (unless key repeat is enabled, i usually disable that, see above.)
love.keypressed = function(key)
if keys[key] then
keys[key].state = 1 -- Pressed.
keys[key].held = 0 -- Clear the time it was held for previously.
end
end
-- This gets called by Löve whenever a key is released, but only at that moment.
-- (same disclaimer as above.)
love.keyreleased = function(key)
if keys[key] then
keys[key].state = 3 -- Released.
end
end
-- Do most of the stuff in love.update
function love.update(dt)
-- Iterate over our keys table and update state.
for key, tbl in pairs(keys) do
if love.keyboard.isDown(key) then
if tbl.state == 1 then
-- It was just pressed.
doStuffPressed() -- Whatever function you need to do.
-- Modify state to held and update held time.
tbl.state = 2
tbl.held = tbl.held + dt
elseif tbl.state == 2 then
-- It was already held for more than one update loop.
doStuffHeld(tbl.held) -- Do whatever you need to do, the passed parameter holds how long it was pressed down for.
-- Update held time.
tbl.held = tbl.held + dt
end
else
-- If state is released, then set state to depressed.
if tbl.state == 3 then
-- Just released.
doStuffReleased(tbl.held) -- If you want to, you can detect a release here.
tbl.state = 0
end
end
end
end
Edit: Fixed a mistake in my code...
Last edited by zorg on Thu Mar 23, 2017 2:57 pm, edited 1 time in total.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
-
- Prole
- Posts: 7
- Joined: Thu Mar 23, 2017 1:21 am
Re: How to time keypresses
Ok, I'll try this! Thank you!
-
- Prole
- Posts: 7
- Joined: Thu Mar 23, 2017 1:21 am
Re: How to time keypresses
I've had an issue with my code, this line returns an error- "attempt to index local 'tbl' (a number value)" I updated to the newest version of Love.
if tbl.state == 3 then
Also, did I do this right? juump is just what i called my shorter jump.
local keys = {state = 0, held = 0}
keys.up = {state = 0, held = 0}
keys.down = {state = 0, held = 0}
keys.left = {state = 0, held = 0}
keys.right = {state = 0, held = 0}
function love.load()
love.keyboard.setKeyRepeat(0)
end
love.keypressed = function(key)
if keys[key] then
keys[key].state = 1
keys[key].held = 0
end
end
love.keyreleased = function(key)
if keys[key] then
keys[key].state = 3
end
end
function love.update(dt)
for key, tbl in pairs(keys) do
if love.keyboard.isDown(key) then
if tbl.state == 1 then
player:jump()
tbl.state = 2
tbl.held = tbl.held + dt
elseif tbl.state == 2 then
doStuffHeld(tbl.held) player:juump()
tbl.held = tbl.held + dt
end
else
if tbl.state == 3 then
doStuffReleased(tbl.held)
tbl.state = 0
end
end
end
end
if tbl.state == 3 then
Also, did I do this right? juump is just what i called my shorter jump.
local keys = {state = 0, held = 0}
keys.up = {state = 0, held = 0}
keys.down = {state = 0, held = 0}
keys.left = {state = 0, held = 0}
keys.right = {state = 0, held = 0}
function love.load()
love.keyboard.setKeyRepeat(0)
end
love.keypressed = function(key)
if keys[key] then
keys[key].state = 1
keys[key].held = 0
end
end
love.keyreleased = function(key)
if keys[key] then
keys[key].state = 3
end
end
function love.update(dt)
for key, tbl in pairs(keys) do
if love.keyboard.isDown(key) then
if tbl.state == 1 then
player:jump()
tbl.state = 2
tbl.held = tbl.held + dt
elseif tbl.state == 2 then
doStuffHeld(tbl.held) player:juump()
tbl.held = tbl.held + dt
end
else
if tbl.state == 3 then
doStuffReleased(tbl.held)
tbl.state = 0
end
end
end
end
- zorg
- Party member
- Posts: 3465
- Joined: Thu Dec 13, 2012 2:55 pm
- Location: Absurdistan, Hungary
- Contact:
Re: How to time keypresses
You're probably getting that error because i had an error in my code; that's what i get for not testing it beforehand.PunchyBreloom wrote: ↑Thu Mar 23, 2017 11:23 am I've had an issue with my code, this line returns an error- "attempt to index local 'tbl' (a number value)" I updated to the newest version of Love.
I went through it again, didn't see any other issues, so yes, hopefully it'll work. (Unless you'll have issues with setKeyRepeat not being happy with a 0 being passed to it; if you did update your Löve... switching out 0 for false would do, i think.)
Also, please do use [ code ] [ /code ] tags, it makes source code easier to read.
Me and my stuff True Neutral Aspirant. Why, yes, i do indeed enjoy sarcastically correcting others when they make the most blatant of spelling mistakes. No bullying or trolling the innocent tho.
Re: How to time keypresses
That seems unnecessarily... hairy.
What I've found to work pretty well is setting the y-velocity to the "max jump velocity" when the key is pressed, and then if it's released while the player is still moving upward, cut the y-velocity in half (or so).
I've attached a small demo (use WASD).
What I've found to work pretty well is setting the y-velocity to the "max jump velocity" when the key is pressed, and then if it's released while the player is still moving upward, cut the y-velocity in half (or so).
I've attached a small demo (use WASD).
- Attachments
-
- jump.love
- (731 Bytes) Downloaded 167 times
-
- Party member
- Posts: 548
- Joined: Wed Oct 05, 2016 11:53 am
Re: How to time keypresses
If you want to reproduce jumping controls from something like Mega Man, you can just set the vertical speed to 0 if player releases the jump button, and gravity hasn't caught up yet (ie. vertical speed is still such that player is ascending).
For funsies, you can pull the exact movement values for Mega Man titles from here and here. Alternatively for something like Sonic, here is a page for that. Should give you plenty of ideas on how plenty of classic platformers handle their jump arcs.
For funsies, you can pull the exact movement values for Mega Man titles from here and here. Alternatively for something like Sonic, here is a page for that. Should give you plenty of ideas on how plenty of classic platformers handle their jump arcs.
Re: How to time keypresses
Worth noting, none of those solutions need to track the amount of time the button was pressed.
That sort of thing seems like the way to go, although setting the velocity to an absolute value (especially 0) feels too abrupt for my liking; I generally prefer something like cutting it in half instead, but of course it depends on the game. Setting it to 0 makes more sense if there are spikes right above your head.
That sort of thing seems like the way to go, although setting the velocity to an absolute value (especially 0) feels too abrupt for my liking; I generally prefer something like cutting it in half instead, but of course it depends on the game. Setting it to 0 makes more sense if there are spikes right above your head.
-
- Prole
- Posts: 7
- Joined: Thu Mar 23, 2017 1:21 am
Re: How to time keypresses
Well thanks guys, I'll give these suggestions a try!
EDIT: I used airtruck's method and it worked fine, thanks!
EDIT: I used airtruck's method and it worked fine, thanks!
Re: How to time keypresses
Glad it worked for you. Just want to note a couple of things about that code.
Because the velocity is cut in half whenever the key is released while the character is ascending, it's technically possible to cut the jump short(er) if you're able to hit the key multiple times while the player is still ascending. I couldn't hit the key fast enough to notice a difference, but if it's a concern you can introduce some kind of "isJumping" flag (maybe your character has really strong legs or lives on the moon). Of course this also wouldn't be an issue if you set velocity to a fixed amount on key release, as in the examples MrFariator gave.
Also, the method used for acceleration/velocity/position integration is heavier than usual because it's designed to be accurate under a variable-length timestep. If you use a fixed-length timestep, you can get away with a cheaper approximation, like vel=vel+acc*dt; pos=pos+vel*dt. Of course you can still use the integration method in the demo with a fixed-length timestep if you just want that "extra" accuracy.
Because the velocity is cut in half whenever the key is released while the character is ascending, it's technically possible to cut the jump short(er) if you're able to hit the key multiple times while the player is still ascending. I couldn't hit the key fast enough to notice a difference, but if it's a concern you can introduce some kind of "isJumping" flag (maybe your character has really strong legs or lives on the moon). Of course this also wouldn't be an issue if you set velocity to a fixed amount on key release, as in the examples MrFariator gave.
Also, the method used for acceleration/velocity/position integration is heavier than usual because it's designed to be accurate under a variable-length timestep. If you use a fixed-length timestep, you can get away with a cheaper approximation, like vel=vel+acc*dt; pos=pos+vel*dt. Of course you can still use the integration method in the demo with a fixed-length timestep if you just want that "extra" accuracy.
Who is online
Users browsing this forum: Ahrefs [Bot], Bing [Bot], Google [Bot] and 4 guests