Search code examples
javalibgdxbox2d2d-games

Libgdx multiTouch not working


I'm developing a game , and I'm using Libgdx Library in this game. It will work on Android and must play with two players on one screen. But I can't get the another player inputs. I can play with bottom or top player, but not both.

This is the get input codes:

public class PlayStateInput implements InputProcessor {

private PlayState playState;
private Vector2 touchPos;
private Vector2 bodyCord;


public PlayStateInput(PlayState playState){

    this.playState = playState;
    touchPos = new Vector2();
    bodyCord = new Vector2();

    touchPos.x=Gdx.input.getX();
    touchPos.y=Gdx.input.getY();
    bodyCord.x=playState.getGameWorld().getPaddle().getBody().getPosition().x;
    bodyCord.y=playState.getGameWorld().getPaddle().getBody().getPosition().y;

}

@Override
public boolean keyDown(int keycode) {
    return false;
}

@Override
public boolean keyUp(int keycode) {
    return false;
}

@Override
public boolean keyTyped(char character) {
    return false;
}

@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {

    if(playState.getGameWorld().getPuck().getCircleRect().contains(screenX,screenY)){

        System.out.println("collision");
    }

    if(screenY > Gdx.graphics.getHeight()/2 && (pointer <= 2)){
        playState.getGameWorld().getPaddle2().setBottomPaddle(true);

    }

    if(screenY < Gdx.graphics.getHeight()/2 && (pointer <= 2)){
        playState.getGameWorld().getPaddle().setTopPaddle(true);
    }

    return false;
}

And the use this inputs here:

public class Paddle implements GameObject {


private World world;
private Body body;
private Body body2;
private BodyDef bodyDef;
private BodyDef bodyDef2;
private Fixture fixture;
private Fixture fixture2;
private FixtureDef fixtureDef;
private FixtureDef fixtureDef2;


private Circle circleRect;
private Circle circleRect2;
boolean TopPaddle = false;
boolean BottomPaddle = false;

private float PPM=100f;
private float power=100f;

private Vector2 touchPos;

private Sprite sprite;

String koordinatlar;


public Paddle(World world){


    this.world = world;

    bodyDef = new BodyDef();
    bodyDef.type = BodyDef.BodyType.DynamicBody;
    bodyDef.position.set((Gdx.graphics.getWidth()/2)/PPM,(Gdx.graphics.getHeight()/3)/PPM);

    body = world.createBody(bodyDef);



    fixtureDef = new FixtureDef();
    fixtureDef.density = 1.0f;
    fixtureDef.friction = 1.0f;
    fixtureDef.restitution=0.3f;


    CircleShape circleShape = new CircleShape();
    circleShape.setRadius((Gdx.graphics.getWidth()/16)/PPM);
    fixtureDef.shape = circleShape;

    fixture = body.createFixture(fixtureDef);

    circleRect = new Circle(body.getPosition().x,body.getPosition().y,(Gdx.graphics.getWidth()/16));

    Sprite.split(ImageLoader.playButtonRegion.getTexture(),20,20);



    sprite = new Sprite(ImageLoader.paddle);
    sprite.setSize((Gdx.graphics.getWidth()/8),(Gdx.graphics.getWidth()/8));
    sprite.setPosition((Gdx.graphics.getWidth()/2)-30f,(Gdx.graphics.getHeight()/3)-30f);


    touchPos = new Vector2();

}

@Override
public void render(SpriteBatch sb) {


    sprite.draw(sb);
    sprite.setPosition(body.getPosition().x*PPM-30f,body.getPosition().y*PPM-30f);
}

@Override
public void update(float delta) {

    touchPos.x=Gdx.input.getX()/PPM;
    touchPos.y=Gdx.input.getY()/PPM;

    System.out.println(touchPos);


    if (TopPaddle) {

        body.setLinearVelocity(power*(touchPos.x-body.getPosition().x),power*(touchPos.y-body.getPosition().y));
        body.setAngularVelocity(0.0f);


        if(Gdx.input.getY()>Gdx.graphics.getHeight()/2){

            body.setLinearVelocity(0f,0f);
        }
        //System.out.println(Gdx.input.getX()+" "+Gdx.input.getY());
    }

}

I hope, I made myself clear.


Solution

  • I think I see your problem, you are relying on the fact that only one input is being taken at a time. As a result, you will be ignoring one of the two players if both are giving input simultaneously.

    There are multiple ways to go about solving your multi-touch input problem but I'll go about explaining a simple technique - modified from this answer.

    To allow both players to take in input you will need two variables - I'll call them topTouchPos and bottomTouchPos. Each of these will be a Vector2 like your current touchPos and they will be calculated as follows (inside your update method):

    //Initialise both vectors to vectors that can't be touched (negative)
    Vector2 topTouchPos = new Vector2(-1,-1), bottomTouchPos = new Vector2(-1,-1);
    
    //Two people can have up to 20 fingers (most touchscreen devices will have a lower limit anyway)
    for (int i = 0; i < 20; i++) {
        //Check if this finger ID is touched
        if (Gdx.input.isTouched(i)) {
            //Classify it as either the top or bottom player
            bool bottom = Gdx.input.getY(i) > Gdx.graphics.getHeight()/2;
            if (bottom) bottomTouchPos.set(Gdx.input.getX(i), Gdx.input.getY(i));
            else topTouchPos.set(Gdx.input.getX(i), Gdx.input.getY(i));
        }
    }
    

    When you get into your main game code you will have to check for both players. If either topTouchPos or bottomTouchPos are not negative then use their touch values for their respective players.

    Hope this helps (I haven't tested any code so beware of any typos).