Controlling XY Movement by finger dragging in Android - java

I'm currently making a 2D scrolling shooter game on Android using AndEngine but I'm having an issue with relative touch control which allow player to control the sprite by dragging the finger up/down/left/right to move the ship and the ship should move to the same direction as the finger just like controlling pointer by touchpad (It is pretty common in touchscreen Space Invader-like games nowadays)
So I came up with this code,
float oldX, oldY;
float X, Y;
public boolean onSceneTouchEvent(Scene pScene,
TouchEvent pSceneTouchEvent) {
if(pSceneTouchEvent.isActionMove()){
float currentX = pSceneTouchEvent.getX();
float currentY = pSceneTouchEvent.getY();
float deltaX = currentX-oldX;
float deltaY = currentY-oldY;
System.out.println("X: " + X + " Y: " + Y);
X= X + deltaX;
Y= Y + deltaY;
oldX = currentX;
oldY = currentY;
}
return true;
}
The problem that I'm having is that variable X, Y which I'll be using to set the sprite position on the screen isn't increasing/decreasing according to my finger movement, if I continuously dragging my finger right side, the X value should be increasing continuously and when I drag my finger left side, the X value should be decreasing continuously also. But what I'm having is that the X value is increasing/decreasing according to the position of my finger on the screen. Am I doing anything wrong ?

I guess the tablet is not able to combine several sweeps. A horizontal sweep is generally a gesture, not a movement.
I think you should set the position of the pointer when you stop sweeping, so you can start fresh with a new sweep.
Please also take a look at Gestures in Android:
http://mobile.tutsplus.com/tutorials/android/android-gesture/
http://www.anddev.org/gesturedetector_and_gesturedetectorongesturelistener-t3204.html
there is a method onScroll(args) in OnGestureListener, that might help you and save time.

Related

Java 3d Game Mouse Camera/Player control

In my Game i want to implement Mouse Controls that control Camera and Player movment.
What i want to have is that when the Mouse moves to the bottom left corner of the window for example, the players Rotation goes towards this Vector.
Also i want the Camera to be shifted in the opposite 2d Vector so it appears that the player, when the cursor is in the bottom left moves into the top right corner.
Like This
And the more the cursor is moved away from the screens middle, the more the player should rotate.
The Camera should also be rotated around the player in order to make it appear that the playermodel is rotated towards the vector it rotates itself in.
This is the function that calculates the camera position:
private void calculateCameraPosition(float horizDistance, float verticDistance)
{
float theta = player.getRotY() + angleAroundPlayer;
float offsetX = (float)((horizDistance ) * Math.sin(Math.toRadians(theta)) );
float offsetZ = (float)(horizDistance * Math.cos(Math.toRadians(theta)));
position.y = player.getPosition().y + verticDistance + 8;
position.x = (player.getPosition().x - offsetX);
position.z = player.getPosition().z - offsetZ ;
this.yaw = 180 - (player.getRotY() + angleAroundPlayer);
}
And i get my Inputs from GFLW, a little bit modified as the Mouse positions, which i subtract from the width/2 and divide into smaller numbers.
angleChange_x = (int) (-(inputHandler.Mouse_x - (Width/2)) /20);
angleChange_y = (int) (-(inputHandler.Mouse_y - (Height/2)) /20 );

I want to limit the Image button animation in specified area

I create an ui in which the image button is animate or moved on touch. But its moving throughout the layout, I want to move it in particular set area.
UPDATE code:
I just clear the animation and use this on behalf. This code lets me to move the Image button on touch in specific radius but it flicker the image means the image is constantly moving around not stopping after touch.
case (MotionEvent.ACTION_MOVE):
x = event.getRawX();
y = event.getRawY();
float deltaX = x - idx;
float deltaY = y - idy;
double angleInDegrees = Math.atan(deltaY / deltaX) * 360 / Math.PI;
idx = x;
idy = y;
imknob.setTranslationX((float)(200*(Math.cos(angleInDegrees))));
imknob.setTranslationY((float)(200*(Math.sin(angleInDegrees))));
break;
Please if someone help me with this !
The red dot image must move inside the black circle. How would I limit it!!

LWJGL Vector2f slowly change into another vector

I have 2 Vectro2f's from LWJGL. One to store the player position and one to store the mouse-right-click destination for the player to move to. In an update method, provided with the delta time, how could I slowly move the position vector points towards the direction vector points, to make the player move to the select position? I've tried this, but this just makes an instant jump and doesn't go to the proper coordinates each time:
if(this.destination != this.position) {
this.position.setX(this.destination.x-this.position.x);
this.position.setY(this.destination.y-this.position.y);
}
You could put this in your loop:
if (destination != position){
position.setX(position.getX() + dX);
position.setY(position.getY() + dY);
}
where dX and dY are the amount the player should travel in the X and Y directions in one frame.
One way to calculate dX and dY is using trig:
dX = velocity * Math.cos(theta) where theta is the angle to the destination from the horizontal (X axis, i.e. the unit circle in trig).
dY = velocity * Math.sin(theta).

Dragging rotated text inside android canvas does not work as expected

There is something I am missing inhere so I hope you can share some light on me.
I am drawing some text inside canvas. For this I have a class Word
public class Word {
private int x;
private int y;
private String text;
}
The app allows the user to rotate the text, and I handle the rotation withing onDraw
protected void onDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(angle, centerX, centerY)
...
canvas.drawText(word.getText(), word.getX(), word.getY())
....
canvas.restore();
}
The problem I get is when the user drags the canvas and there is a rotation set. When angle=0 the movement is going as expected.
#Override
public boolean onTouchEvent(MotionEvent event) {
case MotionEvent.ACTION_DOWN:
initialX = (int) event.getX();
initialY = (int) event.getY();
break;
case MotionEvent.ACTION_MOVE:
int currentX = (int) event.getX();
int currentY = (int) event.getY();
int xMovement = currentX - initialX;
int yMovement = currentY - initialY;
dragWords(xMovement, yMovement);
.....
and on dragWords for each word I do:
private void dragText(int xMovement, int yMovement){
for (Word word : words) {
word.setX(word.getX() + xMovement);
word.setY(word.getY() + yMovement);
}
invalidate();
}
When rotation angle is 0, moving up/down/left/right makes the words move by the same distance. As angle gets bigger, the words start to move in different dirrections, for instance at 60, it is starting to go diagonally up, when 180 it only moves up/down and not left/right.
I think I need to calculate some sort of a difference based on angle and add it to xMovement/yMovement... but how should I do this ?
LE: Here is an image on how it behaves:
The blue lines is how the text is moving on drag while the orange is the finger dragging on the screen. When angle is 0 it works quite well, when angle increases, it starts to move diagonally on left/right, while when angle is even bigger, it only moves up and down and does not respond to left/right
If I understand correctly, the issue is that Canvas.rotate() does not only rotate the text direction, but rather the whole canvas. Therefore, the x-y coordinates of the words are also rotated from the specified pivot point.
In order to match the dragging movement, you can use a Matrix for this, more specifically the inverse matrix of the one you're using to rotate the canvas. It will be used to convert the x-y coordinates of the words to their original, pre-rotate locations.
For example, calculate this once, and update it whenever angle, centerX, or centerY changes.
// rotMatrix is the same operation applied on the canvas.
Matrix rotMatrix = new Matrix();
rotMatrix.postRotate(mAngle, centerX, centerY);
// Invert it to convert x, y to their transformed positions.
Matrix matrix = new Matrix();
rotMatrix.invert(matrix);
Then, when drawing each word:
int wordX = ...
int wordY = ...
String text = ...
float[] coords = new float[] { wordX, wordY };
matrix.mapPoints(coords);
canvas.drawText(text, coords[0], coords[1], paint);
In the ellipses part in the following code:
dragWords(xMovement, yMovement);
..... <<<--------------------- I hope you are updating initialX and initialY
initialX = currentX;
initialY = currentY;
Otherwise, your x and y values will not correspond correctly with the amount of distance moved during the touch gesture.
As user matiash indicated, you should use Matrix#mapPoints(float[]) to transform your x and y values. Declare and initialize a Matrix:
Matrix correctionMatrix;
// Your view's constructor
public MyView() {
....
correctionMatrix = new Matrix();
}
Here's how your onDraw(Canvas) should look like:
#Override
protected void onDraw(Canvas canvas) {
canvas.save(Canvas.MATRIX_SAVE_FLAG);
canvas.rotate(angle, centerX, centerY);
...
// Neutralize the rotation
correctionMatrix.setRotate(-angle, centerX, centerY);
// Initialize a float array that holds the original coordinates
float[] src = {word.getX(), word.getY()};
// Load transformed values into `src` array
correctionMatrix.mapPoints(src);
// `src[0]` and `src[1]` hold the transformed `X` and `Y` coordinates
canvas.drawText(word.text, src[0], src[1], somePaint);
....
canvas.restore();
}
This should give you the desired results - movement in the X and Y axis irrespective of canvas rotation.
You can obviously move the call to setRotate(float, float, float) to a better place. You only need to call it once after changing the angle value.

Java 2D "tank" game: Shooting 'missile' from rotated sprite doesn't work

EDIT: Problem solved. I forgot putting Math.toRadians() anywhere I do Math.cos or Math.sin. :)
I'm working on a simple Java 2D game involving two tanks that shoot missiles and move around the screen.
For this question, let's assume there's only one tank.
Controls:
Adjust angle of movement counter-clockwise: LEFT arrow key
Adjust angle of movement clockwise: RIGHT arrow key
Move forward: UP arrow key
Shoot missile: ENTER
Pressing LEFT or RIGHT also rotates the sprite.
I tried to code the game so that missiles will shoot from the "tank barrerl" (point marked in green). However, the code I wrote doesn't achieve this.
Instead, when pressing ENTER the missile appears in a point on the sprite or around it, that seems to be random.
(Orange point is the tank's origin: tank.getX(),tank.getY() ).
It wouldn't be a problem to code this, if it weren't for the fact the the tank rotates. The location of the green point changes everytime the user rotates the tank.
What is wrong with my code? This code should make the missile 'shoot' from wherever the "barrel" currently is. As I said, doesn't work.
This is what runs when the user presses ENTER.
enterAction = new AbstractAction(){
public void actionPerformed(ActionEvent e){
double missileXposition, missileYposition;
double tankMiddleX,tankMiddleY;
double angle, radius;
tankMiddleX = tank1.getX() + (tank1.getWidth()/2);
tankMiddleY = tank1.getY() + (tank1.getHeight()/2);
angle = tank1.getAngle();
radius = tank1.getWidth()/2;
missileXposition = tankMiddleX + ( Math.cos(angle) * radius );
missileYposition = tankMiddleY + ( Math.sin(angle) * radius );
missiles1.add( new Missile( missileXposition, missileYposition , "red" , tank1.getAngle() , tank1) );
}
};
The Missile class:
public class Missile extends Entity {
public Missile(double x, double y, String type, double angle, Tank tank){
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.type = type;
this.angle = angle;
if(type.equals("red")) image = new ImageIcon(this.getClass().getResource("sprites/redrocket1.png")).getImage();
if(type.equals("blue")) image = new ImageIcon(this.getClass().getResource("sprites/bluerocket1.png")).getImage();
width = image.getWidth(null);
height = image.getHeight(null);
if(type.equals("blue")) dx = (-1) * ( 6 * Math.cos(Math.toRadians(tank.getAngle())) );
if(type.equals("red")) dx = 6 * Math.cos(Math.toRadians(tank.getAngle()));
if(type.equals("blue")) dy = (-1) * ( 6 * Math.sin(Math.toRadians(tank.getAngle()) ) );
if(type.equals("red")) dy = 6 * Math.sin(Math.toRadians(tank.getAngle()));
}
}
Thanks a lot
Determine the distance between the sprite's origin (orange) and the missile start point (green) (d)and the angle between the upper rim of the sprite and the line orange-green a.
Now you set the start point of the missiles to
tank1.getX()+Math.cos(d*Math.toRadians(a+tank1.getAngle()));
tank1.getY()+Math.sin(d*Math.toRadians(a+tank1.getAngle()));
I don't know whether it's 100% correct, but I think it's the right direction.

Categories

Resources