Forum Moderators: open

Message Too Old, No Replies

Grrr Math Moving an object at an angle or curve...

         

ShawnJC

11:59 pm on Feb 28, 2004 (gmt 0)

10+ Year Member



Ok, I suck at math. That's my biggest downfall as a programmer. Alright, now you can all laugh at my attempt at math in the following script. I'm trying to have this shoot into the center of the screen from the cannon. So I have this like 'cannonball' layer offscreen and then move it around after the flash movie gives a command to javascript. And I don't know what I'm doing....I've been over this script in many different ways and well...here's the script for the movement:

function moveToPosition (initualx,initualy,endx,endy,speed){
if ( Math.abs(initualx-endx) > Math.abs(initualy-endy) ) {
speedx = speed;
speedy = Math.round (speed / ( (initualx-endx) / (initualy-endy) ));
}

if ( Math.abs(initualx-endx) < Math.abs(initualy - endy) ) {
speedy = speed;
speedx = Math.round (speed / ( (initualy-endy) / (initualx-endx) ));
}

if ( Math.abs(initualx-endx) == Math.abs(initualy - endy) ) {
speedx = speed;
speedy = speed;
}
if ((initualx< (endx+speed)) ¦¦ (initualy < (endy+speed)) ¦¦ (initualx > (endx-speed)) ¦¦ (initualy > (endy-speed)) ) {

if (initualx < (endx)) {
initualx += speedx;
}

if (initualy < (endy)) {
initualy += speedy;
}

if (initualx > (endx)) {
initualx -= speedx;
}

if (initualy > (endy)) {
initualy -= speedy;
}

setTimeout ('moveToPosition ('+initualx+','+initualy+','+endx+','+endy+','+speed+')',50);
}
positionLayer ("cannonBallLayer", initualx,initualy);
}

the positionLayer function just moves that layer to an absolute position.
I'm calling it with this:
moveToPosition (ballxStart,ballyStart,ballxEnd,ballyEnd,10);

Where:
var cannony = getWindowHeight () -250;
var cannonx = 0;
var ballxStart = 250;
var ballyStart=cannony + 50;
var ballxEnd = (getWindowWidth ()/2 );
var ballyEnd = (getWindowHeight ()/2);

the cannony and cannonx are for the Flash movie.
Now, I thought this might work for a smooth movement to the center of the screen, but instead I get this mess:
[metalblend.com...]

Not only does it not move correctly, if it calls the script a second time, it pops up all over the place. Can anyone shed some light on this? I'm pulling me hair out ha ha.

Hanu

2:20 am on Feb 29, 2004 (gmt 0)

10+ Year Member



Maybe you could address the problem by thinking of the ball's position as a
function of time. Let's assume you want the ball arrive at the center in, say a
total time (tt) of 3 seconds at constant speed. Furthermore, let's assume that
ss=(xs,ys) is the starting point and se=(xe,ye) is the endpoint. For constant
speed movement, the distance travelled is proportional to the time passed and
the current position is the starting point plus the distance:

s = ss + t * v

The speed is the total distance divided by the total time. It can also be
shown that x and y may be treated independently, which gives

x = xs + t * ( xe - xs ) / tt
y = ys + t * ( ye - ys ) / tt

I never tried this but it should give you an idea:

function moveToPosition( t, tt, xs, ys, xe, ye ) {
positionLayer ("cannonBallLayer", xs + t * ( xe - xs ) / tt, ys + t * ( ye - ys ) / tt );
if( t < tt ) {
setTimeout ('moveToPosition ('+t+50+','+tt+','+xs+','+ys+','+xe+','+ye+')',50);
}
}

Call it like

moveToPosition( 0, 3000, ballxStart, ballyStart, ballxEnd, ballyEnd );

3000 is the total time in milliseconds, assuming that setTimeout works on
milliseconds. Things to look out for:

For higher numeric precision, if possible, do multiplication first, then division.

Check the max and min value for the variables you are using. I don't know JS
very well but doesn't it work on 16bit integers? If that is the case, you should
do division first, then multiplication. Otherwise you get numeric overflow. That
might be why your solution doesn't work.

You can also create a more realistic movement by slowing the speed down over time. But try this first and we'll see.

ShawnJC

9:55 am on Feb 29, 2004 (gmt 0)

10+ Year Member



Wow, thanks a lot man. You really know your math. And for not knowing javascript, your code worked perfect. The only thing I had to do is change from passing the t+50 in the setTimeOut function to just t and put a t+=50 earlier in the code. Here's what it looks like so far!

[metalblend.com...]

Now, just to animate an explosion in Flash....This job is a lot of firsts for me. I've never animated an explosion before....I'm thinking of taking some smokey/flamy looking movie clips and duplicating them with a fade out from the center. Anyway, thanks again for the help man, greatly appreciated!

Hanu

1:12 pm on Feb 29, 2004 (gmt 0)

10+ Year Member



You're very welcome! I didn't properly think about the "t + 50" thing but now I know why it didn't work. Putting it in brackets as in "( t + 50 )" should also work. Saves one more line of code ;-).

In reality hardly anything moves at constant speed because friction or air resistance will slow it down. For the cannonball it would mean that its speed decreases linearly. So instead of being constant, speed is a linear function of time. This would get us into quadric equations which I really hate. So we'll use a little trick: time warping. We still animate at a rate of 50 millis, but we'll pretend that less time has passed from step to step. This will fool the equations into producing smaller travelled distances for each iteration and create the impression of slowing the movement down. The only problem is that the whole animation will take longer than estimated. You might wanna compensate for this by reducing the tt parameter.

function moveToPosition( t, a, tt, xs, ys, xe, ye ) {
var v = 50; /* initial velocity */
positionLayer ("cannonBallLayer", xs + t * ( xe - xs ) / tt, ys + t * ( ye - ys ) / tt );
if( t < tt ) {
t += v - a
a += v * v / ( tt - v );
setTimeout ('moveToPosition ('+t+','+a+','+tt+','+xs+','+ys+','+xe+','+ye+')',50);
}
}

Call it like

moveToPosition( 0, 0, 400, ballxStart, ballyStart, ballxEnd, ballyEnd );

ShawnJC

2:46 pm on Feb 29, 2004 (gmt 0)

10+ Year Member



Well, I actually already finished with the code for the most part, thanks to your help. It's at the same addy for now:
[metalblend.com...]

Just need to clean up some unnecessary code, do a couple things for Netscape and Mozilla (currently they don't get to see the explosion), and put some checks for stuff loaded in there, but other than that it's pretty much the way it's gonna be I think. I'm not really happy with the explosion effect, but I really don't know how to go about animating something like that. My favorite of this project has to be the cannon rolling out on the stage. Cannon was done in a shareware 3d program and then textured up in photoshop and the shadow for the rolling wheel was a masked wheel shadow in Flash.
I'll definetally have to look at that new code some more, probably later tonight or tomorrow. I just punched it in to see the difference and whoa...pretty cool effect of shooting a cannon into a heavy wind, but not exactly the desired effect heh... I'll look at it more later though...I'm sure I could use math like that for other variations in the future.

Hanu

8:46 pm on Feb 29, 2004 (gmt 0)

10+ Year Member



>not exactly the desired effect

Yes, not intended. It's a mistake. It should be

a += v * v / ( 2 * ( tt - v ) );

As I said, I suck at quadric equations ;-) Oh, and yes, I don't see the ball in Mozilla ...