Hey guys thought I would post this here as I think the answer will help other too:)
Basically I want to make a function that approaches any number in as big chunks as possible. Like this:
Speed = approach (target number, amount to move by)
So speed = approach(0, 0.5)
If speed was 0.4 before I want it to hit 0 and not -0.1
So if speed was a higher number like 7 every frame till it hits the target 0 it would take 0.5
Really useful for making velocity and stuff feel good :)
Any help very much appreciated :)
If I'm understanding what you want correctly
FUNCTION APPROACH(TARGET, AMOUNT)
IF TARGET>SPEED THEN
RETURN MAX(TARGET, SPEED-AMOUNT)
ELSE
RETURN MIN(TARGET, SPEED+AMOUNT)
END
END
Can you not use mid()?
function _init() -- initial values MINIMUM = 0 DELTA = 0.5 MAXIMUM = 7 SPEED = MAXIMUM end function _update() SPEED = approach(MINIMUM, DELTA) end function approach(t,d) return mid(t, SPEED-d, MAXIMUM) end |
Only two of the three arguments are used for decreasing speed.
The third would impose a maximum speed limit if required.
Nice use of MID(). Must remember that.
Edit: Although, now that I look at it, I think you solved a different problem. You're using MID() to clamp a value to a range, and he wants to take a range and direct it towards a target value. Still a spiffy usage of MID(), though.
I've clarified my code to show that if speed is in a loop it would do what he wants?
If not, then I'm not clear and will need more coffee.
Hey thank you so much for the responses! Matt your function works perfectly when your trying to hit 0 but I've been trying to work out how to make it hit other numbers too, could a similar method be used to include any numbers for example speed = 7 target = 15.2? and also with negatives like speed =-5 target = 2?
I also realized it makes a lot more sense to have the variable represented in the function so you could do this with any numbers so thinking of changing it to:
speed = approach(variable in this case speed,target,max amount to move by)
p.s I didn't know about the MID() function but really smart way to use it :D
mid() just picks the middle value of the three that you pass to it.
i'm not sure it's aligned with that you are doing, is it possible you can post some sample code or a work in progress cart?
@mrh's long form code is probably more what you want, mine was just a nice shortcut for your first use case but may not be suitable for other cases/values.
Hey thank you for taking the time with this :)
So here is a quick example, I have some code that resembles this:
function _init() px = 64 py = 64--player x and y end function _draw() cls() spr(001,px,py) if (btn(0)) then hspeed = -1 end if (btn(1)) then hspeed = 1 end if (btn(0)==false and btn(1)==false) then hspeed = 0 end px+=hspeed end |
Now what I want is something like this:
function _init() px = 64 py = 64 amount_to_jump_by = 0.3 end function _draw() cls() spr(001,px,py) if (btn(0)) then hspeed = -1 end if (btn(1)) then hspeed = 1 end if (btn(0)==false and btn(1)==false) then hspeed = 0 end playerhspeed = approach(playerhspeed,hspeed,amount_to_jump_by) px+=playerspeed end |
So those last 2 lines have changes with the goal of having a characters whose speed is gradual rather than clunky. So if you let go of left and right the hspeed changes to 0 but the players speed will decrease per frame to give the impression of sliding to a stop. And the same for changing direction mid run they will slide and switch more akin to real life motion :)
I was trying to make the function as broad as possible so I can use it for negative and positive numbers and for vertical speed and stuff too but not sure how realistic that is?
I hope that is better explained but let me know if it is not clear :)
the way I do it in Pico Pang is much simpler.
I go for a very subtle slide to a stop, but it's there.
this way, I do not actually care about the values of how much the thing moves each frame.
i just want it to slow down by 20% (or go 80% as fast) per frame.
this code works, make sure there's a sprite in slot zero.
try changing:
player.momentum
player.minimum
player.speed
try to add:
ability to change player.dx gradually when change of direction happens.
function _init() -- lower value for momentum means quicker slide to stop -- player properties player = {spr=0, x=64,y=64, dx=0, speed=2, momentum=0.8, minimum=0.5} end function _update() -- player delta slowly decreases player.dx = player.dx * player.momentum -- clamp to zero if it's within half a pixel if (abs(player.dx) < player.minimum) player.dx = 0 -- override player delta with player speed if keys are bring pressed if (btn(0)) player.dx = -player.speed if (btn(1)) player.dx = player.speed -- change player x position by delta player.x = player.x + player.dx end function _draw() cls() spr(0, player.x,player.y) end |
There's a subtlety in directional movement handling that probably doesn't matter much to most people, but I'll mention it in case it's interesting.
Consider this code:
if (btn(0)) player.dx = -player.speed if (btn(1)) player.dx = player.speed |
If your player is someone playing with a keyboard, where left and right are independent buttons that can be pressed simultaneously, there's a chance that a hurried direction-change can result in both buttons being pressed for a few frames. If that happens a lot, this code produces a bias towards rightward movement, since that's the last condition that's checked.
TL;DR: If I have left and right cursor keys pressed at the same time, I will move right.
Something like this eliminates the problem:
local l = btn(0) and player.speed or 0 local r = btn(1) and player.speed or 0 if (l+r > 0) player.dx = r - l |
Note that holding both keys cancels existing velocity, since it's assumed that the player is in the process of switching directions.
The other thing you can do is to prioritize the direction opposite the one being traveled, such that holding down right and then pressing both left+right while switching to the left will immediately switch to left, rather than halting movement during the transition. That's a little more involved and left as an exercise to the reader. :)
Thank you guys this is all good stuff, ended up using the 80% trick really handy thank you :)
Hey guys I was just digging through the Celeste cart and I found this!
function appr(val,target,amount)
return val > target
and max(val - amount, target)
or min(val + amount, target)
end
[Please log in to post a comment]