Adventure Game Studio

AGS Support => Modules, Plugins & Tools => Topic started by: deltree on Sun 16/11/2003 15:40:52

Title: parabolic movement: a jumping character
Post by: deltree on Sun 16/11/2003 15:40:52
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
Title: Re:scripting basic physical laws.
Post by: Kweepa on Sun 16/11/2003 19:15:11
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
Title: Re:scripting basic physical laws.
Post by: deltree on Sun 16/11/2003 19:35:39
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!
Title: Re:scripting basic physical laws.
Post by: Kweepa on Sun 16/11/2003 22:19:21
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);
 }
}

Title: Re:scripting basic physical laws.
Post by: After on Sun 16/11/2003 23:01:27
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.

//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!]
Title: Re:scripting basic physical laws.
Post by: Kweepa 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().
Title: Re:scripting basic physical laws.
Post by: After on Mon 17/11/2003 09:14:51
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.
Title: Re:scripting basic physical laws.
Post by: deltree on Tue 18/11/2003 00:47:14
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!
Title: Re:parabolic movement
Post by: After on Tue 18/11/2003 06:17:15
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.
Title: Re:parabolic movement
Post by: Kweepa on Tue 18/11/2003 08:43:57
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
Title: Re:parabolic movement
Post by: deltree on Wed 19/11/2003 04:07:21
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?  ::)
Title: Re:parabolic movement: a jumping character
Post by: Kweepa on Thu 20/11/2003 22:49:17
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 :)
Title: Re:parabolic movement: a jumping character
Post by: deltree on Fri 21/11/2003 11:09:36
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.
Title: Re:parabolic movement: a jumping character
Post by: After on Fri 21/11/2003 18:29:47
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.
Title: Re:parabolic movement: a jumping character
Post by: deltree on Fri 21/11/2003 20:19:18
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...
Title: Re:parabolic movement: a jumping character
Post by: After on Sat 22/11/2003 05:41:59
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.
Title: Re:parabolic movement: a jumping character
Post by: on Mon 24/11/2003 07:13:48
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