Reputation: 10790
Just curious. When I bounce a ball off the walls of the stage using the following technique.
if(y > sRef.stageHeight || y < 0)
{
yDir = yDir * -1;
}
else if ( x > sRef.stageWidth || x < 0)
{
xDir = xDir * -1;
}
x += xspeed * xDir;
y += yspeed * yDir;
The above seems fine and works well. But If I choose to use angles instead like the following...
if(y > sRef.stageHeight || y < 0)
{
angle += 45;
}
else if ( x > sRef.stageWidth || x < 0)
{
//angle = angle * -1;
angle += 45;
}
vx = Math.cos(angle * Math.PI / 180) * bSpeed;
vy = Math.sin(angle * Math.PI / 180) * bSpeed;
x += vx;
y += vy;
Not only is the ball jumpy and skippy. but after so often it begins to go either in a vertal motion y = 5; x = 0; or a horzontal motion x = 5, y = 0. And stays that way. Why is it that the first method works fine but the other method works terrible. Could it be because the Math.cos and Math.sin returns very large decimals. could someone help me out please, cause I really prefer to use the second method.
Thanks
Upvotes: 0
Views: 4144
Reputation: 10790
I appreciate all the feed back. But the reason I wanted to use angles, is to control the direction of where the ball goes based on the speed of the paddle. In psuedo, this is what I am trying to do...
var tempSpeedX:Number = xspeed;
var tempSpeedY:Number = yspeed;
var tempDirY:Number = yDir * -1;
tempSpeedY = tempSpeedY * tempDirY;
var angle:Number = Math.atan2(tempSpeedY , tempSpeedX );
//angle = angle + ( paddle.cspeed * .4 );
xspeed = Math.cos(angle);
yspeed = Math.sin(angle);
trace(xspeed);
trace(yspeed);
yDir += tempDirY;
isHit = false;
tempSpeedX, tempSpeedY, and tempDirY are temporary variables used to hold my ball's x and y velocity. tempDirY is used to hold my Y axis direction. Either -1 or 1. What I am doing is trying to recreate the new angle.
Lets say the ball is moving at vx = 3, vy = 3. I know upon impact that ball will be heading at that direction. So what I do is flip the Y axis and get angle. That is what the following code does
tempSpeedY = tempSpeedY * tempDirY;
I take the current direction and multiply it by the speed to flip it going the other direction. What I do next is get the angle using atan2
var angle:Number = Math.atan2(tempSpeedY , tempSpeedX);
Once I get the new angle, At this point in time. I could alter the direction to where I want the ball to go based on my paddle.speed. where it is commented out I put code to alter the direction. I then would put it back to normal angle by using sin and cosine. then at it back to xspeed and yspeed. but this code doesnt work. not sure whats wrong.
I know what I am doing is little too complicated because of my lack of knowledge in physics. But the basic way is causing too many complication that I cant really explain it.
Lets say that the old way , the ball doesnt move in the direction the paddle is trying to take it. xDir is constantly flipping back and forth from -1 to positive makeing the speed flip back and forth from negative to positive. my paddle moves back and forth so that speed is negative and positive. and therefore sometimes the directions dont go they way they are suppose to. so I am trying to think of a better way of controlling the ball with the paddle
Upvotes: 0
Reputation: 308743
Gotta learn some physics to get this right. You need to think about the velocity in a coordinate system that is relative to the wall: one component parallel to the wall and the other perpendicular. (I'll assume 2D for simplicity's sake.)
The component of velocity perpendicular to the wall reverses in sign after the collision and has the same magnitude as before the collision (assuming an elastic impact with no energy loss).
The component of velocity parallel to the wall is unchanged (assuming an elastic impact and neglecting friction and rotational effects).
If you use that recipe to work out the velocity vector after impact you'll get it right.
Upvotes: 0
Reputation: 3794
From your other thread, your vx,vy are actually the cathetus of the angle you are looking for (vector actually, cause it has a magnitude)...
It's good thinking that you may have better control using angles, but for what you are trying to do you will mostly need to work with the X and Y components of that angle...
I think you have only one problem with your previous approach: You need a better control when the collition occurs so in the next step the ball wont collide again. For the walls is quite simple:
if(x<0) {
vx*=-1;
x=0;
}
You can use the same logic with the paddle, but its quite tricky to get it right, since in the next iteration the paddle might move over the position of the bounced ball, bounce back again, this time in the opposite direction, hence get stuck in the paddle.
You could try a few things to correct that, like preventing two or more consecutive paddle collitions, and/or restraining the vertical movement of the paddle, so on each collition you set the Y of the ball away from the paddle to ensure it wont hit it again in the next iteration (like with the walls).
The correct way of doing it though is much harder, since it depends on predicting exactly where the ball will hit (discarding the problem with iterations), combining the vector of the paddle with the ball's on that exact point, and a whole lot more math. Someone else can probably explain this much better than me. Or you might want to check some physics engine ^^
For learning porpouses though, I would advise you to keep trying to solve the collition with your previous approach and then get into the more complex stuff.
Upvotes: 0
Reputation: 64895
For one, incrementing by 45 degrees doesn't represent a reflection off of a surface. Imagine a ball heading nearly straight up, and slightly to the left - angle 70 degrees, say. When it hits the top, you'll add 45 to get 105, which is still nearly straight up, so the ball will continue out of bounds (up), and you'll add 45 again, to get 155, which is still going up, before finally getting around to 200.
You should use -ve the existing angle for a reflection of the "roof" and 180-angle for a reflection off the wall, I think.
Upvotes: 1
Reputation: 91442
it doesn't make sense to add 45 to the angle. That will steer your ball counterclockwise, regardless of which wall it is hitting. why would you prefer to use the second way? the first way makes more sense. you can use angle = Math.atan2(vy,vx)
to get the angle from your vx/vy coordinates
Edit You claim you can have easier way of controlling the speed of the ball hitting a moving paddle using the angle. Actually, what really occurs is that when the ball hits the paddle, some part of the paddle's velocity is transferred to the ball, (in reality some of it is lost due to friction or conversion to angular momemtum)
if (hit a paddle) {
vx = -vx;
vy += a * paddle_vy; // a is a fudge factor between 0 and 1
}
if (hit a vertical wall)
vx = -vx;
if (hit a horizontal wall)
vy = -vy;
There really is no way to simulate this kind of behavior using just an angle.
Upvotes: 2