RemoteInput.java :  » Game » libgdx » com » badlogic » gdx » input » Android Open Source

Android Open Source » Game » libgdx 
libgdx » com » badlogic » gdx » input » RemoteInput.java
package com.badlogic.gdx.input;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;
import java.util.Set;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.utils.GdxRuntimeException;

/**
 * <p>An {@link Input} implementation that receives touch, key, accelerometer
 * and compass events from a remote Android device. Just instantiate it
 * and specify the port it should listen on for incoming connections (default
 * 8190). Then store the new RemoteInput instance in Gdx.input. That's it.</p>
 * 
 * <p>On your Android device you can use the gdx-remote application available
 * on the Google Code page as an APK or in SVN (extensions/gdx-remote). Open it,
 * specify the IP address and the port of the PC your libgdx app is running on
 * and then tap away.</p>
 * 
 * <p>The touch coordinates will be translated to the desktop window's coordinate
 * system, no matter the orientation of the device</p>
 * 
 * @author mzechner
 *
 */
public class RemoteInput implements Runnable, Input {
  class KeyEvent {
    static final int KEY_DOWN = 0;
    static final int KEY_UP = 1;
    static final int KEY_TYPED = 2;

    long timeStamp;
    int type;
    int keyCode;
    char keyChar;
  }

  class TouchEvent {
    static final int TOUCH_DOWN = 0;
    static final int TOUCH_UP = 1;
    static final int TOUCH_DRAGGED = 2;

    long timeStamp;
    int type;
    int x;
    int y;
    int pointer;
  }
  
  class EventTrigger implements Runnable {
    TouchEvent touchEvent;
    KeyEvent keyEvent;
    
    public EventTrigger(TouchEvent touchEvent, KeyEvent keyEvent) {
      this.touchEvent = touchEvent;
      this.keyEvent = keyEvent;    
    }
    
    @Override public void run () {
      justTouched = false;
      if(processor != null) {
        if(touchEvent != null) {
          touchX[touchEvent.pointer] = touchEvent.x;
          touchY[touchEvent.pointer] = touchEvent.y;          
          switch(touchEvent.type) {
          case TouchEvent.TOUCH_DOWN:
            processor.touchDown(touchEvent.x, touchEvent.y, touchEvent.pointer, Input.Buttons.LEFT);
            isTouched[touchEvent.pointer] = true;
            justTouched = true;
            break;
          case TouchEvent.TOUCH_UP:
            processor.touchUp(touchEvent.x, touchEvent.y, touchEvent.pointer, Input.Buttons.LEFT);
            isTouched[touchEvent.pointer] = false;
            break;
          case TouchEvent.TOUCH_DRAGGED:
            processor.touchDragged(touchEvent.x, touchEvent.y, touchEvent.pointer);
            break;
          }
        }
        if(keyEvent != null) {
          switch(keyEvent.type) {
          case KeyEvent.KEY_DOWN:
            processor.keyDown(keyEvent.keyCode);
            keys.add(keyEvent.keyCode);
            break;
          case KeyEvent.KEY_UP:
            processor.keyUp(keyEvent.keyCode);
            keys.remove(keyEvent.keyCode);
            break;
          case KeyEvent.KEY_TYPED:
            processor.keyTyped(keyEvent.keyChar);
            break;
          }
        }
      } else {
        if(touchEvent != null) {
          touchX[touchEvent.pointer] = touchEvent.x;
          touchY[touchEvent.pointer] = touchEvent.y;
          if(touchEvent.type == TouchEvent.TOUCH_DOWN) {            
            isTouched[touchEvent.pointer] = true;
            justTouched = true;
          }
          if(touchEvent.type == TouchEvent.TOUCH_UP) {
            isTouched[touchEvent.pointer] = false;
          }
        }
        if(keyEvent != null) {
          if(keyEvent.type == KeyEvent.KEY_DOWN) keys.add(keyEvent.keyCode);
          if(keyEvent.type == KeyEvent.KEY_UP) keys.remove(keyEvent.keyCode);
        }
      }
    }    
  }
    
  public static int DEFAULT_PORT = 8190;
  private ServerSocket serverSocket;
  private float[] accel = new float[3];
  private float[] compass = new float[3];
  private boolean multiTouch = false;
  private float remoteWidth = 0;
  private float remoteHeight = 0;
  Set<Integer> keys = new HashSet<Integer>();  
  int[] touchX = new int[20];
  int[] touchY = new int[20];
  boolean isTouched[] = new boolean[20];
  boolean justTouched = false;
  InputProcessor processor = null;
  private final int port;
  public final String[] ips;
  
  public RemoteInput() {
    this(DEFAULT_PORT);
  }
  
  public RemoteInput(int port) {
    try {
      this.port = port;
      serverSocket = new ServerSocket(port);
      Thread thread = new Thread(this);
      thread.setDaemon(true);
      thread.start();            
      InetAddress[] allByName = InetAddress.getAllByName(InetAddress.getLocalHost().getHostName());
      ips = new String[allByName.length];
      for(int i = 0; i < allByName.length; i++) {
        ips[i] = allByName[i].getHostAddress();
      }            
    } catch(Exception e) {
      throw new GdxRuntimeException("Couldn't open listening socket at port '" + port+ "'", e);
    }
  }

  @Override public void run () {
    while(true) {
      try { 
        System.out.println("listening, port " + port);
        Socket socket = null;
        while(true) {      
            socket = serverSocket.accept();
            break;      
        }                    
        socket.setTcpNoDelay(true);  
        socket.setSoTimeout(3000);        
        
        DataInputStream in = new DataInputStream(socket.getInputStream());
        multiTouch = in.readBoolean();
        while(true) {
          int event = in.readInt();
          KeyEvent keyEvent = null;
          TouchEvent touchEvent = null;
          switch(event) {
          case RemoteSender.ACCEL:
            accel[0] = in.readFloat();
            accel[1] = in.readFloat();
            accel[2] = in.readFloat();
            break;
          case RemoteSender.COMPASS:
            compass[0] = in.readFloat();
            compass[1] = in.readFloat();
            compass[2] = in.readFloat();
            break;
          case RemoteSender.SIZE:
            remoteWidth = in.readFloat();
            remoteHeight = in.readFloat();
            break;
          case RemoteSender.KEY_DOWN:
            keyEvent = new KeyEvent();
            keyEvent.keyCode = in.readInt();
            keyEvent.type = KeyEvent.KEY_DOWN;
            break;
          case RemoteSender.KEY_UP:
            keyEvent = new KeyEvent();
            keyEvent.keyCode = in.readInt();
            keyEvent.type = KeyEvent.KEY_UP;
            break;
          case RemoteSender.KEY_TYPED:
            keyEvent = new KeyEvent();
            keyEvent.keyChar = in.readChar();
            keyEvent.type = KeyEvent.KEY_TYPED;
            break;
          case RemoteSender.TOUCH_DOWN:
            touchEvent = new TouchEvent();
            touchEvent.x = (int)((in.readInt() / remoteWidth) * Gdx.graphics.getWidth());
            touchEvent.y = (int)((in.readInt() / remoteHeight) * Gdx.graphics.getHeight());
            touchEvent.pointer = in.readInt();
            touchEvent.type = TouchEvent.TOUCH_DOWN;
            break;
          case RemoteSender.TOUCH_UP:
            touchEvent = new TouchEvent();
            touchEvent.x = (int)((in.readInt() / remoteWidth) * Gdx.graphics.getWidth());
            touchEvent.y = (int)((in.readInt() / remoteHeight) * Gdx.graphics.getHeight());
            touchEvent.pointer = in.readInt();
            touchEvent.type = TouchEvent.TOUCH_UP;
            break;
          case RemoteSender.TOUCH_DRAGGED:
            touchEvent = new TouchEvent();
            touchEvent.x = (int)((in.readInt() / remoteWidth) * Gdx.graphics.getWidth());
            touchEvent.y = (int)((in.readInt() / remoteHeight) * Gdx.graphics.getHeight());
            touchEvent.pointer = in.readInt();
            touchEvent.type = TouchEvent.TOUCH_DRAGGED;
            break;
          }
                    
          Gdx.app.postRunnable(new EventTrigger(touchEvent, keyEvent));
        }      
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  @Override public boolean isAccelerometerAvailable () {
    return true;
  }

  @Override public float getAccelerometerX () {
    return accel[0];
  }

  @Override public float getAccelerometerY () {
    return accel[1];
  }

  @Override public float getAccelerometerZ () {
    return accel[2];
  }

  @Override public int getX () {
    return touchX[0];
  }

  @Override public int getX (int pointer) {
    return touchX[pointer];
  }

  @Override public int getY () {
    return touchY[0];
  }

  @Override public int getY (int pointer) {
    return touchY[pointer];
  }

  @Override public boolean isTouched () {        
    return isTouched[0];
  }

  @Override public boolean justTouched () {
    return justTouched;
  }

  @Override public boolean isTouched (int pointer) {
    return isTouched[pointer];
  }

  @Override public boolean isButtonPressed (int button) {
    if(button != Buttons.LEFT) return false;
    for(int i = 0; i < isTouched.length; i++)
      if(isTouched[i]) return true;
    return false;
  }

  @Override public boolean isKeyPressed (int key) {
    return keys.contains(key);
  }

  @Override public void getTextInput (TextInputListener listener, String title, String text) {
    Gdx.app.getInput().getTextInput(listener, title, text);
  }

  @Override public void setOnscreenKeyboardVisible (boolean visible) {    
  }

  @Override public boolean supportsOnscreenKeyboard () {
    return false;
  }

  @Override public boolean supportsMultitouch () {
    return multiTouch;
  }

  @Override public boolean supportsVibrator () {
    return true;
  }

  @Override public void vibrate (int milliseconds) {
    
  }

  @Override public void vibrate (long[] pattern, int repeat) {
    
  }

  @Override public void cancelVibrate () {
    
  }

  @Override public boolean supportsCompass () {
    return true;
  }

  @Override public float getAzimuth () {
    return compass[0];
  }

  @Override public float getPitch () {
    return compass[1];
  }

  @Override public float getRoll () {
    return compass[2];
  }

  @Override public void setCatchBackKey (boolean catchBack) {
    
  }

  @Override public void setInputProcessor (InputProcessor processor) {
    this.processor = processor;
  }
  
  /**
   * @return the IP addresses {@link RemoteSender} or gdx-remote should connect to. Most likely the LAN addresses if behind a NAT.
   */
  public String[] getIPs() {
    return ips;
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.