this is a more math related question.
In my android app I have a canvas that draws a line from start to endpoint.
I also have an angle attribute to rotate the line.
I tried to apply the code bellow to my cocept, but it jumps around weirdly, not pointing in the direction it is supposed to. (0deg = horizontal line)
//Coordinates for P1 and P2
int startx = 0;
int starty = 66;
int endx = 420;
int endy = 66;
//Alpha
float angle = 0.000F;
final float radius = 209.500F;
final float extra_radius = 20.000F; //required later - don't mind it
private void reCal(float[] vals) {
float xAcc = vals[0]*(-1);
float yAcc = vals[1]*(-1);
angle = yAcc / 10.000F * 90.000F;
final float rRadius = radius + extra_radius;
startx = (int) (radius - Math.cos(angle) * rRadius); //left
endx = (int) (radius + Math.cos(angle) * rRadius); //right
starty = 66 + (int) (Math.sin(angle) * rRadius); //top
endy = 66 - (int) (Math.sin(angle) * rRadius); //bot
}
Are their any type conversions that might cause this, or is my math wrong?
UPDATE:
I looked at Math.cos(angle) and Math.sin(angle) at runtime.They jump around between 0 and 1, even if angle is only changed by a little amount.
Now I am wondering: DO THE METHODS TAKE RAD OR DEG AS PARAMETER? (I need deg, obviously)
if you want to rotate a line starting at [cx, cy] and length of dx, use that code snippet:
canvas.save();
canvas.rotate(angle, cx, cy);
canvas.drawLine(cx, cy, cx + dx, cy, paint);
canvas.restore();
Related
I am having a bit of trouble trying to figure out how to draw paths from a point on a canvas with the start of each path being equally distanced from the initial point. To illustrate what I mean, the code that I have so far is able to generate this:
and the desired result is something like this:
My code:
int n = 3;
int r;
double x;
double y;
point1 = new Point(mWidth/2, mHeight/2);
double angle;
double angleFactor;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i = 0; i < 3; i++){
angleFactor = 2 * Math.PI / n;
angle = i * angleFactor;
x = (point1.x) + r * Math.cos(angle);
y = (point1.y) + r * Math.sin(angle);
//Draw paths
path.reset();
path.moveTo(point1.x, point1.y);
path.lineTo((float) x, (float) y);
canvas.drawPath(path, paint);
}
}
Is there a simple solution to this?
Since you want to have a tiny distance between the offset of a line and the center point, you can define start coordinates like this:
double xStart, xEnd;
double yStart, yEnd;
double offsetFraction = 0.1;
Inside the for loop in onDraw() :
double lengthX = r * Math.cos(angle);
double lengthY = r * Math.sin(angle);
xStart = (point1.x) + offsetFraction * lengthX;
yStart = (point1.y) + offsetFraction * lengthY;
xEnd = (point1.x) + lengthX;
yEnd = (point1.y) + lengthY;
//Draw paths
path.reset();
path.moveTo((float) xStart, (float) yStart);
path.lineTo((float) xEnd, (float) yEnd);
canvas.drawPath(path, paint);
I need to get new points of rotation to know the true position and dimension of the object, for a example:
Example 01.
The context of my application is rendering 2D graphics, the main for it below:
protected void paintComponent(Graphics g) {
...
g2d.rotate(Test.angle * Math.PI / 180, Test.hero, Test.heroY);
g2d.drawImage(Main.hero, Test.hero - 15, Test.heroY - 15, this);
...
The image is drawn correctly, but I cannot get the new points.
double angle = ang * Math.PI / 180;
double sin = Math.sin(angle);
double cos = Math.cos(angle);
double a = (centerX + ray) - x0;
double b = centerY - y0;
int xx = (int) (a * cos - b * -sin + x0);
int yy = (int) (a * -sin + b * cos + y0);
ang++;
it will rotate a point around centerX and centerY in a +ray from these origins, the code has tested and works from all angles.
The problem:
I've got this "Shot" class. In the code, the target variables are the mouseX and mouseY.
So when i click the mouse button, my player class will create a new shot object.
But the shooting is inaccurate.
How can i calculate the correct dx and dy?
If i add the dx and dy to the "bullet's" x and y, the bullet will move to the mouse's direction.This is what i want. The mouse position is stored in targetX and targetY, when the object is created. This is the point what the oval wants to reach.
Links:
The game (finished)
The code (from Shot.java):
public class Shot extends Entity {
private float targetX, targetY;
public Shot(World world, float x, float y, int width, int height, Color color, float targetX, float targetY) {
super(world, x, y, width, height, color);
this.targetX = targetX;
this.targetY = targetY;
}
#Override
public void render(GameContainer gc, Graphics g, Camera camera) {
g.setColor(color);
g.fillOval(x - camera.getX(), y - camera.getY(), width, height);
}
#Override
public void update(GameContainer gc, int delta) {
float dx = targetX - x;
float dy = targetY - y;
x += dx * delta * .001f;
y += dy * delta * .001f;
}
}
I tried this, but still not work:
#Override
public void update(GameContainer gc, int delta) {
float length = (float) Math.sqrt((targetX - x) * (targetX - x) + (targetY - y) * (targetY - y));
double dx = (targetX - x) / length * delta;
double dy = (targetY - y) / length * delta;
x += dx;
y += dy;
}
I did it! Here is my solution:
The problem was that, the target was the window's mouse position, and not the world's mouse position.
This is how i calculated the world's mouse positions:
float mouseWorldX = x + (mouseX - screen_width / 2); // x = player's x position
float mouseWorldY = y + (mouseY - screen_height / 2); // y = player's y position
This is code from my game at the moment is used to move a unit to the mouse when the right mouse button is pressed:
length = Math.sqrt((target_X - player_X)*(target_X - player_X) + (target_Y - player_Y)*(target_Y - player_Y)); //calculates the distance between the two points
speed_X = (target_X - player_X) /length * player_Speed;
speed_Y = (target_Y - player_Y) /length * player_Speed;
This will move an object to the target in a line at a set speed.
Edit: this is the actual code right from my game
if(input.isMouseButtonDown(Input.MOUSE_RIGHT_BUTTON))
{
length = (float) Math.sqrt((player_waypoint_X - player_X)*(player_waypoint_X - player_X) + (player_waypoint_Y - player_Y)*(player_waypoint_Y - player_Y));
velocityX = (float) (player_waypoint_X - player_X) /length * (float) PlayerStats.player.db_player_Speed;
velocityY = (float) (player_waypoint_Y - player_Y) /length * (float) PlayerStats.player.db_player_Speed;
player_waypoint_X = input.getMouseX() - 2;
player_waypoint_Y = input.getMouseY() - 2;
}
For testing purposes the velocity's are defined in the init method along with length. Every time the right mouse is pressed the waypoints's X and Y are changed to the mouse location.
I learned this from this question
velocity calculation algorithm.
in order to make the bullets not all change direction every shot, create an array list so that each bullet fired has its own x and y velocity
I'm trying to simulate an analog stick on a mobile platform.
I calculate a stick vector which based on the position of the finger and the radius of the stick returns a value from -1 to 1.
public void calcStickVector(float x, float y)
{
float cx = getCenterX();
float cy = getCenterY();
float distX = x - cx;
float distY = y - cy;
distX /= getRadius();
distY /= getRadius();
distX = JMath.clamp(-1.0f, 1.0f, distX);
distY = JMath.clamp(-1.0f, 1.0f, distY);
stickVector.x = distX;
stickVector.y = distY;
}
public RectF getInnerStickRect()
{
float r = getInnerRadius();
float cx = getCenterX() + (getRadius() * getStickVector().x);
float cy = getCenterY() + (getRadius() * getStickVector().y);
innerStickRect.left = cx - r;
innerStickRect.top = cy - r;
innerStickRect.right = cx + r;
innerStickRect.bottom = cy + r;
return innerStickRect;
}
It almost works, but visually the inner stick, when moved around seems to form a square rather than going around in a circle. Is there something wrong with my logic?
Thanks
As it is, you really are making a box with 1's as the corners. You need to normalize the vector(divide x and y by distance) instead of dividing by radius and clamping.
double dist = Math.sqrt(distX*distX) + (distY*distY));
distX /= dist;
distY /= dist;
I am having an issue with my program; currently it rotates around a set point, and can rotate models around it. Of course, this is a problem as I want it to be a first-person perspective, and currently, it rotates around a point in front of the viewer, instead of the perspective of the viewer. Here is the trigonometric calculations:
protected void drawWireframe(Graphics g) {
double theta = Math.PI * -azimuth / 180.0D;
double phi = Math.PI * elevation / 180.0D;
float cosT = (float) Math.cos(theta);
float sinT = (float) Math.sin(theta);
float cosP = (float) Math.cos(phi);
float sinP = (float) Math.sin(phi);
float cosTcosP = cosT * cosP;
float cosTsinP = cosT * sinP;
float sinTcosP = sinT * cosP;
float sinTsinP = sinT * sinP;
float near = 6.0F;
g.setColor(Color.black);
g.fillRect(0, 0, getWidth(), getHeight());
for (int i = 0; i < tiles.size(); i++) {
Point[] points = new Point[vertices.length];
for (int j = 0; j < points.length; j++) {
float x0 = -(tiles.get(i).getX() + xmod + vertices[j]
.getX());
float y0 = (tiles.get(i).getY() + ymod + vertices[j].getY());
float z0 = -(tiles.get(i).getZ() + zmod + vertices[j]
.getZ());
float x1 = cosT * x0 + sinT * z0;
float y1 = -sinTsinP * x0 + cosP * y0 + cosTsinP * z0;
float z1 = cosTcosP * z0 - sinTcosP * x0 - sinP * y0;
if (z1 + near > 0) {
x1 = x1 * near / (z1 + near);
y1 = y1 * near / (z1 + near);
points[j] = new Point((int) (Math.max(getWidth(),
getHeight()) / 2 - (Math.max(getWidth(),
getHeight()) / near) * x1), (int) (Math.max(
getWidth(), getHeight()) / 2 - (Math.max(
getWidth(), getHeight()) / near) * y1));
}
}
}
}
How would I go about moving the rotational point without actually modifying the xmod, ymod and zmod (these are used for movements like jumping, walking, running, crouching... etc)
I know how to figure out how to get the new x, y and z positions, I just don't know how to apply them; if I add them to the mods, it creates a weird loop-d-loop. If I add them to the x1, y1, z1's it doesn't cover the z not rotating from the perspective.
To change the rotation point, you effectively need three transforms:
Translate the coordinate system so that the rotation point becomes the origin.
Perform a rotation around the origin
Translate the coordinate system back again.
This can be factored a number of ways, but that's the basic priniciple: translate->rotate->translate.
The way you "move the rotation point" of an object is by translating the object so that the rotation point is at the origin; do the rotation; then translate the object back. All of this is done in memory, between frames - the user never actually sees the object moving to the origin and back.
By the way, all this stuff is significantly easier if you understand vectors and matrix transformations - as you've seen yourself, without them the code can get out of hand.
Using vectors/matrices, all your code above could be reduced to only a few lines.