Using trigonometry to shoot multiple bullets like a shotgun - android

I'm making a game where the player follows the mouse and a bullet gets shot out the players back end at the opposite direction that it is moving towards the mouse. Its a bit hard to explain in words so i quickly made a rough draft in paint.net to demonstrate.
Grey ball is the player. yellow cursor is where the player is touching on the touch screen. And the black balls are the bullets.
In example 1 and 2, the player is moving towards the cursor and bullets are behind shot in the opposite direction. What I want to o is like in example 3 where there is more than one bullet coming out the back and they are also spread out like a shotgun shot.
image:
http://i.stack.imgur.com/Q3Q18.png
My goal would be to allow the player to upgrade to be able to shoot more than one bullet at a time. All I want is for the player to be able to shoot up to 5 at a time. Thanks in advance!

The angles of the other bullets would use the same formula you are using, but the angles would be some constant offset relative to the center bullet. For instance, if you are using the following formula for the center bullet:
x += Math.cos(angle * Math.PI/180) * Status.bulletSpeed;
y += Math.sin(angle * Math.PI/180) * Status.bulletSpeed;
then your other bullets would be:
x1 += Math.cos((angle + 10) * Math.PI/180) * Status.bulletSpeed;
y1 += Math.sin((angle + 10) * Math.PI/180) * Status.bulletSpeed;
x2 += Math.cos((angle - 10) * Math.PI/180) * Status.bulletSpeed;
y2 += Math.sin((angle - 10) * Math.PI/180) * Status.bulletSpeed;
You can choose some other value other than 10 if you so choose. If you wanted to shoot 5 at a time, you would also use:
x3 += Math.cos((angle + 20) * Math.PI/180) * Status.bulletSpeed;
y3 += Math.sin((angle + 20) * Math.PI/180) * Status.bulletSpeed;
x4 += Math.cos((angle - 20) * Math.PI/180) * Status.bulletSpeed;
y4 += Math.sin((angle - 20) * Math.PI/180) * Status.bulletSpeed;
Here, the number you use should be twice the value you choose for the first set.

Related

Drawing lines on Canvas

I am developing Mind mapping tool for android. I am creating this type of layout for my mind map http://www.examtime.com/files/2013/08/How-to-create-an-online-mind-map.jpg. Is there any way to create a these type of lines(as created in image) to connect objects at run time. Please Help
You should look into cubic bezier curves (splines). There is no easy way to do this simply with a Canvas. Here's an overview:
Bezier curves use 2 points (P0 - the origin & P1 - the destination), and 2 vectors (V0 - the direction the curve leaves P0, V1 - the direction the curve enters P1). For our purposes, P0, P1, V0, V1 should all be of the type PointF.
We will use t to denote the position on the path. When t = 0, the position is at P0, when t = 1, the position is at P1. Any value of t between 0 and 1 will be along the path. 0 <= t <= 1.
Now, just as an example, lets look at the curve that connects the "Nobody's perfect" node to the "Tidy up later" node.
In this case, P0 will be the right middle side of "Nobody's perfect", and P1 will be the bottom middle side of "Tidy up later".
We'll make both vectors perpendicular to the nodes they're leaving / entering, and so V0's value will be {P1.x - P0.x, 0}. This vector will point right, and will have the strength equivalent to the distance between the two nodes. In a similar manner, we'll construct the V1 vector pointing up towards the node: {0, P0.y - P1.y}
Now that you have the vectors and the points, you'll want to start drawing the curve. To do this, you'll iterate through t using some small stepping value that's dividable by 1, for example, 0.1, 0.025, 0.001, etc. Let's call this value "step" Each iteration will generate a point on the curve, and you'll want to connect a line between each of these points.
Here's a code sample for this part:
PointF start, end;
for (float t = 0; t < 1; t += step)
{
start = getBezierPosition(t);
end = getBezierPosition(t + step)
canvas.drawLine(start.x, start.y, end.x, end.y, paint);
}
Now, the hard part - calculating the position of the bezier curve at position t:
private PointF getBezierPosition(float t)
{
PointF result = new PointF();
float oneMinusT, x, y;
oneMinusT = 1 - t;
x = oneMinusT * oneMinusT * oneMinusT * P0.x +
3 * oneMinusT * oneMinusT * t * V0.x +
3 * oneMinusT * t * t * V1.x +
t * t * t * P1.x;
y = oneMinusT * oneMinusT * oneMinusT * P0.y +
3 * oneMinusT * oneMinusT * t * V0.y +
3 * oneMinusT * t * t * V1.y +
t * t * t * P1.y;
result.set(x, y);
return result;
}
This is the formula for a cubic bezier curve. You can learn more about it here.
I'll let you implement the logic of determining the locations of P0 & P1, and the directions of V0 & V1 (keep in mind that they should always be perpendicular to the node they're leaving / entering for best results). You'll need to play around with the logic to determine what side of the node the P is on, and it's most likely going to be linked to the logic you apply to positioning the nodes in the 1st place.
Also, for best results, try playing around with the stroke width of the paint you're drawing with. For example, When t = 0, use a stroke width of size 5, and when t = 1, use a stroke size of 3. Make sure to iterate smoothly between them (so if t = 0.5, the stroke width will be 4).
I'll admit, this stuff is a bit heavy on the mathematics, and might not be in the comfort zone of a beginner, but if you want to achieve dynamic curves like you showed in that picture, I'm afraid you're going to get your hands a bit dirty.
Best of luck man! Let me know how it all turned out :)

How to find out where the user has touched the screen?

So I am making an android application where I have a set of circles. When the user touches a point in one of the circles I need to calculate a point according to where the user touched.
Somewhat similar to an archer's target.
how do I achieve this?
I have searched about touch interfaces but I haven't been able to figure out how i can do this
You should use TouchListener with following code to get to know that whether your touch event occur inside circle or not.
Formula
(x - center_x)^2 + (y - center_y)^2 < radius^2
code
int x = view.getX();
int y = view.getY();
if((xTouch - (x + radius)) * (xTouch - (x + radius)) + (yTouch - (y + radius)) * (yTouch - (y + radius)) <= (radius * radius)){
...
}
If this satisfies left side equation is less then right side one, your touch event is inside circle else outside circle.
Just set onTouchListener and make your logic with event.getX()/getY()

Perspective Projection in Android in an augmented reality application

Currently I'm writing an augmented reality app and I have some problems to get the objects on my screen. It's very frustrating for me that I'm not able to transform gps-points to the correspending screen-points on my android device. I've read many articles and many other posts on stackoverflow (I've already asked similar questions) but I still need your help.
I did the perspective projection which is explained in wikipedia.
What do I have to do with the result of the perspective projection to get the resulting screenpoint?
The Wikipedia article also confused me when I read it some time ago. Here is my attempt to explain it differently:
The Situation
Let's simplify the situation. We have:
Our projected point D(x,y,z) - what you call relativePositionX|Y|Z
An image plane of size w * h
A half-angle of view α
... and we want:
The coordinates of B in the image plane (let's call them X and Y)
A schema for the X-screen-coordinates:
E is the position of our "eye" in this configuration, which I chose as origin to simplify.
The focal length f can be estimated knowing that:
tan(α) = (w/2) / f (1)
A bit of Geometry
You can see on the picture that the triangles ECD and EBM are similar, so using the Side-Splitter Theorem, we get:
MB / CD = EM / EC <=> X / x = f / z (2)
With both (1) and (2), we now have:
X = (x / z) * ( (w / 2) / tan(α) )
If we go back to the notation used in the Wikipedia article, our equation is equivalent to:
b_x = (d_x / d_z) * r_z
You can notice we are missing the multiplication by s_x / r_x. This is because in our case, the "display size" and the "recording surface" are the same, so s_x / r_x = 1.
Note: Same reasoning for Y.
Practical Use
Some remarks:
Usually, α = 45deg is used, which means tan(α) = 1. That's why this term doesn't appear in many implementations.
If you want to preserve the ratio of the elements you display, keep f constant for both X and Y, ie instead of calculating:
X = (x / z) * ( (w / 2) / tan(α) ) and Y = (y / z) * ( (h / 2) / tan(α) )
... do:
X = (x / z) * ( (min(w,h) / 2) / tan(α) ) and Y = (y / z) * ( (min(w,h) / 2) / tan(α) )
Note: when I said that "the "display size" and the "recording
surface" are the same", that wasn't quite true, and the min
operation is here to compensate this approximation, adapting the
square surface r to the potentially-rectangular surface s.
Note 2: Instead of using min(w,h) / 2, Appunta uses screenRatio=
(getWidth()+getHeight())/2 as you noticed. Both solutions preserve the elements
ratio. The focal, and thus the angle of view, will simply be a bit different,
depending on the screen's own ratio. You can actually use any function you want to
define f.
As you may have noticed on the picture above, the screen coordinates are here defined between [-w/2 ; w/2] for X and [-h/2 ; h/2] for Y, but you probably want [0 ; w] and [0 ; h] instead. X += w/2 and Y += h/2 - Problem solved.
Conclusion
I hope this will answer your questions. I'll stay near if it needs editions.
Bye!
< Self-promotion Alert > I actually made some time ago an article
about 3D projection and rendering. The implementation is in
Javascript, but it should be quite easy to translate.

Android : OpenGL 2.0 Rotation/moving the Camera using Matrix.setLookAtM

So this is my second question today, I might be pushing my luck
In short making a 3D first Person, where you can move about and look around.
In My OnDrawFrame I am using
Matrix.setLookAtM(mViewMatrix, 0, eyeX , eyeY, eyeZ , lookX , lookY , lookZ , upX, upY, upZ);
To move back, forth, sidestep left etc I use something like this(forward code listed)
float v[] = {mRenderer.lookX - mRenderer.eyeX,mRenderer.lookY - mRenderer.eyeY, mRenderer.lookZ - mRenderer.eyeZ};
mRenderer.eyeX += v[0] * SPEED_MOVE;
mRenderer.eyeZ += v[2] * SPEED_MOVE;
mRenderer.lookX += v[0] * SPEED_MOVE;
mRenderer.lookZ += v[2] * SPEED_MOVE;
This works
Now I want to look around and I tried to port my iPhone openGL 1.0 code. This is left/right
float v[] = {mRenderer.lookX - mRenderer.eyeX,mRenderer.lookY - mRenderer.eyeY, mRenderer.lookZ - mRenderer.eyeZ};
if (x > mPreviousX )
{
mRenderer.lookX += ((Math.cos(SPEED_TURN / 2) * v[0]) - (Math.sin(SPEED_TURN / 2) * v[2]));
mRenderer.lookZ += ((Math.sin(SPEED_TURN / 2) * v[0]) + (Math.cos(SPEED_TURN / 2) * v[2]));
}
else
{
mRenderer.lookX -= (Math.cos(SPEED_TURN / 2) *v[0] - Math.sin(SPEED_TURN / 2) * v[2]);
mRenderer.lookZ -= (Math.sin(SPEED_TURN / 2) *v[0] + Math.cos(SPEED_TURN / 2) * v[2]);
}
This works for like 35 degrees and then goes mental?
Any ideas?
First of all I would suggest not to trace the look vector but rather forward vector, then in lookAt method use eye+forward to generate look vector. This way you can loose the update on the look completely when moving, and you don't need to compute the v vector (mRenderer.eyeX += forward.x * SPEED_MOVE;...)
To make things more simple I suggest that you normalize the vectors forward and up whenever you change them (and I will consider as you did in following methods).
Now as for rotation there are 2 ways. Either use right and up vectors to move the forward (and up) which is great for small turning (I'd say about up to 10 degrees and is capped at 90 degrees) or compute the current angle, add any angle you want and recreate the vectors.
The first mentioned method on rotating is quite simple:
vector forward = forward
vector up = up
vector right = cross(forward, up) //this one might be the other way around as up, forward :)
//going left or right:
forward = normalized(forward + right*rotationSpeedX)
//going up or down:
forward = normalized(forward + up*rotationSpeedY)
vector right = cross(forward, up) //this one might be the other way around
vector up = normalized(cross(forward, right)) //this one might be the other way around
//tilt left or right:
up = normalized(up + right*rotationZ)
The second method needs a bit trigonometry:
Normally to compute an angle you could just call atan(forward.z/forward.x) and add some if statements since the produced result is only in 180 degrees angle (I am sure you will be able to find some answers on the web to get rotation from vector though). The same goes with up vector for getting the vertical rotation. Then after you get the angles you can easily just add some degrees to the angles and recreate the vectors with sin and cos. There is a catch though, if you rotate the camera in such way, that forward faces straight up(0,1,0) you need to get the first rotation from up vector and the second from forward vector but you can avoid all that if you cap the maximum vertical angle to something like +- 85 degrees (and there are many games that actually do that). The second thing is if you use this approach your environment must support +-infinitive or this atan(forward.z/forward.x) will brake if forward.x == 0.
And some addition about the first approach. Since I see you are trying to move around the 2D space your forward vector to use with movement speed should be normalized(forward.x, 0, forward.z), it is important to normalize it or you will be moving slower if camera tilts up or down more.
Second thing is when you rotate left/right you might want to force up vector to (0,1,0) + normalize right vector and lastly recreate the up vector from forward and right. Again you then should cap the vertical rotation (up.z should be larger then some small value like .01)
It turned out my rotation code was wrong
if (x > mPreviousX )
{
mRenderer.lookX = (float) (mRenderer.eyeX + ((Math.cos(SPEED_TURN / 2) * v[0]) - (Math.sin(SPEED_TURN / 2) * v[2])));
mRenderer.lookZ = (float) (mRenderer.eyeZ + ((Math.sin(SPEED_TURN / 2) * v[0]) + (Math.cos(SPEED_TURN / 2) * v[2])));
}
else
{
mRenderer.lookX = (float) (mRenderer.eyeX + ((Math.cos(-SPEED_TURN / 2) * v[0]) - (Math.sin(-SPEED_TURN / 2) * v[2])));
mRenderer.lookZ = (float) (mRenderer.eyeZ + ((Math.sin(-SPEED_TURN / 2) * v[0]) + (Math.cos(-SPEED_TURN / 2) * v[2])));
}

opengl android movement with given speed

This is a very basic issue, but I just can't find a complete answer anywhere.
Consider an object is moving along the z axis with a given SPEED. (Ex: -0.2 opengl units)
Now I rotate the object around its local axis with rotationX , Y and Z angles.
Question: what is the next position of my object?
I am using the following equations (which I know are wrong, but I just can't make them right)
positionX += -SPEED * Math.sin(rotationY * Utils.DEG)* Math.cos(rotationX * Utils.DEG);
positionY += SPEED * Math.sin(rotationX * Utils.DEG);
positionZ += -SPEED * Math.cos(rotationX * Utils.DEG)* Math.cos(rotationY * Utils.DEG);
Where is my mistake?
I would store a vector that represents the orientation of the object.
On rotation, rotate the orientation vector.
When moving,
positionX += SPEED * orientation.X
positionY += SPEED * orientation.Y
etc.

Categories

Resources