admin管理员组

文章数量:1287169

I'm making a game in javascript, where an object is supposed to bounce from walls. I really tried to get it to work myself, but it never works correctly.

Let's say theres a ball bouncing inside this cage (blue = 30°, brown = 60°);

The ball's coordinates are known. The angle of movement is known. The point of collision (P) coordinates are known. The angle of the wall is known. The ball's position is updating it's coordinates inside a setInterval function using this function:

function findNewPoint(x, y, angle, distance) {
var result = {};

result.x =(Math.cos(angle * Math.PI / 180) * distance + x);
result.y = (Math.sin(angle * Math.PI / 180) * distance + y);

return result;

So, upon colliding, there should be a function that properly changes the ball's angle. It's a very plicated problem it seems, because even if I know that the wall is 30°, its important to know from what side the ball is colliding into it. I tried using the "Reflection across a line in the plane" formula and also some vectors, but it never worked out for me. I'm not expecting a plete answer with code, if someone could suggest in what way this should be programmed, it would help aswell.

Edit: Thanks for your tips guys, I realized what was causing the most confustion; if I select an angle on the canvas with my mouse, the starting coordinate(0,0) is in the bottom left corner. But since the canvas' starting coordinate is in the top left corner, this has to be considered.

Basically using this formula for calculating the angle:

function angle(cx, cy, ex, ey) {
var dy = ey - cy;
var dx = ex - cx;
var theta = Math.atan2(dy, dx);
theta *= 180 / Math.PI; 
return theta;

}

if the ball moved from (50,50) to (100,100), the angle would be -45.

Now, this angle changes in the following way when hitting walls:

If im honest, I got these out of trial and error, am not really understanding why exactly 60 and 120.

I'm making a game in javascript, where an object is supposed to bounce from walls. I really tried to get it to work myself, but it never works correctly.

Let's say theres a ball bouncing inside this cage (blue = 30°, brown = 60°);

The ball's coordinates are known. The angle of movement is known. The point of collision (P) coordinates are known. The angle of the wall is known. The ball's position is updating it's coordinates inside a setInterval function using this function:

function findNewPoint(x, y, angle, distance) {
var result = {};

result.x =(Math.cos(angle * Math.PI / 180) * distance + x);
result.y = (Math.sin(angle * Math.PI / 180) * distance + y);

return result;

So, upon colliding, there should be a function that properly changes the ball's angle. It's a very plicated problem it seems, because even if I know that the wall is 30°, its important to know from what side the ball is colliding into it. I tried using the "Reflection across a line in the plane" formula and also some vectors, but it never worked out for me. I'm not expecting a plete answer with code, if someone could suggest in what way this should be programmed, it would help aswell.

Edit: Thanks for your tips guys, I realized what was causing the most confustion; if I select an angle on the canvas with my mouse, the starting coordinate(0,0) is in the bottom left corner. But since the canvas' starting coordinate is in the top left corner, this has to be considered.

Basically using this formula for calculating the angle:

function angle(cx, cy, ex, ey) {
var dy = ey - cy;
var dx = ex - cx;
var theta = Math.atan2(dy, dx);
theta *= 180 / Math.PI; 
return theta;

}

if the ball moved from (50,50) to (100,100), the angle would be -45.

Now, this angle changes in the following way when hitting walls:

If im honest, I got these out of trial and error, am not really understanding why exactly 60 and 120.

Share Improve this question edited Jul 18, 2017 at 2:00 Batash asked Jul 17, 2017 at 21:47 BatashBatash 1112 silver badges12 bronze badges 6
  • I realize that you did not ask for this, but have you considered using a javascript physics engine? There are plenty of them that do this kind of thing. If you're interested there is a game engine called (Phaser)[phaser.io/] that is pretty easy and has physics engines built in. If you don't want this, feel free to ignore it :) – Alex Bieg Commented Jul 17, 2017 at 21:52
  • Thanks, but this really is the only "physics" part of my game, which I expected myself to be able to solve it, now I've already done too much using node.js :(. – Batash Commented Jul 17, 2017 at 21:55
  • Can you describe what's not working correctly? Also, try simplifying your problem and start with a vertical wall or a horizontal wall. The angle of reflection is always the angle of incidence. Or as Cyberchase put it, angle in = angle out. This is true for walls at 90 degrees and 0 degrees. But what about some other angle? Well think about what would happen if you took your whole image and rotated it so that the 30 degree wall turned into a 90 degree wall (vertical). How would the angle of the ball change? – Khauri Commented Jul 17, 2017 at 21:56
  • I think one thing that might be confusing is you is saying "blue is 30 degrees, brown is 60", etc. If you look at all the blue walls, the normal line (that the ball's angle will reflect across) is different. Some might be called 30, and some -30 degrees depending where you measure from. Figure out how you're recording your angle for the ball, and use that standard carefully on the walls as well. – arbuthnott Commented Jul 17, 2017 at 23:52
  • Is it even possible to turn this into one function? At the moment I'm simply using if statements for the different functions when hitting different corners (if you look at my edited post). – Batash Commented Jul 18, 2017 at 2:04
 |  Show 1 more ment

3 Answers 3

Reset to default 6

It is not wise to use angle for moving ball and calculate Cos/Sin again and again. Instead use unit velocity direction vector with ponents vx, vy like this:

new_x = old_x + vx * Velocity_Magnitude * Time_Interval

Note that vx = Cos(angle), vy = Sin(angle), but with direction approach you seldom need to use trigonometric functions.

Tilted wall with angle Fi has normal

nx = -Sin(Fi)
ny = Cos(Fi)

To find reflection , you need to calculate dot product of velocity and normal

dot = vx * nx + vy * ny

Velocity after reflection transforms:

vnewx = v.x - 2 * dot * n.x 
vnewy = v.y - 2 * dot * n.y 

Use these values for further moving

(note that you can use both internal and external normal direction, because direction flip changes both ponents, and sign of 2 * dot * n.x remains the same)

Examples:

horizontal moving right
vx=1, vy=0   
30 degrees wall has normal 
nx=-1/2, ny=Sqrt(3)/2  
dot = -1/2
vnewx = 1 - 2 * (-1/2) * (-1/2) = 1/2
vnewy = 0 - 2 * (-1/2) * Sqrt(3)/2 = Sqrt(3)/2
(velocity direction angle bees 60 degrees)

horizontal moving left
vx=-1, vy=0   
330 degrees wall (left bottom corner) has normal 
nx=1/2, ny=Sqrt(3)/2  
dot = -1/2
vnewx = -1 - 2 * (-1/2) * (1/2) = -1/2
vnewy = 0 - 2 * (-1/2) * (Sqrt(3)/2) = Sqrt(3)/2
(velocity direction angle bees 120 degrees)

Here is a function that returns the angle of reflection given an angle of incidence and a surface angle (in degrees). It also ensures that the returned angle is between 0 and 359 degrees.

function angleReflect(incidenceAngle, surfaceAngle){
  var a = surfaceAngle * 2 - incidenceAngle;
  return a >= 360 ? a - 360 : a < 0 ? a + 360 : a;
}

Here's a demonstration, where the blue line is the angle of incidence, the purple line is the angle of reflection, and the black line is the surface.

If you're assuming that the ball behaves like light bouncing off a mirror, then the angle of incidence equals the angle of reflection.

So your board is 30° from 0° (straight up). The means the normal (perpendicular to the board at the point the ball hits ) is 300°. Say the ball arrives from 280°, it must leave at 320° as the difference between the angle of incidence and the normal and the angle of reflection and the normal must be equal.

本文标签: javascriptCalculate angle change after hitting a tilted wallStack Overflow