I'm working on writing a Pong game and I've run across a problem.
I'm trying to figure out how to bounce a point off of a line.
The best method I can figure out to do this with is
Calculate the current and future position of the Ball.
Line Segment: {Ball.location, Ball.location + Ball.direction} (Ball.location and Ball.direction use a custom vector/coordinate class)
Calculate if the generated line segment intersects with any of the walls or paddles.
??? Don't know how to do this yet (Will ask in a separate question)
At the first intersection found
Bounce the ball off of the line
Create a triangle formed with
a = Ball's current position
b = Intersection point of the line.
c = Closest point to the Ball's current position on the line.
Find the angle that the ball hits the line
angle = cos(distance(b, c) / distance(a, b))
Find the angle to rotate the ball's direction
(90 - angle)*2
Rotate Ball's direction and move it to it's new position
ignoring distance traveled to hit the line for now, doesn't need to be exactly on the line
Else if there is no intersection
Move the ball to it's new position.
Is this an acceptable method or am I missing something?
You just need to check if the center of the ball is within its radius of the paddle to tell whether or not its time to bounce. There was an older question asked that has several answers on calculating bounce angle.
If you want the authentic Pong feel, then computing the new vector is much easier than doing real reflections. Pong just reverses the sign of either dx or dy. If the ball hits a horizontal barrier, then negate dy. Vertical, then negate dx.
In your game loop, calculate the new ball position as if there were no obsticals.
Then check to see if the new position intersects with or is PAST the obstical edge.
If either condition is met, then calculate a new ball position by bouncing it off the obstical.
A method that calculates a point given a starting point, angle, and distance would come in handy:
Public Function TranslatePoint(ByVal tStartPoint As Point, _
ByVal tAngle as Decimal, ByVal tDistance As Decimal) As Point
Here is what I would do:
1) assume your pong sides are at the lines x=a and x=b
2) let your balls position be (x0, y0) and traveling on the line Ax+By=C
3) from this you can calculate easily (x1, y1) the point where that line intersects
the wall
4) you can get the equation of the line after the bounce by knowing that
(x0, y1+y0) is the reflection after the bounce. (The ball is y1-y0 below the
intersection point and hence will be y1+y0 above the intersection point.)
5) given the 2 equations you can plot your points (assuming you know the velocity).
You may be interested in the N Tutorials, which discuss collision detection and response (including bounce and friction) used in the game "N".
The tutorials may go deeper than you particularly need, but they're well-written and have interactive examples -- and simple bounce is one of the first topics.
Bouncing is a problem from the physics domain, not the graphics domain. Therefore OpenGL offers no real support for it. If you look at the hardware, you'll notice that there have been seperate physics cards similar to videocards, although the most recent trends are to integrate them.
Related
So basically I'm making a pool game (sort of) on c++. I'm still thinking about the theory and how exactly to make it before I start coding and I'm a bit stuck. So the ball starting coordinates are given and also an input is given on how much power is going into the shot and the direction of the shot with coordinates.
Example:
> Ball: (280,70)
Input:
> 2(power) 230(x) 110(y)
Output:
> 180(x) 150(y)
The power means that basically it's going to go X * the distance of the given coordinates. So if it's 1 it would just go to 230 110 but if it's more it will go double, triple, quadruple, etc. times that distance. (external factors should be ignored - friction, etc.)
By now I've managed to create an algorithm to find the line that the ball is going to travel on. But I can't figure out on what point of this line the ball will stop at. Any help will be greatly appreciated!
Also one more thing, I also need to calculate where it would go if it hits the wall of the pool table(pool table is a 2:1 rectangle with given coordinates of edges) and I've also managed to find the line where it would travel on but not the exact point where it will stop.
TL;DR I need to find the point of the line of travel that a billiards ball will stop at.
You probably want to work in terms of orthogonal components, basically thinking of the displacement of the ball in terms of deltaX and deltaY instead of finding a line it will travel. Conveniently, you are already in rectangular coordinates and can compute your changes in x and y followed by scaling them by your power factor. For example, here, deltaX = 2*(280-230) or -100, so the destination will be 280 + -100, which equals 180.
To account for the edges, you bound the movement in any direction to be within the 4 edges. You'll have some extra displacement if it strikes the edge. You might think of a bounce as reversing some of the remainder and then recursively call your moveBall function with power 1 when given the location on the edge the ball strikes plus the excess deltaX and deltaY changed in sign appropriately. If moveBall took std::pair<int, int> startingPosition, std::pair<int, int> displacement, int power, if it hits the wall, you'll return moveBall(locationOnEdge, predictedLocationBasedOnExcess, 1). This setup will recursively call itself as many times as is needed until the ball finally finds its ending position (a ball can bounce off edges multiple times).
For example, if you had an edge at x = 200 and y = 100 (meaning your asserted desired output was different), you'd have a remaining deltaX of -20 and deltaY of 50. Since the ball was traveling up and to the left, it will bounce down and to the left. You'd call moveBall with starting location (200, 100), displacement (-20, -50), and power 1.
I'm doing some guesswork here since you didn't define the expected behavior when the ball bounces off an edge.
I'm building a server-side(!) for online game and I need to check if bullet hit a target.
Client sends me position and angle of bullet fired, I know all the enemies coordinates and sizes. How can I calculate if bullet hit an enemy after a bullet fired? Enemies have different sizes, bullet is 1px size.
For example, I have player shooting angle of 45 degrees from 0, 0 coordinates, and an enemy on 200, 200 coordinates with 10 width, 15 height. How do I calculate that bullet hit the enemy?
UPDATE: The game is 2d dhooter from the top, like Crimsonland. Projectiles have start speed which decreases slowly.
You should get a glance at the power of a point.
It will allow you to know the minimal distance between a line and a point.
So if the distance is lower than the width of the target, it's a hit !
The easiest way is to just check if the bullet is inside the rectangle of the enemy. If it is, dispose the bullet and the enemy.
basically:
while(game.is_on()){
for(enemy = enemyCollection.begin(); enemy != enemyCollection.end(); ++enemy){
if(enemy.contains(bullet)){
enemy.dead();
bullet.hit();
}
}
If you need to check whether line intersects rectangle, then apply orientation test based on cross product - if sign of cross product is the same for all rectangle vertices - line does not intersect it.
Line L0-L1, point P
Orientation = Cross(P - L0, L1 - L0)
(instead of L1-L0 components you can use Cos(Fi) and Sin(Fi) of shooting angle)
If you need to get intersection points, use some algorithm for line clipping - for example, Liang-Barsky one.
It's not quite as easy as it looks. To get a full solution, you need to extrude your objects along their paths of travel. Then you do object to object intersection tests.
That's difficult, as extrusion of an arbitrary shape by an arbitrary path is hard. So it's easier to cheat a little bit. Bullets can have no area, so they are just line segments. Make sure the step size is low enough for the line segment to be relatively short. Then make the ships rectangles, again with relatively short lines. Now it's lots of short line to line intersection tests. You can do these quickly with the planesweep algorithm. The nice thing about planesweep is that you can also extend it to curves or shapes, by returning possible intersections rather than actual intersections.
Once you have an intersection between a bullet and a ship's collision rectangle, you might need to run a timestep to check that a hit actually takes place rather than a narrow miss. You can also determine whether the hit was on front, left, right or back at this point.
I have some questions for correctly implementing a system that add gravity to my player while still detecting and correcting collision with the floor. I understand the basic math for the AABB and adding gravity vector to the players velocity vector then adding it to the position. For some reason when I try the player stops for the first few frames then eventually the velocity builds up to be more than the tile width and it goes through. I guess my real question is how to properly implement the gravity with the collision. Do I make gravity vector 0, 0 when it hits the floor or when I am just standing on the floor my collision detection will constantly move me out of the floor? I really don't know the flow of the logic with this situation.
Edit 1:
I am trying to make the simple engine myself to gain experience with programming. I kind of solved the one problem, I now can stop on the floor. My current logic is:
add gravity to velocity, check for collision, adjust the velocity by the offset of the collision, if any, add velocity to the position then set velocity to 0.
m_velocity += m_gravity;
glm::vec2 mtd = collideWithObject(objectVector);
m_velocity -= mtd;
m_position += m_velocity;
m_velocity.x = 0.0f;
m_velocity.y = 0.0f;
It works but I am not sure if that is the flow, I guess I just want to know what is the most common way to implement this.
For some reason when I try the player stops for the first few frames then eventually the velocity builds up to be more than the tile width and it goes through.
If you are applying physics in increments - such as once every frame - you must account for the infinite increments that exist between each of those points.
For a simple "plane collision", like your floor, don't test if your current AABB collides with the floor. Create the smallest AABB that includes your current AABB and the last AABB. If that box collides, you've collided with the plane.
as #MorphingDragon mentioned, you should consider Box2D, many games use Box2D.
For your question "Do I make gravity vector 0, 0 when it hits the floor or when I am just standing on the floor my collision detection will constantly move me out of the floor? I really don't know the flow of the logic with this situation.". I just assume you know Verlet integration, for calculate your new position, you don't need to change your gravity, [as you know, gravity is everywhere on earth, or you want to do a game in space, ;)] you just need to handle the collision detection logic as "when collision happens, just make the collision point satisfy my constraints", and your constraint should be "all point should not be placed under the floor, otherwise just move it and make it sit on the floor".
The collection detection and constraint solver theory should be very common in modern physical engine and easy to understand and implement.
Hope this help.
Thanks
An
I need to implement 2D collision detection by arc. I have player(black dot) and enemies(red dots). Player can attack in any direction and his hit area is 120 degrees(green lines show it) and certain radius(black curve).
How to achieve this detection?
I have done code where angle is calculated between player and enemy but i cant understand how to use player's direction vector to check if it inside arc.
Calculate the angle to the enemy and the distance away they are. Use this to check if they are in range.
The problem is simple if the area where a square since you are using Cartesian coordinates so by converting to radial coordinates, this problem becomes simple too.
With new information
Vector A is the player's direction vector.
Calculate a vector B from the enemy to the player.
Check the length of vector B isn't too long.
Then angle between the vectors is given by: acos(|A.B| / |A||B|)
If the angle is less than 60 degrees (half the 120) then the enemy is in range.
First of all the player must have a direction, a 2D vector for example. In simple it's angle with the first green line = it's angle with the other green line.
You should perform two checks:
Check if the distance between the enemy and the player is less than the radius, if not, move to the next enemy, if yes then
Draw a virtual line between the player and the enemy and calculate the angle between this line and the the direction of the player, if it's less than the half of hit-area-angle (in your example, if it's less than 60) then the player CAN hit the enemy, if not move to the next one.
That should be enough as an idea, hope that's helpful.
Let's say you have unit-length vector pointing "forward". And let's say you have unit length vector pointing to potential target. If target is within ark, then;
dot(forwardVector, targetVector) >= cosf(arcAngle/2).
If vectors aren't unit length, it won't work, of course. That checks if the target is within required angle.
Checking if it is within required distance is trivial and is pretty much squaredLength(targetPosition - playerPosition) <= arkDistance*arkDistance where squaredLength is dot(vector, vector).
Ok i know this is quite off-topic for programmers but still I need this for app, so here it is:
Ballistic curve (without wind or any other conditions) is specified by these 2 lines:
So, there is a problem that you got 3 unknown values: x,y and time t, but only 2 equations.
You can't really compute all 3 with just these values, I got:
velocity v
angle Alpha
origin coordinates
Thus, you have to decide which one to specify.
Now you have 2D tanks game, or anything like that, you know you have tank and using ballistic you have to shoot opponent down with setting angle and power.
I need to know when the bullet hit the ground, it can be on-air as it fly, or precomputed.
There comes up my problem. Which way to use? Pre-compute or check for hitting the ground in each step.
If I would like to pre-compute, I would need to know height of terrain, which, logically would have to be constant as I don't know in which x coord. If I would know the X, it would mean that just in front of my turret is wall. So only way to get to result, when I hit the ground, would be with checking in intervals of time for hitting the ground. This is also good because the terrain doesn't have top be static yay! But isn't that too great overhead which could be made much simpler? Have you encountered with such problem/solution?
Thanks in advance, btw the terrain can be flat, using lines or NURBS so I please for general solution, not specific as in which height you shoot in that will be impact.
You can compute the path of the projectile y(x) by solving one equation for t and substituting into the other. You get
Then finding the landing point is a matter of computing the intersections between that function and the function that defines the height of the terrain. One intersection will be the launch point and the other will be the landing point. (If your terrain is very steep and hilly, there could be more than 2 intersections, in which case you take the first one with x greater than the launch point.) You can use any of various root-finding algorithms to actually compute the intersection; check the documentation of whatever mathematical or game-physical libraries you have to see if they provide a method to do this.
David Zaslavsky did a good job of answering your question about solving for the equation, but if your ultimate goal is simple ballistics simluation, I suggest you instead use vector decomposition.
By utilizing vector decomposition, you can derive the x- and y-compenent vectors of your projectile. You can then apply acceleration to each component to account for gravity, wind, etc. Then you can update the projectile's (x,y) position each interval as a function of time.
For example:
double Speed = 100.0; // Speed rather than velocity, as it is only the magnitude
double Angle = 30.0; // Initial angle of 30ยบ
doulbe Position[2] = {0.0,0.0}; // Set the origin to (0,0)
double xvelocity = Speed * Cos(Angle);
double yvelocity = Speed * Sin(Angle);
Then if you can impliment a simple Update function as follows:
void Update(double Time)
{
yvelocity = -9.8 * Time; // Apply gravity
Position[0] *= (xvelocity * Time); // update x position
Position[1] *= (yvelocity * time); // update y position
CheckCollisions(); // check for collisions
}
Of course this is a very basic example, but you can build on it from here.
Fortunately, this is pretty simple kinematics.
Those equations are parametric: For any given time t, they give you the x and y coordinates for that time. All you need to do is plug in the starting velocity v and angle a.
If you're working on level ground, the time for your projectile to come back down is simply 2sin(a)v/g, i.e. the vertical component of your velocity divided by the downward acceleration due to gravity. The 2 is because it takes that amount of time for the speed to drop to 0, then the same time again for it to accelerate back down. Once you know the time you can solve for x.
If your terrain is not flat, you have some additional fun. Something you could try is work out the time for hitting the ground at the same height, and then correct for the extra vertical distance. This will also change your horizontal distance which might again affect your height... but two or three adjustments and the error will be too small for humans to notice :)
I'm not sure you're going about this is right way. The main equation you want is s = si + vi*dt + .5*adtdt. This is a simple equation of one dimension, but it generalizes to vectors cleanly.
Effectively, si is your initial position and vi is your initial velocity and a is acceleration due to gravity.
To make this work, build a vector for perfect horizontal muzzle velocity and project it on the launch angle. That's your vi. Si will be the tip of the barrel. From there it's vector summing and scaling.
Continuous functions do not work well for computers, because computers are implicitly discrete: the floating/double numbers are discrete, the timer is discrete, the game grid is discrete (even if it uses 'doubles').
So just discretize the equation the way Justin Holdsclaw suggested. Have velocity and accelerations vectors in each direction (in your case X and Y; you could also add Z). Update all vectors, and the object's position in space, at every tick.
Note that the result won't be 'exact'. The smaller your 'delta' values (grid coarseness), the closer you'll be to the 'exact' curve. To know precisely how close - if you're interested, find a book on numerical analysis and read the first few chapters. For practical purposes you can just experiment a bit.