How are sine and cosine used for collision detection? - javascript

I'm working through a tutorial to make the old arcade game Breakout - you have a paddle at the bottom of the screen and the goal is to deflect a moving ball into a series of blocks at the top of the screen.
The code to calculate the rebound effect is:
ball.dx = ball.speed * Math.sin(angle);
ball.dy = - ball.speed * Math.cos(angle);
The yellow circle represents the ball:
I understand sine and cosine as ratios of the hypotenuse; I just still can't seem to grasp how they are used to calculate the rebound angle here exactly. Can anyone explain how the resulting numbers, given an angle and a speed value, produce the directionality of the ball on rebound? I feel there's a simple conceptual piece of the puzzle I'm missing.

This is vector adding - the X and Y vector added give you the new speed value.
To easier understand how sin and cos work here, take the case of angel = 0 deg. The ball falls straight down, and should bounce back up:
ball.dx = ball.speed * Math.sin(0); // 0
ball.dy = - ball.speed * Math.cos(0); // 1
So there's no movement left or right, speed is the same but the vertical direction is reversed because of the minus sign.
Using sin and cos here takes care of having a constant speed, as well, as these always sum up to 1.
Hope that's a bit more clarifying than confusing, but I did some similar code tasks that got easily solved with basic vector operations.

Related

N-Body Gravity / Solar System Javascript Simulation

Good day, I am trying to create a simple 2D solar system model in javascript, but am having some trouble understanding how to go about calculating where planets will be for the next frame, aswell as a few other bits which I'll go into detail with soon.
After watching this very nice video and a whole bunch of his others, I made a quick MS paint image to try and simplify my situation.
With the second scene, you can see that the new position is calulated using the velocity, gravitational pull, and the angle between these two 'directions'?
I cannot get my head around how to figure this all out.
Below is a JS fiddle of my code. You'll notice I'm trying my best to use real NASA given data to keep it accurate.
You'll want to look specifically at lines 138 which is where all the calculations for its next move are made.
https://jsfiddle.net/c8eru7mk/9/
attraction: function(p2) {
// Distance to other body
var dx = p2.position.x - this.position.x;
var dy = p2.position.y - this.position.y;
var d = Math.sqrt(dx ** 2 + dy ** 2); // Possibly correct
// Force of attracrtion
this.f = G * (this.mass * p2.mass) / (d ** 2); // Possibly Correct
// Direction of force, If you read it hard enough you should be able to hear my screams of pain
// Not sure if this is correct, most likely not.
var theta = Math.atan2(dy, dx);
var fx = Math.cos(theta) * this.f;
var fy = Math.sin(theta) * this.f;
this.velocity.x += fx / this.mass;
this.velocity.y += fy / this.mass;
this.position.x += this.velocity.x;
this.position.y += this.velocity.y;
}
The problems I'm currently facing are
If I am to use NASA values, the distance between planets is so big, they won't fit on the screen, and I can't simply scale the distances down by multiplying them by 0.0002 or whatever, as that'll mess with the gravitational constant, and the simulation will be completely off.
I have no idea how to caluclate the next position and my brain has imploded several times this past week trying to attempt it several times.
I have no idea on how to check if my configuration data of planets is wrong, or if the simulation is wrong, so I'm pretty much just guessing.
This is also my first time actually coding anything more complex than a button in javascript too, so feedback on code layout and whatnot is welcome!
Many thanks
Using NASA values is not a problem when using separate coordinates for drawing. Using an appropriate linear transfomration from real coordinates to screen coordinatees for displaying does not influence the physical values and computations.
For simulating the motion of a planet with iterative updates one can assume that the gravitational force and the velocity are constant for a small portion of time dt. This factor dt is missing in your conversions from accelration to velocity and from velocity to distance. Choosing an appropriate value for dt may need some experiments. If the value is too big the approximation will be too far off from reality. If the value is too small you may not see any movement or rounding errors may influence the result.
For the beginning let us assume that the sun is always at (0,0). Also for a start let us ignore the forces between the planets. Then here are the necessary formulas for a first not too bad approximation:
scalar acceleration of a planet at position (x,y) by the gravitational force of the sun (with mass M): a = G*M/(d*d) where d=sqrt(x*x+y*y). Note that this is indepent of the planet's mass.
acceleration vector: ax = -a*x/d, ay = -a*y/d (the vector (-x,-y) is pointing towards the sun and must be brought the length a)
change of the planet's velocity (vx,vy): vx += ax*dt, vy += ay*dt
change of the planet's position: x += vx*dt, y += vy*dt

Breakout game math - angle to dx,dy [duplicate]

This question already has an answer here:
How to have ball bounce off paddle in right directions not as a straight line
(1 answer)
Closed 5 years ago.
I am making a basic javascript game of breakout but I have not really learned math yet so I'm having some issues..
I want to have the ball hit the paddle and get bounced off at an angle dependant on where it hits the paddle.
I just made this function that calculates an angle from 0-180 degrees when the ball hits the paddle. That angle is what the ball will need to move at (I know right now that will be an issue if the ball hits the tip of the paddle, but I'll deal with that later) Now I need to find a way to get a dx and dy from that, and I know I will need to use trigonometry to do so. (x is the variable for the ball's x coordinate)
function getBallAngle(){
const maxAngle = 180;
let hitPosition = (x - paddleX);
let ballAngle = 0;
const scaleToAngle = maxAngle / (paddleWidth);
ballAngle = hitPosition * scaleToAngle;
return ballAngle; }
I'm a bit lost right now, would appreciate some math help please.
edit: I already have the game working but without this feature that would change the angle the ball bounces off the paddle.
Consider the moving ball has having both an x and a y component (as you implied with your request for dx and dy). Since you are writing this in javascript, these values can be assigned to your ball object so that they can be referenced on every tick (i.e. every time your program calculates the current state of the game and re-renders all display objects).
Assuming, for the moment, that we are only dealing with the paddle then we can assume that when the ball strikes the paddle the horizontal movement factor (the x) will not change (we don't want the ball careening backwards off the paddle.. except in the literal edge case..). And since we are treating the paddle like a reflective surface, the vertical movement factor (the y) will simply switch from moving in a downward fashion to an upward fashion (accomplished most easily via multiplication by -1).
Therefore, the "angle" that you are looking for is actually just a reversal of the y component of your ball's movement property.

Control object around sphere using quaternions

In my game the user controls an airplane (seen from the top), flying over the earth (a Sphere object). The airplane can rotate (steer) left or right (by pressing the LEFT or RIGHT arrow keys) and it can accelerate by pressing the UP arrow key. So the airplane always has a direction (rotation) and a certain speed (velocity) based on user input, stored in vx & vy variables.
In the render loop the vx & vy variables are used to rotate the globe. So the airplane does not actually move, it is the globe below the airplane that rotates to give the impression of the airplane flying over the earth.
This is all wonderful, until the player "reaches" the other side of the globe with his airplane. Now when the user flies "to the right" of the screen, the earth also rotates to the right, which makes it look that the airplane is flying backwards. The issue comes from trying to fit in some old 2D code of a previous airplane game of mine into this 3D game.
I would like to know how to solve this issue with quaternions. I am certain that I need those, but I just don't understand them fully. I figure that my vx and vy variables could still be useful for this, as they could make some kind of "new location" vector. From what I read is that I should normalize vectors, get an axis and an angle, but I am not sure of what and how to get these. Any help would be greatly appreciated!
Below is the code that rotates the earth when the user flies in a certain x/y direction plus an image to get a better picture of the game situation.
// AIRPLANE VARS
var friction = 0.85;
var vr = 7.5; // Rotate-velocity
var thrust = 0.5;
var max_speed = 20;
var vx = 0; // X-velocity
var vy = 0; // Y-velocity
// RENDER LOOP
function render() {
// check states
if (rotate_left) {
player.rotation.y = player.rotation.y + (vr * (Math.PI / 180));
} else if (rotate_right) {
player.rotation.y = player.rotation.y - (vr * (Math.PI / 180));
}
if(throttle){
//var radians = ((player.rotation.y * Math.PI) / 180);
var radians = player.rotation.y;
var ax = (Math.cos(radians) * thrust);
var ay = (Math.sin(radians) * thrust);
vx = vx + ax;
vy = vy + ay;
} else {
//ship.gotoAndStop(1);
vx = vx * friction;
vy = vy * friction;
}
// rotate the globe in the opposite direction of the airplane movement
globe.rotation.x = globe.rotation.x - (-vx/100);
globe.rotation.y = globe.rotation.y - (vy/100);
}
I am not familiar with your implementation framework, which appears from your tags to be three.js. It is also a bit difficult to see how your 'turn' controls affect the player, because you did not mention how the axes of the plane is defined. I may not be much help but I can give you some starting tips.
Firstly familiarise yourself with the structure of a quaternion and the implementation of it in three.js.
In many texts they appear as q = [w, x, y, z], however it seems in three.js they are defined as q = [x, y, z, w]. Don't worry too much about what those numbers are as they are very counter-intuitive to read.
There are a few ways to rotate the quaternion with respect to your velocity.
I think this is your best shot: rotate the quaternion by using the derivative equation given here, by calculating the angular velocity of the plane around the earth (and thus the earth around the plane). This is given by the 3D particle equation here. You can add the time-scaled derivative (dt*dqdt) to the quaternion q, then renormalise it in order to animate the rotation.
Another way is to pick a quaternion rotation that you want to end at, and use the slerp operation (built in to three.js).
If you give me some more details about how your sphere, plane and global frames are defined, I may be able to help more.

Raphael.js get rectangle coords after transform

I have a small little game I'm making in javascript and Raphael.js(which i'm fairly new to) and I'm making a turret essentially, just a circle that has a rectangle swivel around it. And that works fine and dandy!
Code for transform is :
this.self = this.self.animate({ transform : this.transform }, 250);
However, I need to find the coords of the rectangle after I animate it, but getBBox() keeps getting the same coords. Does anyone have any suggestions? A visual picture of the transform would be:
So I need the turret coords after the transformation. I need to find the front of the turret so I know where the bullet needs to come out of! Any advice will be appreciated!
By using the rotation number, will help you to find the coordinates. Lets say the rotation angel is q = 45 degrees.
This means that y changes by asin(q) and x changes by a - acos(q).
EDIT
Pay attention to all cases. In this particular case, both coordinates got decreased, but if you turn to southeast, then y increases and x decreases. Or if northwest: y and x decrease.
Transform is just a visual effect, it's not affects on coordinates.
You know width of turret and you know rotation angle.
Use sin & cos to calculate new coords.
X = Math.cos((i * Math.PI) / 180) * R + x;
Y = Math.sin((i * Math.PI) / 180) * R + y;
i - angle
R - width of turret
x and y - turret offset

Algorithm for moving an object horizontally in javascript

I am currently working on a game using javascript and processing.js and I am having trouble trying to figure out how to move stuff diagonally. In this game, there is an object in the center that shoots other objects around it. Now I have no problem moving the bullet only vertically or only horizontally, however I am having difficulty implementing a diagonal motion for the bullet algorithm.
In terms of attempts, I tried putting on my math thinking cap and used the y=mx+b formula for motion along a straight line, but this is what my code ends up looking like:
ellipse(shuriken.xPos, shuriken.yPos, shuriken.width, shuriken.height); //this is what I want to move diagonally
if(abs(shuriken.slope) > 0.65) {
if(shuriken.targetY < shuriken.OrigYPos) {
shuriken.yPos -= 4;
} else {
shuriken.yPos += 4;
}
shuriken.xPos = (shuriken.yPos - shuriken.intercept)/shuriken.slope;
} else {
if(shuriken.targetX < shuriken.OrigXPos) {
shuriken.xPos -= 4;
} else {
shuriken.xPos += 4;
}
shuriken.yPos = shuriken.slope * shuriken.xPos + shuriken.intercept;
}
The above code is very bad and hacky as the speed varies with the slope of the line.
I tried implementing a trigonometry relationship but still in vain.
Any help/advice will be greatly appreciated!
Think of it this way: you want the shuriken to move s pixels. If the motion is horizontal, it should move s pixels horizontally; if vertical, s pixels vertically. However, if it's anything else, it will be a combination of pixels horizontally/vertically. What's the correct combination? Well, what shape do you get if you project s distance in any direction from a given point? That's right, a circle with radius s. Let's represent the direction in terms of an angle, a. So we have this picture:
How do we get the x and the y? If you notice, we have a triangle. If you recall your trigonometry, this is precisely what the sine, cosine, and tangent functions are for. I learned their definitions via the mnemonic SOHCAHTOA. That is: Sin (a) = Opposite/Hypotenuse, Cos(a) = Adjacent/Hypotenuse, Tan(a) = Opposite/Adjacent. In this case, opposite of angle a is y, and adjacent of angle a is x. Thus we have:
cos(a) = x / s
sin(a) = y / s
Solving for x and y:
x = s * cos(a)
y = s * sin(a)
So, given the angle a, and that you want to move your shuriken s pixels, you want to move it s * cos(a) horizontally and s * sin(a) vertically.
Just be sure you pass a in radians, not degrees, to javascript's Math.sin and Math.cos functions:
radians = degrees * pi / 180.0
This may be why your trigonometric solution didn't work as this has bitten me a bunch in the past.
If you know the angle and speed you are trying to move at, you can treat it as a polar coordinate, then convert to cartesian coordinates to get an x,y vector you would need to move the object by to go in that direction and speed.
If you don't know the angle, you could also come up with the vector by taking the difference in X and difference in Y (this I know you can do as you are able to calculate the slope between the 2 points). Then take the resulting vector and divide by the length of the vector to get a unit vector, which you can then scale to your speed to get a final vector in which you can move your object by.
(This is what probably what kennypu means by sticking with vectors?)

Categories

Resources