Java get point location from angle change - libgdx

This may be an issue that I simply do no know the proper terminology to research the answer to this, I am pretty sure the solution is a function of trig.
I have a method which accepts an X/Y position coordinate and an angle in degrees. It should return an updated X/Y based on the rotation angle provided.
For example, A point is usually located at x=0,y=2 (top middle). Now I need to rotate it to it's side by 90 degrees. In my mind I know it's location is now x=2,y=0 (middle right) but I do not know the equation to produce this.
I think I need to first determine the quadrant of the starting point, and then perform the proper trig function from there. This is for a game I am developing using libgdx which is where the Vector2 object comes from.
I have come this far:
public Vector2 getPointsRotated(Vector2 startPoint, float angle){
Vector2 newPoint = new Vector2(0,0);
// determine the starting quadrant
int quad=0;
if((startPoint.x>=0)&&(startPoint.y>=0)){quad=0;}
if((startPoint.x<0)&&(startPoint.y>=0)){quad=1;}
if((startPoint.x<0)&&(startPoint.y<0)){quad=2;}
if((startPoint.x>=0)&&(startPoint.y<0)){quad=3;}
if(quad==0){
// doesn't work
newPoint.x = (float) ((newPoint.x)* (Math.sin(angle)));
newPoint.y = (float) ((newPoint.y)* (Math.cos(angle)));
}
// ...
// other quadrants also don't work
// ...
return newPoint;
}
Thanks for any help.
Update:
I have been avoiding and returning to this problem for a few days. Now after finally posting the question here I figure it out within minutes (for ppl using libgdx anyway).
Libgdx provides a rotate function for Vector2s
so something like:
Vector2 position = new Vector2(0,2);
position.rotate(angle);
works perfectly.

I find rotation matrices are very helpful for this sort of problem.
https://gamedev.stackexchange.com/questions/54299/tetris-rotations-using-linear-algebra-rotation-matrices

Related

Get rotation in Cesium

I want to know the rotation angle from Cesium when I turn the map using ctrl+mouseLeft. Like I did on this image:
I tried viewer.camera.roll but doesn't seem to be right. It's always zero.
Any tips in how I can get that value in 2D and 3D? I would also like to set this value.
Thanks in advance!
EDIT:
I have used the solution suggested and now I'm getting different values (in radians). It works both on 2D and 3D maps.
EDIT2: How to set the rotation to an specific angle
setRotation(angle: number): void {
viewer.camera.setView({
heading: (angle / (180 / Math.PI)) // east, default value is 0.0 (north)
})
};
Based on this doc
EDIT 3:
I'm using the following code to get the current heading of the map:
public getAngle(): number {
return viewer.camera.heading;
}
When I call this function and my map is not rotated, as the image shows, I get the result of "6.283185307179586" radians. I thought it should be zero, because it's not rotated at all. If I move the map around with the mouse (pan) and call the getAngle function again it gives differents results, as "1.4612025367455317e-8" if I move it north. Any thoughts about it? I would like to get the heading of the map.
Thanks a lot!
This value is available from viewer.camera.heading and is expressed in radians. You can twist the camera like this using the twistLeft and twistRight functions on the camera.

LibGDX guidance - sprite tracing 2D infinite random bezier curve

I've been able to apply a smooth animation to my sprite and control it using the accelerometer. My sprite is fixed to move left and right along the x-aixs.
From here, I need to figure out how to create a vertical infinite wavy line for the sprite to attempt to trace. the aim of my game is for the user to control the sprite's left/right movement with the accelerometer in an attempt to trace the never ending wavy line as best they can, whilst the sprite and camera both move in a vertical direction to simulate "moving along the line." It would be ideal if the line was randomly generated.
I've researched about splines, planes, bezier curves etc, but I can't find anything that seems to relate close enough to what I'm trying to achieve.
I'm just seeking some guidance as to what methods I could possibly use to achieve this. Any ideas?
You could use sum of 4 to 5 sine waves (each with different amplitude, wavelength and phase difference). All 3 of those parameters could be random.
The resulting curve would be very smooth (since it is primarily sinusoidal) yet it'll look random (it's time period would be LCM of all 4 to 5 random wavelengths which is a huge number).
So the curve won't repeat for a long time, yet it will not be hard on memory. Concerning computational complexity, you can always tune it by changing number of sine terms with FPS.
It should look like this.
It's really easy to implement too. (even I could generate above image.. haha)
Hope this helps. Maths rocks. :D
(The basic idea here is a finite Fourier series which I think should be ideal for your use case)
Edit:
You can create each term like this and assign random values to all terms.
public class SineTerm {
private float amplitude;
private float waveLength;
private float phaseDifference;
public SineTerm(float amplitude, float waveLength, float phaseDifference) {
this.amplitude = amplitude;
this.waveLength = waveLength;
this.phaseDifference = phaseDifference;
}
public float evaluate(float x) {
return amplitude * (float) Math.sin(2 * Math.PI * x / waveLength + phaseDifference);
}
}
Now create an array of SineTerms and add all values returned by evaluate(x) (use one coordinate of sprite as input). Use the output as other coordinate of sprite. You should be good to go.
The real trick would be in tuning those random numbers.
Good luck.

Determine Direction of Circular Motion

I'm doing a motion detection program and want to determine if a person is moving their hand in a clockwise or counterclockwise motion. Would someone know the best way to do this? (I'm coding in AS3, but any ECMA-like code would help).
I believe one way would be to determine if, for instance, a left-right is followed by a top-bottom or a bottom-top, and so on — is there a better way?
If you have a point of reference (0,0), you can sample the change in angle over time:
var sprite:Sprite = new Sprite();
var samples:Array = [];
setInterval(function(){
var len = samples.push(Math.atan2(sprite.mouseY,sprite.mouseX));
if ( len >=2 ) {
if ( samples[len-2]-samples[len-1] > 0 ) {
// clockwise
} else {
// counter-clockwise
}
}
},1000/stage.frameRate);
The reference is the top-left of the sprite (or its natural 0,0 point by atan2), so this snippet samples the mouse coordinate relative to the sprite.
Also, the more samples you consider (I'm only sampling 2 samples[len-2] and samples[len-1]) the better the decision for cw or ccw.
Lastly, and most importantly, my script does consider negative numbers in the radian calculations, it assumes everything is positive - this would require some tweeking.
PS: You'll want to clear samples every now and again since the array length will max out.
My script is incomplete, and I'd welcome edits, suggestions and elaborations. My hope is that it gives you something to consider and work from.

AS3 - geometry - perspective projection of a point on a 2D plane

I'm currently struggling on a problem that seems far beyond my maths capacities (been a long time since I've made some proper maths...) and I would appreciate some help on that.
Here's my setting :
I got some simple shapes (rectangles), and I "project" their bottom points on a line, coming from an Origin point.
Up to this point everything is fine.
But now I'd like to draw the original shape distorted as if it was projected with some perspective on a plane.
Please consider that I have nothing related to any rotation, isometric or any 3D or fake 2D perspective in my code, I'm only trying to draw some shapes using the graphics library to only have a feeling of something real.
Here's a quick drawing of what I'm trying to do :
What I know :
Origin point coordinates
the rect position & sizes
the red line position
the A & B points coordinates
What I want to determine is the coordinates of the C & D points, thing that could be easy if I wasn't struggling to find the "Origin bis" coordinates.
What I'm trying to do is to fake the projection of my rectangle on something that can be considered as a "floor" (related to the plane where my original rectangle is that can be seen as a wall).
Maybe I'm over-complicating the problem or maybe I fail to see any other easier way to do it, but I'm really not good anymore in any geometry or maths thing... :-(
Thanks a lot for your answers !
hmm i don't know if I undestood it correctly but I think you have too few input parameters:
you said the following information is given:
Origin point coordinates
the rect position & sizes
the red line position
the A & B points coordinates
I don't think it is possible to get your projected rectangle with this information alone.
Additionally, I think your green lines and the 'origin Bis' aren't helpful as well.
Perhaps, try this:
Supose, a blue line going through the points C & D is given as well.
Then you could find your projected rectangle by projecting the top of the rectangle onto that blue line.
So in summary:
You define an origin + two parallel lines, a red and a blue one.
Then you can project the top of the rect onto the blue line and the bottom of the rect onto the red line, yielding the points A,B,C,D
I hope this helps.
If I'm right, this code will show what you wanted to see.
First of all, I've ignored your initial setup of objects and information, and focused on the example situation itself; fake-projecting shadow for a "monolith" (any object is possible with the example below, even textured)
My reason was that it's really quite easy with the Matrix class of ActionScript, a handy tool worth learning.
Solution:
You can use the built-in Matrix class to do skew transform on DisplayObjects.
Try this example:
(The "useful" part lies in the _EF EnterFrame handler ;) )
import flash.display.MovieClip;
import flash.geom.Matrix;
import flash.events.Event;
import flash.display.BitmapData;
const PIP180:Number = Math.PI / 180;
const MAX_SHADOW_HEIGHT_MULTIPLIER:Number = 0.25; // you can also calculate this from an angle, like ... = Math.sin(angle * PIP180);
const ANIM_DEG_PER_FRAME:Number = 1.0 * PIP180; // the shadow creeps at a +1 degree per frame rate
var tx:BitmapData = new MonolithTexture(); // define this BitmapData in the library
var skew:Number = -10 * PIP180; // initial
var mono:MovieClip = new MovieClip();
mono.graphics.beginBitmapFill(tx);
// drawn that way the registration point is 0,0, so it's standing on the ground
mono.graphics.drawRect(0, -tx.height, tx.width, tx.height);
mono.graphics.endFill();
// align monolith to the "ground"
mono.x = stage.stageWidth / 2;
mono.y = stage.stageHeight - 100;
// make it be 100x300 pixel
mono.width = 100;
mono.height = 300;
var shad:MovieClip = new MovieClip();
// colored:
shad.graphics.beginFill(0x000000);
// or textured:
//shad.graphics.beginBitmapFill(tx);
shad.graphics.drawRect(0, -tx.height, tx.width, tx.height);
shad.graphics.endFill();
addChild(shad); // shadow first
addChild(mono); // then the caster object
addEventListener(Event.ENTER_FRAME, _EF);
function _EF(e:Event):void {
// animate skew on the positive half circle
skew = (skew + ANIM_DEG_PER_FRAME) % Math.PI;
// Matrix takes 6 parameters: a, b, c, d, x, y
// for this shadow trick, use them as follows:
// a = width scaling (as mono and shad are drawn in the same way, copy mono.scaleX for a perfect fit
// b = 0, because we don't want to project the vertical axis of transformation to the horizontal
// c = horizontal skew
// d = height scaling * skew * making it a bit flat using the constant
// x = mono.x, ...
// y = mono.y since originally mono and shad look alike, only the Matrix makes shad render differently
var mtx:Matrix = new Matrix(mono.scaleX, 0, Math.cos(skew), mono.scaleY * Math.sin(skew) * MAX_SHADOW_HEIGHT_MULTIPLIER, mono.x, mono.y);
shad.transform.matrix = mtx;
}
Now all you got to know to utilize this in your case, is the following N factors:
Q1: from what angle you want to project the shadow?
A1: horizontal factor is the skew variable itself, while vertical angle is stored as constant here, called MAX_SHADOW_HEIGHT_MULTIPLIER
Q2: do you want to project shadow only "upwards", or freely?
A2: if "upwards" is fine, keep skew in the positive range, otherwise let it take negative values as well for a "downward" shadow
P.S.: if you render the internals of the objects that they don't snap to 0 y as a base point, you can make them seem float/sink, or offset both objects vertically with a predefined value, with the opposite sign.
You face 1 very simple problem, as you said:
'What I want to determine is the coordinates of the C & D points, thing that could be easy if I wasn't struggling to find the "Origin bis" coordinates.'
But these co-ordinates relate to each other, so without one (or another value such as an angle) you cannot have the other. If you are to try this in 3D you are simply allowing the 3D engine to define 'Origin bis' and do your calculating for C and D itself.
So regardless you will need an 'Original bis', another value relating to the redline or your Rect for which to calculate the placement of C and D.
I remember making stuff like this and sometimes it's better to just stick with simple, you either make an 'Original bis' defines by yourself (it can be either stationary or move with the player/background) and get C and D the way you got A and B only that you use a lower line than the red line, or as I would of done, once you have A and B, simple skew/rotate your projection from those points down a bit further, and you get something the same as an 'Original bis' that follows the player. This works fine at simulating 'feeling of something real' but sadly as has been said, it looking real depends on what you are portraying. We do not know what the areas above or below the red line are (sky/ground, ground/water) and whether 'Origin' and 'Origin bis' is your light source, vanishing point, etc.

How to track a point on rotating MovieClip?

I have a MovieClip, that is representing a character in my game. Id like to "create bullets" shooting out from the tip of my characters gun. Problem is that when my character turns around, also the point rotates around the MovieClips pivot.
Is it possible to anyhow easily track this point, so that I could dynamically create new objects at the same location.
I tried to add a new MC as a child to my character, with the initial position at the guntip. In some systems child-objects "follow" their parents around, but it didnt seem to work here.
Is there any other "native" way of doing this, or do I just have to have a Polar-coordinates representation of the point relative to character-MovieClips origin, and add the MC rotation to theta, so that I can calculate the X and Y coordinates?
Try localToGlobal() and globalToLocal() methods to transform coordinates from your character movieclip to its parent.
Set up the movie clip with the gun (I'm assuming it's at the end of an arm?) so that the gun tip is straight across from the pivot point.
Then pass the method that fires the bullet three parameters: the x and y position of the gun MC, and its current angle.
The code for your bullets initial position might look something like this:
public function CreateBullet(x,y:Number, degree:Number)
{
// set start position
this.x = x + ARMLENGTH*Math.cos((degree/180)*Math.PI);
this.y = y + ARMLENGTH*Math.sin((degree/180)*Math.PI);
}
Where ARMLENGTH is the distance from the pivot point to the end of the gun.
Two caveats, Flash can do weird things with angles, so you might have to make an if statement in CreateBullet() with inverted degrees if the player if facing backwards. Also, if you have the gun MC as a child of your character, you might have to make a Point where the pivot point is then do a localToGlobal on it. There's a good reference for that here.