public boolean touchDragged(int screenX, int screenY, int pointer) {
if(check) {
sprite.setPosition(screenX - sprite.getWidth() / 2, Gdx.graphics.getHeight() - screenY - sprite.getHeight() / 2);
rect.setPosition(screenX - sprite.getWidth() / 2, Gdx.graphics.getHeight() - screenY - sprite.getHeight() / 2);
}
return false;
}
this is my method in the my custom input processor class i use Input multiplexer in my main because i have 2 classes . Simultaneous drag won't move the sprite i can only move one sprite at a time.
My intention is to drag 2 sprites at the same time.
Thanks for your help and sorry for my bad English.
I don't know if this is the best approach, but a kinda-solution could be something like this:
1. Add a constant that let you know how many object you will allow to move at the same time:
private static final int MAX_TOUCHES = 4;
2. Add a collection with a fixed size, with this you'll manage all sprite that are currently being possible moving:
private final Array<Sprite> sprites = new Array<Sprite>(MAX_TOUCHES);
3. Now, in your class where you are handling touches, implement the touchDown(), touchDragged() and touchUp():
/**
* In the touchDown, add the sprite being touched
**/
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
// Just allow 4 sprites to move at same time
if(pointer >= MAX_TOUCHES) return true;
// Get the sprite at this current position...
Sprite sprite = getSpriteAtThisPosition(screenX, screenY);
// If sprite found, add to list with current pointer, else, do nothing
if(sprite != null) {
sprites.set(pointer, sprite);
}
return true;
}
getSpriteAtThisPosition() is just a method that return the first current sprite in that position, could return null.
/**
* In the touchDragged, move this sprite
**/
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
// Just allow 4 sprites to move at same time
if(pointer >= MAX_TOUCHES) return false;
// Get the sprite with the current pointer
Sprite sprite = sprites.get(pointer);
// if sprite is null, do nothing
if(sprite == null) return false;
// else, move sprite to new position
sprite.setPosition(screenX - sprite.getWidth() / 2,
Gdx.graphics.getHeight() - screenY -
sprite.getHeight() / 2);
return false;
}
/**
* In the touchUp, remove this sprite from the list
**/
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
// Just allow 4 sprites to move at same time
if(pointer >= MAX_TOUCHES) return true;
// remove sprite at pointer position
sprites.set(pointer, null);
return true;
}
The InputMultiplexer is not for dealing with two classes of object to move but to handle two input processors (or more) that you want to have - for example when you have more than one Stage and want to interact with player with each of them.
What you should do here would be to remember what pointer is attached to the touched object and then move it according to the pointer movement. The pointer is just id of for example finger enumerated from 0. So when you will touch screen with first finger it is 0 pointer, second one is 1 - BUT! If you will leave first finger keeping second the second is still 1 so it is perfect for this usage.
To handle remembering pointer id you also need to implement touchDown listener method
The code example would be like:
HashMap<Integer, Sprite> ids = new HashMap<Integer, Sprite>();
...
public boolean touchDown (int x, int y, int pointer, int button)
{
Sprite sprite = getSprite(x, y); //getSprite should iterate over all sprites in your game checking if x/y is inside one of them - you need to implement this one
ids.put(pointer, sprite);
return true;
}
public boolean touchUp (int x, int y, int pointer, int button)
{
ids.remove(pointer); //removing from hashmap
return false;
}
public boolean touchDragged (int x, int y, int pointer)
{
Sprite sprite = ids.get(pointer);
if(sprite != null)
{
sprite.setPosition... //and so on
}
return false;
}
For getting more information about multitouch handling you can check out this tutorial.
Related
What i am trying to do is move a rectangle left and right by dragging my finger on my android device. I want the rectangle to stop when i stop without lifting up my finger. Is this possible?
My InputHandler code:
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
lastTouch.set(screenX, screenY);
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
// Determines if my finger is moving to the left or right
Vector2 newTouch = new Vector2(screenX, screenY);
Vector2 delta = newTouch.cpy().sub(lastTouch);
// Moves the player right
if(delta.x > 0f) {
world.getPlayer().setVel(5.0f, 0f);
} else {
// Moves the player left
if(delta.x < 0f) {
world.getPlayer().setVel(-5.0f, 0);
}
// This is not being called
else
world.getPlayer().setVel(0f, 0f);
}
lastTouch = newTouch;
return false;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
world.getPlayer().setVel(0f, 0f);
return false;
}
The problem is when you touchDrag the input is never exactly the pixel where the finger is on because touch screens are not pixel accurate. Your finger hits the screen at multiple pixels at the same time. The device then decides which pixel is sent to the application.
So a possible solution is to add a minimum delta which must be reached to move the player at all. If the minimum delta is not reached stop movement.
if(delta.x > 20f) {
world.getPlayer().setVel(5.0f, 0f);
} else {
// Moves the player left
if(delta.x < -20f) {
world.getPlayer().setVel(-5.0f, 0);
}
// This is not being called
else
world.getPlayer().setVel(0f, 0f);
}
In this case minimum delta is 20. You need to play around which value fits your needs.
I'm making a game where swiping and justTouched do different things. My problem is that when I swipe on the screen obviously the touchDown() method is also being triggered.
Im extending GestureAdapter:
#Override
public boolean touchDown(float x, float y, int pointer, int button) {
//move when screen is touched
if(life == 1 && overlaps == false) {
timeState = 0;
velocity.y = -120;
velocity.x = 100;
}
return super.touchDown(x, y, pointer, button);
}
#Override
public boolean fling(float velocityX, float velocityY, int button) {
if(velocityX > 10)
//do something
return super.fling(velocityX, velocityY, button);
}
You should not use just touched in this case because when player touched first time you cant know will it be just touch or swipe.
You must use justtouched with touch up method like this
when player justtouched save touched coordinates.
Check coordinates when player touched up.
If distance between this 2 points less than 50 pixels (or what limit you want to set) then you can assume its justtouched otherwise its swipe and you can do calculations about swiping.
I just started a small project with libgdx and I noticed that the camera is lagging behind the mouse a bit. I am moving it like that: (I have cut out everything else)
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
screenXlast = screenX;
screenYlast = screenY;
if (button == Input.Buttons.RIGHT || pointer > 0) {
rightMouseKlicked = true;
return true;
}
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
if (button == Input.Buttons.RIGHT) {
rightMouseKlicked = false;
}
return false;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
if (rightMouseKlicked) {
gamecam.translate((screenXlast - screenX) * gamecam.zoom, (screenY -
screenYlast) * gamecam.zoom);
}
screenXlast = screenX;
screenYlast = screenY;
return false;
}
The game runs at 60fps but it seems like the output is delayed by a few frames. (the mouse cursor does not stay at the same position on the map while moving it around)
Is there an other way of doing it, so that the camera stays up with the mouse?
As far as I know, events in libgdx go into a stack. It is possible to receive the event a few ms after it actually happened.
You can see that if you draw an actor or a texture of the position of the touch dragged event - if you drag fast you will see that the drawn texture is always behind your mouse (or finder on phones).
As #Jankapunkt said, you can try multiplying the position by the delta time (Gdx.graphics.getDeltaTime()) but I am not sure that it will help
You are calculating the screen pixels moved, but not scaling to the size of your camera's viewport. Modify it as shown:
public boolean touchDragged(int screenX, int screenY, int pointer) {
if (rightMouseKlicked) {
float scale = gamecam.zoom * gamecam.viewportWidth / (float)(Gdx.graphics.getWidth);
gamecam.translate((screenXlast - screenX) * scale , (screenY -
screenYlast) * scale );
}
screenXlast = screenX;
screenYlast = screenY;
return false;
}
Also keep in mind that a typical mouse's update rate is pretty low (about 10 FPS I think). If you find camera movement too jerky, you'll have to calculate mouse movement speed and extrapolate the mouse's position and add a smoothing algorithm on top of that. See here for discussion (3D but still generally applies).
I want to check for collision with the current touch point and a previously drawn pixmap line, meaning I must not touch the previously touched line or I must not overlap the coordinates of the line with my current touched coordinates.
I am drawing pixmap on drag like this.
int lastX,lastY;
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
UP = false;
lastX = screenX;
lastY = screenY;
return true;
}
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
UP=false;
pixmap.setColor(Color.RED);
pixmap.drawLine(lastX, lastY, screenX, screenY);
lastX = screenX;
lastY = screenY;
linetexture.draw(pixmap, 0, 0);
return true;
}
So, what I want is: I must not touch the drawn line coordinates again, and to do that I need to store the pixmap line coordinates, but if I try it on the drag method and if I drag fast it doesn't store all the points on the drag path.
How can I store the path of the line efficiently to check that my current touch point (Gdx.input.getX(),Gdx.input.GetY()) is not overlapping the drawn line coordinates?
I'm trying to make a fish character move wherever the player puts their finger. I'm doing this using libgdx's touch dragged. For some reason, the x and y coordinates where the touch is registered is only giving me one number, and doesn't seem to be on screen. I've read other questions related to libgdx touchdragged here, but can't find anyone else having an issue like this. For now, I'm just trying to make the fish move in the basic directions (N, NW, W, etc.) Eventually I will use the delta to make it move to the touch location.
This is the coordinates it keeps giving me in the console:
08-17 15:12:16.181 11497-11595/? I/2367﹕ 721
08-17 15:12:16.211 11497-11595/? I/2362﹕ 728
08-17 15:12:16.231 11497-11595/? I/2359﹕ 733
08-17 15:12:16.251 11497-11595/? I/2356﹕ 736
I'm using Gdx.app.log to log the values, but I can't make any sense of it. This is the code for the onClick:
public void onClick(int clickX, int clickY) {
Gdx.app.log(String.valueOf(clickX),String.valueOf(clickY));
if (this.getX() - clickX < 0){
velocity.x = -5;
}
if (this.getX() - clickX > 0){
velocity.x = 5;
}
if (this.getY() - clickY < 0){
velocity.y = 5;
}
if (this.getY() - clickY > 0) {
velocity.y = -5;
}
}
And lastly, the inputHandler class (relevant area):
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
myFish.onClick(screenX,screenY);
return true;
}
Currently my fish keeps moving towards the bottom left, no matter what I do and I think it's due to the strange x,y coordinates.
I've also tried using Gdx.input.getX() and Gdx.input.getY(), but keep getting the same issue (large single coordinates).
I'm not sure if screenX and screenY are the correct values to use, but using both screenX and Gdx.input.getX() still give me the same problem.
Not sure if this will answer entirely your question but you need to unproject your click/drag coordinate to translate them to your gameworld coordinate system. This is done like this:
#Override
public boolean touchDragged(int screenX, int screenY, int pointer) {
Vector3 v = new Vector3(screenX, screenY, 0);
v = camera.unproject(v);
myFish.onClick(v.x, v.y);
return true;
}