parabolic movement: a jumping character

Started by deltree, Sun 16/11/2003 15:40:52

Previous topic - Next topic

deltree

the title might look strange, but , in the end, all I want to do is to code the movement of a falling stone, including acceleration.
actually, I'd like not only that the stone fall, but if any object is thrown by a character, I should describe a parabolic movement, just like any ordinary object in real life. I'd like to code that precise kind of parabolic move.
Did anyone worked about it?
does anyone have a code source to code it, or a function?
actually, I'd like to code that kind of function:

function parabol(x1,y1,x2,y2,top,object,time)
{
....?
....?
}

That function would do the following thing:
-move an object(object)
-from location (x1,y1)
-to location (x2,y2)
-with a top height(top),
the top height is reached in (time) seconds


- in a parabolic movement - just like if the object was thrown by the player.

???  ;D

Kweepa

#1
Well, it would probably help to use the floating point numbers plugin that was talked about somewhere else. Here's the gist of how to do it...

First, work out how much time it takes to get to the top height.
Considering the vertical movement only,

v = u + a*t

v = 0, a = -g (g = acceleration due to gravity = 9.81m/s for sea level)
therefore u = g*t

s = u.t + 1/2 a*t^2

s = top - y1 = h1, a = -g, t = t1
therefore h1 = g*t1^2 - 1/2 g*t1^2
therefore t1 = sqrt(2*h1/g)

Similarly for the fall back to y2

t2 = sqrt(2*h2/g) where h2 = top - y2

So the total time is t1 + t2
the initial vertical velocity is u_ver = g*t1 = sqrt(2*g*h1)
and the horizontal velocity is u_hor = (x2-x1)(t1+t2)

Then for every frame, you can predict the movement as follows:

x = x1 + u_hor*t
y = y1 + u_ver*t - 1/2*g*t^2

where t goes from 0 up to t1 + t2 in increments of 1/GetGameSpeed()

You can probably get away with using fixed point if you premultiply everything by 100, and scale back down again after the calculations.

Hope that helps,

Steve
Still waiting for Purity of the Surf II

deltree

ok, thanks for the answer.
I finally found something about physcial laws and movement, but unfortunately, AGS doesn't deal with real number, neither with cosinus or sinus, so, I think I won t give my stone a realistic movement...too hard!

Kweepa

Here, try this...

function mod(int a, int b) { return a - (b*(a/b)); }

function sqrt(int L) {

 int temp, div, result = L;

 if (L == 0) return 0;
 else if (L < 5 ) div = L;
 else if (L < 256 ) div = 7;
 else if (L < 65536 ) div = 63;
 else if (L < 16777216) div = 1023;
 else div = 16383;

 while (1) {
   temp = L/div + div;
   div = temp/2;
   div += temp & 1;
   if (result > div) result = div;
   else {
     if (L/result == result-1 && mod(L,result)==0) result--;
     return result;
   }
 }
}

function parabol(int x1, int y1, int x2, int y2, int top, int object) {

 int s = 2*GetGameSpeed();
 int fx1 = s*x1;
 int fy1 = s*y1;
 int fx2 = s*x2;
 int fy2 = s*y2;
 int ftop = s*top;
 int fh1 = fy1 - ftop;
 int fh2 = fy2 - ftop;
 
 if (fh1 < 0 || fh2 < 0) {
   Display("Error in input to parabol.");
 }
 
 int fg = s*9810/100;
 
 int ft1 = sqrt(2*s*s*fh1/fg);
 int ft2 = sqrt(2*s*s*fh2/fg);
 
 int fuh = s*(fx2-fx1)/(ft1+ft2);
 int fuv = sqrt(2*fg*fh1);
 
 int ft = 1;
 
 while (ft < ft1 + ft2) {
   int x = (fx1 + fuh*ft/s)/s;
   int y = (fy1 - fuv*ft/s)/s;
   y = y + (fg*ft*ft/(2*s*s))/s;
   
   SetObjectPosition(object, x, y);
   
   // since we're scaling to twice game speed
   ft = ft + 2;
   Wait(1);
 }
}

Still waiting for Purity of the Surf II

After

#4
This will produce the correct movement.
You only need to emulate continuous functions if you are trying to predict or force the results, such as the highest point, which you don't if you're trying to be realistic. And if you do in some special case, then you can work out beforehand what inputs to provide.

Code: ags
//global y acceleration (pixels per sec per sec). You'll need to find a value of accel that looks good on screen.
#define accel 5

//variables
int xvel,yvel,xdiff,ydiff,vydiff,thrown,cpsec;

function game_start(){
//etc.
cpsec=GetGameSpeed();
thrown=-1;
}

function start_throw(int objID,int initxvel,int inityvel){
thrown=objID;
//velocity in pixels per second.
xvel=initxvel; //doesn't change (ignoring friction).
yvel=inityvel; //negative for upwards.
xdiff=0; //this stores fractional changes in x coordinate.
ydiff=0; // '' in y coordinate.
vydiff=0; // '' in y component of velocity.
}

function repeatedly_execute(){
int a,b;
  if(thrown!=-1){
    vydiff=vydiff+accel;a=vydiff/cpsec;
    if(a!=0){yvel=yvel+a;vydiff=vydiff-a*cpsec;}
    xdiff=xdiff+xvel;a=xdiff/cpsec;
    ydiff=ydiff+yvel;b=ydiff/cpsec;
    if((a+b)!=0){SetObjectPostion(thrown,GetObjectX(thrown)+a,GetObjectY(thrown)+b);xdiff=xdiff-a*cpsec;ydiff=ydiff-b*cpsec;}
  }
}

//set thrown=-1 when you want to stop it.

This could do with some refinement (if not actual debugging), but it should illustrate the basics.
[edit: See? I found something already  ^.^ *tweak, tweak*
Ok, so it wasn't quite as simple as planned. :p]
[edit2: much later. Stupid, stupid, stupid... Well, I couldn't leave it like that!]

Kweepa

Quote from: After on Sun 16/11/2003 23:01:27
You only need to emulate continuous functions if you are trying to predict or force the results, such as the highest point, which you don't if you're trying to be realistic.

Well he did ask for the object to hit a point on the screen and go through a top height. You have to supply *some* start conditions, and what better than those deltree suggested? Presumably the object is being thrown at something.
It's still "realistic" motion...

I like what you've done with the start_throw() and repeatedly_execute().
Still waiting for Purity of the Surf II

After

Quote from: SteveMcCrea on Mon 17/11/2003 08:38:48
Well he did ask for the object to hit a point on the screen and go through a top height. You have to supply *some* start conditions, and what better than those deltree suggested?
Fair enough.
I wasn't criticising anyone though (in case it seems that way). I was mainly concerned that deltree might have confused his original intention with the particular context he was used to seeing it in.
Being misled by knowledge, or words to that effect.

And thanks for the compliment.

deltree

Quote from: SteveMcCrea on Mon 17/11/2003 08:38:48
Quote from: After on Sun 16/11/2003 23:01:27
You only need to emulate continuous functions if you are trying to predict or force the results, such as the highest point, which you don't if you're trying to be realistic.

Well he did ask for the object to hit a point on the screen and go through a top height. You have to supply *some* start conditions, and what better than those deltree suggested? Presumably the object is being thrown at something.
It's still "realistic" motion...

I like what you've done with the start_throw() and repeatedly_execute().

thanx a lot for the above code, I think you've almost done it. (didn't try yet)
Actually, I'm don't get much the speed parameter, so, I've added a new parameter to my function: time (watch the top post, you'll see what I mean)
It will make the job easier and more "compatible" with every game speed I guess...
could you restart the function including this parameter [TIME] ?
thanx!

After

If you are wanting to do a "what is (x,y) at time t" kind of function, then Steve's first post is the place to look for the answer, and his second will provide plenty of clues on how to implement it.

My code doesn't cover that, but if you are only concerned about getting the same answers at different game speeds then either of our methods will do, as they both essentially translate gamespeed to time, so that gamespeed is effectively cancelled out.

Kweepa

Quote from: deltree on Sun 16/11/2003 15:40:52
function parabol(x1,y1,x2,y2,top,object,time)

That function would do the following thing:
-move an object(object)
-from location (x1,y1)
-to location (x2,y2)
-with a top height(top),
the top height is reached in (time) seconds

There are two ways to satisfy all those conditions - scale gravity or scale time - I guess both of them boil down to the same thing, which is:

Change the gravity parameter fg so that ft1 = time:

ft1 = sqrt(2*s*s*fh1/fg);
(substitute ft1 = s*time)
=> int fg = 2*fh1/(time*time);

So, replace the int fg = s*9810/100 line with this line and off you go.

Steve
Still waiting for Purity of the Surf II

deltree

excellent.
It works perfectly!
(I'll make a video to show the movement smoothsness someday...)
There is still one thing that ennoy me:
the time is set in seconds, I'd prefer to have it in milliseconds...
(I'm using your functions to make my character jump when you press the "A" key).
Would you mind modifying the function?  ::)

Kweepa

Sorry, I thought I answered this one already.

I'm worried that going to hundredths or milliseconds will overflow the fixed point calculations, but this should be ok...

So, for time in milliseconds,

int fg = 2*1000*fh1/time*1000/time;
int ft1 = s*time/1000;

Note that I haven't tried this, but I'm assuming the evaluation order is left to right like most languages.

Any more questions are going on the meter, buddy :)
Still waiting for Purity of the Surf II

deltree

thanx.
for now I'm still trynig to improve the jumping character movement:
it would be cool to change the character "baseline" during the jump.

my project is to make a movie , a sort of cartoon using AGS engine, witch will remind us of the good old game in the 80's.

I already made a short movie "lord of the bytes" that can be downloaded here:
www.d3Ltr33.fr.St
it was the first time I used AGS engine, and I'll make it much better this time.

After

Baseline is for the 3rd dimension. To keep it on the same plane, use
SetCharacterBaseline(JUMPER,character[JUMPER].y);
to fix it in place before the jump, then
SetCharacterBaseline(JUMPER,0);
to resume automatically sticking to the character's feet when back on the ground.

deltree

actually, it's not that simple:
the character can jump on a plateform that is higher or lower than the one he was before.
moreover, the plane is not supposed to be in 2d just like mario, but in 3D...

After

In that case,
SetCharacterBaseline(JUMPER,character[JUMPER].y+height);
where height is derived by the same calculation that your 3d enviroment uses, and which tells you where in space the character is.
This will have to be updated continuously, and the default behaviour will not be applicable often enough to bother with.

MagikiDashiki

first of all--- of that animation showing the parabolic movement was made in AGS i'm very impressed... that would be just hard to time out

SMF spam blocked by CleanTalk