So... I guess what I'm aiming for is a back-calculating method for controlling player movement, via globals. So, let's say I'm wanting a typical jump-to-same-level duration to be 90 frames; and for it to go up 3.5 "tiles" of 8 pixels apiece; with a 0.8x accel/decel rate (gravrate). I define the jumpheight as 28 (pixels) and the jumptime as 45 (ground-to-apex; so half of 90), and then use that to calculate jumpvelocity.
My usual go-to is jumpvel=2sqrt(gravity tiles * gravrate), and then letting the typical gravity accel/decel take over from there. "gravity" is seperate from gravrate, in case I want to disable it (by making it 0) reverse it (by making it -1), or reducing it (making it a decimal, usually between 0.5 and 1).
Also, working on a similar accel/decel for horizontal walk/runspeed... so let's say I'm aiming at 0.3 px/frame to be the max speed (18 pixels a second, or a little over 2 tiles, so you can jump four across, level-to-level)... I still want a 20-frame accel and 10-frame decel delta to that, to give some fluidity to the player's motion, it's not all "everything or nothing." So the actual velocity is like "0.3 - (0.015 * runframes, if less than 20)" and then at release, setting that value to 20 and reducing it 2 at a time so that the calculation still affects the movement speed.
I think I'm losing my mind though, so am I still doing this right? >.>
I'm increasingly forgetting stuff, and when I'm working and calculating, it's interfering with my work - and THEN when I'm off, I'm no longer calculating, and everything's kind of getting messy. Dammit!!
function p_run() local aframes=accframes local move=maxrun if (btnp(0)) facing=-1 if (btnp(1)) facing=1 if (btn(0)=1 and btn(1)=1) then (btn(0),btn(1))=(0,0) else if btn(0)=1 or btn(1) aframes-=1 else if btn(0)=0 and btn(1)=0 foreach aframes<accframes aframes+=2 if (aframes>accframes) aframes=accframes end for a=1,aframes move*=fricrate end if (aframes=accframes) move=0 player.x+=move*facing end
Okay. So I've defined a couple parameters in _INIT() above; that being MAXRUN=0.4 (pixels per step) and ACCFRAMES=20 (the amount of frames I want to make build up to full speed). I localize copies of these as MOVE and AFRAMES because in the function, I want these to change, but I don't want the defaults to.
So the idea here is that pressing left or right will change your "facing" value to -1 (left) or 1 (right); and holding either one (but not both!) will drop the AFRAMES by one per frame. The movespeed multiplies itself by friction (presently 0.95) for each value of the AFRAMES, allowing you to get some urgent, immediate movement, but still taking a sub-second to reach full speed. Releasing them (or pressing them both, which does the same thing) then adds back to the AFRAMES twice as fast, reducing the player's momentum until AFRAMES=ACCFRAMES (the default I don't want changing!), where "MOVE" is then 0 (so multiplying a facing value to it doesn't mean anything in the sense of movement).
Now, everything about the horizontal physics can be revised simply by editing the globals defining the parameters.
Working on a jumping algo like this too. Tomorrow, I hope!
NOTE: I have spliced in "IF (AFRAMES>ACCFRAMES) AFRAMES=ACCFRAMES" to cap it back to it's default maximum.
This week, I'm gonna be taking a 3-day weekend from work to try and mash out some projects - hopefully to completion, or at least a playable state. I was kind of an idiot and didn't notice that GDQ also coincided with this week. That said, I'm currently mashing out my movement engine, and I don't want to spend my whole 3 days wrestling it into existence. In particular, a function I'm using for jumping code...
So, it turns out that taking a similar approach to writing Y-Speed control is a bit more contrived than the X-Speed. Where "running" has no limited duration (just the acceleration); trying to control the arc of a jump to coincide with a gravity variable, a number of frames to reach the apex, and the desired height of said apex is convoluted as feck. Because while I can get powers of friction by using a FOR loop to repeat multiplication, inverting that operation is nowhere near as simple!!
Take three constants - the intended apex of the jump ("JHEIGHT"), the factoral implication of gravity per frame, and the number of frames intended to go from ground-to-apex, provided the player holds the jump button and doesn't collide with anything overhead.
What I'm trying to accomplish with this particular function isn't just a static value that determines the initial jump velocity of this arc specifically; but so that the function will calculate that jump velocity even if I change the variables involved. Then I can define the lateral jumping range by doubling the JFRAMES, and multiplying that by the maximum XSpeed. PLAYER MOVEMENT BY DESIGN.
What I think will calculate this result requires me to do a "JFRAMESth root of JHEIGHT." See, with the run code above, I could make powers of the FRICRATE by using a FOR loop to repeat multiplication per step. I can't really use that approach the other way, though. While on some level, an Nth root is repeated division, but that step actually requires the solution as a prerequisite... which I don't really have, since that's what I'm creating this function specifically to solve.
IE: "3rt~8 = 8 / 2 / 2" requires knowing the 2; "3rt~64 = 64 / 4 / 4" requires knowing the 4, "4rt~81 = 81 / 3 / 3 / 3" requires knowing the 3...
...so instead, I have to begin at zero (the apex of the jump), and solve a set so that JHEIGHT breaks up into JFRAMES with an even, factoral difference of GRAVRATE. So the first thing to determine, of course, is exactly what that difference amounts to. Which, with the variables above, would be the 24th root of 28, times 25... or (JFRAMESrt~JHEIGHT)*JFRAMES.
First off... I might be wrong here. But secondly - and probably more what I need feedback on - is that I have ABSOLUTELY NO IDEA how to explain that function in code/syntax. I know PICO can do sqrt() and maybe even curt(); but defining an "Nth root of Y" in code? How do you even...!?
As I mentioned, I'd REALLY not like to spend my entire 3-day weekend banging my head against this; but I need to get my movement code written before I can test either it or the level designs reflected in it's use...
Well, what I ended up going with was a bit different than I'd expected at first, too.
function p_jump(jh or 0, jf or 0) if (jh=0) jh=jumpheight if (jf=0) jf=jumpframes local px=jh/(jf!) for j=-jf,999 ymove=px*j if(ymove>maxdrop)ymove=maxdrop j+=1 if(j>999)j=999 end
So, basically I started with the HIGHEST number of upward frames times negative one, and used that as the factor in calculating the y speed - then just took that number of factoral steps and multiplied it by a decimal that curves the arc as it moves from negative to positive values. After all, whatever the initial takeoff speed is doesn't have to be the maximum y speed.
It took a good week or so to figure out. But most importantly, I decoupled it from the universal physics. So in the event I want an item to obey the same physics as the player, a simple p_jump() will do that. BUT!! If I want an object to follow a DIFFERENT kind of jumping/physics arc, I can specify THAT, too! :D
[Please log in to post a comment]