Android min3D using touch to rotate around an object - java

I'm trying to rotate the camera around an object by using the touchscreen. The rotation around Y axis works fine (The X axis is disabled). Rotation around the X axis is really weird. when the Object (its a rocket) gets higher rocket.position().y++ & scene.camera().position.y++, the rotation around the x axis gets bigger and weird. If the rockets stops rocket.position().y = 500; & scene.camera().position.y = 500;, I can't rotate around x axis, I zoom in or out the object instead. With both axis enabled its weird as hell.
In initScene I set the camera to look at the center of the rocket.
Here's my code:
initScene:
scene.camera().position.z = 90;
scene.camera().target = raketeOBJ.position();
onTouchEvent:
public boolean onTouchEvent(MotionEvent me) {
if (me.getAction() == MotionEvent.ACTION_DOWN) {
xpos = me.getX();
ypos = me.getY();
return true;
}
if (me.getAction() == MotionEvent.ACTION_UP) {
xpos = -1;
ypos = -1;
touchTurn = 0;
touchTurnUp = 0;
return true;
}
if (me.getAction() == MotionEvent.ACTION_MOVE) {
float xd = me.getX() - xpos;
float yd = me.getY() - ypos;
xpos = me.getX();
ypos = me.getY();
touchTurn = xd / -200f;
touchTurnUp = yd / -200f;
return true;
}
try {
Thread.sleep(15);
} catch (Exception e) {
}
return super.onTouchEvent(me);
}
UpdateScene:
if (touchTurn != 0) {
scene.camera().position.rotateY(touchTurn);
touchTurn = 0;
}
if (touchTurnUp != 0) {
scene.camera().position.rotateX(touchTurnUp);
touchTurnUp = 0;
}

I think it is a view-orientation-issue. try basic android opengl example "rotating cubes", i think it is a similar behaviour.
To avoid this you have to transform display-coordinates into min3D object rotation-coordinates.
Think about moving your finger 1cm on display to the left, with 3D-object following your finger. This means x_display = x_object.
If you rotate your object, there is still a fixed connection between display and object.
(x_display = - 1cm) equals (x_object = -1cm)
at 90° & 270° your object will move xy-inverted, at 180° your object will move x-inverted.
use some sin/cos to overcome this.
edit: also rotationangle (object) = - rotationangle (camera)

One option is to rotate the container itself instead of the camera. In min3d you often work with an Object3dContainer as a class variable in your activity that displays the model. When you get your MotionEvent you can use the method rotation() from your Object3dContainer class and set x or y properties as appropriate.

You keep saying wierd, but you know that it doesn't describe what you see. Rotate is actually method of Number3d. It doesn't know about the target, so I guess rotation is done according the center, not according the rocket (Didn't quite check that, just a guess). There might be 2 solutions:
The easiest thing is to set the rocket to (0,0,0) and instead moving the rocket, move evertything else. Well that would be a stupid suggestion. Forget it.
The other solution is to calculate camera rotation traectory using sin() and cos()
There might be a third solution, but I didn't think a a lot about it and it might be wrong. What you have to do is move the camera like target is at (0,0,0), rotate and then return the camera.
Would look like something like this:
Number3d target = scene.camera.target;
Number3d cp = scene.camera.position.clone();
// move position like target is (0,0,0)
cp.x -= target.x;
cp.y -= target.y;
cp.z -= target.z;
cp.roateX(angle);
// restore offset
cp.x += target.x;
cp.y += target.y;
cp.z += target.z;
scene.camera.position.setAllFrom(cp);
You can try 3 but don't rely it'll do the job.

Related

Gun aiming based on position of mouse/finger

I am making a pretty simple 2d game. I would like to have the character be able to hold a gun and it would aim where ever your cursor (or finger on iphone) is on the screen. I would also like the gun to be able to rotate depending on where your aiming to make the effect look better. It may be pretty difficult what I am exactly imaging of but heres an example of what I'm looking for http://www.kongregate.com/games/HotAirRaccoon/kids-vs-santa. I don't need any actual code, I would just need the logic to do this. Thanks for your time!
This is how you get the x and y coordinates of the mouse and you pass for movement. Different mouse events can be tracked using the logic of these coordinates:
public void mouseDragged(MouseEvent e) {
int dx = e.getX() - x;
int dy = e.getY() - y;
if (zrect.isHit(x, y)) {
zrect.addX(dx);
zrect.addY(dy);
repaint();
}
if (zell.isHit(x, y)) {
zell.addX(dx);
zell.addY(dy);
repaint();
}
x += dx;
y += dy;
}
}

Libgdx get scaled touch position

I'm working at a android game using LIBGDX.
#Override
public boolean touchDown(int x, int y, int pointer, int button) {
// TODO Auto-generated method stub
return false;
}
Here, the x and y returns the position of the touch of the device screen, and the values are between 0 and the device screen width and height.
My game resolution is 800x480, and it will keep its aspect ratio on every device.
I want to find out a way to get the touch position, related to the game rectangle, this image can explain exactly:
Is there a way to do it?
I want to get the touch position related to my viewport..
I use this to keep the aspect ratio
http://www.java-gaming.org/index.php?topic=25685.0
Unproject your touch.
Make a Vector3 object for user touch:
Vector3 touch = new Vector3();
And use the camera to convert the screen touch coordinates, to camera coordinates:
#Override
public boolean touchDown(int x, int y, int pointer, int button){
camera.unproject(touch.set(x, y, 0)); //<---
//use touch.x and touch.y as your new touch point
return false;
}
In the newer version of LibGDX you can achieve it with the built in viewports.
Firstly choose your preferred viewport the one you want here is FitViewport.
You can read about them here:
https://github.com/libgdx/libgdx/wiki/Viewports
Next, you declare and initialize the viewport and pass your resolution and camera:
viewport = new FitViewport(800, 480, cam);
Then edit your "resize" method of the screen class to be like that:
#Override
public void resize(int width, int height) {
viewport.update(width, height);
}
Now wherever you want to get touch points you need to transfer them to new points according to the new resolution. Fortunately, the viewport class does it automatically.
Just write this:
Vector2 newPoints = new Vector2(x,y);
newPoints = game.mmScreen.viewport.unproject(newPoints);
Where x and y are the touch points on the screen and in the second line "newPoints" gets the transformed coordinates. Now you can pass them wherever you want.
After 1-2 paintful hours I finnaly found the solution..
if (Gdx.input.isTouched()) {
float x = Gdx.input.getX();
float y = Gdx.input.getY();
float yR = viewport.height / (y - viewport.y); // the y ratio
y = 480 / yR;
float xR = viewport.width / (x - viewport.x); // the x ratio
x = 800 / xR;
bubbles.add(new Bubble(x, 480 - y));
}
Edit: this is an old deprecared way to do it, so don't.

FPS Mouse movement in OpenGL (even outside window)

I'm creating a simple FPS game where the camera movement is controlled with the mouse. It's fairly simple to move the camera with the mouse when it's inside the window. But how can I make this work even when I'm OUT of the window?
I've heard some thing about fixing the mouse in the center of the screen, but I'm not sure how to get this to work.
I currently have the following:
public void mouseMoved(MouseEvent event) {
x = X;
y = Y;
X = event.getX();
Y = event.getY();
}
public void update() {
dX = X - x;
dY = Y - y;
x = X;
y = Y;
}
I've heard some thing about fixing the mouse in the center of the screen, but I'm not sure how to get this to work.
That is a very common way to do it. After you have checked how much your mouse has moved and used that information for camera movement, just move the cursor back to screen center.
Consider something like this:
Vec2 mouseDelta = getMousePosition();
camera.CalculateMovement(mouseDelta);
setMousePosition(0, 0);
You need to "capture" the mouse in your window, typically on the mouse down ( don't forget to release it ).
onMouseDown()
{
BeginCapture();
}
...
ReleaseCapture();

Continuous movement after touch?

Found plenty of questions that were similar, but nothing that answers my own problem. It's probably something really bloody simple, but it's late and I can't fathom it. I've got an android game I'm working on, where you touch the screen and it 'fires' a sprite in that direction. I've got most of the code working, however, after the sprite fires and moves off, it gets to the touch point and then just wiggles. I would like it to carry on along that angle and eventually bounce around...
Here's my code (well the bits that matter):
List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
int len = touchEvents.size();
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if(event.type == TouchEvent.TOUCH_UP) {
touchPoint.set(event.x, event.y);
guiCam.touchToWorld(touchPoint);
}
}
//Log.d("PANDAM", touchPoint.x + "|" + touchPoint.y);
float speed = 112f;
double theta = 180.0 / Math.PI * Math.atan2(panda_y - touchPoint.y, panda_x - touchPoint.x);
Log.d("PANDAM", " > "+theta+" < ");
movePanda(theta, speed, deltaTime);
And the "movePanda" method:
private void movePanda(double angle, float speed, float deltaTime)
{
panda_x += speed * Math.cos(angle)*deltaTime;
panda_y += speed * Math.sin(angle)*deltaTime;
}
My question is, how do I get the panda to carry on along the touch vector and not spaz out when it reaches the original touch point?
You seem to be recalculating the angle each step of the animation, but you actually need to remember what the angle was when you first started moving. As you pass the original touch point, the angle changes to point the other direction, so if you reclcalculate it every animation step, it will change and eventually point the other way.

Moving objects getting stuck in a corner

I am working on a program which simulates objects moving in a field. The field has a boundary of 1024x1024. The object cannot go below 0 in terms of x,y coordinate and it cannot go above 1024. I have a method for each object called "move()" which moves the object in its current direction at its current speed. If the object approaches the boundary, it then turns around with a new direction and same speed.
The problem I am having is that when one of my objects gets close to both the x and y bound (corner of the field), it gets stuck in the corner. It is almost as if it is trying to move away from the corner, but then it turns back. It must love that corner. I looked over my code and to me, my logic seems correct. I check to make sure the new direction is not negative or over 359. I check to make sure the new x,y coordinate with the new direction is within the bounds too. I even have a method to set a new direction.
I have tried re-implementing this method with different logic, but no luck. If anyone could possibly find a flaw in my programming or point out what may be causing it, then that would be much appreciated.
I have tried to debug and step through my program and I see that when it gets to the corner, it changes direction to turn around, moves about 3 spaces, then goes back to the corner. Must be a wonderful corner.
Code for move method is below:
public void move(){
localX = super.getX();
localY = super.getY();
float newX=0, newY=0;
float testX, testY;
boolean acceptX = false, acceptY = false;
testX = (float) (Math.cos(direction)*10) + localX;
testY = (float) (Math.sin(direction)*10) + localY;
int testDirection;
while(!acceptX){
if(testX >= 0 && testX <= bound){
newX = testX;
acceptX = true;
}//end if statement
else{
if(direction+180 > 359){
setDirection(direction-180);
testX = (float) (Math.cos(Math.toRadians(direction))*speed) + localX;
}
else{
setDirection(direction+180);
testX = (float) (Math.cos(Math.toRadians(direction))*speed) + localX;
}
}//end else
}//end while that checks for X value
while(!acceptY){
if(testY >= 0 && testY <= bound){
newY = testY;
acceptY = true;
}//end if statement
else{
if(direction+180 > 359){
setDirection(direction-180);
testY = (float) (Math.sin(Math.toRadians(direction))*speed) + localY;
}
else{
setDirection(direction+180);
testY = (float) (Math.sin(Math.toRadians(direction))*speed) + localY;
}
}//end else
}//end while that checks for Y value
super.setX(newX);
super.setY(newY);
}
and here is the code for setDirection
public void setDirection(int d) {
direction = d;
}
Say you have an object in the upper left corner, going up. Your first test turns it around so it goes down. Then comes your second check, which turns it around again to go up... again.
Your code could also use some more readability. The very first thing I noticed is that you're using the >359 checks to normalize the new direction to go in. Yet all cases include the movement code as well. I would do something like:
setDirection(direction + 180); //turn around
if (direction >= 360) direction -= 360; //normalize
testY = ...; //move
to move the movement code out of the direction checking if/else blocks. 360 is also a better magic number to use; 359 degrees means nothing. As has been suggested, you should ultimately use a vector library and thus throw away most of the math.
I'd really recommend storing your direction as a vector (x, y) instead of calculating that vector from a scalar; I think that would help you immensely with your code.
Issue: When your object hits an edge, you turn it 180 degrees. If it hits both edges, it'll spin in place, and the test coordinates will always be in the wrong spot.
When one of your objects hits an edge, it needs to bounce, not About Face! Angle of incidence == angle of refraction, or some such. In other words, if you're checking the x coordinate and it bounces, negate the x velocity, not both x & y.

Categories