Adventure Game Studio

AGS Support => Advanced Technical Forum => Topic started by: Miori on Tue 17/05/2011 22:38:09

Title: how to let a ball fly like a ball
Post by: Miori on Tue 17/05/2011 22:38:09
I try to program a golf game and everything works fine until now. But the way the ball flies looks really... straight. I just used the walk function, with a waypoint. The ball is player character, so the screen is following it automaticaly. How far the ball flies is calculated with a hitbar. So there is a variable that says where the ball should land. It should fly with a curve. But I don't know how to do that. Could anybody help me? I'm using 3.2.1 Version of AGS.

Thanks for every helpful answer  :)
Title: Re: how to let a ball fly like a ball
Post by: Khris on Tue 17/05/2011 23:19:50
Could you post a screenshot or mockup so we can get a clearer picture of how the ball is supposed to fly?
Title: Re: how to let a ball fly like a ball
Post by: Sephiroth on Tue 17/05/2011 23:37:22
One solution would be to use a function to move the ball, then you could use basic curves maths, I'm not that good with maths, but I think parabolla function would look like this: y = ax²

So you'd need to update the coords with something like this, assuming the ball moves from left to right on the screen.


function parabolla_movement()
{
 cBall.x = start_x;
 while(cBall.x < final_x)
 {
   cBall.x++;
   cBall.y = 2 * FloatToInt(Maths.RaiseToPower(IntToFloat(cBall.x),  2.0));
   Wait(1);
 }
}


This is just a basic example, you'd need to set the ball's starting point coords, the ending point coords, and then create the appropriate curve function.
Title: Re: how to let a ball fly like a ball
Post by: Snarky on Tue 17/05/2011 23:40:52
For this, what you want to do is not have the ball "walk", but move it by setting the x and y coordinates of its position according to a function that describes how it flies.

Appropriately enough, the science of how things fly when you throw them (or in this case hit them) is called ballistics. The simple answer is that a flying projectile follows a parabolic path, or in other words the curve described by -X^2.

If your starting point and ending points are at the same height and you know the distance to the ending point, you just need to decide how high up the top point of your curve should be. With that decided, you can define a function that gives you the Y coordinate for every X coordinate.

Then you can just do something like:


int ball_x = 0;
int ball_y = 0;
while(x<=target_dist)
{
 ball_y = calculateHeight(x, target_dist, max_height);

 ball.X = start_X + ball_x;
 ball.Y = start_y - ball_y;

 Wait(1);

 x++;
}


Off the top of my head, I think you would define the calculateHeight function something like this:


function calculateHeight(int x, int target_dist, int max_height)
{
 return max_height - (x-target_dist/2)*(x-target_dist/2)*max_height/(target_dist/2)/(target_dist/2);
}


(That expression can definitely be simplified, and may not be 100% correct. But I can't be bothered to do algebra at this hour.)
Title: Re: how to let a ball fly like a ball
Post by: Khris on Tue 17/05/2011 23:49:09
I think maybe it's better here not to use a fixed endpoint.
After all, golf is basically choosing direction and force, and aiming for the hole is the whole point.

I'll wait for the screenshot.
Title: Re: how to let a ball fly like a ball
Post by: Wyz on Tue 17/05/2011 23:56:44
Don't you need something like friction then? Well I don't know what the view it uses so a picture would certainly help.
Title: Re: how to let a ball fly like a ball
Post by: Sephiroth on Wed 18/05/2011 00:14:34
Don't you need a fixed end_point? I mean you calculate the impact point according to whatever(wind, force accuracy etc) then make the ball go to that point with a curve? Or did you mean it should rather have an impact on a random point inside a restricted area?
Title: Re: how to let a ball fly like a ball
Post by: Khris on Wed 18/05/2011 01:04:58
No, what you'd usually do is use a movement vector for the ball and add that to its position every frame.
The initial vector is determined by direction and force (= length), and during the flight, wind and gravity change the vector. Gravity for instance will add a constant value to the y component every frame.

The only downside of this physically accurate method is predetermining the flight path is a bit harder.
On the other hand, calculating ground collisions and bouncing is a piece of cake (at least on even ground).
Title: Re: how to let a ball fly like a ball
Post by: Miori on Wed 18/05/2011 01:07:11
Thanks for the answers  :).

@ Snarky
I tried your script, but maybe I am to stupid to implement it XD. The ball just flies high, and falls down again. But it doesnt move on the x-scale. When I try to just + the cBall.x while its under the distance, it doesnt work anymore.


The Golf Scenes of the game will just be simple sideview. Here is a screenshot:

(http://img856.imageshack.us/img856/3855/screent.th.png) (http://imageshack.us/photo/my-images/856/screent.png/)

Uploaded with ImageShack.us (http://imageshack.us)

Don't wonder about the simple graphics, it's just for testing. It works following:

1. Mouseclick
Make the black bar move on the grey one, to the max and back.

2. Mouseclick
Marks the sport hitted on the bar and shows the distance in the upper label in yards and the bottom label in pixel.

3. Mouseclick
Stop the bar moving and hit the ball. If you hit the white bar, it adds distance.

If you don't click after the first Click the black bar will move to the beginning and you can try again.

The distance will also be caused on which racket you choose, wind, equip and character stats.

Title: Re: how to let a ball fly like a ball
Post by: Khris on Wed 18/05/2011 01:34:32
So is the ball supposed to hit arbitrarily sloped ground? With bouncing and rolling?
Title: Re: how to let a ball fly like a ball
Post by: Miori on Wed 18/05/2011 01:47:13
Yeah it should bounce and roll after it landed somewhere  :) but for now it is even not flying, so not able to land somewhere  ;D
Title: Re: how to let a ball fly like a ball
Post by: Snarky on Wed 18/05/2011 07:14:15
Quote from: Miori on Wed 18/05/2011 01:07:11
Thanks for the answers  :).

@ Snarky
I tried your script, but maybe I am to stupid to implement it XD. The ball just flies high, and falls down again. But it doesnt move on the x-scale. When I try to just + the cBall.x while its under the distance, it doesnt work anymore.

Ah, that's because I forgot what I had called the x variable. Try this:


int ball_x = 0;
int ball_y = 0;
while(ball_x<=target_dist)
{
 ball_y = calculateHeight(ball_x, target_dist, max_height);

 ball.X = start_X + ball_x;
 ball.Y = start_y - ball_y;

 Wait(1);

 ball_x++;
}


QuoteThe Golf Scenes of the game will just be simple sideview. Here is a screenshot:

(http://img856.imageshack.us/img856/3855/screent.th.png) (http://imageshack.us/photo/my-images/856/screent.png/)

Uploaded with ImageShack.us (http://imageshack.us)

The distance will also be caused on which racket you choose, wind, equip and character stats.
Quote from: Miori on Wed 18/05/2011 01:47:13
Yeah it should bounce and roll after it landed somewhere  :) but for now it is even not flying, so not able to land somewhere  ;D

Well, the code I showed will work well for the simplest case, but if you want sloped ground and bouncing and rolling balls and stuff like that, I think you're better off with Khris's suggestion. It will be a fair bit more difficult, though (particularly rolling, which is going to take a whole other chunk of programming). If you're not confident in your programming and math skills, I'd suggest scaling back your ambitions slightly.

What we're ultimately looking for here is a 2D physics engine, like Box2D (http://www.box2d.org/) (used in Angry Birds, Fantastic Contraption, Crayon Physics etc.). It would be awesome if there were a module like that for AGS.
Title: Re: how to let a ball fly like a ball
Post by: Calin Leafshade on Wed 18/05/2011 11:14:59
I actually half started an interface for Box2D. The format of that library makes it very AGS friendly.

I never finished it though because no one uses plugins  :=
Title: Re: how to let a ball fly like a ball
Post by: Snarky on Wed 18/05/2011 12:50:57
Yeah, that's why I suggested a module instead, with a simplified version of the library.

An actual Box2D API would be awesome, though. And it wouldn't even have to be a plugin, now: it could go directly in the engine! (Box2D is at least as portable as AGS, and the license is very flexible.) If only there was more call for it; not too many adventure games use physics-based gameplay.

To come clean, the reason I'm interested in this (apart from the fact that the very first piece of AGS code I wrote back in 2004 was a simple ballistics function to replicate the "rubber tree" scene from Monkey Island) is that I've planned a physics-based puzzle for the game I'm working on. I take it SSH just wrote a simple projectile motion function for Pigeon Pingers?
Title: Re: how to let a ball fly like a ball
Post by: Khris on Wed 18/05/2011 13:01:11
This (http://dl.dropbox.com/u/995571/Pinball.rar) is how far I got a few days ago; I still have to implement rolling though. It's pretty modular but the ball occasionally drops through the lines so I'd rather not publish it yet.
Tap Space to hurl the ball upwards, F9 restarts, Esc quits.
Title: Re: how to let a ball fly like a ball
Post by: Miori on Wed 18/05/2011 14:05:47
Quote from: Snarky on Wed 18/05/2011 07:14:15
Well, the code I showed will work well for the simplest case, but if you want sloped ground and bouncing and rolling balls and stuff like that, I think you're better off with Khris's suggestion. It will be a fair bit more difficult, though (particularly rolling, which is going to take a whole other chunk of programming). If you're not confident in your programming and math skills, I'd suggest scaling back your ambitions slightly.

To be honest I would be really happy if it just would fly like it should. I added your change. Now the ball moves on x-scale yay  ;D but not on y-scale anymore  :o It doesn't wanna do both  :P

Title: Re: how to let a ball fly like a ball
Post by: Snarky on Wed 18/05/2011 14:43:34
Yeah, I missed another instance of x in the script that should have been ball_x (fixed now). Sorry about that. I'm a sloppy coder; even if I know how to solve a problem, it usually doesn't come out right the first time. It's just a matter of looking at the code, figuring out what's wrong and fixing it until it does what you want.

But let me put this to you: Do you understand the code? Do you see why it works or doesn't work? I mean, if you just copy-paste this stuff without building any understanding yourself, you might get this particular thing to work, but you'll never be able to change and improve on it, and those other things you describe won't be possible.
Title: Re: how to let a ball fly like a ball
Post by: Miori on Wed 18/05/2011 15:04:48
Now it works, thank you very much. And I programm my games in the same way, I'm a bit sloppy too.  :P

I understand how it works a bit, but not completely. It says it should calculate y while its moving to the targeted x. But I don't really know, how you calculate the y in the formula

return max_height - (x-target_dist/2)*(x-target_dist/2)*max_height/(target_dist/2)/(target_dist/2);

I don't know what that all means, and why the ball flies slower, when it's higher.

And is it possible to change the speed of the ball, it's flying very slow.
Title: Re: how to let a ball fly like a ball
Post by: Snarky on Wed 18/05/2011 17:22:54
OK, good!

The y-calculation is the formula for an upside-down parabola which crosses the x-axis at 0 and target_dist, and reaches max_height in the middle (which it is symmetric around). Since the standard X^2 function is symmetric around x = 0, we subtract target_dist/2 from the x-value so it'll be symmetric around that point instead (essentially shifting the curve to the right). Apart from the first term, the rest of the equation is with a negative sign so that the parabola is upside-down.

*max_height/(target_dist/2)/(target_dist/2) is a way to scale the parabola along the y-axis, because we want the difference in height between the lowest points (x=0 and x=target_dist) and the highest point (x = target_dist/2) to be max_height, not (target_dist/2)^2.  And having (+) max_height at the beginning shifts the curve up so that the top point is at that y-value. Like I said, this isn't the simplest form of this equation, I just wrote it down according to the logic just described.

The ball should move at the same speed along the x-axis (you increment ball.x by one each loop, moving the ball one pixel to the right), but along the y-axis it moves slower when it's higher. Why? Because of course it starts moving up quickly, then more and more slowly until reaches the highest point, and then it turns around and starts falling faster and faster. That's realistic. However, by doing this all with ints, there's likely to be some serious rounding errors, so the y-movement could be off in ways that makes it move even slower. Really the best way is to convert everything to floats, do the calculation, and then round the result to the nearest int.

To make it move faster, instead of doing ball_x++ at the end of the loop, you can increment ball_x by 2 or more. But then you should set the coordinates to the target after the loop finishes, since it might skip the last step otherwise. Again, you can use floats to set fraction-of-a-pixel movements, but you'll need to keep track of error terms and stuff like that, and at that point you might as well go with Khris's vector idea.
Title: Re: how to let a ball fly like a ball
Post by: Miori on Wed 18/05/2011 20:58:23
Ah, I think I understand it better now, even if not completely. I'm happy its working now, also that could make it faster. No slow-motion flying ball anymore  ;D

But could I bother you with another question? How can I make the function stop? I mean, you see the hill on my screenshot. A variable has to be true, when the shot begins. I made a collidingwithobject function, that makes this variable false, to stop it and do other things. It works, but not until the ball reached the target.

With other words: Can I abort the while-process, before it reaches the target?
Title: Re: how to let a ball fly like a ball
Post by: Kweepa on Wed 18/05/2011 21:23:40
A golf ball trajectory doesn't look like a parabola.
This page might help:
http://www.golf-simulators.com/physics.htm
Title: Re: how to let a ball fly like a ball
Post by: Ryan Timothy B on Thu 19/05/2011 17:39:22
Quote from: Calin Leafshade on Wed 18/05/2011 11:14:59
I actually half started an interface for Box2D. The format of that library makes it very AGS friendly.

I would definitely use that plugin. But since AGS is now open-sourced, we may not need to have it as a plugin.

And yes. I would have a huge use for Box2D in AGS. Maybe not for your standard adventure game, but for other projects I've been dreaming of making.
Title: Re: how to let a ball fly like a ball
Post by: Calin Leafshade on Thu 19/05/2011 18:40:45
Ahhh, I would advise against that.

We shouldn't add loads of tenuous shit to the engine for the sake of it.

What we should do however is expand the plugin system and make it cross platform and *then* add physics using that system.
Title: Re: how to let a ball fly like a ball
Post by: Snarky on Thu 19/05/2011 19:39:52
Yeah, I don't think we should bundle a physics engine with AGS unless there's actually significant proven demand for one. (And even then it would probably be better to modularize the engine through the plugin system.) If we could have a plugin first, we can see how much use it gets. I haven't had time to look at Khris's example, but I'd much appreciate any module/plugin code either of you get to a releasable state.

Quote from: Miori on Wed 18/05/2011 20:58:23
Ah, I think I understand it better now, even if not completely. I'm happy its working now, also that could make it faster. No slow-motion flying ball anymore  ;D

But could I bother you with another question? How can I make the function stop? I mean, you see the hill on my screenshot. A variable has to be true, when the shot begins. I made a collidingwithobject function, that makes this variable false, to stop it and do other things. It works, but not until the ball reached the target.

With other words: Can I abort the while-process, before it reaches the target?

It's possible (add an additional check in the while condition), but like I said above, the more fancy you want to get, the more it makes sense to go with Khris's proposal, because you can extend it cleanly to cover all sorts of things (like Kweepa's non-parabolic trajectories) and cases you haven't thought of, instead of having to add special hacks for everything that might happen.
Title: Re: how to let a ball fly like a ball
Post by: Ryan Timothy B on Thu 19/05/2011 20:17:30
Oh I didn't mean as an actual version that is released on the website as AGS already is. I meant as a separate engine designed for arcade games.
But I know it has been expressed that AGS shouldn't go into different paths, but I don't see a problem with an arcade AGS engine.
Title: Re: how to let a ball fly like a ball
Post by: Rocco on Fri 20/05/2011 15:43:22
Quote from: Khris on Wed 18/05/2011 13:01:11
This (http://dl.dropbox.com/u/995571/Pinball.rar) is how far I got a few days ago; I still have to implement rolling though. It's pretty modular but the ball occasionally drops through the lines so I'd rather not publish it yet.
Tap Space to hurl the ball upwards, F9 restarts, Esc quits.

Hey Khris, great example, would love to see the code for this.   :)
Title: Re: how to let a ball fly like a ball
Post by: Kweepa on Sat 21/05/2011 04:42:39
Here's something to get you started using the Magnus effect:

float bx, by;
float dx, dy;
float av;

float airDensity = 1.225; // kg/m^3
float ballRadius = 0.02055; // m
float ballMass = 0.05; // kg
float dragCoeff = 0.5; // ball drag coefficient
float gravity = 9.8; // m/s^2

function room_RepExec()
{
  // use bearman and harvey
  float streamArea = Maths.Pi * ballRadius * ballRadius;
  float ddConstant = airDensity*streamArea/(2.0*ballMass);
  float dt = 0.025; // s

  // simulation step
  float vel2 = dx*dx + dy*dy;
  float vel = Maths.Sqrt(vel2);
  // calculate magnus effect
  float liftCoeff = av*vel/700.0;
  float cosAlpha = dx/vel;
  float sinAlpha = dy/vel;
  float ddx = -ddConstant*vel2*(dragCoeff*cosAlpha + liftCoeff*sinAlpha);
  dx = dx + ddx*dt;
  bx = bx + dx*dt + 0.5*ddx*dt*dt;
  float ddy = ddConstant*vel2*(liftCoeff*cosAlpha - dragCoeff*sinAlpha) - gravity;
  dy = dy + ddy*dt;
  by = by + dy*dt + 0.5*ddy*dt*dt;
 
  // bounce - depends on spin
  if (dy < 0.0 && by < 0.0)
  {
    vel = 0.7*Maths.Sqrt(dx*dx + dy*dy);
    // rotate a bit depending on the angular velocity
    float alpha = Maths.ArcTan2(-dy, dx);
    alpha = alpha + (av*av)/1000.0;
    dx = vel*Maths.Cos(alpha);
    dy = vel*Maths.Sin(alpha);
    av = 0.5*av;
  }
 
  // draw
  DrawingSurface *ds = Room.GetDrawingSurfaceForBackground();
  ds.DrawingColor = 7;
  ds.DrawPixel(FloatToInt(bx), FloatToInt(200.0-by));
  ds.Release();
}

function room_Load()
{
  // driver
  float launchSpeed = 150.0; // mph
  float launchAngle = 7.0; // degrees
  float spin = 3600.0; // rpm

  // 5 iron
  launchSpeed = 100.0;
  launchAngle = 30.0;
  spin = 7200.0;

  float vel = (1602.0/3600.0)*launchSpeed;
  float alpha = Maths.DegreesToRadians(launchAngle);

  bx = 0.0;
  by = 0.0;
  dx = vel*Maths.Cos(alpha);
  dy = vel*Maths.Sin(alpha);
  av = spin * 2.0 * Maths.Pi / 3600.0;
}
Title: Re: how to let a ball fly like a ball
Post by: Dualnames on Sun 22/05/2011 16:52:45
When all else fails SteveMcCrea ALWAYS PREVAILS. God, how are you so awesome?!!!! Please make a tutorial with details on how to become awesome. ;)