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).
Related
I'm working on a simple little game/simulation where I want to bounce a ball. I'm trying to make the ball bounce not quite realistically, but more in a "game universe" way.
I have these variables to work with:
Vector ball_direction; // Direction the ball was moving in prior to impact
Vector ball_bounce_direction; // New direction of the ball computed from the collided face's normal
Vector collide_face_normal; // The normal of the collided face
Vector collide_face_perp; // perpendicular to the normal of the collided face
Vector gravity; // The gravity of the world-- doesn't really factor in since I want to do this operation based on the collision normal
So basically what I want to do is:
multiply ball_bounce_direction by .6 in the direction of collide_face_normal.
multiply ball_bounce_direction by 1.0 in the direction of collide_face_perp.
So a bouncing ball on a flat surface, I want the bounces to get smaller, while it completely maintains its sideways velocity.
Cans someone tell me what I need to do to ball_bounce_direction to achieve this?
If you think of the dot product as "the magnitude of a vector in the direction of another vector", you can break ball_bounce_direction into two parts (I'm assuming you have a dot function):
Vector bbd_norm = ball_bounce_direction.dot(collide_face_normal)*ball_bounce_direction;
Vector bbd_perp = ball_bounce_direction.dot(collide_face_perp)*ball_bounce_direction;
This works because collide_face_* vectors are perpendicular, then you can build a new vector:
ball_bounce_direction = 0.6*bbd_norm + bbd_perp;
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.
This is separate to a previous question I asked.
To make the collision detection simpler I am now using euclidean distance to work out if objects intersect.
I am working in a 3D environment using openGL with bounding walls around the
edges.
I have a player (just displayed as a quad for now)
There are also several randomly displayed cylinders acting as pillars, created using gluCylinder.
Intersection with the walls is fine, and I know that if there is an intersection with the left wall for example the player should be positioned at an X co ordinate that is 0.5 away from the bounding wall.That way if the player is going to go through the wall then it will have the appearance of being able to walk into the wall but not through it.
I am having trouble with the inner pillars, and what i should do with the player when i detect they are within a certain distance of a pillar.
I am using a euclidean distance calculation to detect collisions when diet is < than a value 1 for example.
double dist = sqrt(pow((playerX - xPosi[i]),2) + pow((playerZ - zPosi[i]),2));
xPosi[i] and zPosi[i] are arrays holding the x and z co ordinates of my pillars, and player X and Z hold the co ordinates of the player. Could anyone suggest how to handle the interaction with the pillars, as i now have the collision detection working.
The player will only be travelling in either a +ve or -ve x direction or +ve or -ve z direction, I would like the player to stop if a collision is detected and no longer be able to move through the pillar.
Im working on a 2D game in which the terrain can vary and is composed of any shape of polygons except for self intersecting ones. The player collision box is in the shape of a square and can move about. My question is this: How do I keep an always-upright box to collide with variable terrain and always stay outside?
My current approach that I made up albeit no code yet works like the following:
The blue square is the player hitbox. First, it moves with a velocity downwards as an example. My goal is to find the heighest point in its travel path where it can be safely outside of the terrain polygon. I test all the terrain vertex points inside its travel path and project them to the velocity of the box. I take the farthest projection.
The farthest projection will be the max distance allowed to move in without going into the terrain.
Move the square by distance in the direction of velocity and done.
However, there are few scenarios that I encountered where this does not work. Take this as an example:
To remedy this situation, I now test for one corner of the square. If the distance from the corner is shorter than the farthest projection, then that distance will give the appropriate shift in distance. This pretty much makes the algorithm full-proof. Unless someone states another exception.
Im going a little crazy and I would appreciate feedback on my algorithm. If anyone has any suggestions or good reads about 2D upright box collisions on terrain or anything similar, that would be great.
This may be useful, and here I'll quickly elaborate on "upright" square collision.
First the collision may occur on the side of the square, and not necessarily a corner. A simple solution to check any collision is describe the region delimited by the square, and then check if any point of your uneven terrain is within this region.
To define the square region, assume your upright square is has the corners (x1,y1), (x2,y1), (x2,y2), (x1,y2), where x2>x1 and y2>y1. Then for a point (x,y) to be within the square it needs to satisfy the conditions
If( x1< x < x2 and y1< y <y2) Then (x,y) is in the square.
Then to conclude, all you need do is check if any point on the terrain satisfies the above condition.
Good luck.
So, I have a Triangle->AABB collision algorithm and I have it returning the triangle that the AABB collided with. I was hoping with the 3 vectors of the triangle and the direction/magnitude of the movement would let me determine a deflected vector so that when you run against the wall at an angle you move slower, depending on the angle of collision, but along side the wall. This would remove the sticky collision problem with only moving when there is not a collision. Any suggestions or references would be greatly appreciated! Thanks.
First, I would convert magnitude/direction to a vector (it's much more convenient).
Then (c++):
float towards=dot(velocity,norm); // velocity component into triangle
if(towards<0) // is moving into triangle
velocity-=towards*norm; // remove component
Then it can't move into the triangle. towards<0 might need to be reversed depending on your normal. It's also nice to have a spring force pushing it out.
Remove the component of the velocity along the normal of the triangle.
The idea is that you can represent the movement as the part that's moving "into" the triangle and the remainder (which will be in perpendicular directions). If you then just move with the remainder, you will no longer be getting any closer to the triangle by the movement (or further, but you shouldn't be detecting a collision in that case).
In pseudo-code:
// v := velocity vector of moving object
// p[3] := points that make up the triangle
triangle_normal = cross(p[2]-p[0], p[1]-p[0])
problematic_v = project(v, onto=triangle_normal)
safe_movement = v - problematic_movement
Note that this intentionally doesn't preserve the magnitude of the movement vector, as doing so would make you slide along a wall very quickly when running straight at it.
For more details and some nice pictures, see Pool Hall Lessons: Fast, Accurate Collision Detection Between Circles or Spheres at Gamasutra. You're not using spheres, but you are essentially doing a perfectly plastic (since you don't bounce) collision.