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.
Related
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.
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 :)
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])));
}
I'm looking for a tutorial that allows me to make a simple line tracing app, no other fancy stuff such as collision. If I can get an object to follow a line drawn on the screen at the end of this week that would be wonderful.
After getting familiar with android dev, creating a few apps (calculators, converters), I think I'm ready to step it up a bit with a game containing a main loop.
I think this is exactly what I'm looking for: http://www.rengelbert.com/tutorial.php?id=182
Here is the demo: http://www.rengelbert.com/swf/LineDrawing.html
Your question is actually quite vague and it would help if you actually supplied some code snippets, variables, formulas, to help us understand your scenario. I'm going to make the following assumptions to help me guide an answer:
I have a line segment defined by (x1, y1) - (x2, y2)
I want to make an animation of an object that follows the line segment
The object needs to be orientated the correct direction
Lets assume the object moves at a speed of 1 pixel per second
Okay, now we have established the parameters, we can provide some Java code:
// Define the line segment.
double x1 = /* ... insert value here */;
double y1 = /* ... insert value here */;;
double x2 = /* ... insert value here */;;
double y2 = /* ... insert value here */;;
// Determine both the direction and the length of the line segment.
double dx = x2 - x1;
double dy = y2 - y1;
double length = Math.sqrt(dx * dx + dy * dy); // length of the line segment
double orientation = Math.atan2(dy, dx);
// Now for any time 't' between 0 and length, let's calculate the object position.
double x = x1 + t * dx / length;
double y = y1 + t * dy / length;
showObjectAt(x, y, orientation);
As to following a tutorial on building a game loop for your application, I highly recommend you follow the series on http://www.mybringback.com/ particularly Travis' Android tutorial on working with the SurfaceView object at http://www.mybringback.com/tutorial-series/3266/android-the-basics-28-introduction-to-the-surfaceview/
I'm working on implementing gesture recognition in my app, using the Gestures Builder to create a library of gestures. I'm wondering if having multiple variations of a gesture will help or hinder recognition (or performance). For example, I want to recognize a circular gesture. I'm going to have at least two variations - one for a clockwise circle, and one for counterclockwise, with the same semantic meaning so that the user doesn't have to think about it. However, I'm wondering if it would be desirable to save several gestures for each direction, for example, of various radii, or with different shapes that are "close enough" - like egg shapes, ellipses, etc., including different angular rotations of each. Anybody have experience with this?
OK, after some experimenation and reading of the android source, I've learned a little... First, it appears that I don't necessarily have to worry about creating different gestures in my gesture library to cover different angular rotations or directions (clockwise/counterclockwise) of my circular gesture. By default, a GestureStore uses a sequence type of SEQUENCE_SENSITIVE (meaning that the starting point and ending points matter), and an orientation style of ORIENTATION_SENSITIVE (meaning that the rotational angle matters). However, these defaults can be overridden with 'setOrientationStyle(ORIENTATION_INVARIANT)' and setSequenceType(SEQUENCE_INVARIANT).
Furthermore, to quote from the comments in the source... "when SEQUENCE_SENSITIVE is used, only single stroke gestures are currently allowed" and "ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures".
Interestingly, ORIENTATION_SENSITIVE appears to mean more than just "orientation matters". It's value is 2, and the comments associated with it and some related (undocumented) constants imply that you can request different levels of sensitivity.
// at most 2 directions can be recognized
public static final int ORIENTATION_SENSITIVE = 2;
// at most 4 directions can be recognized
static final int ORIENTATION_SENSITIVE_4 = 4;
// at most 8 directions can be recognized
static final int ORIENTATION_SENSITIVE_8 = 8;
During a call to GestureLibary.recognize(), the orientation type value (1, 2, 4, or 8) is passed through to GestureUtils.minimumCosineDistance() as the parameter numOrientations, whereupon some calculations are performed that are above my pay grade (see below). If someone can explain this, I'm interested. I get that it is calculating the angular difference between two gestures, but I don't understand the way it's using the numOrientations parameter. My expectation is that if I specify a value of 2, it finds the minimum distance between gesture A and two variations of gesture B -- one variation being "normal B", and the other being B spun around 180 degrees. Thus, I would expect a value of 8 would consider 8 variations of B, spaced 45 degrees apart. However, even though I don't fully understand the math below, it doesn't look to me like a numOrientations value of 4 or 8 is used directly in any calculations, although values greater than 2 do result in a distinct code path. Maybe that's why those other values are undocumented.
/**
* Calculates the "minimum" cosine distance between two instances.
*
* #param vector1
* #param vector2
* #param numOrientations the maximum number of orientation allowed
* #return the distance between the two instances (between 0 and Math.PI)
*/
static float minimumCosineDistance(float[] vector1, float[] vector2, int numOrientations) {
final int len = vector1.length;
float a = 0;
float b = 0;
for (int i = 0; i < len; i += 2) {
a += vector1[i] * vector2[i] + vector1[i + 1] * vector2[i + 1];
b += vector1[i] * vector2[i + 1] - vector1[i + 1] * vector2[i];
}
if (a != 0) {
final float tan = b/a;
final double angle = Math.atan(tan);
if (numOrientations > 2 && Math.abs(angle) >= Math.PI / numOrientations) {
return (float) Math.acos(a);
} else {
final double cosine = Math.cos(angle);
final double sine = cosine * tan;
return (float) Math.acos(a * cosine + b * sine);
}
} else {
return (float) Math.PI / 2;
}
}
Based on my reading, I theorized that the simplest and best approach would be to have one stored circular gesture, setting the sequence type and orientation to invariant. That way, anything circular should match pretty well, regardless of direction or orientation. So I tried that, and it did return high scores (in the range of about 25 to 70) for pretty much anything remotely resembling a circle. However, it also returned scores of 20 or so for gestures that were not even close to circular (horizontal lines, V shapes, etc.). So, I didn't feel good about the separation between what should be matches and what should not. What seems to be working best is to have two stored gestures, one in each direction, and using SEQUENCE_SENSITIVE in conjunction with ORIENTATION_INVARIANT. That's giving me scores of 2.5 or higher for anything vaguely circular, but scores below 1 (or no matches at all) for gestures that are not circular.