Shooting prediction algortithm in java - java

I have an issue in my current game dev hobby. I have two units, which are hostile in 2D space. One is shooting directly at the opponent, so if he moves it misses. But the other should predict it's opponents movement and shoot "ahead".
Let's assume first unit is A and second one is B. I can calculate their distances and I have their viewing angle and I have the speed at which they are moving. (player speed and bullet speed are different constants)
I tried with approximations to calculate distance between A and B and then use the Bv and orientation angle to calculate where the B will be in the next second and then scale that by the distance of two players divided by the bullet speed. But this is very inefficient and does not work well.
float distanceK = MathUtil.distance(unit.x, unit.y, opponent.x, opponent.y) / Constants.BULLET_VELOCITY;
float x = (float) (opponent.x + (Constants.UNIT_FORWARD_VELOCITY * distanceK * Math.cos(opponent.orientationAngle)));
float y = (float) (opponent.y + (Constants.UNIT_FORWARD_VELOCITY * distanceK * Math.sin(opponent.orientationAngle)));
float angleToRotate = MathUtil.angleBetweenUnitAndPoint(unit, x, y);
In the example above I then use angleToRotate variable to determine how much do I have to rotate to hit opponent, but the rotation too takes some time (54deg/s)
I would need a more optimal solution for this problem.
a) predict opponent movement when you are standing still.
b) predict opponent movement when you are moving.

You could use a vector representation of the space. So BA would represent the vector between A and B from A's point of view. You could then add the vector Bv of unit B's velocity. The resultant vector would be the vector between B and Bvp the predicted position of B at some time t in the future. As for a moving calculation, you'd need to also account for the movement vector of A.

Related

Raytracer warps cube based on camera angle?

Essentially, what is happening is there is some strange warping of the 3D cube being rendered by my raytracer, which continues to worsen as the camera moves up, even if the cube is in the same location on the screen.
The code is at http://pastebin.com/HucgjRtx
Here is a picture of the output:
http://postimg.org/image/5rnfrlkej/
EDIT: Problem resolved as being that I was just calculating the angles for vectors wrong. The best method I have found is creating a vector based on your FOV (Z) current pixel X, and current pixel Y, then normalizing that vector.
It looks like you're calculating rays to cast based on Euler angles instead of the usual projection.
Typically a "3D" camera is modeled such that the camera is at a point with rays projecting through a grid spaced some distance from it... which is, incidentally, exactly like looking at a monitor placed some distance from your face and projecting a ray through each pixel of the monitor.
The calculations are conceptually simple in fixed cases.. e.g.
double pixelSpacing = 0.005;
double screenDistance = 0.7;
for (int yIndex= -100; yIndex<= 100; yIndex++)
for (int xIndex= -100; xIndex<= 100; xIndex++) {
Vector3 ray = new Vector3(
xIndex * pixelSpacing,
yIndex * pixelSpacing,
screenDistance
);
ray = vec.normalize();
// And 'ray' is now a vector with our ray direction
}
You can use one of the usual techniques (e.g. 4x4 matrix multiplication) if you want to rotate this field of view.

JAVA elastic collision of moving and non moving circles

I'm trying to write a java mobile application (J2ME) and I got stuck with a problem: in my project there are moving circles called shots, and non moving circles called orbs. When a shot hits an orb, it should bounce off by classical physical laws. However I couldn't find any algorithm of this sort.
The movement of a shot is described by velocity on axis x and y (pixels/update). all the information about the circles is known: their location, radius and the speed (on axis x and y) of the shot.
Note: the orb does not start moving after the collision, it stays at its place. The collision is an elastic collision between the two while the orb remains static
here is the collision solution method in class Shot:
public void collision(Orb o)
{
//the orb's center point
Point oc=new Point(o.getTopLeft().x+o.getWidth()/2,o.getTopLeft().y+o.getWidth()/2);
//the shot's center point
Point sc=new Point(topLeft.x+width/2,topLeft.y+width/2);
//variables vx and vy are the shot's velocity on axis x and y
if(oc.x==sc.x)
{
vy=-vy;
return ;
}
if(oc.y==sc.y)
{
vx=-vx;
return ;
}
// o.getWidth() returns the orb's width, width is the shot's width
double angle=0; //here should be some sort of calculation of the shot's angle
setAngle(angle);
}
public void setAngle(double angle)
{
double v=Math.sqrt(vx*vx+vy*vy);
vx=Math.cos(Math.toRadians(angle))*v;
vy=-Math.sin(Math.toRadians(angle))*v;
}
thanks in advance for all helpers
At the point of collision, momentum, angular momentum and energy are preserved. Set m1, m2 the masses of the disks, p1=(p1x,p1y), p2=(p2x,p2y) the positions of the centers of the disks at collition time, u1, u2 the velocities before and v1,v2 the velocities after collision. Then the conservation laws demand that
0 = m1*(u1-v1)+m2*(u2-v2)
0 = m1*cross(p1,u1-v1)+m2*cross(p2,u2-v2)
0 = m1*dot(u1-v1,u1+v1)+m2*dot(u2-v2,u2+v2)
Eliminate u2-v2 using the first equation
0 = m1*cross(p1-p2,u1-v1)
0 = m1*dot(u1-v1,u1+v1-u2-v2)
The first tells us that (u1-v1) and thus (u2-v2) is a multiple of (p1-p2), the impulse exchange is in the normal or radial direction, no tangential interaction. Conservation of impulse and energy now leads to a interaction constant a so that
u1-v1 = m2*a*(p1-p2)
u2-v2 = m1*a*(p2-p1)
0 = dot(m2*a*(p1-p2), 2*u1-m2*a*(p1-p2)-2*u2+m1*a*(p2-p1))
resulting in a condition for the non-zero interaction term a
2 * dot(p1-p2, u1-u2) = (m1+m2) * dot(p1-p2,p1-p2) * a
which can now be solved using the fraction
b = dot(p1-p2, u1-u2) / dot(p1-p2, p1-p2)
as
a = 2/(m1+m2) * b
v1 = u1 - 2 * m2/(m1+m2) * b * (p1-p2)
v2 = u2 - 2 * m1/(m1+m2) * b * (p2-p1)
To get the second disk stationary, set u2=0 and its mass m2 to be very large or infinite, then the second formula says v2=u2=0 and the first
v1 = u1 - 2 * dot(p1-p2, u1) / dot(p1-p2, p1-p2) * (p1-p2)
that is, v1 is the reflection of u1 on the plane that has (p1-p2) as its normal. Note that the point of collision is characterized by norm(p1-p2)=r1+r2 or
dot(p1-p2, p1-p2) = (r1+r2)^2
so that the denominator is already known from collision detection.
Per your code, oc{x,y} contains the center of the fixed disk or orb, sc{x,y} the center and {vx,vy} the velocity of the moving disk.
Compute dc={sc.x-oc.x, sc.y-oc.y} and dist2=dc.x*dc.x+dc.y*dc.y
1.a Check that sqrt(dist2) is sufficiently close to sc.radius+oc.radius. Common lore says that comparing the squares is more efficient. Fine-tune the location of the intersection point if dist2 is too small.
Compute dot = dc.x*vx+dcy*vy and dot = dot/dist2
Update vx = vx - 2*dot*dc.x, vy = vy - 2*dot*dc.y
The special cases are contained inside these formulas, e.g., for dc.y==0, that is, oc.y==sc.y one gets dot=vx/dc.x, so that vx=-vx, vy=vy results.
Considering that one circle is static I would say that including energy and momentum is redundant. The system's momentum will be preserved as long as the moving ball contains the same speed before and after the collision. Thus the only thing you need to change is the angle at which the ball is moving.
I know there's a lot of opinions against using trigonometric functions if you can solve the issue using vector math. However, once you know the contact point between the two circles, the trigonometric way of dealing with the issue is this simple:
dx = -dx; //Reverse direction
dy = -dy;
double speed = Math.sqrt(dx*dx + dy*dy);
double currentAngle = Math.atan2(dy, dx);
//The angle between the ball's center and the orbs center
double reflectionAngle = Math.atan2(oc.y - sc.y, oc.x - sc.x);
//The outcome of this "static" collision is just a angular reflection with preserved speed
double newAngle = 2*reflectionAngle - currentAngle;
dx = speed * Math.cos(newAngle); //Setting new velocity
dy = speed * Math.sin(newAngle);
Using the orb's coordinates in the calculation is an approximation that gains accuracy the closer your shot is to the actual impact point in time when this method is executed. Thus you might want to do one of the following:
Replace the orb's coordinates by the actual point of impact (a tad more accurate)
Replace the shot's coordinates by the position it has exactly when the impact will/did occur. This is the best scenario in respect to the outcome angle, however may lead to slight positional displacements compared to a fully realistic scenario.

Getting bullet X to Y movement ratio from 2 points

I'm making pretty simple game. You have a sprite onscreen with a gun, and he shoots a bullet in the direction the mouse is pointing. The method I'm using to do this is to find the X to Y ratio based on 2 points (the center of the sprite, and the mouse position). The X to Y ratio is essentially "for every time the X changes by 1, the Y changes by __".
This is my method so far:
public static Vector2f getSimplifiedSlope(Vector2f v1, Vector2f v2) {
float x = v2.x - v1.x;
float y = v2.y - v1.y;
// find the reciprocal of X
float invert = 1.0f / x;
x *= invert;
y *= invert;
return new Vector2f(x, y);
}
This Vector2f is then passed to the bullet, which moves that amount each frame.
But it isn't working. When my mouse is directly above or below the sprite, the bullets move very fast. When the mouse is to the right of the sprite, they move very slow. And if the mouse is on the left side, the bullets shoot out the right side all the same.
When I remove the invert variable from the mix, it seems to work fine. So here are my 2 questions:
Am I way off-track, and there's a simpler, cleaner, more widely used, etc. way to do this?
If I'm on the right track, how do I "normalize" the vector so that it stays the same regardless of how far away the mouse is from the sprite?
Thanks in advance.
Use vectors to your advantage. I don't know if Java's Vector2f class has this method, but here's how I'd do it:
return (v2 - v1).normalize(); // `v2` is obj pos and `v1` is the mouse pos
To normalize a vector, just divide it (i.e. each component) by the magnitude of the entire vector:
Vector2f result = new Vector2f(v2.x - v1.x, v2.y - v1.y);
float length = sqrt(result.x^2 + result.y^2);
return new Vector2f(result.x / length, result.y / length);
The result is unit vector (its magnitude is 1). So to adjust the speed, just scale the vector.
Yes for both questions:
to find what you call ratio you can use the arctan function which will provide the angle of of the vector which goes from first object to second object
to normalize it, since now you are starting from an angle you don't need to do anything: you can directly use polar coordinates
Code is rather simple:
float magnitude = 3.0; // your max speed
float angle = Math.atan2(y,x);
Vector2D vector = new Vector(magnitude*sin(angle), magnitude*cos(angle));

move object in a projectile path

I'm working on an android project, I want to move an object in a projectile path, but have no idea how to do that..
I got the initial X and initial Y, i.e. left bottom corner of the phone in landscape mode. Also I fetch the X and Y were the user touch the phone, so I can calculate the angle too by tan-1(y/x), but how to calculate the curve path i.e X and Y for the object.
Any help will be appreciated.
Thanks
You have initial point p1 (X, Y) where you throw your projectile. And you have a point where user touched the screen, say p2. So, find the direction vector, like dir = p2 - p1 and normalize it. Then do following:
You have initial velocity, v = speed * dir, where speed is scalar factor
Then, on every game tick append to your current position vector v = v + (0, -10); v *= dt, where (0, -10) is gravity factor and dt - time between game frames.
You can eliminate having to increment by time intervals by using the parametric form of the projectile equations.
All you'd need to do is determine how far across (left to right) the screen you want to travel. I'll call that the X direction. Then, for each position in the X direction (could be a pixel, could be some number of pixels), you calculate the corresponding position in the Y (down to up) direction.
You'll need to set a value for the downward acceleration due to gravity. Whatever value you choose, I'll just call it g. You'll also need to set a value for how fast the projectile begins it's motion. Whatever value you choose, I'll just call it V.
The parametric equation is then:
Y = X * tan(theta) - (g * X^2) / (2 * V^2 * (cosine(theta))^2)
So, once you have the user touch point, you can calculate the angle, theta, determine V, g, and the maximum value for X, then just iterate from 0 to max X and you'll get a point (X,Y) for each iteration.

Find degree at intersection between vectors in convex polygon

It's a bit of a homework question but I've been derping around for a while and haven't been able to get a 100% accurate answer. Given a polygon, I have to find the internal angle of any random vertex within that polygon. What I have been doing is taking the vertex before that and the vertex after it and then calculating the angle of incidence (say I treat my vertex as B), I make the edges AB and BC, then find the magnitude of each, then divide the dot product of the two by the magnitude of each.
I'm still off, particularly in the instance where I have vectors (0,10), (0,0), (10,0). Obviously the interior angle on that middle vector is 90 degrees, but when I compute it using magnitude and dot product I get 45 degrees for some weird reason.
Here is my code
double dx21 = one.x - two.x;
double dx31 = one.x - three.x;
double dy21 = one.y - two.y;
double dy31 = one.y - three.y;
double m12 = Math.sqrt(dx21*dx21 + dy21*dy21);
double m13 = Math.sqrt(dx31*dx31 + dy31*dy31);
double theta = Math.acos((dx21*dx31 + dy21*dy31)/ (m12 * m13));
System.out.println(theta);
System.out.println(Math.toDegrees(theta));
Is there anything blindingly obvious that I've missed? I'm traversing the vertexes counter-clockwise, as that is how the set is organised.
Your code is using point 'one' as the centre point, and then calculates the angle between 'two' and 'three' from that. So, if you put , in the vertices (0,0), (0,10), (10,0), you would get an angle of 90. The actual calculation is fine and works, you just have your vertex order messed up.

Categories