From c6f310884aa76244db4ddd1dd207492758d61809 Mon Sep 17 00:00:00 2001 From: Miguel Astor Date: Mon, 13 Jan 2014 14:33:35 -0430 Subject: [PATCH 01/16] Testing video streaming framerate. --- .gitignore | 1 + src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 21 +++++++++++++++++-- .../nxtar/network/VideoStreamingThread.java | 21 +++++++++++++++++++ 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 87a44e0..709398b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ local.properties # Eclipse project files .classpath .project +libs/ # Proguard folder generated by Eclipse proguard/ diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index 533bfa6..026f21f 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -28,11 +28,13 @@ import ve.ucv.ciens.ccg.nxtar.utils.Size; import com.badlogic.gdx.Application; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.FPSLogger; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture.TextureFilter; +import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; @@ -47,6 +49,8 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener private Sprite sprite; private Toaster toaster; private MulticastEnabler mcastEnabler; + private FPSLogger fps; + private BitmapFont font; private int connections; private VideoFrameMonitor frameMonitor; @@ -71,7 +75,10 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener float w = Gdx.graphics.getWidth(); float h = Gdx.graphics.getHeight(); - Gdx.app.setLogLevel(Application.LOG_DEBUG); + fps = new FPSLogger(); + font = new BitmapFont(); + + //Gdx.app.setLogLevel(Application.LOG_NONE); camera = new OrthographicCamera(1, h/w); batch = new SpriteBatch(); @@ -103,6 +110,7 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener public void dispose() { batch.dispose(); texture.dispose(); + font.dispose(); } @Override @@ -129,18 +137,27 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener TextureRegion region = new TextureRegion(texture, 0, 0, dimensions.getWidth(), dimensions.getHeight()); sprite = new Sprite(region); - sprite.setSize(0.9f, 0.9f * sprite.getHeight() / sprite.getWidth()); + sprite.setSize(0.9f, 0.9f * sprite.getWidth() / sprite.getHeight()); sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2); sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2); + sprite.rotate90(true); batch.setProjectionMatrix(camera.combined); batch.begin();{ sprite.draw(batch); + font.setColor(0.0f, 0.0f, 0.0f, 1.0f); + font.setScale(100.0f); + font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), 10, 300); }batch.end(); + Gdx.app.log("Main", String.format("Network FPS: %d", videoThread.getFps())); + Gdx.app.log("Main", String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond())); + texture.dispose(); temp.dispose(); image.dispose(); + + //fps.log(); } } diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java index b7b5889..ba71dd3 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java @@ -50,10 +50,15 @@ public class VideoStreamingThread extends Thread { private ObjectInputStream reader; private ObjectOutputStream writer; private VideoFrameMonitor frameMonitor; + private long then; + private long now; + private long delta; + private int fps; private VideoStreamingThread(){ super(THREAD_NAME); + fps = 0; netListener = null; toaster = null; protocolStarted = false; @@ -330,9 +335,14 @@ public class VideoStreamingThread extends Thread { Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Received something unknown."); } } + + public int getFps(){ + return fps; + } @Override public void run(){ + int frames = 0; // Listen on the server socket until a client successfully connects. do{ try{ @@ -349,8 +359,19 @@ public class VideoStreamingThread extends Thread { } }while(client != null && !client.isConnected()); + then = System.currentTimeMillis(); + while(!done){ receiveImage(); + frames++; + now = System.currentTimeMillis(); + delta = now - then; + if(delta >= 1000){ + fps = frames; + frames = 0; + then = now; + delta = 0; + } } try{ From da044c5b1c432335b043651f199cdacc1c50bf7a Mon Sep 17 00:00:00 2001 From: Miguel Astor Date: Wed, 15 Jan 2014 14:50:54 -0430 Subject: [PATCH 02/16] Changed the streaming to use UDP. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 2 +- .../nxtar/network/VideoStreamingThread.java | 86 +++++++++++++++++-- 2 files changed, 82 insertions(+), 6 deletions(-) diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index 026f21f..6b37a43 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -78,7 +78,7 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener fps = new FPSLogger(); font = new BitmapFont(); - //Gdx.app.setLogLevel(Application.LOG_NONE); + Gdx.app.setLogLevel(Application.LOG_DEBUG); camera = new OrthographicCamera(1, h/w); batch = new SpriteBatch(); diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java index ba71dd3..27b6e57 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java @@ -15,17 +15,18 @@ */ package ve.ucv.ciens.ccg.nxtar.network; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.net.DatagramPacket; +import java.net.DatagramSocket; import java.net.ServerSocket; import java.net.Socket; import ve.ucv.ciens.ccg.networkdata.VideoFrameDataMessage; -import ve.ucv.ciens.ccg.networkdata.VideoStreamingControlMessage; import ve.ucv.ciens.ccg.nxtar.interfaces.NetworkConnectionListener; import ve.ucv.ciens.ccg.nxtar.interfaces.Toaster; -import ve.ucv.ciens.ccg.nxtar.network.protocols.VideoStreamingProtocol; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import com.badlogic.gdx.Gdx; @@ -39,6 +40,7 @@ public class VideoStreamingThread extends Thread { private NetworkConnectionListener netListener; private ServerSocket server; + private DatagramSocket socket; private Toaster toaster; private ProtocolState_t protocolState; private boolean protocolStarted; @@ -71,6 +73,7 @@ public class VideoStreamingThread extends Thread { try{ server = new ServerSocket(ProjectConstants.SERVER_TCP_PORT_1); + socket = new DatagramSocket(ProjectConstants.SERVER_TCP_PORT_2); }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".VideoStreamingThread() :: Error creating server: " + io.getMessage(), io); } @@ -335,7 +338,78 @@ public class VideoStreamingThread extends Thread { Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Received something unknown."); } } - + + private int byteArray2Int(byte[] array){ + int number = 0; + for(int i = 0; i < 4; i++){ + number |= (array[3-i] & 0xff) << (i << 3); + } + return number; + } + + private void receiveUdp(){ + try{ + int intSize; + byte[] size = new byte[4]; + byte[] data; + DatagramPacket packet; + VideoFrameDataMessage dataMessage; + Object tmpMessage; + + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Reading message size from socket."); + try{ + packet = new DatagramPacket(size, size.length); + socket.receive(packet); + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException receiving size " + io.getMessage()); + return; + } + + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Creating buffers."); + intSize = byteArray2Int(size); + data = new byte[intSize]; + + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Reading message from socket."); + try{ + packet = new DatagramPacket(data, data.length); + socket.receive(packet); + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException receiving data " + io.getMessage()); + return; + } + + ByteArrayInputStream bais = new ByteArrayInputStream(data); + + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Saving message in monitor."); + try{ + ObjectInputStream ois = new ObjectInputStream(bais); + tmpMessage = ois.readObject(); + + if(tmpMessage instanceof VideoFrameDataMessage){ + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received a data message."); + dataMessage = (VideoFrameDataMessage) tmpMessage; + + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received frame dimensions are: " + + Integer.toString(dataMessage.imageWidth) + "x" + Integer.toString(dataMessage.imageHeight)); + frameMonitor.setFrameDimensions(dataMessage.imageWidth, dataMessage.imageHeight); + frameMonitor.setNewFrame(dataMessage.data); + + }else{ + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received something unknown."); + } + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException received deserializing message " + io.getMessage()); + return; + }catch(ClassNotFoundException cn){ + Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: ClassNotFoundException received " + cn.getMessage()); + return; + } + }catch(Exception e){ + Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: Exception received " + e.getMessage()); + return; + } + } + public int getFps(){ return fps; } @@ -360,9 +434,11 @@ public class VideoStreamingThread extends Thread { }while(client != null && !client.isConnected()); then = System.currentTimeMillis(); - + while(!done){ - receiveImage(); + //receiveImage(); + Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Receiving."); + receiveUdp(); frames++; now = System.currentTimeMillis(); delta = now - then; From b937b93767d10049b07ece7cc03fd15f5809fd93 Mon Sep 17 00:00:00 2001 From: Miguel Astor Date: Mon, 20 Jan 2014 13:00:29 -0430 Subject: [PATCH 03/16] Minor cosmetic touches. --- .../nxtar/network/VideoStreamingThread.java | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java index 27b6e57..f163f29 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java @@ -349,61 +349,61 @@ public class VideoStreamingThread extends Thread { private void receiveUdp(){ try{ - int intSize; - byte[] size = new byte[4]; - byte[] data; - DatagramPacket packet; - VideoFrameDataMessage dataMessage; - Object tmpMessage; + int intSize; + byte[] size = new byte[4]; + byte[] data; + DatagramPacket packet; + VideoFrameDataMessage dataMessage; + Object tmpMessage; - Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Reading message size from socket."); - try{ - packet = new DatagramPacket(size, size.length); - socket.receive(packet); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException receiving size " + io.getMessage()); - return; - } - - Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Creating buffers."); - intSize = byteArray2Int(size); - data = new byte[intSize]; - - Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Reading message from socket."); - try{ - packet = new DatagramPacket(data, data.length); - socket.receive(packet); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException receiving data " + io.getMessage()); - return; - } - - ByteArrayInputStream bais = new ByteArrayInputStream(data); - - Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Saving message in monitor."); - try{ - ObjectInputStream ois = new ObjectInputStream(bais); - tmpMessage = ois.readObject(); - - if(tmpMessage instanceof VideoFrameDataMessage){ - Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received a data message."); - dataMessage = (VideoFrameDataMessage) tmpMessage; - - Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received frame dimensions are: " + - Integer.toString(dataMessage.imageWidth) + "x" + Integer.toString(dataMessage.imageHeight)); - frameMonitor.setFrameDimensions(dataMessage.imageWidth, dataMessage.imageHeight); - frameMonitor.setNewFrame(dataMessage.data); - - }else{ - Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received something unknown."); + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Reading message size from socket."); + try{ + packet = new DatagramPacket(size, size.length); + socket.receive(packet); + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException receiving size " + io.getMessage()); + return; + } + + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Creating buffers."); + intSize = byteArray2Int(size); + data = new byte[intSize]; + + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Reading message from socket."); + try{ + packet = new DatagramPacket(data, data.length); + socket.receive(packet); + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException receiving data " + io.getMessage()); + return; + } + + ByteArrayInputStream bais = new ByteArrayInputStream(data); + + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Saving message in monitor."); + try{ + ObjectInputStream ois = new ObjectInputStream(bais); + tmpMessage = ois.readObject(); + + if(tmpMessage instanceof VideoFrameDataMessage){ + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received a data message."); + dataMessage = (VideoFrameDataMessage) tmpMessage; + + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received frame dimensions are: " + + Integer.toString(dataMessage.imageWidth) + "x" + Integer.toString(dataMessage.imageHeight)); + frameMonitor.setFrameDimensions(dataMessage.imageWidth, dataMessage.imageHeight); + frameMonitor.setNewFrame(dataMessage.data); + + }else{ + Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received something unknown."); + } + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException received deserializing message " + io.getMessage()); + return; + }catch(ClassNotFoundException cn){ + Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: ClassNotFoundException received " + cn.getMessage()); + return; } - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException received deserializing message " + io.getMessage()); - return; - }catch(ClassNotFoundException cn){ - Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: ClassNotFoundException received " + cn.getMessage()); - return; - } }catch(Exception e){ Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: Exception received " + e.getMessage()); return; From 0b790bce8fa98bdd55405caa89a3c57140a0ab1d Mon Sep 17 00:00:00 2001 From: Miguel Astor Date: Tue, 21 Jan 2014 12:20:38 -0430 Subject: [PATCH 04/16] Removed the TCP video streaming code. --- .../ucv/ciens/ccg/networkdata/MotorEvent.java | 37 ++++++++++++ src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 8 ++- .../nxtar/network/VideoStreamingThread.java | 59 +++++++++---------- 3 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 src/ve/ucv/ciens/ccg/networkdata/MotorEvent.java diff --git a/src/ve/ucv/ciens/ccg/networkdata/MotorEvent.java b/src/ve/ucv/ciens/ccg/networkdata/MotorEvent.java new file mode 100644 index 0000000..5cdcfc9 --- /dev/null +++ b/src/ve/ucv/ciens/ccg/networkdata/MotorEvent.java @@ -0,0 +1,37 @@ +package ve.ucv.ciens.ccg.networkdata; + +import java.io.Serializable; + +public class MotorEvent implements Serializable{ + private static final long serialVersionUID = 9989L; + + public enum motor_t {NONE, MOTOR_A, MOTOR_B, MOTOR_C, MOTOR_AC}; + + private motor_t motor; + private byte power; + + public MotorEvent(){ + motor = motor_t.NONE; + power = 0; + } + + public void setMotor(motor_t motor){ + this.motor = motor; + } + + public void setPower(byte power) throws IllegalArgumentException{ + if(power > 100 || power < -100){ + throw new IllegalArgumentException("Motor power must be a number between -100 and 100"); + }else{ + this.power = power; + } + } + + public motor_t getMotor(){ + return this.motor; + } + + public byte getPower(){ + return this.power; + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index 6b37a43..d078110 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -97,7 +97,7 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener frameMonitor = VideoFrameMonitor.getInstance(); mcastEnabler.enableMulticast(); udpThread = ServiceDiscoveryThread.getInstance(); - videoThread = VideoStreamingThread.getInstance().setToaster(toaster); + videoThread = VideoStreamingThread.getInstance()/*.setToaster(toaster)*/; //robotThread = RobotControlThread.getInstance().setToaster(toaster); udpThread.start(); @@ -138,8 +138,10 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener sprite = new Sprite(region); sprite.setSize(0.9f, 0.9f * sprite.getWidth() / sprite.getHeight()); - sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2); - sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2); + /*sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2); + sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2);*/ + sprite.setOrigin(0, 0); + sprite.setPosition(-sprite.getWidth()/2, (-sprite.getHeight()/3)); sprite.rotate90(true); batch.setProjectionMatrix(camera.combined); diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java index f163f29..32170ce 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java @@ -18,15 +18,12 @@ package ve.ucv.ciens.ccg.nxtar.network; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; import java.net.DatagramPacket; import java.net.DatagramSocket; -import java.net.ServerSocket; import java.net.Socket; import ve.ucv.ciens.ccg.networkdata.VideoFrameDataMessage; import ve.ucv.ciens.ccg.nxtar.interfaces.NetworkConnectionListener; -import ve.ucv.ciens.ccg.nxtar.interfaces.Toaster; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import com.badlogic.gdx.Gdx; @@ -36,21 +33,21 @@ public class VideoStreamingThread extends Thread { private static final String TAG = "NXTAR_CORE_VIDEOTHREAD"; private static final String CLASS_NAME = VideoStreamingThread.class.getSimpleName(); - private enum ProtocolState_t {WAIT_FOR_START, SEND_CONTINUE, RECEIVE_DATA, SEND_ACK_NEXT, SEND_ACK_WAIT, PAUSED, END_STREAM}; + //private enum ProtocolState_t {WAIT_FOR_START, SEND_CONTINUE, RECEIVE_DATA, SEND_ACK_NEXT, SEND_ACK_WAIT, PAUSED, END_STREAM}; private NetworkConnectionListener netListener; - private ServerSocket server; + //private ServerSocket server; private DatagramSocket socket; - private Toaster toaster; - private ProtocolState_t protocolState; + //private Toaster toaster; + //private ProtocolState_t protocolState; private boolean protocolStarted; - private boolean pauseProtocol; - private boolean endProtocol; + /*private boolean pauseProtocol; + private boolean endProtocol;*/ private boolean done; private Object protocolPauseMonitor; private Socket client; - private ObjectInputStream reader; - private ObjectOutputStream writer; + //private ObjectInputStream reader; + //private ObjectOutputStream writer; private VideoFrameMonitor frameMonitor; private long then; private long now; @@ -62,18 +59,18 @@ public class VideoStreamingThread extends Thread { fps = 0; netListener = null; - toaster = null; + //toaster = null; protocolStarted = false; - endProtocol = false; - pauseProtocol = false; + /*endProtocol = false; + pauseProtocol = false;*/ done = false; - protocolState = ProtocolState_t.WAIT_FOR_START; + //protocolState = ProtocolState_t.WAIT_FOR_START; protocolPauseMonitor = new Object(); frameMonitor = VideoFrameMonitor.getInstance(); try{ - server = new ServerSocket(ProjectConstants.SERVER_TCP_PORT_1); - socket = new DatagramSocket(ProjectConstants.SERVER_TCP_PORT_2); + //server = new ServerSocket(ProjectConstants.SERVER_TCP_PORT_1); + socket = new DatagramSocket(ProjectConstants.SERVER_TCP_PORT_1); }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".VideoStreamingThread() :: Error creating server: " + io.getMessage(), io); } @@ -87,26 +84,26 @@ public class VideoStreamingThread extends Thread { return SingletonHolder.INSTANCE; } - public VideoStreamingThread setToaster(Toaster toaster){ + /*public VideoStreamingThread setToaster(Toaster toaster){ this.toaster = toaster; return this; - } + }*/ public void addNetworkConnectionListener(NetworkConnectionListener listener){ netListener = listener; } - private void toast(String message){ + /*private void toast(String message){ if(toaster != null) toaster.showShortToast(message); - } + }*/ public void startStreaming(){ if(!protocolStarted){ Gdx.app.debug(TAG, CLASS_NAME + ".startStreaming() :: Requesting protocol start."); synchronized(protocolPauseMonitor){ protocolStarted = true; - protocolState = ProtocolState_t.SEND_CONTINUE; + //protocolState = ProtocolState_t.SEND_CONTINUE; protocolPauseMonitor.notifyAll(); } } @@ -115,7 +112,7 @@ public class VideoStreamingThread extends Thread { public void pauseStreaming(){ if(protocolStarted){ Gdx.app.debug(TAG, CLASS_NAME + ".pauseStreaming() :: Requesting protocol pause."); - pauseProtocol = true; + //pauseProtocol = true; }else return; } @@ -124,7 +121,7 @@ public class VideoStreamingThread extends Thread { if(protocolStarted){ Gdx.app.debug(TAG, CLASS_NAME + ".resumeStreaming() :: Requesting protocol resume."); synchronized(protocolPauseMonitor){ - pauseProtocol = false; + //pauseProtocol = false; protocolPauseMonitor.notifyAll(); } }else @@ -134,7 +131,7 @@ public class VideoStreamingThread extends Thread { public void finishStreaming(){ if(protocolStarted){ Gdx.app.debug(TAG, CLASS_NAME + ".finishStreaming() :: Requesting protocol end."); - endProtocol = true; + //endProtocol = true; }else return; } @@ -312,7 +309,7 @@ public class VideoStreamingThread extends Thread { Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Thread finished."); }*/ - private void receiveImage(){ + /*private void receiveImage(){ Object tmpMessage; VideoFrameDataMessage dataMessage; @@ -337,7 +334,7 @@ public class VideoStreamingThread extends Thread { }else{ Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Received something unknown."); } - } + }*/ private int byteArray2Int(byte[] array){ int number = 0; @@ -418,26 +415,28 @@ public class VideoStreamingThread extends Thread { public void run(){ int frames = 0; // Listen on the server socket until a client successfully connects. - do{ + /*do{ try{ Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Listening for client."); client = server.accept(); if(netListener != null) netListener.networkStreamConnected(THREAD_NAME); - writer = new ObjectOutputStream(client.getOutputStream()); + //writer = new ObjectOutputStream(client.getOutputStream()); reader = new ObjectInputStream(client.getInputStream()); toast("Client connected"); }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error accepting client: " + io.getMessage(), io); client = null; } - }while(client != null && !client.isConnected()); + }while(client != null && !client.isConnected());*/ then = System.currentTimeMillis(); while(!done){ //receiveImage(); Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Receiving."); + if(netListener != null) + netListener.networkStreamConnected(THREAD_NAME); receiveUdp(); frames++; now = System.currentTimeMillis(); From bfea25e95ea96ed2674d6e10dbc398801a25722b Mon Sep 17 00:00:00 2001 From: Miguel Astor Date: Fri, 24 Jan 2014 12:25:58 -0430 Subject: [PATCH 05/16] Added gui buttons. Removed tcp connection for video code. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 281 +++++++++++++++--- .../nxtar/network/VideoStreamingThread.java | 21 +- .../ccg/nxtar/utils/ProjectConstants.java | 2 + 3 files changed, 266 insertions(+), 38 deletions(-) diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index d078110..b738911 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -28,6 +28,8 @@ import ve.ucv.ciens.ccg.nxtar.utils.Size; import com.badlogic.gdx.Application; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.InputProcessor; +import com.badlogic.gdx.controllers.mappings.Ouya; import com.badlogic.gdx.graphics.FPSLogger; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.OrthographicCamera; @@ -38,20 +40,35 @@ import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; -public class NxtARCore implements ApplicationListener, NetworkConnectionListener { +public class NxtARCore implements ApplicationListener, NetworkConnectionListener, InputProcessor{ private static final String TAG = "NXTAR_CORE_MAIN"; private static final String CLASS_NAME = NxtARCore.class.getSimpleName(); private OrthographicCamera camera; + private OrthographicCamera pixelPerfectCamera; private SpriteBatch batch; private Texture texture; + private Texture buttonTexture; private Sprite sprite; + private Sprite motorA; + private Sprite motorB; + private Sprite motorC; + private Sprite motorD; private Toaster toaster; private MulticastEnabler mcastEnabler; private FPSLogger fps; private BitmapFont font; private int connections; + private float fontX; + private float fontY; + private Pixmap image; + private Vector3 win2world; + private Vector2 touchPountWorldCoords; + private boolean[] motorButtonsTouched; + private int[] motorButtonsPointers; private VideoFrameMonitor frameMonitor; private ServiceDiscoveryThread udpThread; @@ -66,40 +83,54 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener this.mcastEnabler = (MulticastEnabler)concreteApp; }catch(ClassCastException cc){ Gdx.app.debug(TAG, CLASS_NAME + ".Main() :: concreteApp does not implement any of the required interfaces."); - System.exit(ProjectConstants.EXIT_FAILURE); + Gdx.app.exit(); } } @Override public void create(){ - float w = Gdx.graphics.getWidth(); - float h = Gdx.graphics.getHeight(); + image = null; + fontX = -(Gdx.graphics.getWidth() / 2) + 10; + fontY = (Gdx.graphics.getHeight() / 2) - 10; + win2world = new Vector3(0.0f, 0.0f, 0.0f); + touchPountWorldCoords = new Vector2(); + motorButtonsTouched = new boolean[4]; + motorButtonsTouched[0] = false; + motorButtonsTouched[1] = false; + motorButtonsTouched[2] = false; + motorButtonsTouched[3] = false; + + motorButtonsPointers = new int[4]; + motorButtonsPointers[0] = -1; + motorButtonsPointers[1] = -1; + motorButtonsPointers[2] = -1; + motorButtonsPointers[3] = -1; + + Gdx.input.setInputProcessor(this); fps = new FPSLogger(); font = new BitmapFont(); - Gdx.app.setLogLevel(Application.LOG_DEBUG); + font.setColor(1.0f, 1.0f, 0.0f, 1.0f); + font.setScale(1.0f); - camera = new OrthographicCamera(1, h/w); + Gdx.app.setLogLevel(Application.LOG_DEBUG); + //Gdx.app.setLogLevel(Application.LOG_NONE); + + pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + camera = new OrthographicCamera(1.0f, Gdx.graphics.getHeight() / Gdx.graphics.getWidth()); batch = new SpriteBatch(); - texture = new Texture(Gdx.files.internal("data/libgdx.png")); - texture.setFilter(TextureFilter.Linear, TextureFilter.Linear); - - TextureRegion region = new TextureRegion(texture, 0, 0, 512, 275); - - sprite = new Sprite(region); - sprite.setSize(0.9f, 0.9f * sprite.getHeight() / sprite.getWidth()); - sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2); - sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2); + if(!Ouya.runningOnOuya) setUpButtons(); Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); frameMonitor = VideoFrameMonitor.getInstance(); - mcastEnabler.enableMulticast(); udpThread = ServiceDiscoveryThread.getInstance(); videoThread = VideoStreamingThread.getInstance()/*.setToaster(toaster)*/; //robotThread = RobotControlThread.getInstance().setToaster(toaster); + mcastEnabler.enableMulticast(); + udpThread.start(); videoThread.start(); videoThread.startStreaming(); @@ -110,57 +141,73 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener public void dispose() { batch.dispose(); texture.dispose(); + buttonTexture.dispose(); font.dispose(); + image.dispose(); + videoThread.finish(); } @Override public void render(){ - Pixmap image; Pixmap temp; byte[] frame; - Size dimensions; + Size dimensions = null; Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); frame = frameMonitor.getCurrentFrame(); if(frame != null){ - texture.dispose(); - dimensions = frameMonitor.getFrameDimensions(); temp = new Pixmap(frame, 0, dimensions.getWidth() * dimensions.getHeight()); - image = new Pixmap(1024, 512, temp.getFormat()); + if(image == null){ + try{ + image = new Pixmap(getOptimalTextureSize(dimensions.getWidth()), getOptimalTextureSize(dimensions.getHeight()), temp.getFormat()); + }catch(ImageTooBigException e){ + toaster.showLongToast("Cannot display received frame.\n" + e.getMessage()); + Gdx.app.exit(); + return; + } + } image.drawPixmap(temp, 0, 0); + temp.dispose(); texture = new Texture(image); texture.setFilter(TextureFilter.Linear, TextureFilter.Linear); TextureRegion region = new TextureRegion(texture, 0, 0, dimensions.getWidth(), dimensions.getHeight()); sprite = new Sprite(region); - sprite.setSize(0.9f, 0.9f * sprite.getWidth() / sprite.getHeight()); - /*sprite.setOrigin(sprite.getWidth()/2, sprite.getHeight()/2); - sprite.setPosition(-sprite.getWidth()/2, -sprite.getHeight()/2);*/ - sprite.setOrigin(0, 0); - sprite.setPosition(-sprite.getWidth()/2, (-sprite.getHeight()/3)); - sprite.rotate90(true); + sprite.setOrigin(sprite.getWidth() / 2, sprite.getHeight() / 2); + if(!Ouya.runningOnOuya){ + sprite.setSize(1.0f, sprite.getHeight() / sprite.getWidth() ); + sprite.rotate90(true); + }else{ + //float scaleRatioY = Gdx.graphics.getHeight() / dimensions.getHeight(); + //sprite.scale(scaleRatioY); + //sprite.setSize(dimensions.getWidth() * scaleRatioY, dimensions.getHeight() * scaleRatioY); + sprite.setSize(1.0f, sprite.getHeight() / sprite.getWidth() ); + } + sprite.translate(-sprite.getWidth() / 2, 0.5f - sprite.getHeight()); batch.setProjectionMatrix(camera.combined); batch.begin();{ sprite.draw(batch); - font.setColor(0.0f, 0.0f, 0.0f, 1.0f); - font.setScale(100.0f); - font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), 10, 300); }batch.end(); - Gdx.app.log("Main", String.format("Network FPS: %d", videoThread.getFps())); - Gdx.app.log("Main", String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond())); - texture.dispose(); - temp.dispose(); - image.dispose(); - - //fps.log(); } + + batch.setProjectionMatrix(pixelPerfectCamera.combined); + batch.begin();{ + if(!Ouya.runningOnOuya){ + motorA.draw(batch); + motorB.draw(batch); + motorC.draw(batch); + motorD.draw(batch); + } + font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), fontX, fontY); + font.draw(batch, String.format("Network FPS: %d", videoThread.getFps()), fontX, fontY - font.getCapHeight() - 5); + }batch.end(); } @Override @@ -169,10 +216,14 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener @Override public void pause(){ + if(videoThread != null) + videoThread.pause(); } @Override public void resume(){ + if(videoThread != null) + videoThread.play(); } @Override @@ -185,4 +236,160 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener mcastEnabler.disableMulticast(); } } + + private int getOptimalTextureSize(int imageSideLength) throws ImageTooBigException{ + for(int po2: ProjectConstants.POWERS_OF_2){ + if(imageSideLength < po2) return po2; + } + throw new ImageTooBigException("No valid texture size found. Image too large."); + } + + private void setUpButtons(){ + buttonTexture = new Texture(Gdx.files.internal("data/gfx/gui/PBCrichton_Flat_Button.png")); + buttonTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); + + TextureRegion region = new TextureRegion(buttonTexture, 0, 0, buttonTexture.getWidth(), buttonTexture.getHeight()); + + motorA = new Sprite(region); + motorA.setSize(motorA.getWidth() * 0.7f, motorA.getHeight() * 0.7f); + + motorB = new Sprite(region); + motorB.setSize(motorB.getWidth() * 0.7f, motorB.getHeight() * 0.7f); + + motorC = new Sprite(region); + motorC.setSize(motorC.getWidth() * 0.7f, motorC.getHeight() * 0.7f); + + motorD = new Sprite(region); + motorD.setSize(motorD.getWidth() * 0.7f, motorD.getHeight() * 0.7f); + + motorA.setPosition(-(Gdx.graphics.getWidth() / 2) + 10, -(Gdx.graphics.getHeight() / 2) + motorB.getHeight() + 20); + motorB.setPosition(-(Gdx.graphics.getWidth() / 2) + 20 + (motorA.getWidth() / 2), -(Gdx.graphics.getHeight() / 2) + 10); + motorC.setPosition((Gdx.graphics.getWidth() / 2) - (1.5f * (motorD.getWidth())) - 20, -(Gdx.graphics.getHeight() / 2) + 10); + motorD.setPosition((Gdx.graphics.getWidth() / 2) - motorD.getWidth() - 10, -(Gdx.graphics.getHeight() / 2) + 20 + motorC.getHeight()); + } + + private class ImageTooBigException extends Exception{ + private static final long serialVersionUID = 9989L; + + public ImageTooBigException(String msg){ + super(msg); + } + } + + @Override + public boolean keyDown(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyUp(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyTyped(char character) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPountWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPountWorldCoords.x, touchPountWorldCoords.y)); + + if(motorA.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); + motorButtonsTouched[0] = true; + motorButtonsPointers[0] = pointer; + }else if(motorB.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); + motorButtonsTouched[1] = true; + motorButtonsPointers[1] = pointer; + }else if(motorC.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); + motorButtonsTouched[2] = true; + motorButtonsPointers[2] = pointer; + }else if(motorD.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); + motorButtonsTouched[3] = true; + motorButtonsPointers[3] = pointer; + } + return true; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button) { + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPountWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPountWorldCoords.x, touchPountWorldCoords.y)); + + if(motorA.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + }else if(motorB.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + }else if(motorC.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + }else if(motorD.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + } + return true; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPountWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + + /*Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d)", screenX, screenY, pointer)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPountWorldCoords.x, touchPountWorldCoords.y));*/ + + if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPountWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + } + return true; + } + + @Override + public boolean mouseMoved(int screenX, int screenY) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean scrolled(int amount) { + // TODO Auto-generated method stub + return false; + }; } diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java index 32170ce..9cb45ff 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java @@ -44,6 +44,7 @@ public class VideoStreamingThread extends Thread { /*private boolean pauseProtocol; private boolean endProtocol;*/ private boolean done; + private boolean pause; private Object protocolPauseMonitor; private Socket client; //private ObjectInputStream reader; @@ -53,10 +54,12 @@ public class VideoStreamingThread extends Thread { private long now; private long delta; private int fps; + private Object pauseMonitor; private VideoStreamingThread(){ super(THREAD_NAME); + pauseMonitor = new Object(); fps = 0; netListener = null; //toaster = null; @@ -433,7 +436,11 @@ public class VideoStreamingThread extends Thread { then = System.currentTimeMillis(); while(!done){ - //receiveImage(); + synchronized (pauseMonitor) { + while(pause){ + try{ pauseMonitor.wait(); }catch(InterruptedException ie){ } + } + } Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Receiving."); if(netListener != null) netListener.networkStreamConnected(THREAD_NAME); @@ -458,4 +465,16 @@ public class VideoStreamingThread extends Thread { Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Thread finished."); } + public void pause(){ + synchronized (pauseMonitor){ + pause = true; + } + } + + public void play(){ + synchronized (pauseMonitor){ + pause = false; + pauseMonitor.notifyAll(); + } + } } diff --git a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java index 1d2ab19..a32c6f7 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java +++ b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java @@ -24,4 +24,6 @@ public abstract class ProjectConstants { public static final int EXIT_FAILURE = 1; public static final boolean DEBUG = true; + + public static final int[] POWERS_OF_2 = {64, 128, 256, 512, 1024, 2048}; } From e5b43beaea3ca3797bca63b2149993175c25f1ae Mon Sep 17 00:00:00 2001 From: Miguel Angel Astor Romero Date: Tue, 28 Jan 2014 19:14:35 -0430 Subject: [PATCH 06/16] VideoStreamingThread now reports the number of lost frames per second. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 50 +++++++++---------- .../nxtar/network/VideoStreamingThread.java | 16 ++++++ 2 files changed, 40 insertions(+), 26 deletions(-) diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index b738911..d5630ad 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -30,7 +30,6 @@ import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.InputProcessor; import com.badlogic.gdx.controllers.mappings.Ouya; -import com.badlogic.gdx.graphics.FPSLogger; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Pixmap; @@ -59,19 +58,18 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener private Sprite motorD; private Toaster toaster; private MulticastEnabler mcastEnabler; - private FPSLogger fps; private BitmapFont font; private int connections; private float fontX; private float fontY; private Pixmap image; private Vector3 win2world; - private Vector2 touchPountWorldCoords; + private Vector2 touchPointWorldCoords; private boolean[] motorButtonsTouched; private int[] motorButtonsPointers; private VideoFrameMonitor frameMonitor; - private ServiceDiscoveryThread udpThread; + private ServiceDiscoveryThread serviceDiscoveryThread; private VideoStreamingThread videoThread; private RobotControlThread robotThread; @@ -93,7 +91,7 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener fontX = -(Gdx.graphics.getWidth() / 2) + 10; fontY = (Gdx.graphics.getHeight() / 2) - 10; win2world = new Vector3(0.0f, 0.0f, 0.0f); - touchPountWorldCoords = new Vector2(); + touchPointWorldCoords = new Vector2(); motorButtonsTouched = new boolean[4]; motorButtonsTouched[0] = false; motorButtonsTouched[1] = false; @@ -108,7 +106,6 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener Gdx.input.setInputProcessor(this); - fps = new FPSLogger(); font = new BitmapFont(); font.setColor(1.0f, 1.0f, 0.0f, 1.0f); @@ -125,13 +122,13 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); frameMonitor = VideoFrameMonitor.getInstance(); - udpThread = ServiceDiscoveryThread.getInstance(); + serviceDiscoveryThread = ServiceDiscoveryThread.getInstance(); videoThread = VideoStreamingThread.getInstance()/*.setToaster(toaster)*/; //robotThread = RobotControlThread.getInstance().setToaster(toaster); mcastEnabler.enableMulticast(); - udpThread.start(); + serviceDiscoveryThread.start(); videoThread.start(); videoThread.startStreaming(); //robotThread.start(); @@ -207,6 +204,7 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener } font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), fontX, fontY); font.draw(batch, String.format("Network FPS: %d", videoThread.getFps()), fontX, fontY - font.getCapHeight() - 5); + font.draw(batch, String.format("Lost Network FPS: %d", videoThread.getLostFrames()), fontX, fontY - (2 * font.getCapHeight()) - 10); }batch.end(); } @@ -232,7 +230,7 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener connections += 1; if(connections >= 2){ Gdx.app.debug(TAG, CLASS_NAME + ".networkStreamConnected() :: Stopping service broadcast."); - udpThread.finish(); + serviceDiscoveryThread.finish(); mcastEnabler.disableMulticast(); } } @@ -298,24 +296,24 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener public boolean touchDown(int screenX, int screenY, int pointer, int button) { win2world.set(screenX, screenY, 0.0f); camera.unproject(win2world); - touchPountWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPountWorldCoords.x, touchPountWorldCoords.y)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - if(motorA.getBoundingRectangle().contains(touchPountWorldCoords)){ + if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); motorButtonsTouched[0] = true; motorButtonsPointers[0] = pointer; - }else if(motorB.getBoundingRectangle().contains(touchPountWorldCoords)){ + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); motorButtonsTouched[1] = true; motorButtonsPointers[1] = pointer; - }else if(motorC.getBoundingRectangle().contains(touchPountWorldCoords)){ + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); motorButtonsTouched[2] = true; motorButtonsPointers[2] = pointer; - }else if(motorD.getBoundingRectangle().contains(touchPountWorldCoords)){ + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); motorButtonsTouched[3] = true; motorButtonsPointers[3] = pointer; @@ -327,24 +325,24 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener public boolean touchUp(int screenX, int screenY, int pointer, int button) { win2world.set(screenX, screenY, 0.0f); camera.unproject(win2world); - touchPountWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPountWorldCoords.x, touchPountWorldCoords.y)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - if(motorA.getBoundingRectangle().contains(touchPountWorldCoords)){ + if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); motorButtonsPointers[0] = -1; motorButtonsTouched[0] = false; - }else if(motorB.getBoundingRectangle().contains(touchPountWorldCoords)){ + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); motorButtonsPointers[1] = -1; motorButtonsTouched[1] = false; - }else if(motorC.getBoundingRectangle().contains(touchPountWorldCoords)){ + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); motorButtonsPointers[2] = -1; motorButtonsTouched[2] = false; - }else if(motorD.getBoundingRectangle().contains(touchPountWorldCoords)){ + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); motorButtonsPointers[3] = -1; motorButtonsTouched[3] = false; @@ -356,24 +354,24 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener public boolean touchDragged(int screenX, int screenY, int pointer) { win2world.set(screenX, screenY, 0.0f); camera.unproject(win2world); - touchPountWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); /*Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d)", screenX, screenY, pointer)); Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPountWorldCoords.x, touchPountWorldCoords.y));*/ - if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPountWorldCoords)){ + if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); motorButtonsPointers[0] = -1; motorButtonsTouched[0] = false; - }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPountWorldCoords)){ + }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); motorButtonsPointers[1] = -1; motorButtonsTouched[1] = false; - }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPountWorldCoords)){ + }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); motorButtonsPointers[2] = -1; motorButtonsTouched[2] = false; - }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPountWorldCoords)){ + }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); motorButtonsPointers[3] = -1; motorButtonsTouched[3] = false; diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java index 9cb45ff..1894420 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java @@ -54,6 +54,8 @@ public class VideoStreamingThread extends Thread { private long now; private long delta; private int fps; + private int lostFramesPerSecond; + private int lostFrames; private Object pauseMonitor; private VideoStreamingThread(){ @@ -61,6 +63,7 @@ public class VideoStreamingThread extends Thread { pauseMonitor = new Object(); fps = 0; + lostFramesPerSecond = 0; netListener = null; //toaster = null; protocolStarted = false; @@ -362,6 +365,7 @@ public class VideoStreamingThread extends Thread { socket.receive(packet); }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException receiving size " + io.getMessage()); + lostFramesPerSecond += 1; return; } @@ -375,6 +379,7 @@ public class VideoStreamingThread extends Thread { socket.receive(packet); }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException receiving data " + io.getMessage()); + lostFramesPerSecond += 1; return; } @@ -396,16 +401,20 @@ public class VideoStreamingThread extends Thread { }else{ Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Received something unknown."); + lostFramesPerSecond += 1; } }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException received deserializing message " + io.getMessage()); + lostFramesPerSecond += 1; return; }catch(ClassNotFoundException cn){ Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: ClassNotFoundException received " + cn.getMessage()); + lostFramesPerSecond += 1; return; } }catch(Exception e){ Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: Exception received " + e.getMessage()); + lostFramesPerSecond += 1; return; } } @@ -413,10 +422,15 @@ public class VideoStreamingThread extends Thread { public int getFps(){ return fps; } + + public int getLostFrames(){ + return lostFrames; + } @Override public void run(){ int frames = 0; + lostFrames = 0; // Listen on the server socket until a client successfully connects. /*do{ try{ @@ -451,6 +465,8 @@ public class VideoStreamingThread extends Thread { if(delta >= 1000){ fps = frames; frames = 0; + lostFrames = lostFramesPerSecond; + lostFramesPerSecond = 0; then = now; delta = 0; } From 5c795ce8e34c2c25eeaa85d8821dacb242b9138b Mon Sep 17 00:00:00 2001 From: Miguel Angel Astor Romero Date: Wed, 29 Jan 2014 03:30:40 -0430 Subject: [PATCH 07/16] Got this thing to render on Ouya. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 172 ++++++++++++---------- 1 file changed, 95 insertions(+), 77 deletions(-) diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index d5630ad..35c638c 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -46,6 +46,8 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener private static final String TAG = "NXTAR_CORE_MAIN"; private static final String CLASS_NAME = NxtARCore.class.getSimpleName(); + private float overscan; + private OrthographicCamera camera; private OrthographicCamera pixelPerfectCamera; private SpriteBatch batch; @@ -88,8 +90,6 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener @Override public void create(){ image = null; - fontX = -(Gdx.graphics.getWidth() / 2) + 10; - fontY = (Gdx.graphics.getHeight() / 2) - 10; win2world = new Vector3(0.0f, 0.0f, 0.0f); touchPointWorldCoords = new Vector2(); motorButtonsTouched = new boolean[4]; @@ -109,15 +109,22 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener font = new BitmapFont(); font.setColor(1.0f, 1.0f, 0.0f, 1.0f); - font.setScale(1.0f); + if(!Ouya.runningOnOuya){ + font.setScale(1.0f); + }else{ + font.setScale(2.5f); + } - Gdx.app.setLogLevel(Application.LOG_DEBUG); + Gdx.app.setLogLevel(Application.LOG_INFO); //Gdx.app.setLogLevel(Application.LOG_NONE); pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); camera = new OrthographicCamera(1.0f, Gdx.graphics.getHeight() / Gdx.graphics.getWidth()); batch = new SpriteBatch(); + overscan = Ouya.runningOnOuya ? 0.9f : 1.0f; + fontX = -((Gdx.graphics.getWidth() * overscan) / 2) + 10; + fontY = ((Gdx.graphics.getHeight() * overscan) / 2) - 10; if(!Ouya.runningOnOuya) setUpButtons(); Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); @@ -137,8 +144,10 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener @Override public void dispose() { batch.dispose(); - texture.dispose(); - buttonTexture.dispose(); + if(texture != null) + texture.dispose(); + if(buttonTexture != null) + buttonTexture.dispose(); font.dispose(); image.dispose(); videoThread.finish(); @@ -178,15 +187,19 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener if(!Ouya.runningOnOuya){ sprite.setSize(1.0f, sprite.getHeight() / sprite.getWidth() ); sprite.rotate90(true); + sprite.translate(-sprite.getWidth() / 2, 0.5f - sprite.getHeight()); }else{ - //float scaleRatioY = Gdx.graphics.getHeight() / dimensions.getHeight(); - //sprite.scale(scaleRatioY); - //sprite.setSize(dimensions.getWidth() * scaleRatioY, dimensions.getHeight() * scaleRatioY); - sprite.setSize(1.0f, sprite.getHeight() / sprite.getWidth() ); + float xSize = Gdx.graphics.getHeight() * (dimensions.getWidth() / dimensions.getHeight()); + sprite.setSize(xSize * overscan, Gdx.graphics.getHeight() * overscan); + sprite.rotate90(true); + sprite.translate(-sprite.getWidth() / 2, -sprite.getHeight() / 2); } - sprite.translate(-sprite.getWidth() / 2, 0.5f - sprite.getHeight()); - batch.setProjectionMatrix(camera.combined); + if(!Ouya.runningOnOuya){ + batch.setProjectionMatrix(camera.combined); + }else{ + batch.setProjectionMatrix(pixelPerfectCamera.combined); + } batch.begin();{ sprite.draw(batch); }batch.end(); @@ -205,6 +218,8 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), fontX, fontY); font.draw(batch, String.format("Network FPS: %d", videoThread.getFps()), fontX, fontY - font.getCapHeight() - 5); font.draw(batch, String.format("Lost Network FPS: %d", videoThread.getLostFrames()), fontX, fontY - (2 * font.getCapHeight()) - 10); + if(dimensions != null) + font.draw(batch, String.format("Frame size: (%d, %d)", dimensions.getWidth(), dimensions.getHeight()), fontX, fontY - (3 * font.getCapHeight()) - 15); }batch.end(); } @@ -294,94 +309,97 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener @Override public boolean touchDown(int screenX, int screenY, int pointer, int button) { - win2world.set(screenX, screenY, 0.0f); - camera.unproject(win2world); - touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + if(!Ouya.runningOnOuya){ + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); - motorButtonsTouched[0] = true; - motorButtonsPointers[0] = pointer; - }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); - motorButtonsTouched[1] = true; - motorButtonsPointers[1] = pointer; - }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); - motorButtonsTouched[2] = true; - motorButtonsPointers[2] = pointer; - }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); - motorButtonsTouched[3] = true; - motorButtonsPointers[3] = pointer; + if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); + motorButtonsTouched[0] = true; + motorButtonsPointers[0] = pointer; + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); + motorButtonsTouched[1] = true; + motorButtonsPointers[1] = pointer; + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); + motorButtonsTouched[2] = true; + motorButtonsPointers[2] = pointer; + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); + motorButtonsTouched[3] = true; + motorButtonsPointers[3] = pointer; + } } return true; } @Override public boolean touchUp(int screenX, int screenY, int pointer, int button) { - win2world.set(screenX, screenY, 0.0f); - camera.unproject(win2world); - touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + if(!Ouya.runningOnOuya){ + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; - }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; - }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; - }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; + if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + } } return true; } @Override public boolean touchDragged(int screenX, int screenY, int pointer) { - win2world.set(screenX, screenY, 0.0f); - camera.unproject(win2world); - touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + if(!Ouya.runningOnOuya){ + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); - /*Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d)", screenX, screenY, pointer)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPountWorldCoords.x, touchPountWorldCoords.y));*/ - - if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; - }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; - }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; - }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; + if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + } } return true; } @Override public boolean mouseMoved(int screenX, int screenY) { - // TODO Auto-generated method stub + Gdx.app.error(TAG, "MOUSE MOVED!"); return false; } From c5fe36116f7b9ec5cace5d96d1ed79efc9751450 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 4 Feb 2014 17:14:35 -0430 Subject: [PATCH 08/16] Minor refactorings. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 95 +++++++++++++++++-- .../ccg/nxtar/network/RobotControlThread.java | 2 +- .../ccg/nxtar/utils/ProjectConstants.java | 10 +- 3 files changed, 96 insertions(+), 11 deletions(-) diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index 35c638c..1688bb3 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -29,6 +29,10 @@ import com.badlogic.gdx.Application; import com.badlogic.gdx.ApplicationListener; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.InputProcessor; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.ControllerListener; +import com.badlogic.gdx.controllers.Controllers; +import com.badlogic.gdx.controllers.PovDirection; import com.badlogic.gdx.controllers.mappings.Ouya; import com.badlogic.gdx.graphics.GL10; import com.badlogic.gdx.graphics.OrthographicCamera; @@ -42,12 +46,10 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; -public class NxtARCore implements ApplicationListener, NetworkConnectionListener, InputProcessor{ +public class NxtARCore implements ApplicationListener, NetworkConnectionListener, InputProcessor, ControllerListener{ private static final String TAG = "NXTAR_CORE_MAIN"; private static final String CLASS_NAME = NxtARCore.class.getSimpleName(); - private float overscan; - private OrthographicCamera camera; private OrthographicCamera pixelPerfectCamera; private SpriteBatch batch; @@ -105,6 +107,7 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener motorButtonsPointers[3] = -1; Gdx.input.setInputProcessor(this); + Controllers.addListener(this); font = new BitmapFont(); @@ -115,16 +118,15 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener font.setScale(2.5f); } - Gdx.app.setLogLevel(Application.LOG_INFO); - //Gdx.app.setLogLevel(Application.LOG_NONE); + //Gdx.app.setLogLevel(Application.LOG_INFO); + Gdx.app.setLogLevel(Application.LOG_NONE); pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); camera = new OrthographicCamera(1.0f, Gdx.graphics.getHeight() / Gdx.graphics.getWidth()); batch = new SpriteBatch(); - overscan = Ouya.runningOnOuya ? 0.9f : 1.0f; - fontX = -((Gdx.graphics.getWidth() * overscan) / 2) + 10; - fontY = ((Gdx.graphics.getHeight() * overscan) / 2) - 10; + fontX = -((Gdx.graphics.getWidth() * ProjectConstants.OVERSCAN) / 2) + 10; + fontY = ((Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN) / 2) - 10; if(!Ouya.runningOnOuya) setUpButtons(); Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); @@ -190,7 +192,7 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener sprite.translate(-sprite.getWidth() / 2, 0.5f - sprite.getHeight()); }else{ float xSize = Gdx.graphics.getHeight() * (dimensions.getWidth() / dimensions.getHeight()); - sprite.setSize(xSize * overscan, Gdx.graphics.getHeight() * overscan); + sprite.setSize(xSize * ProjectConstants.OVERSCAN, Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN); sprite.rotate90(true); sprite.translate(-sprite.getWidth() / 2, -sprite.getHeight() / 2); } @@ -407,5 +409,80 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener public boolean scrolled(int amount) { // TODO Auto-generated method stub return false; + } + + @Override + public void connected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public void disconnected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public boolean buttonDown(Controller controller, int buttonCode) { + if(buttonCode == Ouya.BUTTON_L1){ + // Start right motor. + } + if(buttonCode == Ouya.BUTTON_L2){ + // Start left motor. + } + if(buttonCode == Ouya.BUTTON_DPAD_LEFT){ + // Look left. + } + if(buttonCode == Ouya.BUTTON_DPAD_RIGHT){ + // Look right; + } + return false; + } + + @Override + public boolean buttonUp(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean axisMoved(Controller controller, int axisCode, float value) { + if(axisCode == Ouya.AXIS_LEFT_TRIGGER){ + + } + if(axisCode == Ouya.AXIS_RIGHT_TRIGGER){ + // Start + } + + return false; + } + + @Override + public boolean povMoved(Controller controller, int povCode, + PovDirection value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean xSliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean ySliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean accelerometerMoved(Controller controller, + int accelerometerCode, Vector3 value) { + // TODO Auto-generated method stub + return false; }; } diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/RobotControlThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/RobotControlThread.java index eb120f5..212772f 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/RobotControlThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/RobotControlThread.java @@ -46,7 +46,7 @@ public class RobotControlThread extends Thread { Gdx.app.error(TAG, CLASS_NAME + ".RobotControlThread() :: Error creating server: " + io.getMessage(), io); } } - + private static class SingletonHolder{ public static final RobotControlThread INSTANCE = new RobotControlThread(); } diff --git a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java index a32c6f7..d27d3b6 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java +++ b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java @@ -15,6 +15,8 @@ */ package ve.ucv.ciens.ccg.nxtar.utils; +import com.badlogic.gdx.controllers.mappings.Ouya; + public abstract class ProjectConstants { public static final int SERVER_UDP_PORT = 8889; public static final int SERVER_TCP_PORT_1 = 9989; @@ -24,6 +26,12 @@ public abstract class ProjectConstants { public static final int EXIT_FAILURE = 1; public static final boolean DEBUG = true; - + public static final int[] POWERS_OF_2 = {64, 128, 256, 512, 1024, 2048}; + + public static final float OVERSCAN; + + static{ + OVERSCAN = Ouya.runningOnOuya ? 0.9f : 1.0f; + } } From 5bd79f0d5821e2697f5781b012eff72be6d5a5be Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Feb 2014 15:10:02 -0430 Subject: [PATCH 09/16] Deleted useless Artemis classes. --- .../ccg/nxtar/components/VideoFrame.java | 40 ------------------- .../ciens/ccg/nxtar/systems/RenderSystem.java | 36 ----------------- 2 files changed, 76 deletions(-) delete mode 100644 src/ve/ucv/ciens/ccg/nxtar/components/VideoFrame.java delete mode 100644 src/ve/ucv/ciens/ccg/nxtar/systems/RenderSystem.java diff --git a/src/ve/ucv/ciens/ccg/nxtar/components/VideoFrame.java b/src/ve/ucv/ciens/ccg/nxtar/components/VideoFrame.java deleted file mode 100644 index 6a85af6..0000000 --- a/src/ve/ucv/ciens/ccg/nxtar/components/VideoFrame.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2013 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.components; - -import com.artemis.Component; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.Texture; - -public class VideoFrame extends Component { - private Texture frame; - - public VideoFrame(){ } - - public VideoFrame(byte[] imageData){ - frame = new Texture(new Pixmap(imageData, 0, imageData.length)); - } - - public Texture getFrame(){ - return frame; - } - - public void setFrame(byte[] imageData){ - if(frame != null) - frame.dispose(); - frame = new Texture(new Pixmap(imageData, 0, imageData.length)); - } -} diff --git a/src/ve/ucv/ciens/ccg/nxtar/systems/RenderSystem.java b/src/ve/ucv/ciens/ccg/nxtar/systems/RenderSystem.java deleted file mode 100644 index 614a69b..0000000 --- a/src/ve/ucv/ciens/ccg/nxtar/systems/RenderSystem.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2013 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.systems; - -import ve.ucv.ciens.ccg.nxtar.components.VideoFrame; - -import com.artemis.Aspect; -import com.artemis.Entity; -import com.artemis.systems.EntityProcessingSystem; - -public class RenderSystem extends EntityProcessingSystem { - - @SuppressWarnings("unchecked") - public RenderSystem(Aspect aspect) { - super(Aspect.getAspectForAll(VideoFrame.class)); - } - - @Override - protected void process(Entity arg0) { - - } - -} From 40d390baecb7a5faf64fa70399fec29c99b308c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 5 Feb 2014 17:06:29 -0430 Subject: [PATCH 10/16] Started refactoring the app to use State Pattern. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 497 ++++-------------- .../ImageTooBigException.java} | 17 +- .../ucv/ciens/ccg/nxtar/states/BaseState.java | 83 +++ .../ciens/ccg/nxtar/states/InGameState.java | 393 +++++++++++++- ...DummyState.java => MainMenuStateBase.java} | 44 +- .../ccg/nxtar/states/OuyaMainMenuState.java | 154 ++++++ .../ciens/ccg/nxtar/states/PauseState.java | 190 +++++++ .../ccg/nxtar/states/TabletMainMenuState.java | 154 ++++++ 8 files changed, 1117 insertions(+), 415 deletions(-) rename src/ve/ucv/ciens/ccg/nxtar/{states/NxtARState.java => exceptions/ImageTooBigException.java} (68%) create mode 100644 src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java rename src/ve/ucv/ciens/ccg/nxtar/states/{DummyState.java => MainMenuStateBase.java} (54%) create mode 100644 src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java create mode 100644 src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java create mode 100644 src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index 1688bb3..9f79b33 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -20,63 +20,62 @@ import ve.ucv.ciens.ccg.nxtar.interfaces.NetworkConnectionListener; import ve.ucv.ciens.ccg.nxtar.interfaces.Toaster; import ve.ucv.ciens.ccg.nxtar.network.RobotControlThread; import ve.ucv.ciens.ccg.nxtar.network.ServiceDiscoveryThread; -import ve.ucv.ciens.ccg.nxtar.network.VideoFrameMonitor; import ve.ucv.ciens.ccg.nxtar.network.VideoStreamingThread; +import ve.ucv.ciens.ccg.nxtar.states.BaseState; +import ve.ucv.ciens.ccg.nxtar.states.InGameState; +import ve.ucv.ciens.ccg.nxtar.states.OuyaMainMenuState; +import ve.ucv.ciens.ccg.nxtar.states.PauseState; +import ve.ucv.ciens.ccg.nxtar.states.TabletMainMenuState; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; -import ve.ucv.ciens.ccg.nxtar.utils.Size; import com.badlogic.gdx.Application; -import com.badlogic.gdx.ApplicationListener; +import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.InputProcessor; -import com.badlogic.gdx.controllers.Controller; -import com.badlogic.gdx.controllers.ControllerListener; import com.badlogic.gdx.controllers.Controllers; -import com.badlogic.gdx.controllers.PovDirection; import com.badlogic.gdx.controllers.mappings.Ouya; -import com.badlogic.gdx.graphics.GL10; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.Texture.TextureFilter; import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.math.Vector3; -public class NxtARCore implements ApplicationListener, NetworkConnectionListener, InputProcessor, ControllerListener{ +public class NxtARCore extends Game implements NetworkConnectionListener{ private static final String TAG = "NXTAR_CORE_MAIN"; private static final String CLASS_NAME = NxtARCore.class.getSimpleName(); - private OrthographicCamera camera; - private OrthographicCamera pixelPerfectCamera; - private SpriteBatch batch; - private Texture texture; - private Texture buttonTexture; - private Sprite sprite; - private Sprite motorA; - private Sprite motorB; - private Sprite motorC; - private Sprite motorD; - private Toaster toaster; - private MulticastEnabler mcastEnabler; - private BitmapFont font; - private int connections; - private float fontX; - private float fontY; - private Pixmap image; - private Vector3 win2world; - private Vector2 touchPointWorldCoords; - private boolean[] motorButtonsTouched; - private int[] motorButtonsPointers; + // Game state management fields. + public enum game_states_t { + MAIN_MENU(0), IN_GAME(1), PAUSED(2); - private VideoFrameMonitor frameMonitor; + private int value; + + private game_states_t(int value){ + this.value = value; + } + + public int getValue(){ + return this.value; + } + }; + public game_states_t nextState; + private game_states_t currState; + + // Screens. + private BaseState[] states; + + // Assorted fields. + public SpriteBatch batch; + public Toaster toaster; + + // Networking related fields. + private int connections; + private MulticastEnabler mcastEnabler; private ServiceDiscoveryThread serviceDiscoveryThread; private VideoStreamingThread videoThread; private RobotControlThread robotThread; + // Overlay font. + private float fontX; + private float fontY; + private BitmapFont font; + public NxtARCore(Application concreteApp){ super(); connections = 0; @@ -84,150 +83,93 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener this.toaster = (Toaster)concreteApp; this.mcastEnabler = (MulticastEnabler)concreteApp; }catch(ClassCastException cc){ - Gdx.app.debug(TAG, CLASS_NAME + ".Main() :: concreteApp does not implement any of the required interfaces."); + Gdx.app.debug(TAG, CLASS_NAME + ".Main() :: concreteApp does not implement some of the required interfaces."); Gdx.app.exit(); } } @Override public void create(){ - image = null; - win2world = new Vector3(0.0f, 0.0f, 0.0f); - touchPointWorldCoords = new Vector2(); - motorButtonsTouched = new boolean[4]; - motorButtonsTouched[0] = false; - motorButtonsTouched[1] = false; - motorButtonsTouched[2] = false; - motorButtonsTouched[3] = false; + // Create the state objects. + states = new BaseState[3]; + if(Ouya.runningOnOuya)states[0] = new OuyaMainMenuState(this); + else states[1] = new TabletMainMenuState(this); + states[1] = new InGameState(this); + states[2] = new PauseState(this); - motorButtonsPointers = new int[4]; - motorButtonsPointers[0] = -1; - motorButtonsPointers[1] = -1; - motorButtonsPointers[2] = -1; - motorButtonsPointers[3] = -1; - - Gdx.input.setInputProcessor(this); - Controllers.addListener(this); - - font = new BitmapFont(); - - font.setColor(1.0f, 1.0f, 0.0f, 1.0f); - if(!Ouya.runningOnOuya){ - font.setScale(1.0f); - }else{ - font.setScale(2.5f); - } - - //Gdx.app.setLogLevel(Application.LOG_INFO); - Gdx.app.setLogLevel(Application.LOG_NONE); - - pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); - camera = new OrthographicCamera(1.0f, Gdx.graphics.getHeight() / Gdx.graphics.getWidth()); + // Set up fields. batch = new SpriteBatch(); - fontX = -((Gdx.graphics.getWidth() * ProjectConstants.OVERSCAN) / 2) + 10; - fontY = ((Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN) / 2) - 10; - if(!Ouya.runningOnOuya) setUpButtons(); + if(ProjectConstants.DEBUG){ + // Set up the overlay font. + fontX = -((Gdx.graphics.getWidth() * ProjectConstants.OVERSCAN) / 2) + 10; + fontY = ((Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN) / 2) - 10; + + font = new BitmapFont(); + font.setColor(1.0f, 1.0f, 0.0f, 1.0f); + if(!Ouya.runningOnOuya){ + font.setScale(1.0f); + }else{ + font.setScale(2.5f); + } + } + + // Start networking. + mcastEnabler.enableMulticast(); Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); - frameMonitor = VideoFrameMonitor.getInstance(); serviceDiscoveryThread = ServiceDiscoveryThread.getInstance(); videoThread = VideoStreamingThread.getInstance()/*.setToaster(toaster)*/; //robotThread = RobotControlThread.getInstance().setToaster(toaster); - mcastEnabler.enableMulticast(); - serviceDiscoveryThread.start(); videoThread.start(); videoThread.startStreaming(); //robotThread.start(); - } - @Override - public void dispose() { - batch.dispose(); - if(texture != null) - texture.dispose(); - if(buttonTexture != null) - buttonTexture.dispose(); - font.dispose(); - image.dispose(); - videoThread.finish(); + // Set the current and next states. + currState = game_states_t.MAIN_MENU; + nextState = null; + this.setScreen(states[currState.getValue()]); + + // Set initial input handlers. + Gdx.input.setInputProcessor(states[currState.getValue()]); + Controllers.addListener(states[currState.getValue()]); + + // Anything else. + Gdx.app.setLogLevel(Application.LOG_INFO); + // Gdx.app.setLogLevel(Application.LOG_NONE); } @Override public void render(){ - Pixmap temp; - byte[] frame; - Size dimensions = null; + super.render(); - Gdx.gl.glClearColor(1, 1, 1, 1); - Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); + // If the current state set a value for nextState then switch to that state. + if(nextState != null){ + // Change the input processors. + Gdx.input.setInputProcessor(states[nextState.getValue()]); + Controllers.removeListener(states[currState.getValue()]); + Controllers.addListener(states[nextState.getValue()]); - frame = frameMonitor.getCurrentFrame(); - if(frame != null){ - dimensions = frameMonitor.getFrameDimensions(); - temp = new Pixmap(frame, 0, dimensions.getWidth() * dimensions.getHeight()); - if(image == null){ - try{ - image = new Pixmap(getOptimalTextureSize(dimensions.getWidth()), getOptimalTextureSize(dimensions.getHeight()), temp.getFormat()); - }catch(ImageTooBigException e){ - toaster.showLongToast("Cannot display received frame.\n" + e.getMessage()); - Gdx.app.exit(); - return; - } - } - image.drawPixmap(temp, 0, 0); - temp.dispose(); - texture = new Texture(image); - texture.setFilter(TextureFilter.Linear, TextureFilter.Linear); - - TextureRegion region = new TextureRegion(texture, 0, 0, dimensions.getWidth(), dimensions.getHeight()); - - sprite = new Sprite(region); - sprite.setOrigin(sprite.getWidth() / 2, sprite.getHeight() / 2); - if(!Ouya.runningOnOuya){ - sprite.setSize(1.0f, sprite.getHeight() / sprite.getWidth() ); - sprite.rotate90(true); - sprite.translate(-sprite.getWidth() / 2, 0.5f - sprite.getHeight()); - }else{ - float xSize = Gdx.graphics.getHeight() * (dimensions.getWidth() / dimensions.getHeight()); - sprite.setSize(xSize * ProjectConstants.OVERSCAN, Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN); - sprite.rotate90(true); - sprite.translate(-sprite.getWidth() / 2, -sprite.getHeight() / 2); - } - - if(!Ouya.runningOnOuya){ - batch.setProjectionMatrix(camera.combined); - }else{ - batch.setProjectionMatrix(pixelPerfectCamera.combined); - } - batch.begin();{ - sprite.draw(batch); - }batch.end(); - - texture.dispose(); + // Swap the pointers and set the new screen. + currState = nextState; + nextState = null; + setScreen(states[currState.getValue()]); } - batch.setProjectionMatrix(pixelPerfectCamera.combined); - batch.begin();{ - if(!Ouya.runningOnOuya){ - motorA.draw(batch); - motorB.draw(batch); - motorC.draw(batch); - motorD.draw(batch); - } - font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), fontX, fontY); - font.draw(batch, String.format("Network FPS: %d", videoThread.getFps()), fontX, fontY - font.getCapHeight() - 5); - font.draw(batch, String.format("Lost Network FPS: %d", videoThread.getLostFrames()), fontX, fontY - (2 * font.getCapHeight()) - 10); - if(dimensions != null) - font.draw(batch, String.format("Frame size: (%d, %d)", dimensions.getWidth(), dimensions.getHeight()), fontX, fontY - (3 * font.getCapHeight()) - 15); - }batch.end(); + if(ProjectConstants.DEBUG){ + // Draw the FPS overlay. + batch.begin();{ + font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), fontX, fontY); + font.draw(batch, String.format("Total stream FPS: %d", videoThread.getFps()), fontX, fontY - font.getCapHeight() - 5); + font.draw(batch, String.format("Lost stream FPS: %d", videoThread.getLostFrames()), fontX, fontY - (2 * font.getCapHeight()) - 10); + }batch.end(); + } } @Override - public void resize(int width, int height){ - } + public void resize(int width, int height){ } @Override public void pause(){ @@ -241,6 +183,23 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener videoThread.play(); } + @Override + public void dispose(){ + // Finish network threads. + videoThread.finish(); + + // Dispose graphic objects. + batch.dispose(); + if(ProjectConstants.DEBUG){ + font.dispose(); + } + + // Dispose screens. + for(int i = 0; i < states.length; i++){ + states[i].dispose(); + } + } + @Override public synchronized void networkStreamConnected(String streamName){ if(streamName.compareTo(VideoStreamingThread.THREAD_NAME) == 0 || streamName.compareTo(RobotControlThread.THREAD_NAME) == 0) @@ -251,238 +210,4 @@ public class NxtARCore implements ApplicationListener, NetworkConnectionListener mcastEnabler.disableMulticast(); } } - - private int getOptimalTextureSize(int imageSideLength) throws ImageTooBigException{ - for(int po2: ProjectConstants.POWERS_OF_2){ - if(imageSideLength < po2) return po2; - } - throw new ImageTooBigException("No valid texture size found. Image too large."); - } - - private void setUpButtons(){ - buttonTexture = new Texture(Gdx.files.internal("data/gfx/gui/PBCrichton_Flat_Button.png")); - buttonTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); - - TextureRegion region = new TextureRegion(buttonTexture, 0, 0, buttonTexture.getWidth(), buttonTexture.getHeight()); - - motorA = new Sprite(region); - motorA.setSize(motorA.getWidth() * 0.7f, motorA.getHeight() * 0.7f); - - motorB = new Sprite(region); - motorB.setSize(motorB.getWidth() * 0.7f, motorB.getHeight() * 0.7f); - - motorC = new Sprite(region); - motorC.setSize(motorC.getWidth() * 0.7f, motorC.getHeight() * 0.7f); - - motorD = new Sprite(region); - motorD.setSize(motorD.getWidth() * 0.7f, motorD.getHeight() * 0.7f); - - motorA.setPosition(-(Gdx.graphics.getWidth() / 2) + 10, -(Gdx.graphics.getHeight() / 2) + motorB.getHeight() + 20); - motorB.setPosition(-(Gdx.graphics.getWidth() / 2) + 20 + (motorA.getWidth() / 2), -(Gdx.graphics.getHeight() / 2) + 10); - motorC.setPosition((Gdx.graphics.getWidth() / 2) - (1.5f * (motorD.getWidth())) - 20, -(Gdx.graphics.getHeight() / 2) + 10); - motorD.setPosition((Gdx.graphics.getWidth() / 2) - motorD.getWidth() - 10, -(Gdx.graphics.getHeight() / 2) + 20 + motorC.getHeight()); - } - - private class ImageTooBigException extends Exception{ - private static final long serialVersionUID = 9989L; - - public ImageTooBigException(String msg){ - super(msg); - } - } - - @Override - public boolean keyDown(int keycode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean keyUp(int keycode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean keyTyped(char character) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button) { - if(!Ouya.runningOnOuya){ - win2world.set(screenX, screenY, 0.0f); - camera.unproject(win2world); - touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); - - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - - if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); - motorButtonsTouched[0] = true; - motorButtonsPointers[0] = pointer; - }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); - motorButtonsTouched[1] = true; - motorButtonsPointers[1] = pointer; - }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); - motorButtonsTouched[2] = true; - motorButtonsPointers[2] = pointer; - }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); - motorButtonsTouched[3] = true; - motorButtonsPointers[3] = pointer; - } - } - return true; - } - - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button) { - if(!Ouya.runningOnOuya){ - win2world.set(screenX, screenY, 0.0f); - camera.unproject(win2world); - touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); - - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - - if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; - }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; - }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; - }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; - } - } - return true; - } - - @Override - public boolean touchDragged(int screenX, int screenY, int pointer) { - if(!Ouya.runningOnOuya){ - win2world.set(screenX, screenY, 0.0f); - camera.unproject(win2world); - touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); - - if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; - }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; - }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; - }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; - } - } - return true; - } - - @Override - public boolean mouseMoved(int screenX, int screenY) { - Gdx.app.error(TAG, "MOUSE MOVED!"); - return false; - } - - @Override - public boolean scrolled(int amount) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void connected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public void disconnected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public boolean buttonDown(Controller controller, int buttonCode) { - if(buttonCode == Ouya.BUTTON_L1){ - // Start right motor. - } - if(buttonCode == Ouya.BUTTON_L2){ - // Start left motor. - } - if(buttonCode == Ouya.BUTTON_DPAD_LEFT){ - // Look left. - } - if(buttonCode == Ouya.BUTTON_DPAD_RIGHT){ - // Look right; - } - return false; - } - - @Override - public boolean buttonUp(Controller controller, int buttonCode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean axisMoved(Controller controller, int axisCode, float value) { - if(axisCode == Ouya.AXIS_LEFT_TRIGGER){ - - } - if(axisCode == Ouya.AXIS_RIGHT_TRIGGER){ - // Start - } - - return false; - } - - @Override - public boolean povMoved(Controller controller, int povCode, - PovDirection value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean xSliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean ySliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean accelerometerMoved(Controller controller, - int accelerometerCode, Vector3 value) { - // TODO Auto-generated method stub - return false; - }; } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/NxtARState.java b/src/ve/ucv/ciens/ccg/nxtar/exceptions/ImageTooBigException.java similarity index 68% rename from src/ve/ucv/ciens/ccg/nxtar/states/NxtARState.java rename to src/ve/ucv/ciens/ccg/nxtar/exceptions/ImageTooBigException.java index 90dee4f..716119a 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/NxtARState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/exceptions/ImageTooBigException.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Miguel Angel Astor Romero + * Copyright (C) 2014 Miguel Angel Astor Romero * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,13 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package ve.ucv.ciens.ccg.nxtar.states; +package ve.ucv.ciens.ccg.nxtar.exceptions; -public interface NxtARState{ - public void input(); - public void update(); - public void render(); - public void pause(); - public void resume(); - public void dispose(); +public class ImageTooBigException extends Exception{ + private static final long serialVersionUID = 9989L; + + public ImageTooBigException(String msg){ + super(msg); + } } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java b/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java new file mode 100644 index 0000000..664135e --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.NxtARCore; + +import com.badlogic.gdx.InputProcessor; +import com.badlogic.gdx.Screen; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.ControllerListener; +import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.math.Vector3; + +public abstract class BaseState implements Screen, ControllerListener, InputProcessor { + protected NxtARCore core; + + /* SCREEN METHODS*/ + @Override + public abstract void render(float delta); + @Override + public abstract void resize(int width, int height); + @Override + public abstract void show(); + @Override + public abstract void hide(); + @Override + public abstract void pause(); + @Override + public abstract void resume(); + @Override + public abstract void dispose(); + + /* INPUT PROCESSOR METHODS. */ + @Override + public abstract boolean keyDown(int keycode); + @Override + public abstract boolean keyUp(int keycode); + @Override + public abstract boolean keyTyped(char character); + @Override + public abstract boolean touchDown(int screenX, int screenY, int pointer, int button); + @Override + public abstract boolean touchUp(int screenX, int screenY, int pointer, int button); + @Override + public abstract boolean touchDragged(int screenX, int screenY, int pointer); + @Override + public abstract boolean mouseMoved(int screenX, int screenY); + @Override + public abstract boolean scrolled(int amount); + + /* CONTROLLER LISTENER METHODS. */ + @Override + public abstract void connected(Controller controller); + @Override + public abstract void disconnected(Controller controller); + @Override + public abstract boolean buttonDown(Controller controller, int buttonCode); + @Override + public abstract boolean buttonUp(Controller controller, int buttonCode); + @Override + public abstract boolean axisMoved(Controller controller, int axisCode, float value); + @Override + public abstract boolean povMoved(Controller controller, int povCode, PovDirection value); + @Override + public abstract boolean xSliderMoved(Controller controller, int sliderCode, boolean value); + @Override + public abstract boolean ySliderMoved(Controller controller, int sliderCode, boolean value); + @Override + public abstract boolean accelerometerMoved(Controller controller, int accelerometerCode, Vector3 value); +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java index 0e94ede..bd24e3d 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Miguel Angel Astor Romero + * Copyright (C) 2014 Miguel Angel Astor Romero * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,22 +15,164 @@ */ package ve.ucv.ciens.ccg.nxtar.states; -public class InGameState implements NxtARState{ +import ve.ucv.ciens.ccg.nxtar.NxtARCore; +import ve.ucv.ciens.ccg.nxtar.exceptions.ImageTooBigException; +import ve.ucv.ciens.ccg.nxtar.network.VideoFrameMonitor; +import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; +import ve.ucv.ciens.ccg.nxtar.utils.Size; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.controllers.mappings.Ouya; +import com.badlogic.gdx.graphics.GL10; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.Texture.TextureFilter; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; + +public class InGameState extends BaseState{ + private static final String TAG = "IN_GAME_STATE"; + private static final String CLASS_NAME = InGameState.class.getSimpleName(); + + private NxtARCore core; + + // Cameras. + private OrthographicCamera camera; + private OrthographicCamera pixelPerfectCamera; + + // Video stream graphics. + private Texture videoFrameTexture; + private Sprite renderableVideoFrame; + private Pixmap videoFrame; + + // Interface buttons. + private Texture buttonTexture; + private Sprite motorA; + private Sprite motorB; + private Sprite motorC; + private Sprite motorD; + + // Button touch helper fields. + private Vector3 win2world; + private Vector2 touchPointWorldCoords; + private boolean[] motorButtonsTouched; + private int[] motorButtonsPointers; + + private VideoFrameMonitor frameMonitor; + + public InGameState(final NxtARCore core){ + if(!Ouya.runningOnOuya) setUpButtons(); + + this.core = core; + frameMonitor = VideoFrameMonitor.getInstance(); + + // Set up rendering fields; + videoFrame = null; + + // Set up the cameras. + pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + camera = new OrthographicCamera(1.0f, Gdx.graphics.getHeight() / Gdx.graphics.getWidth()); + + // Set up input handling support fields. + win2world = new Vector3(0.0f, 0.0f, 0.0f); + touchPointWorldCoords = new Vector2(); + motorButtonsTouched = new boolean[4]; + motorButtonsTouched[0] = false; + motorButtonsTouched[1] = false; + motorButtonsTouched[2] = false; + motorButtonsTouched[3] = false; + + motorButtonsPointers = new int[4]; + motorButtonsPointers[0] = -1; + motorButtonsPointers[1] = -1; + motorButtonsPointers[2] = -1; + motorButtonsPointers[3] = -1; + } @Override - public void input() { + public void render(float delta) { + Pixmap temp; + byte[] frame; + Size dimensions = null; + + Gdx.gl.glClearColor(1, 1, 1, 1); + Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); + + frame = frameMonitor.getCurrentFrame(); + if(frame != null){ + dimensions = frameMonitor.getFrameDimensions(); + temp = new Pixmap(frame, 0, dimensions.getWidth() * dimensions.getHeight()); + if(videoFrame == null){ + try{ + videoFrame = new Pixmap(getOptimalTextureSize(dimensions.getWidth()), getOptimalTextureSize(dimensions.getHeight()), temp.getFormat()); + }catch(ImageTooBigException e){ + core.toaster.showLongToast("Cannot display received frame.\n" + e.getMessage()); + Gdx.app.exit(); + return; + } + } + videoFrame.drawPixmap(temp, 0, 0); + temp.dispose(); + videoFrameTexture = new Texture(videoFrame); + videoFrameTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); + + TextureRegion region = new TextureRegion(videoFrameTexture, 0, 0, dimensions.getWidth(), dimensions.getHeight()); + + renderableVideoFrame = new Sprite(region); + renderableVideoFrame.setOrigin(renderableVideoFrame.getWidth() / 2, renderableVideoFrame.getHeight() / 2); + if(!Ouya.runningOnOuya){ + renderableVideoFrame.setSize(1.0f, renderableVideoFrame.getHeight() / renderableVideoFrame.getWidth() ); + renderableVideoFrame.rotate90(true); + renderableVideoFrame.translate(-renderableVideoFrame.getWidth() / 2, 0.5f - renderableVideoFrame.getHeight()); + }else{ + float xSize = Gdx.graphics.getHeight() * (dimensions.getWidth() / dimensions.getHeight()); + renderableVideoFrame.setSize(xSize * ProjectConstants.OVERSCAN, Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN); + renderableVideoFrame.rotate90(true); + renderableVideoFrame.translate(-renderableVideoFrame.getWidth() / 2, -renderableVideoFrame.getHeight() / 2); + } + + if(!Ouya.runningOnOuya){ + core.batch.setProjectionMatrix(camera.combined); + }else{ + core.batch.setProjectionMatrix(pixelPerfectCamera.combined); + } + core.batch.begin();{ + renderableVideoFrame.draw(core.batch); + }core.batch.end(); + + videoFrameTexture.dispose(); + } + + core.batch.setProjectionMatrix(pixelPerfectCamera.combined); + core.batch.begin();{ + if(!Ouya.runningOnOuya){ + motorA.draw(core.batch); + motorB.draw(core.batch); + motorC.draw(core.batch); + motorD.draw(core.batch); + } + }core.batch.end(); + } + + @Override + public void resize(int width, int height) { // TODO Auto-generated method stub } @Override - public void update() { + public void show() { // TODO Auto-generated method stub } @Override - public void render() { + public void hide() { // TODO Auto-generated method stub } @@ -49,8 +191,249 @@ public class InGameState implements NxtARState{ @Override public void dispose() { + if(videoFrameTexture != null) + videoFrameTexture.dispose(); + if(buttonTexture != null) + buttonTexture.dispose(); + if(videoFrame != null) + videoFrame.dispose(); + } + + private int getOptimalTextureSize(int imageSideLength) throws ImageTooBigException{ + for(int po2: ProjectConstants.POWERS_OF_2){ + if(imageSideLength < po2) return po2; + } + throw new ImageTooBigException("No valid texture size found. Image too large."); + } + + private void setUpButtons(){ + buttonTexture = new Texture(Gdx.files.internal("data/gfx/gui/PBCrichton_Flat_Button.png")); + buttonTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); + + TextureRegion region = new TextureRegion(buttonTexture, 0, 0, buttonTexture.getWidth(), buttonTexture.getHeight()); + + motorA = new Sprite(region); + motorA.setSize(motorA.getWidth() * 0.7f, motorA.getHeight() * 0.7f); + + motorB = new Sprite(region); + motorB.setSize(motorB.getWidth() * 0.7f, motorB.getHeight() * 0.7f); + + motorC = new Sprite(region); + motorC.setSize(motorC.getWidth() * 0.7f, motorC.getHeight() * 0.7f); + + motorD = new Sprite(region); + motorD.setSize(motorD.getWidth() * 0.7f, motorD.getHeight() * 0.7f); + + motorA.setPosition(-(Gdx.graphics.getWidth() / 2) + 10, -(Gdx.graphics.getHeight() / 2) + motorB.getHeight() + 20); + motorB.setPosition(-(Gdx.graphics.getWidth() / 2) + 20 + (motorA.getWidth() / 2), -(Gdx.graphics.getHeight() / 2) + 10); + motorC.setPosition((Gdx.graphics.getWidth() / 2) - (1.5f * (motorD.getWidth())) - 20, -(Gdx.graphics.getHeight() / 2) + 10); + motorD.setPosition((Gdx.graphics.getWidth() / 2) - motorD.getWidth() - 10, -(Gdx.graphics.getHeight() / 2) + 20 + motorC.getHeight()); + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean keyDown(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyUp(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyTyped(char character) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + if(!Ouya.runningOnOuya){ + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); + motorButtonsTouched[0] = true; + motorButtonsPointers[0] = pointer; + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); + motorButtonsTouched[1] = true; + motorButtonsPointers[1] = pointer; + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); + motorButtonsTouched[2] = true; + motorButtonsPointers[2] = pointer; + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); + motorButtonsTouched[3] = true; + motorButtonsPointers[3] = pointer; + } + } + return true; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button) { + if(!Ouya.runningOnOuya){ + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + } + } + return true; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + if(!Ouya.runningOnOuya){ + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + + if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + } + } + return true; + } + + @Override + public boolean mouseMoved(int screenX, int screenY) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + @Override + public boolean scrolled(int amount) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void connected(Controller controller) { // TODO Auto-generated method stub } + @Override + public void disconnected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public boolean buttonDown(Controller controller, int buttonCode) { + if(buttonCode == Ouya.BUTTON_L1){ + // Start right motor. + } + if(buttonCode == Ouya.BUTTON_L2){ + // Start left motor. + } + if(buttonCode == Ouya.BUTTON_DPAD_LEFT){ + // Look left. + } + if(buttonCode == Ouya.BUTTON_DPAD_RIGHT){ + // Look right; + } + return false; + } + + @Override + public boolean buttonUp(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean axisMoved(Controller controller, int axisCode, float value) { + if(axisCode == Ouya.AXIS_LEFT_TRIGGER){ + + } + if(axisCode == Ouya.AXIS_RIGHT_TRIGGER){ + // Start + } + return false; + } + + @Override + public boolean povMoved(Controller controller, int povCode, + PovDirection value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean xSliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean ySliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean accelerometerMoved(Controller controller, + int accelerometerCode, Vector3 value) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/DummyState.java b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java similarity index 54% rename from src/ve/ucv/ciens/ccg/nxtar/states/DummyState.java rename to src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java index 0aa0f8f..da9e345 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/DummyState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Miguel Angel Astor Romero + * Copyright (C) 2014 Miguel Angel Astor Romero * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,31 +15,45 @@ */ package ve.ucv.ciens.ccg.nxtar.states; -/** - * Empty state. - * - * Completely empty state for debugging purposes. - * - * @author miky - */ -public class DummyState implements NxtARState{ + +public abstract class MainMenuStateBase extends BaseState{ + @Override + public abstract void render(float delta); @Override - public void input(){ } + public void resize(int width, int height) { + // TODO Auto-generated method stub + + } @Override - public void update(){ } + public void show() { + // TODO Auto-generated method stub + + } @Override - public void render(){ } + public void hide() { + // TODO Auto-generated method stub + + } @Override - public void pause(){ } + public void pause() { + // TODO Auto-generated method stub + + } @Override - public void resume(){ } + public void resume() { + // TODO Auto-generated method stub + + } @Override - public void dispose(){ } + public void dispose() { + // TODO Auto-generated method stub + + } } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java new file mode 100644 index 0000000..5d981d1 --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.NxtARCore; + +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.math.Vector3; + +public class OuyaMainMenuState extends MainMenuStateBase{ + + public OuyaMainMenuState(final NxtARCore core){ + this.core = core; + } + + @Override + public void render(float delta) { + // TODO Auto-generated method stub + + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean keyDown(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyUp(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyTyped(char character) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean mouseMoved(int screenX, int screenY) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + @Override + public boolean scrolled(int amount) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void connected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public void disconnected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public boolean buttonDown(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean buttonUp(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean axisMoved(Controller controller, int axisCode, float value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean povMoved(Controller controller, int povCode, + PovDirection value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean xSliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean ySliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean accelerometerMoved(Controller controller, + int accelerometerCode, Vector3 value) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java b/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java new file mode 100644 index 0000000..f7f811c --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.NxtARCore; + +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.math.Vector3; + +public class PauseState extends BaseState { + + public PauseState(final NxtARCore core){ + this.core = core; + } + + @Override + public void render(float delta) { + // TODO Auto-generated method stub + + } + + @Override + public void resize(int width, int height) { + // TODO Auto-generated method stub + + } + + @Override + public void show() { + // TODO Auto-generated method stub + + } + + @Override + public void hide() { + // TODO Auto-generated method stub + + } + + @Override + public void pause() { + // TODO Auto-generated method stub + + } + + @Override + public void resume() { + // TODO Auto-generated method stub + + } + + @Override + public void dispose() { + // TODO Auto-generated method stub + + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean keyDown(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyUp(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyTyped(char character) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean mouseMoved(int screenX, int screenY) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + @Override + public boolean scrolled(int amount) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void connected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public void disconnected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public boolean buttonDown(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean buttonUp(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean axisMoved(Controller controller, int axisCode, float value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean povMoved(Controller controller, int povCode, + PovDirection value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean xSliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean ySliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean accelerometerMoved(Controller controller, + int accelerometerCode, Vector3 value) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java new file mode 100644 index 0000000..ddc4cac --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.NxtARCore; + +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.math.Vector3; + +public class TabletMainMenuState extends MainMenuStateBase{ + + public TabletMainMenuState(final NxtARCore core){ + this.core = core; + } + + @Override + public void render(float delta) { + // TODO Auto-generated method stub + + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean keyDown(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyUp(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyTyped(char character) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean mouseMoved(int screenX, int screenY) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + @Override + public boolean scrolled(int amount) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void connected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public void disconnected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public boolean buttonDown(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean buttonUp(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean axisMoved(Controller controller, int axisCode, float value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean povMoved(Controller controller, int povCode, + PovDirection value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean xSliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean ySliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean accelerometerMoved(Controller controller, + int accelerometerCode, Vector3 value) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ +} From e88305f0ffb5228c84c0f2360f35dd2f0179c274 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Feb 2014 18:56:20 -0430 Subject: [PATCH 11/16] Refactoring finished. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 81 ++++-- .../nxtar/network/VideoStreamingThread.java | 6 +- .../ucv/ciens/ccg/nxtar/states/BaseState.java | 3 + .../ciens/ccg/nxtar/states/InGameState.java | 24 +- .../ccg/nxtar/states/MainMenuStateBase.java | 138 +++++++--- .../ccg/nxtar/states/OuyaMainMenuState.java | 62 ++++- .../ciens/ccg/nxtar/states/PauseState.java | 16 +- .../ccg/nxtar/states/TabletMainMenuState.java | 240 ++++++++++++------ .../ccg/nxtar/utils/ProjectConstants.java | 2 + 9 files changed, 429 insertions(+), 143 deletions(-) diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index 9f79b33..20d4637 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -23,6 +23,7 @@ import ve.ucv.ciens.ccg.nxtar.network.ServiceDiscoveryThread; import ve.ucv.ciens.ccg.nxtar.network.VideoStreamingThread; import ve.ucv.ciens.ccg.nxtar.states.BaseState; import ve.ucv.ciens.ccg.nxtar.states.InGameState; +import ve.ucv.ciens.ccg.nxtar.states.MainMenuStateBase; import ve.ucv.ciens.ccg.nxtar.states.OuyaMainMenuState; import ve.ucv.ciens.ccg.nxtar.states.PauseState; import ve.ucv.ciens.ccg.nxtar.states.TabletMainMenuState; @@ -33,14 +34,28 @@ import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.controllers.mappings.Ouya; +import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.SpriteBatch; +/** + *

Core of the application.

+ * + *

This class has three basic resposibilities:

+ *
    + *
  • Handling the main game loop.
  • + *
  • Starting and destroying the networking threads.
  • + *
  • Rendering debug information.
  • + *
+ * @author Miguel Angel Astor Romero + */ public class NxtARCore extends Game implements NetworkConnectionListener{ private static final String TAG = "NXTAR_CORE_MAIN"; private static final String CLASS_NAME = NxtARCore.class.getSimpleName(); - // Game state management fields. + /** + * Valid game states. + */ public enum game_states_t { MAIN_MENU(0), IN_GAME(1), PAUSED(2); @@ -54,15 +69,22 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ return this.value; } }; - public game_states_t nextState; + /** + * The current application state. + */ private game_states_t currState; + /** + *

The state to change to.

+ *

Usually null. A state change is scheduled by setting this field to a {@link game_states_t} value.

+ */ + public game_states_t nextState; // Screens. private BaseState[] states; // Assorted fields. public SpriteBatch batch; - public Toaster toaster; + private Toaster toaster; // Networking related fields. private int connections; @@ -72,35 +94,45 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ private RobotControlThread robotThread; // Overlay font. + private OrthographicCamera pixelPerfectCamera; private float fontX; private float fontY; private BitmapFont font; + /** + *

Set up the basic application fields.

+ */ public NxtARCore(Application concreteApp){ super(); connections = 0; try{ this.toaster = (Toaster)concreteApp; + }catch(ClassCastException cc){ + Gdx.app.debug(TAG, CLASS_NAME + ".Main() :: concreteApp does not implement the Toaster interface. Toasting disabled."); + this.toaster = null; + } + + try{ this.mcastEnabler = (MulticastEnabler)concreteApp; }catch(ClassCastException cc){ - Gdx.app.debug(TAG, CLASS_NAME + ".Main() :: concreteApp does not implement some of the required interfaces."); + Gdx.app.error(TAG, CLASS_NAME + ".Main() :: concreteApp does not implement MulticastEnabler. Quitting."); Gdx.app.exit(); } } - @Override public void create(){ // Create the state objects. states = new BaseState[3]; - if(Ouya.runningOnOuya)states[0] = new OuyaMainMenuState(this); - else states[1] = new TabletMainMenuState(this); - states[1] = new InGameState(this); - states[2] = new PauseState(this); + if(Ouya.runningOnOuya)states[game_states_t.MAIN_MENU.getValue()] = new OuyaMainMenuState(this); + else states[game_states_t.MAIN_MENU.getValue()] = new TabletMainMenuState(this); + states[game_states_t.IN_GAME.getValue()] = new InGameState(this); + states[game_states_t.PAUSED.getValue()] = new PauseState(this); // Set up fields. batch = new SpriteBatch(); - if(ProjectConstants.DEBUG){ + if(ProjectConstants.DEBUG) + pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());{ // Set up the overlay font. fontX = -((Gdx.graphics.getWidth() * ProjectConstants.OVERSCAN) / 2) + 10; fontY = ((Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN) / 2) - 10; @@ -125,12 +157,14 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ serviceDiscoveryThread.start(); videoThread.start(); videoThread.startStreaming(); + videoThread.addNetworkConnectionListener(this); //robotThread.start(); // Set the current and next states. currState = game_states_t.MAIN_MENU; nextState = null; this.setScreen(states[currState.getValue()]); + states[currState.getValue()].onStateSet(); // Set initial input handlers. Gdx.input.setInputProcessor(states[currState.getValue()]); @@ -141,25 +175,25 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ // Gdx.app.setLogLevel(Application.LOG_NONE); } - @Override public void render(){ super.render(); // If the current state set a value for nextState then switch to that state. if(nextState != null){ - // Change the input processors. - Gdx.input.setInputProcessor(states[nextState.getValue()]); + // Invalidate all input processors. + Gdx.input.setInputProcessor(null); Controllers.removeListener(states[currState.getValue()]); - Controllers.addListener(states[nextState.getValue()]); // Swap the pointers and set the new screen. currState = nextState; nextState = null; setScreen(states[currState.getValue()]); + states[currState.getValue()].onStateSet(); } if(ProjectConstants.DEBUG){ // Draw the FPS overlay. + batch.setProjectionMatrix(pixelPerfectCamera.combined); batch.begin();{ font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), fontX, fontY); font.draw(batch, String.format("Total stream FPS: %d", videoThread.getFps()), fontX, fontY - font.getCapHeight() - 5); @@ -168,22 +202,16 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ } } - @Override - public void resize(int width, int height){ } - - @Override public void pause(){ if(videoThread != null) videoThread.pause(); } - @Override public void resume(){ if(videoThread != null) videoThread.play(); } - @Override public void dispose(){ // Finish network threads. videoThread.finish(); @@ -202,12 +230,21 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ @Override public synchronized void networkStreamConnected(String streamName){ - if(streamName.compareTo(VideoStreamingThread.THREAD_NAME) == 0 || streamName.compareTo(RobotControlThread.THREAD_NAME) == 0) + if(streamName.equals(VideoStreamingThread.THREAD_NAME) || streamName.equals(RobotControlThread.THREAD_NAME)) connections += 1; - if(connections >= 2){ + if(connections >= 1){ Gdx.app.debug(TAG, CLASS_NAME + ".networkStreamConnected() :: Stopping service broadcast."); serviceDiscoveryThread.finish(); mcastEnabler.disableMulticast(); + toaster.showShortToast("Client connected"); + ((MainMenuStateBase)states[game_states_t.MAIN_MENU.getValue()]).onClientConnected(); + } + } + + public void toast(String msg, boolean longToast){ + if(toaster != null){ + if(longToast) toaster.showLongToast(msg); + else toaster.showShortToast(msg); } } } diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java index 1894420..2e7af9d 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java @@ -45,6 +45,7 @@ public class VideoStreamingThread extends Thread { private boolean endProtocol;*/ private boolean done; private boolean pause; + private boolean coreNotified; private Object protocolPauseMonitor; private Socket client; //private ObjectInputStream reader; @@ -70,6 +71,7 @@ public class VideoStreamingThread extends Thread { /*endProtocol = false; pauseProtocol = false;*/ done = false; + coreNotified = false; //protocolState = ProtocolState_t.WAIT_FOR_START; protocolPauseMonitor = new Object(); frameMonitor = VideoFrameMonitor.getInstance(); @@ -456,8 +458,10 @@ public class VideoStreamingThread extends Thread { } } Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Receiving."); - if(netListener != null) + if(netListener != null && !coreNotified && frameMonitor.getCurrentFrame() != null){ + coreNotified = true; netListener.networkStreamConnected(THREAD_NAME); + } receiveUdp(); frames++; now = System.currentTimeMillis(); diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java b/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java index 664135e..9b68658 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java @@ -27,6 +27,9 @@ import com.badlogic.gdx.math.Vector3; public abstract class BaseState implements Screen, ControllerListener, InputProcessor { protected NxtARCore core; + /* STATE METHODS */ + public abstract void onStateSet(); + /* SCREEN METHODS*/ @Override public abstract void render(float delta); diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java index bd24e3d..d89152a 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java @@ -23,9 +23,10 @@ import ve.ucv.ciens.ccg.nxtar.utils.Size; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.controllers.PovDirection; import com.badlogic.gdx.controllers.mappings.Ouya; -import com.badlogic.gdx.graphics.GL10; +import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; @@ -101,7 +102,7 @@ public class InGameState extends BaseState{ Size dimensions = null; Gdx.gl.glClearColor(1, 1, 1, 1); - Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); frame = frameMonitor.getCurrentFrame(); if(frame != null){ @@ -111,7 +112,7 @@ public class InGameState extends BaseState{ try{ videoFrame = new Pixmap(getOptimalTextureSize(dimensions.getWidth()), getOptimalTextureSize(dimensions.getHeight()), temp.getFormat()); }catch(ImageTooBigException e){ - core.toaster.showLongToast("Cannot display received frame.\n" + e.getMessage()); + core.toast("Cannot display received frame.\n" + e.getMessage(), true); Gdx.app.exit(); return; } @@ -206,6 +207,16 @@ public class InGameState extends BaseState{ throw new ImageTooBigException("No valid texture size found. Image too large."); } + /*;;;;;;;;;;;;;;;;;; + ; HELPER METHODS ; + ;;;;;;;;;;;;;;;;;;*/ + + @Override + public void onStateSet(){ + Controllers.addListener(this); + Gdx.input.setInputProcessor(this); + } + private void setUpButtons(){ buttonTexture = new Texture(Gdx.files.internal("data/gfx/gui/PBCrichton_Flat_Button.png")); buttonTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); @@ -347,13 +358,11 @@ public class InGameState extends BaseState{ // TODO Auto-generated method stub return false; } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; END INPUT PROCESSOR METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; BEGIN CONTROLLER LISTENER METHODS ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + @Override public boolean scrolled(int amount) { // TODO Auto-generated method stub @@ -433,7 +442,4 @@ public class InGameState extends BaseState{ // TODO Auto-generated method stub return false; } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; END CONTROLLER LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java index da9e345..c64a00e 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java @@ -15,45 +15,125 @@ */ package ve.ucv.ciens.ccg.nxtar.states; +import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.controllers.Controllers; +import com.badlogic.gdx.controllers.mappings.Ouya; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.NinePatch; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; +import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle; +import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; + public abstract class MainMenuStateBase extends BaseState{ + protected static final String TAG = "MAIN_MENU"; + + // Client connection helper fields. + protected boolean clientConnected; + + // Buttons and other gui components. + protected TextButton startButton; + protected Rectangle startButtonBBox; + protected Sprite clientConnectedLedOn; + protected Sprite clientConnectedLedOff; + + // Graphic data for the start button. + private Texture startButtonEnabledTexture; + private Texture startButtonDisabledTexture; + private Texture startButtonPressedTexture; + private NinePatch startButtonEnabled9p; + private NinePatch startButtonDisabled9p; + private NinePatch startButtonPressed9p; + private BitmapFont font; + + // Other graphics. + private Texture clientConnectedLedOffTexture; + private Texture clientConnectedLedOnTexture; + + public MainMenuStateBase(){ + // Create the start button background. + startButtonEnabledTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Yellow.png")); + startButtonEnabled9p = new NinePatch(new TextureRegion(startButtonEnabledTexture, 0, 0, startButtonEnabledTexture.getWidth(), startButtonEnabledTexture.getHeight()), 49, 49, 45, 45); + + startButtonDisabledTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Cyan.png")); + startButtonDisabled9p = new NinePatch(new TextureRegion(startButtonDisabledTexture, 0, 0, startButtonDisabledTexture.getWidth(), startButtonDisabledTexture.getHeight()), 49, 49, 45, 45); + + startButtonPressedTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Blue.png")); + startButtonPressed9p = new NinePatch(new TextureRegion(startButtonPressedTexture, 0, 0, startButtonPressedTexture.getWidth(), startButtonPressedTexture.getHeight()), 49, 49, 45, 45); + + // Create the start button font. + FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("data/fonts/d-puntillas-B-to-tiptoe.ttf")); + font = generator.generateFont(Ouya.runningOnOuya ? 60 : 40, ProjectConstants.FONT_CHARS, false); + generator.dispose(); + + // Create the start button itself. + TextButtonStyle tbs = new TextButtonStyle(); + tbs.font = font; + tbs.up = new NinePatchDrawable(startButtonEnabled9p); + tbs.checked = new NinePatchDrawable(startButtonPressed9p); + tbs.disabled = new NinePatchDrawable(startButtonDisabled9p); + tbs.disabledFontColor = new Color(0, 0, 0, 1); + startButton = new TextButton("Start server", tbs); + startButton.setText("Start game"); + startButton.setDisabled(true); + startButtonBBox = new Rectangle(0, 0, startButton.getWidth(), startButton.getHeight()); + + // Create the connection leds. + TextureRegion region; + clientConnectedLedOnTexture = new Texture("data/gfx/gui/Anonymous_Button_Green.png"); + region = new TextureRegion(clientConnectedLedOnTexture, clientConnectedLedOnTexture.getWidth(), clientConnectedLedOnTexture.getHeight()); + clientConnectedLedOn = new Sprite(region); + + clientConnectedLedOffTexture = new Texture("data/gfx/gui/Anonymous_Button_Red.png"); + region = new TextureRegion(clientConnectedLedOffTexture, clientConnectedLedOffTexture.getWidth(), clientConnectedLedOffTexture.getHeight()); + clientConnectedLedOff = new Sprite(region); + + clientConnected = false; + } + @Override public abstract void render(float delta); @Override - public void resize(int width, int height) { - // TODO Auto-generated method stub + public abstract void resize(int width, int height); + @Override + public abstract void show(); + @Override + public abstract void hide(); + + @Override + public abstract void pause(); + + @Override + public abstract void resume(); + + @Override + public void dispose(){ + startButtonEnabledTexture.dispose(); + startButtonDisabledTexture.dispose(); + startButtonPressedTexture.dispose(); + clientConnectedLedOnTexture.dispose(); + clientConnectedLedOffTexture.dispose(); + font.dispose(); } @Override - public void show() { - // TODO Auto-generated method stub - + public void onStateSet(){ + Controllers.addListener(this); + Gdx.input.setInputProcessor(this); } - - @Override - public void hide() { - // TODO Auto-generated method stub - + + public void onClientConnected(){ + clientConnected = true; + startButton.setDisabled(false); } - - @Override - public void pause() { - // TODO Auto-generated method stub - - } - - @Override - public void resume() { - // TODO Auto-generated method stub - - } - - @Override - public void dispose() { - // TODO Auto-generated method stub - - } - } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java index 5d981d1..1cd4fc3 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java @@ -17,22 +17,77 @@ package ve.ucv.ciens.ccg.nxtar.states; import ve.ucv.ciens.ccg.nxtar.NxtARCore; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.graphics.GL10; +import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.math.Vector3; public class OuyaMainMenuState extends MainMenuStateBase{ + private OrthographicCamera pixelPerfectCamera; public OuyaMainMenuState(final NxtARCore core){ this.core = core; + this.pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); } @Override public void render(float delta) { + Gdx.gl.glClearColor(1, 1, 1, 1); + Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); + + core.batch.setProjectionMatrix(pixelPerfectCamera.combined); + core.batch.begin();{ + this.startButton.draw(core.batch, 1.0f); + }core.batch.end(); + } + + @Override + public void resize(int width, int height) { // TODO Auto-generated method stub } + @Override + public void show() { + // TODO Auto-generated method stub + + } + + @Override + public void hide() { + // TODO Auto-generated method stub + + } + + @Override + public void pause() { + // TODO Auto-generated method stub + + } + + @Override + public void resume() { + // TODO Auto-generated method stub + + } + + @Override + public void dispose(){ + super.dispose(); + } + + /*;;;;;;;;;;;;;;;;;; + ; HELPER METHODS ; + ;;;;;;;;;;;;;;;;;;*/ + + @Override + public void onStateSet(){ + super.onStateSet(); + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; BEGIN INPUT PROCESSOR METHODS ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ @@ -78,13 +133,11 @@ public class OuyaMainMenuState extends MainMenuStateBase{ // TODO Auto-generated method stub return false; } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; END INPUT PROCESSOR METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; BEGIN CONTROLLER LISTENER METHODS ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + @Override public boolean scrolled(int amount) { // TODO Auto-generated method stub @@ -148,7 +201,4 @@ public class OuyaMainMenuState extends MainMenuStateBase{ // TODO Auto-generated method stub return false; } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; END CONTROLLER LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java b/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java index f7f811c..36f02d8 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java @@ -26,7 +26,7 @@ public class PauseState extends BaseState { public PauseState(final NxtARCore core){ this.core = core; } - + @Override public void render(float delta) { // TODO Auto-generated method stub @@ -69,10 +69,18 @@ public class PauseState extends BaseState { } + /*;;;;;;;;;;;;;;;;;; + ; HELPER METHODS ; + ;;;;;;;;;;;;;;;;;;*/ + + @Override + public void onStateSet(){ + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; BEGIN INPUT PROCESSOR METHODS ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - + @Override public boolean keyDown(int keycode) { // TODO Auto-generated method stub @@ -130,13 +138,13 @@ public class PauseState extends BaseState { @Override public void connected(Controller controller) { // TODO Auto-generated method stub - + } @Override public void disconnected(Controller controller) { // TODO Auto-generated method stub - + } @Override diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java index ddc4cac..6897560 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java @@ -16,139 +16,235 @@ package ve.ucv.ciens.ccg.nxtar.states; import ve.ucv.ciens.ccg.nxtar.NxtARCore; +import ve.ucv.ciens.ccg.nxtar.NxtARCore.game_states_t; +import com.badlogic.gdx.Gdx; import com.badlogic.gdx.controllers.Controller; import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.graphics.GL10; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; public class TabletMainMenuState extends MainMenuStateBase{ + protected static final String CLASS_NAME = TabletMainMenuState.class.getSimpleName(); + + private OrthographicCamera pixelPerfectCamera; + + // Button touch helper fields. + private Vector3 win2world; + private Vector2 touchPointWorldCoords; + private boolean startButtonTouched; + private int startButtonTouchPointer; public TabletMainMenuState(final NxtARCore core){ this.core = core; + pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + startButton.setPosition(-(startButton.getWidth() / 2), -(startButton.getHeight() / 2)); + startButtonBBox.setPosition(startButton.getX(), startButton.getY()); + + win2world = new Vector3(0.0f, 0.0f, 0.0f); + touchPointWorldCoords = new Vector2(); + + startButtonTouched = false; + startButtonTouchPointer = -1; + + float ledYPos = (-(Gdx.graphics.getHeight() / 2) * 0.5f) + (startButton.getY() * 0.5f); + clientConnectedLedOn.setSize(clientConnectedLedOn.getWidth() * 0.5f, clientConnectedLedOn.getHeight() * 0.5f); + clientConnectedLedOn.setPosition(-(clientConnectedLedOn.getWidth() / 2), ledYPos); + + clientConnectedLedOff.setSize(clientConnectedLedOff.getWidth() * 0.5f, clientConnectedLedOff.getHeight() * 0.5f); + clientConnectedLedOff.setPosition(-(clientConnectedLedOff.getWidth() / 2), ledYPos); } @Override - public void render(float delta) { - // TODO Auto-generated method stub + public void render(float delta){ + Gdx.gl.glClearColor(1, 1, 1, 1); + Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); + core.batch.setProjectionMatrix(pixelPerfectCamera.combined); + core.batch.begin();{ + if(clientConnected){ + clientConnectedLedOn.draw(core.batch); + }else{ + clientConnectedLedOff.draw(core.batch); + } + startButton.draw(core.batch, 1.0f); + }core.batch.end(); } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; BEGIN INPUT PROCESSOR METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + @Override + public void resize(int width, int height){ } @Override - public boolean keyDown(int keycode) { - // TODO Auto-generated method stub + public void show(){ } + + @Override + public void hide(){ } + + @Override + public void pause(){ } + + @Override + public void resume(){ } + + @Override + public void dispose(){ + super.dispose(); + } + + /*;;;;;;;;;;;;;;;;;; + ; HELPER METHODS ; + ;;;;;;;;;;;;;;;;;;*/ + + @Override + public void onStateSet(){ + super.onStateSet(); + } + + private void unprojectTouch(int screenX, int screenY){ + win2world.set(screenX, screenY, 0.0f); + pixelPerfectCamera.unproject(win2world); + touchPointWorldCoords.set(win2world.x, win2world.y); + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button){ + unprojectTouch(screenX, screenY); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ + startButton.setChecked(true); + startButtonTouched = true; + startButtonTouchPointer = pointer; + core.nextState = game_states_t.IN_GAME; + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button pressed."); + } + + return true; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button){ + unprojectTouch(screenX, screenY); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ + startButton.setChecked(false); + startButtonTouched = false; + startButtonTouchPointer = -1; + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button released."); + } + + return true; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer){ + unprojectTouch(screenX, screenY); + + if(!startButton.isDisabled() && startButtonTouched && pointer == startButtonTouchPointer && !startButtonBBox.contains(touchPointWorldCoords)){ + startButtonTouchPointer = -1; + startButtonTouched = false; + startButton.setChecked(false); + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Start button released."); + } + + return true; + } + + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; UNUSED CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean keyDown(int keycode){ + // Unused. return false; } @Override - public boolean keyUp(int keycode) { - // TODO Auto-generated method stub + public boolean keyUp(int keycode){ + // Unused. return false; } @Override - public boolean keyTyped(char character) { - // TODO Auto-generated method stub + public boolean keyTyped(char character){ + // Unused. return false; } @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button) { - // TODO Auto-generated method stub + public boolean mouseMoved(int screenX, int screenY){ + // Unused. return false; } @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button) { - // TODO Auto-generated method stub + public boolean scrolled(int amount){ + // Unused. return false; } @Override - public boolean touchDragged(int screenX, int screenY, int pointer) { - // TODO Auto-generated method stub + public void connected(Controller controller){ + // Unused. + } + + @Override + public void disconnected(Controller controller){ + // Unused. + } + + @Override + public boolean buttonDown(Controller controller, int buttonCode){ + // Unused. return false; } @Override - public boolean mouseMoved(int screenX, int screenY) { - // TODO Auto-generated method stub - return false; - } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; END INPUT PROCESSOR METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; BEGIN CONTROLLER LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - @Override - public boolean scrolled(int amount) { - // TODO Auto-generated method stub + public boolean buttonUp(Controller controller, int buttonCode){ + // Unused. return false; } @Override - public void connected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public void disconnected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public boolean buttonDown(Controller controller, int buttonCode) { - // TODO Auto-generated method stub + public boolean axisMoved(Controller controller, int axisCode, float value){ + // Unused. return false; } @Override - public boolean buttonUp(Controller controller, int buttonCode) { - // TODO Auto-generated method stub + public boolean povMoved(Controller controller, int povCode, PovDirection value){ + // Unused. return false; } @Override - public boolean axisMoved(Controller controller, int axisCode, float value) { - // TODO Auto-generated method stub + public boolean xSliderMoved(Controller controller, int sliderCode, boolean value){ + // Unused. return false; } @Override - public boolean povMoved(Controller controller, int povCode, - PovDirection value) { - // TODO Auto-generated method stub + public boolean ySliderMoved(Controller controller, int sliderCode, boolean value){ + // Unused. return false; } @Override - public boolean xSliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub + public boolean accelerometerMoved(Controller controller, int accelerometerCode, Vector3 value){ + // Unused. return false; } - - @Override - public boolean ySliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean accelerometerMoved(Controller controller, - int accelerometerCode, Vector3 value) { - // TODO Auto-generated method stub - return false; - } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; END CONTROLLER LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ } diff --git a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java index d27d3b6..8a0f8f4 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java +++ b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java @@ -31,6 +31,8 @@ public abstract class ProjectConstants { public static final float OVERSCAN; + public static final String FONT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.,:;!¡?¿"; + static{ OVERSCAN = Ouya.runningOnOuya ? 0.9f : 1.0f; } From 39426cd2a611670a9ef7c7fe67b52f55465bc8e9 Mon Sep 17 00:00:00 2001 From: Miguel Angel Astor Romero Date: Thu, 6 Feb 2014 22:34:37 -0430 Subject: [PATCH 12/16] Fixed OuyaMainMenuState. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 77 +- .../exceptions/ImageTooBigException.java | 48 +- .../ucv/ciens/ccg/nxtar/states/BaseState.java | 174 ++-- .../ciens/ccg/nxtar/states/InGameState.java | 899 +++++++++--------- .../ccg/nxtar/states/MainMenuStateBase.java | 373 +++++--- .../ccg/nxtar/states/OuyaMainMenuState.java | 359 +++---- .../ciens/ccg/nxtar/states/PauseState.java | 402 ++++---- .../ccg/nxtar/states/TabletMainMenuState.java | 406 +++----- .../ccg/nxtar/utils/ProjectConstants.java | 2 +- 9 files changed, 1356 insertions(+), 1384 deletions(-) diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index 20d4637..c7d65b9 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -128,51 +128,55 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ states[game_states_t.IN_GAME.getValue()] = new InGameState(this); states[game_states_t.PAUSED.getValue()] = new PauseState(this); + for(BaseState state : states){ + Controllers.addListener(state); + } + // Set up fields. batch = new SpriteBatch(); if(ProjectConstants.DEBUG) pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());{ - // Set up the overlay font. - fontX = -((Gdx.graphics.getWidth() * ProjectConstants.OVERSCAN) / 2) + 10; - fontY = ((Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN) / 2) - 10; + // Set up the overlay font. + fontX = -((Gdx.graphics.getWidth() * ProjectConstants.OVERSCAN) / 2) + 10; + fontY = ((Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN) / 2) - 10; - font = new BitmapFont(); - font.setColor(1.0f, 1.0f, 0.0f, 1.0f); - if(!Ouya.runningOnOuya){ - font.setScale(1.0f); - }else{ - font.setScale(2.5f); + font = new BitmapFont(); + font.setColor(1.0f, 1.0f, 0.0f, 1.0f); + if(!Ouya.runningOnOuya){ + font.setScale(1.0f); + }else{ + font.setScale(2.5f); + } } - } - // Start networking. - mcastEnabler.enableMulticast(); + // Start networking. + mcastEnabler.enableMulticast(); - Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); - serviceDiscoveryThread = ServiceDiscoveryThread.getInstance(); - videoThread = VideoStreamingThread.getInstance()/*.setToaster(toaster)*/; - //robotThread = RobotControlThread.getInstance().setToaster(toaster); + Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); + serviceDiscoveryThread = ServiceDiscoveryThread.getInstance(); + videoThread = VideoStreamingThread.getInstance()/*.setToaster(toaster)*/; + //robotThread = RobotControlThread.getInstance().setToaster(toaster); - serviceDiscoveryThread.start(); - videoThread.start(); - videoThread.startStreaming(); - videoThread.addNetworkConnectionListener(this); - //robotThread.start(); + serviceDiscoveryThread.start(); + videoThread.start(); + videoThread.startStreaming(); + videoThread.addNetworkConnectionListener(this); + //robotThread.start(); - // Set the current and next states. - currState = game_states_t.MAIN_MENU; - nextState = null; - this.setScreen(states[currState.getValue()]); - states[currState.getValue()].onStateSet(); + // Set the current and next states. + currState = game_states_t.MAIN_MENU; + nextState = null; + this.setScreen(states[currState.getValue()]); + states[currState.getValue()].onStateSet(); - // Set initial input handlers. - Gdx.input.setInputProcessor(states[currState.getValue()]); - Controllers.addListener(states[currState.getValue()]); + // Set initial input handlers. + Gdx.input.setInputProcessor(states[currState.getValue()]); + Controllers.addListener(states[currState.getValue()]); - // Anything else. - Gdx.app.setLogLevel(Application.LOG_INFO); - // Gdx.app.setLogLevel(Application.LOG_NONE); + // Anything else. + Gdx.app.setLogLevel(Application.LOG_INFO); + // Gdx.app.setLogLevel(Application.LOG_NONE); } public void render(){ @@ -180,15 +184,14 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ // If the current state set a value for nextState then switch to that state. if(nextState != null){ - // Invalidate all input processors. - Gdx.input.setInputProcessor(null); - Controllers.removeListener(states[currState.getValue()]); + states[currState.getValue()].onStateUnset(); - // Swap the pointers and set the new screen. currState = nextState; nextState = null; - setScreen(states[currState.getValue()]); + states[currState.getValue()].onStateSet(); + + setScreen(states[currState.getValue()]); } if(ProjectConstants.DEBUG){ diff --git a/src/ve/ucv/ciens/ccg/nxtar/exceptions/ImageTooBigException.java b/src/ve/ucv/ciens/ccg/nxtar/exceptions/ImageTooBigException.java index 716119a..d3196d7 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/exceptions/ImageTooBigException.java +++ b/src/ve/ucv/ciens/ccg/nxtar/exceptions/ImageTooBigException.java @@ -1,24 +1,24 @@ -/* - * Copyright (C) 2014 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.exceptions; - -public class ImageTooBigException extends Exception{ - private static final long serialVersionUID = 9989L; - - public ImageTooBigException(String msg){ - super(msg); - } -} +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.exceptions; + +public class ImageTooBigException extends Exception{ + private static final long serialVersionUID = 9989L; + + public ImageTooBigException(String msg){ + super(msg); + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java b/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java index 9b68658..731bce3 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/BaseState.java @@ -1,86 +1,88 @@ -/* - * Copyright (C) 2014 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.states; - -import ve.ucv.ciens.ccg.nxtar.NxtARCore; - -import com.badlogic.gdx.InputProcessor; -import com.badlogic.gdx.Screen; -import com.badlogic.gdx.controllers.Controller; -import com.badlogic.gdx.controllers.ControllerListener; -import com.badlogic.gdx.controllers.PovDirection; -import com.badlogic.gdx.math.Vector3; - -public abstract class BaseState implements Screen, ControllerListener, InputProcessor { - protected NxtARCore core; - - /* STATE METHODS */ - public abstract void onStateSet(); - - /* SCREEN METHODS*/ - @Override - public abstract void render(float delta); - @Override - public abstract void resize(int width, int height); - @Override - public abstract void show(); - @Override - public abstract void hide(); - @Override - public abstract void pause(); - @Override - public abstract void resume(); - @Override - public abstract void dispose(); - - /* INPUT PROCESSOR METHODS. */ - @Override - public abstract boolean keyDown(int keycode); - @Override - public abstract boolean keyUp(int keycode); - @Override - public abstract boolean keyTyped(char character); - @Override - public abstract boolean touchDown(int screenX, int screenY, int pointer, int button); - @Override - public abstract boolean touchUp(int screenX, int screenY, int pointer, int button); - @Override - public abstract boolean touchDragged(int screenX, int screenY, int pointer); - @Override - public abstract boolean mouseMoved(int screenX, int screenY); - @Override - public abstract boolean scrolled(int amount); - - /* CONTROLLER LISTENER METHODS. */ - @Override - public abstract void connected(Controller controller); - @Override - public abstract void disconnected(Controller controller); - @Override - public abstract boolean buttonDown(Controller controller, int buttonCode); - @Override - public abstract boolean buttonUp(Controller controller, int buttonCode); - @Override - public abstract boolean axisMoved(Controller controller, int axisCode, float value); - @Override - public abstract boolean povMoved(Controller controller, int povCode, PovDirection value); - @Override - public abstract boolean xSliderMoved(Controller controller, int sliderCode, boolean value); - @Override - public abstract boolean ySliderMoved(Controller controller, int sliderCode, boolean value); - @Override - public abstract boolean accelerometerMoved(Controller controller, int accelerometerCode, Vector3 value); -} +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.NxtARCore; + +import com.badlogic.gdx.InputProcessor; +import com.badlogic.gdx.Screen; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.ControllerListener; +import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.math.Vector3; + +public abstract class BaseState implements Screen, ControllerListener, InputProcessor { + protected NxtARCore core; + protected boolean stateActive; + + /* STATE METHODS */ + public abstract void onStateSet(); + public abstract void onStateUnset(); + + /* SCREEN METHODS*/ + @Override + public abstract void render(float delta); + @Override + public abstract void resize(int width, int height); + @Override + public abstract void show(); + @Override + public abstract void hide(); + @Override + public abstract void pause(); + @Override + public abstract void resume(); + @Override + public abstract void dispose(); + + /* INPUT PROCESSOR METHODS. */ + @Override + public abstract boolean keyDown(int keycode); + @Override + public abstract boolean keyUp(int keycode); + @Override + public abstract boolean keyTyped(char character); + @Override + public abstract boolean touchDown(int screenX, int screenY, int pointer, int button); + @Override + public abstract boolean touchUp(int screenX, int screenY, int pointer, int button); + @Override + public abstract boolean touchDragged(int screenX, int screenY, int pointer); + @Override + public abstract boolean mouseMoved(int screenX, int screenY); + @Override + public abstract boolean scrolled(int amount); + + /* CONTROLLER LISTENER METHODS. */ + @Override + public abstract void connected(Controller controller); + @Override + public abstract void disconnected(Controller controller); + @Override + public abstract boolean buttonDown(Controller controller, int buttonCode); + @Override + public abstract boolean buttonUp(Controller controller, int buttonCode); + @Override + public abstract boolean axisMoved(Controller controller, int axisCode, float value); + @Override + public abstract boolean povMoved(Controller controller, int povCode, PovDirection value); + @Override + public abstract boolean xSliderMoved(Controller controller, int sliderCode, boolean value); + @Override + public abstract boolean ySliderMoved(Controller controller, int sliderCode, boolean value); + @Override + public abstract boolean accelerometerMoved(Controller controller, int accelerometerCode, Vector3 value); +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java index d89152a..502d275 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java @@ -1,445 +1,454 @@ -/* - * Copyright (C) 2014 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.states; - -import ve.ucv.ciens.ccg.nxtar.NxtARCore; -import ve.ucv.ciens.ccg.nxtar.exceptions.ImageTooBigException; -import ve.ucv.ciens.ccg.nxtar.network.VideoFrameMonitor; -import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; -import ve.ucv.ciens.ccg.nxtar.utils.Size; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.controllers.Controller; -import com.badlogic.gdx.controllers.Controllers; -import com.badlogic.gdx.controllers.PovDirection; -import com.badlogic.gdx.controllers.mappings.Ouya; -import com.badlogic.gdx.graphics.GL20; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.graphics.Pixmap; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.Texture.TextureFilter; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.math.Vector3; - -public class InGameState extends BaseState{ - private static final String TAG = "IN_GAME_STATE"; - private static final String CLASS_NAME = InGameState.class.getSimpleName(); - - private NxtARCore core; - - // Cameras. - private OrthographicCamera camera; - private OrthographicCamera pixelPerfectCamera; - - // Video stream graphics. - private Texture videoFrameTexture; - private Sprite renderableVideoFrame; - private Pixmap videoFrame; - - // Interface buttons. - private Texture buttonTexture; - private Sprite motorA; - private Sprite motorB; - private Sprite motorC; - private Sprite motorD; - - // Button touch helper fields. - private Vector3 win2world; - private Vector2 touchPointWorldCoords; - private boolean[] motorButtonsTouched; - private int[] motorButtonsPointers; - - private VideoFrameMonitor frameMonitor; - - public InGameState(final NxtARCore core){ - if(!Ouya.runningOnOuya) setUpButtons(); - - this.core = core; - frameMonitor = VideoFrameMonitor.getInstance(); - - // Set up rendering fields; - videoFrame = null; - - // Set up the cameras. - pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); - camera = new OrthographicCamera(1.0f, Gdx.graphics.getHeight() / Gdx.graphics.getWidth()); - - // Set up input handling support fields. - win2world = new Vector3(0.0f, 0.0f, 0.0f); - touchPointWorldCoords = new Vector2(); - motorButtonsTouched = new boolean[4]; - motorButtonsTouched[0] = false; - motorButtonsTouched[1] = false; - motorButtonsTouched[2] = false; - motorButtonsTouched[3] = false; - - motorButtonsPointers = new int[4]; - motorButtonsPointers[0] = -1; - motorButtonsPointers[1] = -1; - motorButtonsPointers[2] = -1; - motorButtonsPointers[3] = -1; - } - - @Override - public void render(float delta) { - Pixmap temp; - byte[] frame; - Size dimensions = null; - - Gdx.gl.glClearColor(1, 1, 1, 1); - Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); - - frame = frameMonitor.getCurrentFrame(); - if(frame != null){ - dimensions = frameMonitor.getFrameDimensions(); - temp = new Pixmap(frame, 0, dimensions.getWidth() * dimensions.getHeight()); - if(videoFrame == null){ - try{ - videoFrame = new Pixmap(getOptimalTextureSize(dimensions.getWidth()), getOptimalTextureSize(dimensions.getHeight()), temp.getFormat()); - }catch(ImageTooBigException e){ - core.toast("Cannot display received frame.\n" + e.getMessage(), true); - Gdx.app.exit(); - return; - } - } - videoFrame.drawPixmap(temp, 0, 0); - temp.dispose(); - videoFrameTexture = new Texture(videoFrame); - videoFrameTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); - - TextureRegion region = new TextureRegion(videoFrameTexture, 0, 0, dimensions.getWidth(), dimensions.getHeight()); - - renderableVideoFrame = new Sprite(region); - renderableVideoFrame.setOrigin(renderableVideoFrame.getWidth() / 2, renderableVideoFrame.getHeight() / 2); - if(!Ouya.runningOnOuya){ - renderableVideoFrame.setSize(1.0f, renderableVideoFrame.getHeight() / renderableVideoFrame.getWidth() ); - renderableVideoFrame.rotate90(true); - renderableVideoFrame.translate(-renderableVideoFrame.getWidth() / 2, 0.5f - renderableVideoFrame.getHeight()); - }else{ - float xSize = Gdx.graphics.getHeight() * (dimensions.getWidth() / dimensions.getHeight()); - renderableVideoFrame.setSize(xSize * ProjectConstants.OVERSCAN, Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN); - renderableVideoFrame.rotate90(true); - renderableVideoFrame.translate(-renderableVideoFrame.getWidth() / 2, -renderableVideoFrame.getHeight() / 2); - } - - if(!Ouya.runningOnOuya){ - core.batch.setProjectionMatrix(camera.combined); - }else{ - core.batch.setProjectionMatrix(pixelPerfectCamera.combined); - } - core.batch.begin();{ - renderableVideoFrame.draw(core.batch); - }core.batch.end(); - - videoFrameTexture.dispose(); - } - - core.batch.setProjectionMatrix(pixelPerfectCamera.combined); - core.batch.begin();{ - if(!Ouya.runningOnOuya){ - motorA.draw(core.batch); - motorB.draw(core.batch); - motorC.draw(core.batch); - motorD.draw(core.batch); - } - }core.batch.end(); - } - - @Override - public void resize(int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void show() { - // TODO Auto-generated method stub - - } - - @Override - public void hide() { - // TODO Auto-generated method stub - - } - - @Override - public void pause() { - // TODO Auto-generated method stub - - } - - @Override - public void resume() { - // TODO Auto-generated method stub - - } - - @Override - public void dispose() { - if(videoFrameTexture != null) - videoFrameTexture.dispose(); - if(buttonTexture != null) - buttonTexture.dispose(); - if(videoFrame != null) - videoFrame.dispose(); - } - - private int getOptimalTextureSize(int imageSideLength) throws ImageTooBigException{ - for(int po2: ProjectConstants.POWERS_OF_2){ - if(imageSideLength < po2) return po2; - } - throw new ImageTooBigException("No valid texture size found. Image too large."); - } - - /*;;;;;;;;;;;;;;;;;; - ; HELPER METHODS ; - ;;;;;;;;;;;;;;;;;;*/ - - @Override - public void onStateSet(){ - Controllers.addListener(this); - Gdx.input.setInputProcessor(this); - } - - private void setUpButtons(){ - buttonTexture = new Texture(Gdx.files.internal("data/gfx/gui/PBCrichton_Flat_Button.png")); - buttonTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); - - TextureRegion region = new TextureRegion(buttonTexture, 0, 0, buttonTexture.getWidth(), buttonTexture.getHeight()); - - motorA = new Sprite(region); - motorA.setSize(motorA.getWidth() * 0.7f, motorA.getHeight() * 0.7f); - - motorB = new Sprite(region); - motorB.setSize(motorB.getWidth() * 0.7f, motorB.getHeight() * 0.7f); - - motorC = new Sprite(region); - motorC.setSize(motorC.getWidth() * 0.7f, motorC.getHeight() * 0.7f); - - motorD = new Sprite(region); - motorD.setSize(motorD.getWidth() * 0.7f, motorD.getHeight() * 0.7f); - - motorA.setPosition(-(Gdx.graphics.getWidth() / 2) + 10, -(Gdx.graphics.getHeight() / 2) + motorB.getHeight() + 20); - motorB.setPosition(-(Gdx.graphics.getWidth() / 2) + 20 + (motorA.getWidth() / 2), -(Gdx.graphics.getHeight() / 2) + 10); - motorC.setPosition((Gdx.graphics.getWidth() / 2) - (1.5f * (motorD.getWidth())) - 20, -(Gdx.graphics.getHeight() / 2) + 10); - motorD.setPosition((Gdx.graphics.getWidth() / 2) - motorD.getWidth() - 10, -(Gdx.graphics.getHeight() / 2) + 20 + motorC.getHeight()); - } - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; BEGIN INPUT PROCESSOR METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - @Override - public boolean keyDown(int keycode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean keyUp(int keycode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean keyTyped(char character) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button) { - if(!Ouya.runningOnOuya){ - win2world.set(screenX, screenY, 0.0f); - camera.unproject(win2world); - touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); - - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - - if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); - motorButtonsTouched[0] = true; - motorButtonsPointers[0] = pointer; - }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); - motorButtonsTouched[1] = true; - motorButtonsPointers[1] = pointer; - }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); - motorButtonsTouched[2] = true; - motorButtonsPointers[2] = pointer; - }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); - motorButtonsTouched[3] = true; - motorButtonsPointers[3] = pointer; - } - } - return true; - } - - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button) { - if(!Ouya.runningOnOuya){ - win2world.set(screenX, screenY, 0.0f); - camera.unproject(win2world); - touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); - - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - - if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; - }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; - }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; - }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; - } - } - return true; - } - - @Override - public boolean touchDragged(int screenX, int screenY, int pointer) { - if(!Ouya.runningOnOuya){ - win2world.set(screenX, screenY, 0.0f); - camera.unproject(win2world); - touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); - - if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; - }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; - }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; - }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; - } - } - return true; - } - - @Override - public boolean mouseMoved(int screenX, int screenY) { - // TODO Auto-generated method stub - return false; - } - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; BEGIN CONTROLLER LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - @Override - public boolean scrolled(int amount) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void connected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public void disconnected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public boolean buttonDown(Controller controller, int buttonCode) { - if(buttonCode == Ouya.BUTTON_L1){ - // Start right motor. - } - if(buttonCode == Ouya.BUTTON_L2){ - // Start left motor. - } - if(buttonCode == Ouya.BUTTON_DPAD_LEFT){ - // Look left. - } - if(buttonCode == Ouya.BUTTON_DPAD_RIGHT){ - // Look right; - } - return false; - } - - @Override - public boolean buttonUp(Controller controller, int buttonCode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean axisMoved(Controller controller, int axisCode, float value) { - if(axisCode == Ouya.AXIS_LEFT_TRIGGER){ - - } - if(axisCode == Ouya.AXIS_RIGHT_TRIGGER){ - // Start - } - return false; - } - - @Override - public boolean povMoved(Controller controller, int povCode, - PovDirection value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean xSliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean ySliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean accelerometerMoved(Controller controller, - int accelerometerCode, Vector3 value) { - // TODO Auto-generated method stub - return false; - } -} +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.NxtARCore; +import ve.ucv.ciens.ccg.nxtar.exceptions.ImageTooBigException; +import ve.ucv.ciens.ccg.nxtar.network.VideoFrameMonitor; +import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; +import ve.ucv.ciens.ccg.nxtar.utils.Size; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.Controllers; +import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.controllers.mappings.Ouya; +import com.badlogic.gdx.graphics.GL20; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.Texture.TextureFilter; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; + +public class InGameState extends BaseState{ + private static final String TAG = "IN_GAME_STATE"; + private static final String CLASS_NAME = InGameState.class.getSimpleName(); + + private NxtARCore core; + + // Cameras. + private OrthographicCamera camera; + private OrthographicCamera pixelPerfectCamera; + + // Video stream graphics. + private Texture videoFrameTexture; + private Sprite renderableVideoFrame; + private Pixmap videoFrame; + + // Interface buttons. + private Texture buttonTexture; + private Sprite motorA; + private Sprite motorB; + private Sprite motorC; + private Sprite motorD; + + // Button touch helper fields. + private Vector3 win2world; + private Vector2 touchPointWorldCoords; + private boolean[] motorButtonsTouched; + private int[] motorButtonsPointers; + + private VideoFrameMonitor frameMonitor; + + public InGameState(final NxtARCore core){ + if(!Ouya.runningOnOuya) setUpButtons(); + + this.core = core; + frameMonitor = VideoFrameMonitor.getInstance(); + + // Set up rendering fields; + videoFrame = null; + + // Set up the cameras. + pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + camera = new OrthographicCamera(1.0f, Gdx.graphics.getHeight() / Gdx.graphics.getWidth()); + + // Set up input handling support fields. + win2world = new Vector3(0.0f, 0.0f, 0.0f); + touchPointWorldCoords = new Vector2(); + motorButtonsTouched = new boolean[4]; + motorButtonsTouched[0] = false; + motorButtonsTouched[1] = false; + motorButtonsTouched[2] = false; + motorButtonsTouched[3] = false; + + motorButtonsPointers = new int[4]; + motorButtonsPointers[0] = -1; + motorButtonsPointers[1] = -1; + motorButtonsPointers[2] = -1; + motorButtonsPointers[3] = -1; + } + + @Override + public void render(float delta) { + Pixmap temp; + byte[] frame; + Size dimensions = null; + + Gdx.gl.glClearColor(1, 1, 1, 1); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + frame = frameMonitor.getCurrentFrame(); + if(frame != null){ + dimensions = frameMonitor.getFrameDimensions(); + temp = new Pixmap(frame, 0, dimensions.getWidth() * dimensions.getHeight()); + if(videoFrame == null){ + try{ + videoFrame = new Pixmap(getOptimalTextureSize(dimensions.getWidth()), getOptimalTextureSize(dimensions.getHeight()), temp.getFormat()); + }catch(ImageTooBigException e){ + core.toast("Cannot display received frame.\n" + e.getMessage(), true); + Gdx.app.exit(); + return; + } + } + videoFrame.drawPixmap(temp, 0, 0); + temp.dispose(); + videoFrameTexture = new Texture(videoFrame); + videoFrameTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); + + TextureRegion region = new TextureRegion(videoFrameTexture, 0, 0, dimensions.getWidth(), dimensions.getHeight()); + + renderableVideoFrame = new Sprite(region); + renderableVideoFrame.setOrigin(renderableVideoFrame.getWidth() / 2, renderableVideoFrame.getHeight() / 2); + if(!Ouya.runningOnOuya){ + renderableVideoFrame.setSize(1.0f, renderableVideoFrame.getHeight() / renderableVideoFrame.getWidth() ); + renderableVideoFrame.rotate90(true); + renderableVideoFrame.translate(-renderableVideoFrame.getWidth() / 2, 0.5f - renderableVideoFrame.getHeight()); + }else{ + float xSize = Gdx.graphics.getHeight() * (dimensions.getWidth() / dimensions.getHeight()); + renderableVideoFrame.setSize(xSize * ProjectConstants.OVERSCAN, Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN); + renderableVideoFrame.rotate90(true); + renderableVideoFrame.translate(-renderableVideoFrame.getWidth() / 2, -renderableVideoFrame.getHeight() / 2); + } + + if(!Ouya.runningOnOuya){ + core.batch.setProjectionMatrix(camera.combined); + }else{ + core.batch.setProjectionMatrix(pixelPerfectCamera.combined); + } + core.batch.begin();{ + renderableVideoFrame.draw(core.batch); + }core.batch.end(); + + videoFrameTexture.dispose(); + } + + core.batch.setProjectionMatrix(pixelPerfectCamera.combined); + core.batch.begin();{ + if(!Ouya.runningOnOuya){ + motorA.draw(core.batch); + motorB.draw(core.batch); + motorC.draw(core.batch); + motorD.draw(core.batch); + } + }core.batch.end(); + } + + @Override + public void resize(int width, int height) { + // TODO Auto-generated method stub + + } + + @Override + public void show() { + // TODO Auto-generated method stub + + } + + @Override + public void hide() { + // TODO Auto-generated method stub + + } + + @Override + public void pause() { + // TODO Auto-generated method stub + + } + + @Override + public void resume() { + // TODO Auto-generated method stub + + } + + @Override + public void dispose() { + if(videoFrameTexture != null) + videoFrameTexture.dispose(); + if(buttonTexture != null) + buttonTexture.dispose(); + if(videoFrame != null) + videoFrame.dispose(); + } + + private int getOptimalTextureSize(int imageSideLength) throws ImageTooBigException{ + for(int po2: ProjectConstants.POWERS_OF_2){ + if(imageSideLength < po2) return po2; + } + throw new ImageTooBigException("No valid texture size found. Image too large."); + } + + /*;;;;;;;;;;;;;;;;;; + ; HELPER METHODS ; + ;;;;;;;;;;;;;;;;;;*/ + + @Override + public void onStateSet(){ + stateActive = true; + Gdx.input.setInputProcessor(this); + } + + @Override + public void onStateUnset(){ + stateActive = false; + Gdx.input.setInputProcessor(null); + } + + private void setUpButtons(){ + buttonTexture = new Texture(Gdx.files.internal("data/gfx/gui/PBCrichton_Flat_Button.png")); + buttonTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); + + TextureRegion region = new TextureRegion(buttonTexture, 0, 0, buttonTexture.getWidth(), buttonTexture.getHeight()); + + motorA = new Sprite(region); + motorA.setSize(motorA.getWidth() * 0.7f, motorA.getHeight() * 0.7f); + + motorB = new Sprite(region); + motorB.setSize(motorB.getWidth() * 0.7f, motorB.getHeight() * 0.7f); + + motorC = new Sprite(region); + motorC.setSize(motorC.getWidth() * 0.7f, motorC.getHeight() * 0.7f); + + motorD = new Sprite(region); + motorD.setSize(motorD.getWidth() * 0.7f, motorD.getHeight() * 0.7f); + + motorA.setPosition(-(Gdx.graphics.getWidth() / 2) + 10, -(Gdx.graphics.getHeight() / 2) + motorB.getHeight() + 20); + motorB.setPosition(-(Gdx.graphics.getWidth() / 2) + 20 + (motorA.getWidth() / 2), -(Gdx.graphics.getHeight() / 2) + 10); + motorC.setPosition((Gdx.graphics.getWidth() / 2) - (1.5f * (motorD.getWidth())) - 20, -(Gdx.graphics.getHeight() / 2) + 10); + motorD.setPosition((Gdx.graphics.getWidth() / 2) - motorD.getWidth() - 10, -(Gdx.graphics.getHeight() / 2) + 20 + motorC.getHeight()); + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean keyDown(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyUp(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyTyped(char character) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + if(!Ouya.runningOnOuya){ + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); + motorButtonsTouched[0] = true; + motorButtonsPointers[0] = pointer; + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); + motorButtonsTouched[1] = true; + motorButtonsPointers[1] = pointer; + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); + motorButtonsTouched[2] = true; + motorButtonsPointers[2] = pointer; + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); + motorButtonsTouched[3] = true; + motorButtonsPointers[3] = pointer; + } + } + return true; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button) { + if(!Ouya.runningOnOuya){ + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + } + } + return true; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + if(!Ouya.runningOnOuya){ + win2world.set(screenX, screenY, 0.0f); + camera.unproject(win2world); + touchPointWorldCoords.set(win2world.x * Gdx.graphics.getWidth(), win2world.y * Gdx.graphics.getHeight()); + + if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + } + } + return true; + } + + @Override + public boolean mouseMoved(int screenX, int screenY) { + // TODO Auto-generated method stub + return false; + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean buttonDown(Controller controller, int buttonCode) { + if(stateActive){ + Gdx.app.log(TAG, CLASS_NAME + ".buttonDown() :: " + controller.getName() + " :: " + Integer.toString(buttonCode)); + return true; + }else{ + return false; + } + } + + @Override + public boolean buttonUp(Controller controller, int buttonCode) { + if(stateActive){ + Gdx.app.log(TAG, CLASS_NAME + ".buttonDown() :: " + controller.getName() + " :: " + Integer.toString(buttonCode)); + return true; + }else{ + return false; + } + } + + @Override + public boolean axisMoved(Controller controller, int axisCode, float value) { + if(stateActive){ + if(value >= Ouya.STICK_DEADZONE){ + if(axisCode == Ouya.AXIS_LEFT_TRIGGER){ + Gdx.app.log(TAG, CLASS_NAME + ".axisMoved() :: LEFT TRIGGER pressed."); + } + if(axisCode == Ouya.AXIS_RIGHT_TRIGGER){ + Gdx.app.log(TAG, CLASS_NAME + ".axisMoved() :: RIGHT TRIGGER pressed."); + } + } + return true; + }else{ + return false; + } + } + + @Override + public boolean scrolled(int amount) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void connected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public void disconnected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public boolean povMoved(Controller controller, int povCode, + PovDirection value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean xSliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean ySliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean accelerometerMoved(Controller controller, + int accelerometerCode, Vector3 value) { + // TODO Auto-generated method stub + return false; + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java index c64a00e..a6aa5e0 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java @@ -1,139 +1,234 @@ -/* - * Copyright (C) 2014 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.states; - -import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.controllers.Controllers; -import com.badlogic.gdx.controllers.mappings.Ouya; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.Texture; -import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.NinePatch; -import com.badlogic.gdx.graphics.g2d.Sprite; -import com.badlogic.gdx.graphics.g2d.TextureRegion; -import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; -import com.badlogic.gdx.math.Rectangle; -import com.badlogic.gdx.scenes.scene2d.ui.TextButton; -import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle; -import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; - - -public abstract class MainMenuStateBase extends BaseState{ - protected static final String TAG = "MAIN_MENU"; - - // Client connection helper fields. - protected boolean clientConnected; - - // Buttons and other gui components. - protected TextButton startButton; - protected Rectangle startButtonBBox; - protected Sprite clientConnectedLedOn; - protected Sprite clientConnectedLedOff; - - // Graphic data for the start button. - private Texture startButtonEnabledTexture; - private Texture startButtonDisabledTexture; - private Texture startButtonPressedTexture; - private NinePatch startButtonEnabled9p; - private NinePatch startButtonDisabled9p; - private NinePatch startButtonPressed9p; - private BitmapFont font; - - // Other graphics. - private Texture clientConnectedLedOffTexture; - private Texture clientConnectedLedOnTexture; - - public MainMenuStateBase(){ - // Create the start button background. - startButtonEnabledTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Yellow.png")); - startButtonEnabled9p = new NinePatch(new TextureRegion(startButtonEnabledTexture, 0, 0, startButtonEnabledTexture.getWidth(), startButtonEnabledTexture.getHeight()), 49, 49, 45, 45); - - startButtonDisabledTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Cyan.png")); - startButtonDisabled9p = new NinePatch(new TextureRegion(startButtonDisabledTexture, 0, 0, startButtonDisabledTexture.getWidth(), startButtonDisabledTexture.getHeight()), 49, 49, 45, 45); - - startButtonPressedTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Blue.png")); - startButtonPressed9p = new NinePatch(new TextureRegion(startButtonPressedTexture, 0, 0, startButtonPressedTexture.getWidth(), startButtonPressedTexture.getHeight()), 49, 49, 45, 45); - - // Create the start button font. - FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("data/fonts/d-puntillas-B-to-tiptoe.ttf")); - font = generator.generateFont(Ouya.runningOnOuya ? 60 : 40, ProjectConstants.FONT_CHARS, false); - generator.dispose(); - - // Create the start button itself. - TextButtonStyle tbs = new TextButtonStyle(); - tbs.font = font; - tbs.up = new NinePatchDrawable(startButtonEnabled9p); - tbs.checked = new NinePatchDrawable(startButtonPressed9p); - tbs.disabled = new NinePatchDrawable(startButtonDisabled9p); - tbs.disabledFontColor = new Color(0, 0, 0, 1); - startButton = new TextButton("Start server", tbs); - startButton.setText("Start game"); - startButton.setDisabled(true); - startButtonBBox = new Rectangle(0, 0, startButton.getWidth(), startButton.getHeight()); - - // Create the connection leds. - TextureRegion region; - clientConnectedLedOnTexture = new Texture("data/gfx/gui/Anonymous_Button_Green.png"); - region = new TextureRegion(clientConnectedLedOnTexture, clientConnectedLedOnTexture.getWidth(), clientConnectedLedOnTexture.getHeight()); - clientConnectedLedOn = new Sprite(region); - - clientConnectedLedOffTexture = new Texture("data/gfx/gui/Anonymous_Button_Red.png"); - region = new TextureRegion(clientConnectedLedOffTexture, clientConnectedLedOffTexture.getWidth(), clientConnectedLedOffTexture.getHeight()); - clientConnectedLedOff = new Sprite(region); - - clientConnected = false; - } - - @Override - public abstract void render(float delta); - - @Override - public abstract void resize(int width, int height); - - @Override - public abstract void show(); - @Override - public abstract void hide(); - - @Override - public abstract void pause(); - - @Override - public abstract void resume(); - - @Override - public void dispose(){ - startButtonEnabledTexture.dispose(); - startButtonDisabledTexture.dispose(); - startButtonPressedTexture.dispose(); - clientConnectedLedOnTexture.dispose(); - clientConnectedLedOffTexture.dispose(); - font.dispose(); - } - - @Override - public void onStateSet(){ - Controllers.addListener(this); - Gdx.input.setInputProcessor(this); - } - - public void onClientConnected(){ - clientConnected = true; - startButton.setDisabled(false); - } -} +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.controllers.mappings.Ouya; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.NinePatch; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; +import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle; +import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; + + +public abstract class MainMenuStateBase extends BaseState{ + protected static final String TAG = "MAIN_MENU"; + + // Client connection helper fields. + protected boolean clientConnected; + + // Buttons and other gui components. + protected TextButton startButton; + protected Rectangle startButtonBBox; + protected Sprite clientConnectedLedOn; + protected Sprite clientConnectedLedOff; + + // Graphic data for the start button. + private Texture startButtonEnabledTexture; + private Texture startButtonDisabledTexture; + private Texture startButtonPressedTexture; + private NinePatch startButtonEnabled9p; + private NinePatch startButtonDisabled9p; + private NinePatch startButtonPressed9p; + private BitmapFont font; + + // Other graphics. + private Texture clientConnectedLedOffTexture; + private Texture clientConnectedLedOnTexture; + + public MainMenuStateBase(){ + // Create the start button background. + startButtonEnabledTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Yellow.png")); + startButtonEnabled9p = new NinePatch(new TextureRegion(startButtonEnabledTexture, 0, 0, startButtonEnabledTexture.getWidth(), startButtonEnabledTexture.getHeight()), 49, 49, 45, 45); + + startButtonDisabledTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Cyan.png")); + startButtonDisabled9p = new NinePatch(new TextureRegion(startButtonDisabledTexture, 0, 0, startButtonDisabledTexture.getWidth(), startButtonDisabledTexture.getHeight()), 49, 49, 45, 45); + + startButtonPressedTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Blue.png")); + startButtonPressed9p = new NinePatch(new TextureRegion(startButtonPressedTexture, 0, 0, startButtonPressedTexture.getWidth(), startButtonPressedTexture.getHeight()), 49, 49, 45, 45); + + // Create the start button font. + FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("data/fonts/d-puntillas-B-to-tiptoe.ttf")); + font = generator.generateFont(Ouya.runningOnOuya ? 60 : 40, ProjectConstants.FONT_CHARS, false); + generator.dispose(); + + // Create the start button itself. + TextButtonStyle tbs = new TextButtonStyle(); + tbs.font = font; + tbs.up = new NinePatchDrawable(startButtonEnabled9p); + tbs.checked = new NinePatchDrawable(startButtonPressed9p); + tbs.disabled = new NinePatchDrawable(startButtonDisabled9p); + tbs.disabledFontColor = new Color(0, 0, 0, 1); + startButton = new TextButton("Start server", tbs); + startButton.setText("Start game"); + startButton.setDisabled(true); + startButtonBBox = new Rectangle(0, 0, startButton.getWidth(), startButton.getHeight()); + + // Create the connection leds. + TextureRegion region; + clientConnectedLedOnTexture = new Texture("data/gfx/gui/Anonymous_Button_Green.png"); + region = new TextureRegion(clientConnectedLedOnTexture, clientConnectedLedOnTexture.getWidth(), clientConnectedLedOnTexture.getHeight()); + clientConnectedLedOn = new Sprite(region); + + clientConnectedLedOffTexture = new Texture("data/gfx/gui/Anonymous_Button_Red.png"); + region = new TextureRegion(clientConnectedLedOffTexture, clientConnectedLedOffTexture.getWidth(), clientConnectedLedOffTexture.getHeight()); + clientConnectedLedOff = new Sprite(region); + + clientConnected = false; + + stateActive = false; + } + + @Override + public abstract void render(float delta); + + @Override + public abstract void resize(int width, int height); + + @Override + public abstract void show(); + @Override + public abstract void hide(); + + @Override + public abstract void pause(); + + @Override + public abstract void resume(); + + @Override + public void dispose(){ + startButtonEnabledTexture.dispose(); + startButtonDisabledTexture.dispose(); + startButtonPressedTexture.dispose(); + clientConnectedLedOnTexture.dispose(); + clientConnectedLedOffTexture.dispose(); + font.dispose(); + } + + @Override + public void onStateSet(){ + stateActive = true; + Gdx.input.setInputProcessor(this); + } + + @Override + public void onStateUnset(){ + stateActive = false; + Gdx.input.setInputProcessor(null); + } + + public void onClientConnected(){ + clientConnected = true; + startButton.setDisabled(false); + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; INPUT LISTENER METHOD STUBS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @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){ + return false; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button){ + return false; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer){ + return false; + } + + @Override + public boolean mouseMoved(int screenX, int screenY){ + return false; + } + + @Override + public boolean scrolled(int amount){ + return false; + } + + @Override + public void connected(Controller controller){ } + + @Override + public void disconnected(Controller controller){ } + + @Override + public boolean buttonDown(Controller controller, int buttonCode){ + return false; + } + + @Override + public boolean buttonUp(Controller controller, int buttonCode){ + return false; + } + + @Override + public boolean axisMoved(Controller controller, int axisCode, float value){ + return false; + } + + @Override + public boolean povMoved(Controller controller, int povCode, PovDirection value){ + return false; + } + + @Override + public boolean xSliderMoved(Controller controller, int sliderCode, boolean value){ + return false; + } + + @Override + public boolean ySliderMoved(Controller controller, int sliderCode, boolean value){ + return false; + } + + @Override + public boolean accelerometerMoved(Controller controller, int accelerometerCode, Vector3 value){ + return false; + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java index 1cd4fc3..dd53b98 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java @@ -1,204 +1,155 @@ -/* - * Copyright (C) 2014 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.states; - -import ve.ucv.ciens.ccg.nxtar.NxtARCore; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.controllers.Controller; -import com.badlogic.gdx.controllers.Controllers; -import com.badlogic.gdx.controllers.PovDirection; -import com.badlogic.gdx.graphics.GL10; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.math.Vector3; - -public class OuyaMainMenuState extends MainMenuStateBase{ - private OrthographicCamera pixelPerfectCamera; - - public OuyaMainMenuState(final NxtARCore core){ - this.core = core; - this.pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); - } - - @Override - public void render(float delta) { - Gdx.gl.glClearColor(1, 1, 1, 1); - Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); - - core.batch.setProjectionMatrix(pixelPerfectCamera.combined); - core.batch.begin();{ - this.startButton.draw(core.batch, 1.0f); - }core.batch.end(); - } - - @Override - public void resize(int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void show() { - // TODO Auto-generated method stub - - } - - @Override - public void hide() { - // TODO Auto-generated method stub - - } - - @Override - public void pause() { - // TODO Auto-generated method stub - - } - - @Override - public void resume() { - // TODO Auto-generated method stub - - } - - @Override - public void dispose(){ - super.dispose(); - } - - /*;;;;;;;;;;;;;;;;;; - ; HELPER METHODS ; - ;;;;;;;;;;;;;;;;;;*/ - - @Override - public void onStateSet(){ - super.onStateSet(); - } - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; BEGIN INPUT PROCESSOR METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - @Override - public boolean keyDown(int keycode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean keyUp(int keycode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean keyTyped(char character) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean touchDragged(int screenX, int screenY, int pointer) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean mouseMoved(int screenX, int screenY) { - // TODO Auto-generated method stub - return false; - } - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; BEGIN CONTROLLER LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - @Override - public boolean scrolled(int amount) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void connected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public void disconnected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public boolean buttonDown(Controller controller, int buttonCode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean buttonUp(Controller controller, int buttonCode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean axisMoved(Controller controller, int axisCode, float value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean povMoved(Controller controller, int povCode, - PovDirection value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean xSliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean ySliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean accelerometerMoved(Controller controller, - int accelerometerCode, Vector3 value) { - // TODO Auto-generated method stub - return false; - } -} +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.NxtARCore; +import ve.ucv.ciens.ccg.nxtar.NxtARCore.game_states_t; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.mappings.Ouya; +import com.badlogic.gdx.graphics.GL10; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.TextureRegion; + +public class OuyaMainMenuState extends MainMenuStateBase{ + private static final String CLASS_NAME = OuyaMainMenuState.class.getSimpleName(); + + private OrthographicCamera pixelPerfectCamera; + private Texture ouyaOButtonTexture; + private Sprite ouyaOButton; + private boolean oButtonPressed; + + public OuyaMainMenuState(final NxtARCore core){ + this.core = core; + this.pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + + startButton.setPosition(-(startButton.getWidth() / 2), -(startButton.getHeight() / 2)); + startButtonBBox.setPosition(startButton.getX(), startButton.getY()); + + float ledYPos = (-(Gdx.graphics.getHeight() / 2) * 0.5f) + (startButton.getY() * 0.5f); + clientConnectedLedOn.setSize(clientConnectedLedOn.getWidth() * 0.5f, clientConnectedLedOn.getHeight() * 0.5f); + clientConnectedLedOn.setPosition(-(clientConnectedLedOn.getWidth() / 2), ledYPos); + + clientConnectedLedOff.setSize(clientConnectedLedOff.getWidth() * 0.5f, clientConnectedLedOff.getHeight() * 0.5f); + clientConnectedLedOff.setPosition(-(clientConnectedLedOff.getWidth() / 2), ledYPos); + + ouyaOButtonTexture = new Texture("data/gfx/gui/OUYA_O.png"); + TextureRegion region = new TextureRegion(ouyaOButtonTexture, ouyaOButtonTexture.getWidth(), ouyaOButtonTexture.getHeight()); + ouyaOButton = new Sprite(region); + ouyaOButton.setSize(ouyaOButton.getWidth() * 0.6f, ouyaOButton.getHeight() * 0.6f); + ouyaOButton.setPosition(startButton.getX() - ouyaOButton.getWidth() - 20, startButton.getY()); + + oButtonPressed = false; + } + + @Override + public void render(float delta) { + Gdx.gl.glClearColor(1, 1, 1, 1); + Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); + + core.batch.setProjectionMatrix(pixelPerfectCamera.combined); + core.batch.begin();{ + if(clientConnected){ + clientConnectedLedOn.draw(core.batch); + }else{ + clientConnectedLedOff.draw(core.batch); + } + startButton.draw(core.batch, 1.0f); + ouyaOButton.draw(core.batch); + }core.batch.end(); + } + + @Override + public void resize(int width, int height) { + // TODO Auto-generated method stub + + } + + @Override + public void show() { + // TODO Auto-generated method stub + + } + + @Override + public void hide() { + // TODO Auto-generated method stub + + } + + @Override + public void pause() { + // TODO Auto-generated method stub + + } + + @Override + public void resume() { + // TODO Auto-generated method stub + + } + + @Override + public void dispose(){ + super.dispose(); + ouyaOButtonTexture.dispose(); + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean buttonDown(Controller controller, int buttonCode) { + if(stateActive){ + if(buttonCode == Ouya.BUTTON_O){ + if(!clientConnected){ + core.toast("Can't start the game. No client is connected.", true); + }else{ + oButtonPressed = true; + startButton.setChecked(true); + } + } + + return true; + + }else{ + return false; + } + } + + @Override + public boolean buttonUp(Controller controller, int buttonCode) { + if(stateActive){ + if(buttonCode == Ouya.BUTTON_O){ + if(oButtonPressed){ + oButtonPressed = false; + startButton.setChecked(false); + core.nextState = game_states_t.IN_GAME; + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button released."); + } + } + + return true; + + }else{ + return false; + } + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java b/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java index 36f02d8..4b95ffc 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java @@ -1,198 +1,204 @@ -/* - * Copyright (C) 2014 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.states; - -import ve.ucv.ciens.ccg.nxtar.NxtARCore; - -import com.badlogic.gdx.controllers.Controller; -import com.badlogic.gdx.controllers.PovDirection; -import com.badlogic.gdx.math.Vector3; - -public class PauseState extends BaseState { - - public PauseState(final NxtARCore core){ - this.core = core; - } - - @Override - public void render(float delta) { - // TODO Auto-generated method stub - - } - - @Override - public void resize(int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void show() { - // TODO Auto-generated method stub - - } - - @Override - public void hide() { - // TODO Auto-generated method stub - - } - - @Override - public void pause() { - // TODO Auto-generated method stub - - } - - @Override - public void resume() { - // TODO Auto-generated method stub - - } - - @Override - public void dispose() { - // TODO Auto-generated method stub - - } - - /*;;;;;;;;;;;;;;;;;; - ; HELPER METHODS ; - ;;;;;;;;;;;;;;;;;;*/ - - @Override - public void onStateSet(){ - } - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; BEGIN INPUT PROCESSOR METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - @Override - public boolean keyDown(int keycode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean keyUp(int keycode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean keyTyped(char character) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean touchDragged(int screenX, int screenY, int pointer) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean mouseMoved(int screenX, int screenY) { - // TODO Auto-generated method stub - return false; - } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; END INPUT PROCESSOR METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; BEGIN CONTROLLER LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - @Override - public boolean scrolled(int amount) { - // TODO Auto-generated method stub - return false; - } - - @Override - public void connected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public void disconnected(Controller controller) { - // TODO Auto-generated method stub - - } - - @Override - public boolean buttonDown(Controller controller, int buttonCode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean buttonUp(Controller controller, int buttonCode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean axisMoved(Controller controller, int axisCode, float value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean povMoved(Controller controller, int povCode, - PovDirection value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean xSliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean ySliderMoved(Controller controller, int sliderCode, - boolean value) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean accelerometerMoved(Controller controller, - int accelerometerCode, Vector3 value) { - // TODO Auto-generated method stub - return false; - } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; END CONTROLLER LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ -} +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.NxtARCore; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.controllers.Controller; +import com.badlogic.gdx.controllers.Controllers; +import com.badlogic.gdx.controllers.PovDirection; +import com.badlogic.gdx.math.Vector3; + +public class PauseState extends BaseState { + + public PauseState(final NxtARCore core){ + this.core = core; + } + + @Override + public void render(float delta) { + // TODO Auto-generated method stub + + } + + @Override + public void resize(int width, int height) { + // TODO Auto-generated method stub + + } + + @Override + public void show() { + // TODO Auto-generated method stub + + } + + @Override + public void hide() { + // TODO Auto-generated method stub + + } + + @Override + public void pause() { + // TODO Auto-generated method stub + + } + + @Override + public void resume() { + // TODO Auto-generated method stub + + } + + @Override + public void dispose() { + // TODO Auto-generated method stub + + } + + /*;;;;;;;;;;;;;;;;;; + ; HELPER METHODS ; + ;;;;;;;;;;;;;;;;;;*/ + + @Override + public void onStateSet(){ + } + + @Override + public void onStateUnset(){ + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean keyDown(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyUp(int keycode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean keyTyped(char character) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean mouseMoved(int screenX, int screenY) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END INPUT PROCESSOR METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; BEGIN CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + @Override + public boolean scrolled(int amount) { + // TODO Auto-generated method stub + return false; + } + + @Override + public void connected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public void disconnected(Controller controller) { + // TODO Auto-generated method stub + + } + + @Override + public boolean buttonDown(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean buttonUp(Controller controller, int buttonCode) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean axisMoved(Controller controller, int axisCode, float value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean povMoved(Controller controller, int povCode, + PovDirection value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean xSliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean ySliderMoved(Controller controller, int sliderCode, + boolean value) { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean accelerometerMoved(Controller controller, + int accelerometerCode, Vector3 value) { + // TODO Auto-generated method stub + return false; + } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; END CONTROLLER LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java index 6897560..6565ffc 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java @@ -1,250 +1,156 @@ -/* - * Copyright (C) 2014 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.states; - -import ve.ucv.ciens.ccg.nxtar.NxtARCore; -import ve.ucv.ciens.ccg.nxtar.NxtARCore.game_states_t; - -import com.badlogic.gdx.Gdx; -import com.badlogic.gdx.controllers.Controller; -import com.badlogic.gdx.controllers.PovDirection; -import com.badlogic.gdx.graphics.GL10; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.math.Vector3; - -public class TabletMainMenuState extends MainMenuStateBase{ - protected static final String CLASS_NAME = TabletMainMenuState.class.getSimpleName(); - - private OrthographicCamera pixelPerfectCamera; - - // Button touch helper fields. - private Vector3 win2world; - private Vector2 touchPointWorldCoords; - private boolean startButtonTouched; - private int startButtonTouchPointer; - - public TabletMainMenuState(final NxtARCore core){ - this.core = core; - pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); - startButton.setPosition(-(startButton.getWidth() / 2), -(startButton.getHeight() / 2)); - startButtonBBox.setPosition(startButton.getX(), startButton.getY()); - - win2world = new Vector3(0.0f, 0.0f, 0.0f); - touchPointWorldCoords = new Vector2(); - - startButtonTouched = false; - startButtonTouchPointer = -1; - - float ledYPos = (-(Gdx.graphics.getHeight() / 2) * 0.5f) + (startButton.getY() * 0.5f); - clientConnectedLedOn.setSize(clientConnectedLedOn.getWidth() * 0.5f, clientConnectedLedOn.getHeight() * 0.5f); - clientConnectedLedOn.setPosition(-(clientConnectedLedOn.getWidth() / 2), ledYPos); - - clientConnectedLedOff.setSize(clientConnectedLedOff.getWidth() * 0.5f, clientConnectedLedOff.getHeight() * 0.5f); - clientConnectedLedOff.setPosition(-(clientConnectedLedOff.getWidth() / 2), ledYPos); - } - - @Override - public void render(float delta){ - Gdx.gl.glClearColor(1, 1, 1, 1); - Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); - - core.batch.setProjectionMatrix(pixelPerfectCamera.combined); - core.batch.begin();{ - if(clientConnected){ - clientConnectedLedOn.draw(core.batch); - }else{ - clientConnectedLedOff.draw(core.batch); - } - startButton.draw(core.batch, 1.0f); - }core.batch.end(); - } - - @Override - public void resize(int width, int height){ } - - @Override - public void show(){ } - - @Override - public void hide(){ } - - @Override - public void pause(){ } - - @Override - public void resume(){ } - - @Override - public void dispose(){ - super.dispose(); - } - - /*;;;;;;;;;;;;;;;;;; - ; HELPER METHODS ; - ;;;;;;;;;;;;;;;;;;*/ - - @Override - public void onStateSet(){ - super.onStateSet(); - } - - private void unprojectTouch(int screenX, int screenY){ - win2world.set(screenX, screenY, 0.0f); - pixelPerfectCamera.unproject(win2world); - touchPointWorldCoords.set(win2world.x, win2world.y); - } - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; INPUT PROCESSOR METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button){ - unprojectTouch(screenX, screenY); - - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - - if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ - startButton.setChecked(true); - startButtonTouched = true; - startButtonTouchPointer = pointer; - core.nextState = game_states_t.IN_GAME; - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button pressed."); - } - - return true; - } - - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button){ - unprojectTouch(screenX, screenY); - - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - - if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ - startButton.setChecked(false); - startButtonTouched = false; - startButtonTouchPointer = -1; - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button released."); - } - - return true; - } - - @Override - public boolean touchDragged(int screenX, int screenY, int pointer){ - unprojectTouch(screenX, screenY); - - if(!startButton.isDisabled() && startButtonTouched && pointer == startButtonTouchPointer && !startButtonBBox.contains(touchPointWorldCoords)){ - startButtonTouchPointer = -1; - startButtonTouched = false; - startButton.setChecked(false); - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Start button released."); - } - - return true; - } - - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; UNUSED CONTROLLER LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - @Override - public boolean keyDown(int keycode){ - // Unused. - return false; - } - - @Override - public boolean keyUp(int keycode){ - // Unused. - return false; - } - - @Override - public boolean keyTyped(char character){ - // Unused. - return false; - } - - @Override - public boolean mouseMoved(int screenX, int screenY){ - // Unused. - return false; - } - - @Override - public boolean scrolled(int amount){ - // Unused. - return false; - } - - @Override - public void connected(Controller controller){ - // Unused. - } - - @Override - public void disconnected(Controller controller){ - // Unused. - } - - @Override - public boolean buttonDown(Controller controller, int buttonCode){ - // Unused. - return false; - } - - @Override - public boolean buttonUp(Controller controller, int buttonCode){ - // Unused. - return false; - } - - @Override - public boolean axisMoved(Controller controller, int axisCode, float value){ - // Unused. - return false; - } - - @Override - public boolean povMoved(Controller controller, int povCode, PovDirection value){ - // Unused. - return false; - } - - @Override - public boolean xSliderMoved(Controller controller, int sliderCode, boolean value){ - // Unused. - return false; - } - - @Override - public boolean ySliderMoved(Controller controller, int sliderCode, boolean value){ - // Unused. - return false; - } - - @Override - public boolean accelerometerMoved(Controller controller, int accelerometerCode, Vector3 value){ - // Unused. - return false; - } -} +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.states; + +import ve.ucv.ciens.ccg.nxtar.NxtARCore; +import ve.ucv.ciens.ccg.nxtar.NxtARCore.game_states_t; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.GL10; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.math.Vector3; + +public class TabletMainMenuState extends MainMenuStateBase{ + private static final String CLASS_NAME = TabletMainMenuState.class.getSimpleName(); + + private OrthographicCamera pixelPerfectCamera; + + // Button touch helper fields. + private Vector3 win2world; + private Vector2 touchPointWorldCoords; + private boolean startButtonTouched; + private int startButtonTouchPointer; + + public TabletMainMenuState(final NxtARCore core){ + this.core = core; + pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + startButton.setPosition(-(startButton.getWidth() / 2), -(startButton.getHeight() / 2)); + startButtonBBox.setPosition(startButton.getX(), startButton.getY()); + + win2world = new Vector3(0.0f, 0.0f, 0.0f); + touchPointWorldCoords = new Vector2(); + + startButtonTouched = false; + startButtonTouchPointer = -1; + + float ledYPos = (-(Gdx.graphics.getHeight() / 2) * 0.5f) + (startButton.getY() * 0.5f); + clientConnectedLedOn.setSize(clientConnectedLedOn.getWidth() * 0.5f, clientConnectedLedOn.getHeight() * 0.5f); + clientConnectedLedOn.setPosition(-(clientConnectedLedOn.getWidth() / 2), ledYPos); + + clientConnectedLedOff.setSize(clientConnectedLedOff.getWidth() * 0.5f, clientConnectedLedOff.getHeight() * 0.5f); + clientConnectedLedOff.setPosition(-(clientConnectedLedOff.getWidth() / 2), ledYPos); + } + + @Override + public void render(float delta){ + Gdx.gl.glClearColor(1, 1, 1, 1); + Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT); + + core.batch.setProjectionMatrix(pixelPerfectCamera.combined); + core.batch.begin();{ + if(clientConnected){ + clientConnectedLedOn.draw(core.batch); + }else{ + clientConnectedLedOff.draw(core.batch); + } + startButton.draw(core.batch, 1.0f); + }core.batch.end(); + } + + @Override + public void resize(int width, int height){ } + + @Override + public void show(){ } + + @Override + public void hide(){ } + + @Override + public void pause(){ } + + @Override + public void resume(){ } + + @Override + public void dispose(){ + super.dispose(); + } + + /*;;;;;;;;;;;;;;;;;; + ; HELPER METHODS ; + ;;;;;;;;;;;;;;;;;;*/ + + private void unprojectTouch(int screenX, int screenY){ + win2world.set(screenX, screenY, 0.0f); + pixelPerfectCamera.unproject(win2world); + touchPointWorldCoords.set(win2world.x, win2world.y); + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; INPUT LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button){ + unprojectTouch(screenX, screenY); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ + startButton.setChecked(true); + startButtonTouched = true; + startButtonTouchPointer = pointer; + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button pressed."); + } + + return true; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button){ + unprojectTouch(screenX, screenY); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ + startButton.setChecked(false); + startButtonTouched = false; + startButtonTouchPointer = -1; + core.nextState = game_states_t.IN_GAME; + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button released."); + } + + return true; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer){ + unprojectTouch(screenX, screenY); + + if(!startButton.isDisabled() && startButtonTouched && pointer == startButtonTouchPointer && !startButtonBBox.contains(touchPointWorldCoords)){ + startButtonTouchPointer = -1; + startButtonTouched = false; + startButton.setChecked(false); + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Start button released."); + } + + return true; + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java index 8a0f8f4..e0d15ab 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java +++ b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java @@ -31,7 +31,7 @@ public abstract class ProjectConstants { public static final float OVERSCAN; - public static final String FONT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.,:;!¡?¿"; + public static final String FONT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.,:;!?"; static{ OVERSCAN = Ouya.runningOnOuya ? 0.9f : 1.0f; From be1a392c4a4b876c8d52ddc2f454ba1f7e089f0f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Feb 2014 14:10:10 -0430 Subject: [PATCH 13/16] Basic main menu finished. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 4 +- .../ccg/nxtar/network/SensorReportThread.java | 36 +++ .../nxtar/network/VideoStreamingThread.java | 241 +----------------- .../{ => monitors}/VideoFrameMonitor.java | 4 +- .../ciens/ccg/nxtar/states/InGameState.java | 63 ++++- .../ccg/nxtar/states/MainMenuStateBase.java | 61 ++++- .../ccg/nxtar/states/OuyaMainMenuState.java | 1 + .../ciens/ccg/nxtar/states/PauseState.java | 2 - .../ccg/nxtar/states/TabletMainMenuState.java | 1 + 9 files changed, 156 insertions(+), 257 deletions(-) create mode 100644 src/ve/ucv/ciens/ccg/nxtar/network/SensorReportThread.java rename src/ve/ucv/ciens/ccg/nxtar/network/{ => monitors}/VideoFrameMonitor.java (97%) diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index c7d65b9..45435fe 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -175,8 +175,8 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ Controllers.addListener(states[currState.getValue()]); // Anything else. - Gdx.app.setLogLevel(Application.LOG_INFO); - // Gdx.app.setLogLevel(Application.LOG_NONE); + //Gdx.app.setLogLevel(Application.LOG_DEBUG); + Gdx.app.setLogLevel(Application.LOG_NONE); } public void render(){ diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/SensorReportThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/SensorReportThread.java new file mode 100644 index 0000000..d6d935e --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtar/network/SensorReportThread.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.network; + +public class SensorReportThread extends Thread { + + private SensorReportThread(){ + + } + + private static class SingletonHolder{ + public final static SensorReportThread INSTANCE = new SensorReportThread(); + } + + public static SensorReportThread getInstance(){ + return SingletonHolder.INSTANCE; + } + + @Override + public void run(){ + + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java index 2e7af9d..df9d6c0 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java @@ -24,6 +24,7 @@ import java.net.Socket; import ve.ucv.ciens.ccg.networkdata.VideoFrameDataMessage; import ve.ucv.ciens.ccg.nxtar.interfaces.NetworkConnectionListener; +import ve.ucv.ciens.ccg.nxtar.network.monitors.VideoFrameMonitor; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import com.badlogic.gdx.Gdx; @@ -33,23 +34,14 @@ public class VideoStreamingThread extends Thread { private static final String TAG = "NXTAR_CORE_VIDEOTHREAD"; private static final String CLASS_NAME = VideoStreamingThread.class.getSimpleName(); - //private enum ProtocolState_t {WAIT_FOR_START, SEND_CONTINUE, RECEIVE_DATA, SEND_ACK_NEXT, SEND_ACK_WAIT, PAUSED, END_STREAM}; - private NetworkConnectionListener netListener; - //private ServerSocket server; private DatagramSocket socket; - //private Toaster toaster; - //private ProtocolState_t protocolState; private boolean protocolStarted; - /*private boolean pauseProtocol; - private boolean endProtocol;*/ private boolean done; private boolean pause; private boolean coreNotified; private Object protocolPauseMonitor; private Socket client; - //private ObjectInputStream reader; - //private ObjectOutputStream writer; private VideoFrameMonitor frameMonitor; private long then; private long now; @@ -66,18 +58,13 @@ public class VideoStreamingThread extends Thread { fps = 0; lostFramesPerSecond = 0; netListener = null; - //toaster = null; protocolStarted = false; - /*endProtocol = false; - pauseProtocol = false;*/ done = false; coreNotified = false; - //protocolState = ProtocolState_t.WAIT_FOR_START; protocolPauseMonitor = new Object(); frameMonitor = VideoFrameMonitor.getInstance(); try{ - //server = new ServerSocket(ProjectConstants.SERVER_TCP_PORT_1); socket = new DatagramSocket(ProjectConstants.SERVER_TCP_PORT_1); }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".VideoStreamingThread() :: Error creating server: " + io.getMessage(), io); @@ -92,26 +79,15 @@ public class VideoStreamingThread extends Thread { return SingletonHolder.INSTANCE; } - /*public VideoStreamingThread setToaster(Toaster toaster){ - this.toaster = toaster; - return this; - }*/ - public void addNetworkConnectionListener(NetworkConnectionListener listener){ netListener = listener; } - /*private void toast(String message){ - if(toaster != null) - toaster.showShortToast(message); - }*/ - public void startStreaming(){ if(!protocolStarted){ Gdx.app.debug(TAG, CLASS_NAME + ".startStreaming() :: Requesting protocol start."); synchronized(protocolPauseMonitor){ protocolStarted = true; - //protocolState = ProtocolState_t.SEND_CONTINUE; protocolPauseMonitor.notifyAll(); } } @@ -120,7 +96,6 @@ public class VideoStreamingThread extends Thread { public void pauseStreaming(){ if(protocolStarted){ Gdx.app.debug(TAG, CLASS_NAME + ".pauseStreaming() :: Requesting protocol pause."); - //pauseProtocol = true; }else return; } @@ -129,7 +104,6 @@ public class VideoStreamingThread extends Thread { if(protocolStarted){ Gdx.app.debug(TAG, CLASS_NAME + ".resumeStreaming() :: Requesting protocol resume."); synchronized(protocolPauseMonitor){ - //pauseProtocol = false; protocolPauseMonitor.notifyAll(); } }else @@ -139,7 +113,6 @@ public class VideoStreamingThread extends Thread { public void finishStreaming(){ if(protocolStarted){ Gdx.app.debug(TAG, CLASS_NAME + ".finishStreaming() :: Requesting protocol end."); - //endProtocol = true; }else return; } @@ -148,202 +121,6 @@ public class VideoStreamingThread extends Thread { done = true; } - /*@Override - public void run(){ - Object tmpMessage; - VideoStreamingControlMessage controlMessage; - VideoFrameDataMessage dataMessage; - - // Listen on the server socket until a client successfully connects. - do{ - try{ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Listening for client."); - client = server.accept(); - if(netListener != null) - netListener.networkStreamConnected(THREAD_NAME); - writer = new ObjectOutputStream(client.getOutputStream()); - reader = new ObjectInputStream(client.getInputStream()); - toast("Client connected"); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error accepting client: " + io.getMessage(), io); - client = null; - } - }while(client != null && !client.isConnected()); - - while(!done){ - switch(protocolState){ - case WAIT_FOR_START: - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: State is WAIT_FOR_START."); - // If the app has not started the protocol then wait. - synchronized(protocolPauseMonitor){ - while(!protocolStarted){ - try{ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Protocol has not started, waiting."); - protocolPauseMonitor.wait(); - }catch(InterruptedException ie){ } - } - } - break; - - case SEND_CONTINUE: - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: State is SEND_CONTINUE."); - // Prepare the message. - controlMessage = new VideoStreamingControlMessage(); - if(!endProtocol){ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Preparing STREAM_CONTROL_END message."); - controlMessage.message = VideoStreamingProtocol.STREAM_CONTROL_END; - }else{ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Preparing FLOW_CONTROL_CONTINUE message."); - controlMessage.message = VideoStreamingProtocol.FLOW_CONTROL_CONTINUE; - } - - // Send it! - try{ - writer.writeObject(controlMessage); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error sending message: " + io.getMessage(), io); - }finally{ - protocolState = ProtocolState_t.RECEIVE_DATA; - } - break; - - case RECEIVE_DATA: - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: State is RECEIVE_DATA."); - - try{ - tmpMessage = reader.readObject(); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: IOException while receiving message: " + io.getMessage(), io); - break; - }catch(ClassNotFoundException cn){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: ClassNotFoundException while receiving message: " + cn.getMessage(), cn); - break; - } - - if(tmpMessage instanceof VideoStreamingControlMessage){ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Received a control message."); - controlMessage = (VideoStreamingControlMessage) tmpMessage; - // TODO: handle this case correctly. - - }else if(tmpMessage instanceof VideoFrameDataMessage){ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Received a data message."); - dataMessage = (VideoFrameDataMessage) tmpMessage; - - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Received frame dimensions are: " + - Integer.toString(dataMessage.imageWidth) + "x" + Integer.toString(dataMessage.imageHeight)); - frameMonitor.setFrameDimensions(dataMessage.imageWidth, dataMessage.imageHeight); - frameMonitor.setNewFrame(dataMessage.data); - - if(pauseProtocol) - protocolState = ProtocolState_t.SEND_ACK_WAIT; - else - protocolState = ProtocolState_t.SEND_ACK_NEXT; - - }else{ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: Unrecognized message received!."); - // TODO: handle this case correctly. - System.exit(ProjectConstants.EXIT_FAILURE); - } - - break; - - case SEND_ACK_NEXT: - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: State is SEND_ACK_NEXT."); - // Prepare the message. - controlMessage = new VideoStreamingControlMessage(); - if(!endProtocol){ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Preparing STREAM_CONTROL_END message."); - controlMessage.message = VideoStreamingProtocol.STREAM_CONTROL_END; - }else{ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Preparing ACK_SEND_NEXT message."); - controlMessage.message = VideoStreamingProtocol.ACK_SEND_NEXT; - } - - // Send it! - try{ - writer.writeObject(controlMessage); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error sending message: " + io.getMessage(), io); - }finally{ - if(!endProtocol) - protocolState = ProtocolState_t.RECEIVE_DATA; - else - protocolState = ProtocolState_t.END_STREAM; - } - break; - - case SEND_ACK_WAIT: - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: State is SEND_ACK_WAIT."); - // Prepare the message. - controlMessage = new VideoStreamingControlMessage(); - controlMessage.message = VideoStreamingProtocol.ACK_WAIT; - - // Send it! - try{ - writer.writeObject(controlMessage); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error sending message: " + io.getMessage(), io); - }finally{ - protocolState = ProtocolState_t.PAUSED; - } - break; - - case PAUSED: - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: State is PAUSED."); - // The app requested to stop the protocol temporarily. - synchronized(protocolPauseMonitor){ - while(pauseProtocol){ - try{ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Protocol pause requested, waiting."); - protocolPauseMonitor.wait(); - }catch(InterruptedException ie){ } - } - } - protocolState = ProtocolState_t.SEND_CONTINUE; - break; - - case END_STREAM: - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: State is END_STREAM."); - // Simply disconnect from the client and end the thread. - try{ - client.close(); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error closing client: " + io.getMessage(), io); - } - done = true; - break; - } - } - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Thread finished."); - }*/ - - /*private void receiveImage(){ - Object tmpMessage; - VideoFrameDataMessage dataMessage; - - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Receiving data."); - - try{ - tmpMessage = (VideoFrameDataMessage)reader.readObject(); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: IOException while receiving message: " + io.getMessage()); - return; - }catch(ClassNotFoundException cn){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: ClassNotFoundException while receiving message: " + cn.getMessage()); - return; - } - - if(tmpMessage instanceof VideoFrameDataMessage){ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Received a data message."); - dataMessage = (VideoFrameDataMessage) tmpMessage; - frameMonitor.setFrameDimensions(dataMessage.imageWidth, dataMessage.imageHeight); - frameMonitor.setNewFrame(dataMessage.data); - - }else{ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Received something unknown."); - } - }*/ - private int byteArray2Int(byte[] array){ int number = 0; for(int i = 0; i < 4; i++){ @@ -433,22 +210,6 @@ public class VideoStreamingThread extends Thread { public void run(){ int frames = 0; lostFrames = 0; - // Listen on the server socket until a client successfully connects. - /*do{ - try{ - Gdx.app.debug(TAG, CLASS_NAME + ".run() :: Listening for client."); - client = server.accept(); - if(netListener != null) - netListener.networkStreamConnected(THREAD_NAME); - //writer = new ObjectOutputStream(client.getOutputStream()); - reader = new ObjectInputStream(client.getInputStream()); - toast("Client connected"); - }catch(IOException io){ - Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error accepting client: " + io.getMessage(), io); - client = null; - } - }while(client != null && !client.isConnected());*/ - then = System.currentTimeMillis(); while(!done){ diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoFrameMonitor.java b/src/ve/ucv/ciens/ccg/nxtar/network/monitors/VideoFrameMonitor.java similarity index 97% rename from src/ve/ucv/ciens/ccg/nxtar/network/VideoFrameMonitor.java rename to src/ve/ucv/ciens/ccg/nxtar/network/monitors/VideoFrameMonitor.java index 939cea0..a0902ec 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoFrameMonitor.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/monitors/VideoFrameMonitor.java @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package ve.ucv.ciens.ccg.nxtar.network; +package ve.ucv.ciens.ccg.nxtar.network.monitors; import ve.ucv.ciens.ccg.nxtar.utils.Size; @@ -63,9 +63,9 @@ public class VideoFrameMonitor{ Gdx.app.debug(TAG, CLASS_NAME + ".setNewFrame() :: Loading new frame in frameA."); frameA = frame; + temp = frameA; synchronized(frameMonitor){ Gdx.app.debug(TAG, CLASS_NAME + ".setNewFrame() :: Swapping frameA and frameB."); - temp = frameA; frameA = frameB; frameB = temp; Gdx.app.debug(TAG, CLASS_NAME + ".setNewFrame() :: Swapping done."); diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java index 502d275..96371bb 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java @@ -15,15 +15,17 @@ */ package ve.ucv.ciens.ccg.nxtar.states; +import java.util.Arrays; + import ve.ucv.ciens.ccg.nxtar.NxtARCore; import ve.ucv.ciens.ccg.nxtar.exceptions.ImageTooBigException; -import ve.ucv.ciens.ccg.nxtar.network.VideoFrameMonitor; +import ve.ucv.ciens.ccg.nxtar.network.monitors.VideoFrameMonitor; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import ve.ucv.ciens.ccg.nxtar.utils.Size; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.controllers.Controller; -import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.controllers.PovDirection; import com.badlogic.gdx.controllers.mappings.Ouya; import com.badlogic.gdx.graphics.GL20; @@ -31,8 +33,10 @@ import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture.TextureFilter; +import com.badlogic.gdx.graphics.Texture.TextureWrap; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureRegion; +import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; @@ -40,8 +44,15 @@ public class InGameState extends BaseState{ private static final String TAG = "IN_GAME_STATE"; private static final String CLASS_NAME = InGameState.class.getSimpleName(); + private static final String SHADER_PATH = "shaders/bckg/bckg"; + private NxtARCore core; + private float u_scaling[]; + protected Sprite background; + private Texture backgroundTexture; + private ShaderProgram backgroundShader; + // Cameras. private OrthographicCamera camera; private OrthographicCamera pixelPerfectCamera; @@ -67,8 +78,6 @@ public class InGameState extends BaseState{ private VideoFrameMonitor frameMonitor; public InGameState(final NxtARCore core){ - if(!Ouya.runningOnOuya) setUpButtons(); - this.core = core; frameMonitor = VideoFrameMonitor.getInstance(); @@ -79,6 +88,8 @@ public class InGameState extends BaseState{ pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); camera = new OrthographicCamera(1.0f, Gdx.graphics.getHeight() / Gdx.graphics.getWidth()); + if(!Ouya.runningOnOuya) setUpButtons(); + // Set up input handling support fields. win2world = new Vector3(0.0f, 0.0f, 0.0f); touchPointWorldCoords = new Vector2(); @@ -93,19 +104,48 @@ public class InGameState extends BaseState{ motorButtonsPointers[1] = -1; motorButtonsPointers[2] = -1; motorButtonsPointers[3] = -1; + + backgroundTexture = new Texture(Gdx.files.internal("data/gfx/textures/tile_aqua.png")); + backgroundTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat); + backgroundTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); + background = new Sprite(backgroundTexture); + background.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + background.setPosition(-(Gdx.graphics.getWidth() / 2), -(Gdx.graphics.getHeight() / 2)); + + backgroundShader = new ShaderProgram(Gdx.files.internal(SHADER_PATH + ".vert"), Gdx.files.internal(SHADER_PATH + ".frag")); + if(!backgroundShader.isCompiled()){ + Gdx.app.error(TAG, CLASS_NAME + ".MainMenuStateBase() :: Failed to compile the background shader."); + Gdx.app.error(TAG, CLASS_NAME + backgroundShader.getLog()); + backgroundShader = null; + } + + u_scaling = new float[2]; + u_scaling[0] = Gdx.graphics.getWidth() > Gdx.graphics.getHeight() ? 16.0f : 9.0f; + u_scaling[1] = Gdx.graphics.getHeight() > Gdx.graphics.getWidth() ? 16.0f : 9.0f; } @Override public void render(float delta) { Pixmap temp; byte[] frame; + byte[] prevFrame = null; Size dimensions = null; Gdx.gl.glClearColor(1, 1, 1, 1); Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + core.batch.setProjectionMatrix(pixelPerfectCamera.combined); + core.batch.begin();{ + if(backgroundShader != null){ + core.batch.setShader(backgroundShader); + backgroundShader.setUniform2fv("u_scaling", u_scaling, 0, 2); + } + background.draw(core.batch); + if(backgroundShader != null) core.batch.setShader(null); + }core.batch.end(); + frame = frameMonitor.getCurrentFrame(); - if(frame != null){ + if(frame != null && !Arrays.equals(frame, prevFrame)){ dimensions = frameMonitor.getFrameDimensions(); temp = new Pixmap(frame, 0, dimensions.getWidth() * dimensions.getHeight()); if(videoFrame == null){ @@ -158,6 +198,8 @@ public class InGameState extends BaseState{ motorD.draw(core.batch); } }core.batch.end(); + + prevFrame = frame; } @Override @@ -198,6 +240,8 @@ public class InGameState extends BaseState{ buttonTexture.dispose(); if(videoFrame != null) videoFrame.dispose(); + backgroundTexture.dispose(); + if(backgroundShader != null) backgroundShader.dispose(); } private int getOptimalTextureSize(int imageSideLength) throws ImageTooBigException{ @@ -215,12 +259,16 @@ public class InGameState extends BaseState{ public void onStateSet(){ stateActive = true; Gdx.input.setInputProcessor(this); + Gdx.input.setCatchBackKey(true); + Gdx.input.setCatchMenuKey(true); } @Override public void onStateUnset(){ stateActive = false; Gdx.input.setInputProcessor(null); + Gdx.input.setCatchBackKey(false); + Gdx.input.setCatchMenuKey(false); } private void setUpButtons(){ @@ -253,7 +301,10 @@ public class InGameState extends BaseState{ @Override public boolean keyDown(int keycode) { - // TODO Auto-generated method stub + if(keycode == Input.Keys.BACK){ + // TODO: Go to pause state. + return true; + } return false; } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java index a6aa5e0..923bf95 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java @@ -18,16 +18,21 @@ package ve.ucv.ciens.ccg.nxtar.states; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input; import com.badlogic.gdx.controllers.Controller; import com.badlogic.gdx.controllers.PovDirection; import com.badlogic.gdx.controllers.mappings.Ouya; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.Texture.TextureFilter; +import com.badlogic.gdx.graphics.Texture.TextureWrap; import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.Sprite; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; +import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; @@ -37,15 +42,20 @@ import com.badlogic.gdx.scenes.scene2d.utils.NinePatchDrawable; public abstract class MainMenuStateBase extends BaseState{ protected static final String TAG = "MAIN_MENU"; + private static final String CLASS_NAME = MainMenuStateBase.class.getSimpleName(); - // Client connection helper fields. + private static final String SHADER_PATH = "shaders/bckg/bckg"; + + // Helper fields. protected boolean clientConnected; + private float u_scaling[]; // Buttons and other gui components. protected TextButton startButton; protected Rectangle startButtonBBox; protected Sprite clientConnectedLedOn; protected Sprite clientConnectedLedOff; + protected Sprite background; // Graphic data for the start button. private Texture startButtonEnabledTexture; @@ -59,8 +69,12 @@ public abstract class MainMenuStateBase extends BaseState{ // Other graphics. private Texture clientConnectedLedOffTexture; private Texture clientConnectedLedOnTexture; + private Texture backgroundTexture; + private ShaderProgram backgroundShader; public MainMenuStateBase(){ + TextureRegion region; + // Create the start button background. startButtonEnabledTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Yellow.png")); startButtonEnabled9p = new NinePatch(new TextureRegion(startButtonEnabledTexture, 0, 0, startButtonEnabledTexture.getWidth(), startButtonEnabledTexture.getHeight()), 49, 49, 45, 45); @@ -89,17 +103,35 @@ public abstract class MainMenuStateBase extends BaseState{ startButtonBBox = new Rectangle(0, 0, startButton.getWidth(), startButton.getHeight()); // Create the connection leds. - TextureRegion region; clientConnectedLedOnTexture = new Texture("data/gfx/gui/Anonymous_Button_Green.png"); - region = new TextureRegion(clientConnectedLedOnTexture, clientConnectedLedOnTexture.getWidth(), clientConnectedLedOnTexture.getHeight()); + region = new TextureRegion(clientConnectedLedOnTexture); clientConnectedLedOn = new Sprite(region); clientConnectedLedOffTexture = new Texture("data/gfx/gui/Anonymous_Button_Red.png"); - region = new TextureRegion(clientConnectedLedOffTexture, clientConnectedLedOffTexture.getWidth(), clientConnectedLedOffTexture.getHeight()); + region = new TextureRegion(clientConnectedLedOffTexture); clientConnectedLedOff = new Sprite(region); - clientConnected = false; + // Set up the background. + backgroundTexture = new Texture(Gdx.files.internal("data/gfx/textures/tile_aqua.png")); + backgroundTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat); + backgroundTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); + region = new TextureRegion(backgroundTexture); + background = new Sprite(backgroundTexture); + background.setSize(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + background.setPosition(-(Gdx.graphics.getWidth() / 2), -(Gdx.graphics.getHeight() / 2)); + backgroundShader = new ShaderProgram(Gdx.files.internal(SHADER_PATH + ".vert"), Gdx.files.internal(SHADER_PATH + ".frag")); + if(!backgroundShader.isCompiled()){ + Gdx.app.error(TAG, CLASS_NAME + ".MainMenuStateBase() :: Failed to compile the background shader."); + Gdx.app.error(TAG, CLASS_NAME + backgroundShader.getLog()); + backgroundShader = null; + } + + u_scaling = new float[2]; + u_scaling[0] = Gdx.graphics.getWidth() > Gdx.graphics.getHeight() ? 16.0f : 9.0f; + u_scaling[1] = Gdx.graphics.getHeight() > Gdx.graphics.getWidth() ? 16.0f : 9.0f; + + clientConnected = false; stateActive = false; } @@ -127,19 +159,34 @@ public abstract class MainMenuStateBase extends BaseState{ startButtonPressedTexture.dispose(); clientConnectedLedOnTexture.dispose(); clientConnectedLedOffTexture.dispose(); + backgroundTexture.dispose(); + if(backgroundShader != null) backgroundShader.dispose(); font.dispose(); } + protected void drawBackground(SpriteBatch batch){ + if(backgroundShader != null){ + batch.setShader(backgroundShader); + backgroundShader.setUniform2fv("u_scaling", u_scaling, 0, 2); + } + background.draw(batch); + if(backgroundShader != null) batch.setShader(null); + } + @Override public void onStateSet(){ stateActive = true; Gdx.input.setInputProcessor(this); + Gdx.input.setCatchBackKey(true); + Gdx.input.setCatchMenuKey(true); } @Override public void onStateUnset(){ stateActive = false; Gdx.input.setInputProcessor(null); + Gdx.input.setCatchBackKey(false); + Gdx.input.setCatchMenuKey(false); } public void onClientConnected(){ @@ -153,6 +200,10 @@ public abstract class MainMenuStateBase extends BaseState{ @Override public boolean keyDown(int keycode){ + if(keycode == Input.Keys.BACK){ + // TODO: Go to pause state. + return true; + } return false; } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java index dd53b98..9fe9d4a 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java @@ -65,6 +65,7 @@ public class OuyaMainMenuState extends MainMenuStateBase{ core.batch.setProjectionMatrix(pixelPerfectCamera.combined); core.batch.begin();{ + drawBackground(core.batch); if(clientConnected){ clientConnectedLedOn.draw(core.batch); }else{ diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java b/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java index 4b95ffc..a7c51bb 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/PauseState.java @@ -17,9 +17,7 @@ package ve.ucv.ciens.ccg.nxtar.states; import ve.ucv.ciens.ccg.nxtar.NxtARCore; -import com.badlogic.gdx.Gdx; import com.badlogic.gdx.controllers.Controller; -import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.controllers.PovDirection; import com.badlogic.gdx.math.Vector3; diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java index 6565ffc..061ea69 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java @@ -62,6 +62,7 @@ public class TabletMainMenuState extends MainMenuStateBase{ core.batch.setProjectionMatrix(pixelPerfectCamera.combined); core.batch.begin();{ + drawBackground(core.batch); if(clientConnected){ clientConnectedLedOn.draw(core.batch); }else{ From 5d80d5f866a50ed98511ec3f07c0355b4477f533 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 7 Feb 2014 17:02:53 -0430 Subject: [PATCH 14/16] Added state transitions with Universal Tween Library. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 150 +++++++++++++----- .../protocols/VideoStreamingProtocol.java | 46 ------ .../ciens/ccg/nxtar/states/InGameState.java | 3 +- .../ccg/nxtar/states/OuyaMainMenuState.java | 2 + .../ccg/nxtar/states/TabletMainMenuState.java | 3 + 5 files changed, 117 insertions(+), 87 deletions(-) delete mode 100644 src/ve/ucv/ciens/ccg/nxtar/network/protocols/VideoStreamingProtocol.java diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index 45435fe..d62959e 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -29,13 +29,24 @@ import ve.ucv.ciens.ccg.nxtar.states.PauseState; import ve.ucv.ciens.ccg.nxtar.states.TabletMainMenuState; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; +import aurelienribon.tweenengine.Tween; +import aurelienribon.tweenengine.TweenEquation; +import aurelienribon.tweenengine.TweenEquations; +import aurelienribon.tweenengine.primitives.MutableFloat; + import com.badlogic.gdx.Application; import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.controllers.mappings.Ouya; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Pixmap.Format; +import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; /** @@ -93,12 +104,18 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ private VideoStreamingThread videoThread; private RobotControlThread robotThread; - // Overlay font. + // Overlays. private OrthographicCamera pixelPerfectCamera; private float fontX; private float fontY; private BitmapFont font; + private Texture fadeTexture; + private MutableFloat alpha; + private Tween fadeOut; + private Tween fadeIn; + private boolean fading; + /** *

Set up the basic application fields.

*/ @@ -135,48 +152,65 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ // Set up fields. batch = new SpriteBatch(); - if(ProjectConstants.DEBUG) - pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());{ - // Set up the overlay font. - fontX = -((Gdx.graphics.getWidth() * ProjectConstants.OVERSCAN) / 2) + 10; - fontY = ((Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN) / 2) - 10; + pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); - font = new BitmapFont(); - font.setColor(1.0f, 1.0f, 0.0f, 1.0f); - if(!Ouya.runningOnOuya){ - font.setScale(1.0f); - }else{ - font.setScale(2.5f); - } + if(ProjectConstants.DEBUG){ + // Set up the overlay font. + fontX = -((Gdx.graphics.getWidth() * ProjectConstants.OVERSCAN) / 2) + 10; + fontY = ((Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN) / 2) - 10; + + font = new BitmapFont(); + font.setColor(1.0f, 1.0f, 0.0f, 1.0f); + if(!Ouya.runningOnOuya){ + font.setScale(1.0f); + }else{ + font.setScale(2.5f); } + } - // Start networking. - mcastEnabler.enableMulticast(); + // Start networking. + mcastEnabler.enableMulticast(); - Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); - serviceDiscoveryThread = ServiceDiscoveryThread.getInstance(); - videoThread = VideoStreamingThread.getInstance()/*.setToaster(toaster)*/; - //robotThread = RobotControlThread.getInstance().setToaster(toaster); + Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); + serviceDiscoveryThread = ServiceDiscoveryThread.getInstance(); + videoThread = VideoStreamingThread.getInstance()/*.setToaster(toaster)*/; + //robotThread = RobotControlThread.getInstance().setToaster(toaster); - serviceDiscoveryThread.start(); - videoThread.start(); - videoThread.startStreaming(); - videoThread.addNetworkConnectionListener(this); - //robotThread.start(); + serviceDiscoveryThread.start(); + videoThread.start(); + videoThread.startStreaming(); + videoThread.addNetworkConnectionListener(this); + //robotThread.start(); - // Set the current and next states. - currState = game_states_t.MAIN_MENU; - nextState = null; - this.setScreen(states[currState.getValue()]); - states[currState.getValue()].onStateSet(); + // Set the current and next states. + currState = game_states_t.MAIN_MENU; + nextState = null; + this.setScreen(states[currState.getValue()]); + states[currState.getValue()].onStateSet(); - // Set initial input handlers. - Gdx.input.setInputProcessor(states[currState.getValue()]); - Controllers.addListener(states[currState.getValue()]); + // Prepare the fadeToBlack sprite; + Pixmap pixmap = new Pixmap(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), Format.RGBA4444); + pixmap.setColor(0, 0, 0, 1); + pixmap.fill(); + fadeTexture = new Texture(pixmap); + pixmap.dispose(); - // Anything else. - //Gdx.app.setLogLevel(Application.LOG_DEBUG); - Gdx.app.setLogLevel(Application.LOG_NONE); + alpha = new MutableFloat(0.0f); + fadeOut = Tween.to(alpha, 0, 0.5f).target(1.0f).ease(TweenEquations.easeInQuint); + fadeIn = Tween.to(alpha, 0, 0.5f).target(0.0f).ease(TweenEquations.easeInQuint); + + fading = false; + + // Set initial input handlers. + Gdx.input.setInputProcessor(states[currState.getValue()]); + Controllers.addListener(states[currState.getValue()]); + + // Anything else. + Gdx.app.setLogLevel(Application.LOG_INFO); + //Gdx.app.setLogLevel(Application.LOG_DEBUG); + //Gdx.app.setLogLevel(Application.LOG_NONE); + + //batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); } public void render(){ @@ -186,18 +220,53 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ if(nextState != null){ states[currState.getValue()].onStateUnset(); - currState = nextState; - nextState = null; + if(!fadeOut.isStarted()){ + Gdx.app.log(TAG, CLASS_NAME + ".onRender() :: Starting fade out."); + fadeOut.start(); + fading = true; + }else{ + Gdx.app.log(TAG, CLASS_NAME + ".onRender() :: Updating fade out."); + fadeOut.update(Gdx.graphics.getDeltaTime()); - states[currState.getValue()].onStateSet(); + if(fadeOut.isFinished()){ + currState = nextState; + nextState = null; - setScreen(states[currState.getValue()]); + states[currState.getValue()].onStateSet(); + + setScreen(states[currState.getValue()]); + + Gdx.app.log(TAG, CLASS_NAME + ".onRender() :: Freeing fade out."); + fadeOut.free(); + fadeOut = Tween.to(alpha, 0, 0.5f).target(1.0f).ease(TweenEquations.easeInQuint); + fadeIn.start(); + } + } + } + + if(fadeIn.isStarted()){ + if(!fadeIn.isFinished()){ + fadeIn.update(Gdx.graphics.getDeltaTime()); + }else{ + fading = false; + fadeIn.free(); + fadeIn = Tween.to(alpha, 0, 0.5f).target(0.0f).ease(TweenEquations.easeInQuint); + } + } + + if(fading){ + batch.setProjectionMatrix(pixelPerfectCamera.combined); + batch.begin();{ + batch.setColor(1, 1, 1, alpha.floatValue()); + batch.draw(fadeTexture, -(Gdx.graphics.getWidth() / 2), -(Gdx.graphics.getHeight() / 2)); + batch.setColor(1, 1, 1, 1); + }batch.end(); } if(ProjectConstants.DEBUG){ - // Draw the FPS overlay. batch.setProjectionMatrix(pixelPerfectCamera.combined); batch.begin();{ + // Draw the FPS overlay. font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), fontX, fontY); font.draw(batch, String.format("Total stream FPS: %d", videoThread.getFps()), fontX, fontY - font.getCapHeight() - 5); font.draw(batch, String.format("Lost stream FPS: %d", videoThread.getLostFrames()), fontX, fontY - (2 * font.getCapHeight()) - 10); @@ -218,6 +287,7 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ public void dispose(){ // Finish network threads. videoThread.finish(); + fadeTexture.dispose(); // Dispose graphic objects. batch.dispose(); diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/protocols/VideoStreamingProtocol.java b/src/ve/ucv/ciens/ccg/nxtar/network/protocols/VideoStreamingProtocol.java deleted file mode 100644 index 183fdb0..0000000 --- a/src/ve/ucv/ciens/ccg/nxtar/network/protocols/VideoStreamingProtocol.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2013 Miguel Angel Astor Romero - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package ve.ucv.ciens.ccg.nxtar.network.protocols; - -public final class VideoStreamingProtocol{ - public static final byte STREAM_CONTROL_END = 0x10; - public static final byte ACK_SEND_NEXT = 0x20; - public static final byte ACK_WAIT = 0x30; - public static final byte FLOW_CONTROL_WAIT = 0x40; - public static final byte FLOW_CONTROL_CONTINUE = 0x50; - public static final byte IMAGE_DATA = 0x60; - public static final byte UNRECOGNIZED = (byte)0xFF; - - public static boolean checkValidityOfMessage(byte message){ - boolean validity; - - switch(message){ - case STREAM_CONTROL_END: - case ACK_SEND_NEXT: - case ACK_WAIT: - case FLOW_CONTROL_WAIT: - case FLOW_CONTROL_CONTINUE: - case IMAGE_DATA: - case UNRECOGNIZED: - validity = true; - break; - default: - validity = false; - } - - return validity; - } -} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java index 96371bb..c1a3b0f 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java @@ -18,6 +18,7 @@ package ve.ucv.ciens.ccg.nxtar.states; import java.util.Arrays; import ve.ucv.ciens.ccg.nxtar.NxtARCore; +import ve.ucv.ciens.ccg.nxtar.NxtARCore.game_states_t; import ve.ucv.ciens.ccg.nxtar.exceptions.ImageTooBigException; import ve.ucv.ciens.ccg.nxtar.network.monitors.VideoFrameMonitor; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; @@ -302,7 +303,7 @@ public class InGameState extends BaseState{ @Override public boolean keyDown(int keycode) { if(keycode == Input.Keys.BACK){ - // TODO: Go to pause state. + core.nextState = game_states_t.MAIN_MENU; return true; } return false; diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java index 9fe9d4a..def2202 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java @@ -65,7 +65,9 @@ public class OuyaMainMenuState extends MainMenuStateBase{ core.batch.setProjectionMatrix(pixelPerfectCamera.combined); core.batch.begin();{ + core.batch.disableBlending(); drawBackground(core.batch); + core.batch.enableBlending(); if(clientConnected){ clientConnectedLedOn.draw(core.batch); }else{ diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java index 061ea69..2d3043f 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java @@ -62,7 +62,10 @@ public class TabletMainMenuState extends MainMenuStateBase{ core.batch.setProjectionMatrix(pixelPerfectCamera.combined); core.batch.begin();{ + core.batch.disableBlending(); drawBackground(core.batch); + core.batch.enableBlending(); + if(clientConnected){ clientConnectedLedOn.draw(core.batch); }else{ From 5816e77e36a22f92f9ab52e86f0e679c54cba2ca Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 10 Feb 2014 15:27:27 -0430 Subject: [PATCH 15/16] RobotControlThread sends data. --- .../ciens/ccg/networkdata/MotorEventACK.java | 32 ++ src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 30 +- .../ccg/nxtar/network/RobotControlThread.java | 122 ++++++- .../nxtar/network/ServiceDiscoveryThread.java | 7 +- .../nxtar/network/VideoStreamingThread.java | 4 +- .../network/monitors/MotorEventQueue.java | 72 ++++ .../ciens/ccg/nxtar/states/InGameState.java | 313 ++++++++++++------ .../ccg/nxtar/states/MainMenuStateBase.java | 114 +++++-- .../ccg/nxtar/states/OuyaMainMenuState.java | 35 +- .../ccg/nxtar/states/TabletMainMenuState.java | 104 ------ .../ccg/nxtar/utils/ProjectConstants.java | 16 +- 11 files changed, 540 insertions(+), 309 deletions(-) create mode 100644 src/ve/ucv/ciens/ccg/networkdata/MotorEventACK.java create mode 100644 src/ve/ucv/ciens/ccg/nxtar/network/monitors/MotorEventQueue.java diff --git a/src/ve/ucv/ciens/ccg/networkdata/MotorEventACK.java b/src/ve/ucv/ciens/ccg/networkdata/MotorEventACK.java new file mode 100644 index 0000000..a2911f9 --- /dev/null +++ b/src/ve/ucv/ciens/ccg/networkdata/MotorEventACK.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.networkdata; + +import java.io.Serializable; + +public class MotorEventACK implements Serializable { + private static final long serialVersionUID = 9989L; + + private boolean clientQueueIsFull; + + public MotorEventACK(boolean isQueueFull){ + this.clientQueueIsFull = isQueueFull; + } + + public boolean isClientQueueFull(){ + return this.clientQueueIsFull; + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index d62959e..eb633f3 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -28,9 +28,7 @@ import ve.ucv.ciens.ccg.nxtar.states.OuyaMainMenuState; import ve.ucv.ciens.ccg.nxtar.states.PauseState; import ve.ucv.ciens.ccg.nxtar.states.TabletMainMenuState; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; - import aurelienribon.tweenengine.Tween; -import aurelienribon.tweenengine.TweenEquation; import aurelienribon.tweenengine.TweenEquations; import aurelienribon.tweenengine.primitives.MutableFloat; @@ -39,14 +37,11 @@ import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.controllers.Controllers; import com.badlogic.gdx.controllers.mappings.Ouya; -import com.badlogic.gdx.graphics.Color; -import com.badlogic.gdx.graphics.GL20; import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.graphics.Pixmap.Format; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.BitmapFont; -import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.SpriteBatch; /** @@ -173,14 +168,17 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ Gdx.app.debug(TAG, CLASS_NAME + ".create() :: Creating network threads"); serviceDiscoveryThread = ServiceDiscoveryThread.getInstance(); - videoThread = VideoStreamingThread.getInstance()/*.setToaster(toaster)*/; - //robotThread = RobotControlThread.getInstance().setToaster(toaster); + videoThread = VideoStreamingThread.getInstance(); + robotThread = RobotControlThread.getInstance(); serviceDiscoveryThread.start(); + videoThread.start(); videoThread.startStreaming(); videoThread.addNetworkConnectionListener(this); - //robotThread.start(); + + robotThread.addNetworkConnectionListener(this); + robotThread.start(); // Set the current and next states. currState = game_states_t.MAIN_MENU; @@ -206,11 +204,9 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ Controllers.addListener(states[currState.getValue()]); // Anything else. - Gdx.app.setLogLevel(Application.LOG_INFO); - //Gdx.app.setLogLevel(Application.LOG_DEBUG); + //Gdx.app.setLogLevel(Application.LOG_INFO); + Gdx.app.setLogLevel(Application.LOG_DEBUG); //Gdx.app.setLogLevel(Application.LOG_NONE); - - //batch.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); } public void render(){ @@ -287,9 +283,10 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ public void dispose(){ // Finish network threads. videoThread.finish(); - fadeTexture.dispose(); + robotThread.finish(); // Dispose graphic objects. + fadeTexture.dispose(); batch.dispose(); if(ProjectConstants.DEBUG){ font.dispose(); @@ -303,9 +300,10 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ @Override public synchronized void networkStreamConnected(String streamName){ - if(streamName.equals(VideoStreamingThread.THREAD_NAME) || streamName.equals(RobotControlThread.THREAD_NAME)) - connections += 1; - if(connections >= 1){ + //if(streamName.equals(VideoStreamingThread.THREAD_NAME) || streamName.equals(RobotControlThread.THREAD_NAME)) + Gdx.app.log(TAG, CLASS_NAME + ".networkStreamConnected() :: Stream " + streamName + " connected."); + connections += 1; + if(connections >= 2){ Gdx.app.debug(TAG, CLASS_NAME + ".networkStreamConnected() :: Stopping service broadcast."); serviceDiscoveryThread.finish(); mcastEnabler.disableMulticast(); diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/RobotControlThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/RobotControlThread.java index 212772f..3c1374f 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/RobotControlThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/RobotControlThread.java @@ -16,11 +16,16 @@ package ve.ucv.ciens.ccg.nxtar.network; import java.io.IOException; +import java.io.InvalidClassException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.net.ServerSocket; import java.net.Socket; +import ve.ucv.ciens.ccg.networkdata.MotorEvent; +import ve.ucv.ciens.ccg.networkdata.MotorEventACK; import ve.ucv.ciens.ccg.nxtar.interfaces.NetworkConnectionListener; -import ve.ucv.ciens.ccg.nxtar.interfaces.Toaster; +import ve.ucv.ciens.ccg.nxtar.network.monitors.MotorEventQueue; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import com.badlogic.gdx.Gdx; @@ -33,15 +38,24 @@ public class RobotControlThread extends Thread { private NetworkConnectionListener netListener; private ServerSocket server; private Socket client; - private Toaster toaster; + private MotorEventQueue queue; + private Object pauseMonitor; + private boolean paused; + private boolean done; + private ObjectOutputStream os; + private ObjectInputStream is; private RobotControlThread(){ super(THREAD_NAME); netListener = null; + queue = MotorEventQueue.getInstance(); + pauseMonitor = new Object(); + paused = false; + done = false; try{ - server = new ServerSocket(ProjectConstants.SERVER_TCP_PORT_2); + server = new ServerSocket(ProjectConstants.MOTOR_CONTROL_PORT); }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".RobotControlThread() :: Error creating server: " + io.getMessage(), io); } @@ -55,25 +69,109 @@ public class RobotControlThread extends Thread { return SingletonHolder.INSTANCE; } - public RobotControlThread setToaster(Toaster toaster){ - this.toaster = toaster; - return this; - } - public void addNetworkConnectionListener(NetworkConnectionListener listener){ netListener = listener; } + public void pauseThread(){ + synchronized(pauseMonitor){ + paused = true; + } + } + + public void resumeThread(){ + synchronized(pauseMonitor){ + paused = false; + } + } + + public void finish(){ + done = true; + } + @Override public void run(){ + MotorEvent message; + MotorEventACK ack; + try{ client = server.accept(); - if(netListener != null) - netListener.networkStreamConnected(THREAD_NAME); - toaster.showShortToast("Client connected to RobotControlThread"); - client.close(); + if(netListener != null) netListener.networkStreamConnected(THREAD_NAME); + os = new ObjectOutputStream(client.getOutputStream()); + is = new ObjectInputStream(client.getInputStream()); + }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error accepting client: " + io.getMessage(), io); + return; + } + + while(!paused){ + if(done){ + break; + } + + // Send the motor event. + try{ + message = queue.getNextEvent(); + os.writeObject(message); + message = null; + + }catch(InvalidClassException ic){ + Gdx.app.error(TAG, CLASS_NAME + ".run() :: InvalidClassException during transmission: " + ic.getMessage(), ic); + break; + + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".run() :: IOException during transmission: " + io.getMessage(), io); + break; + } + + // Receive ack. + try{ + ack = (MotorEventACK)is.readObject(); + }catch(ClassNotFoundException cn){ + Gdx.app.error(TAG, CLASS_NAME + ".run() :: InvalidClassException during reception: " + cn.getMessage(), cn); + break; + + }catch(ClassCastException cc){ + Gdx.app.error(TAG, CLASS_NAME + ".run() :: InvalidClassException during reception: " + cc.getMessage(), cc); + break; + + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".run() :: InvalidClassException during reception: " + io.getMessage(), io); + break; + } + + if(ack.isClientQueueFull()){ + // Wait for client to notify. + // A client will never send two queue full acks in a row. + try{ + ack = (MotorEventACK)is.readObject(); + }catch(ClassNotFoundException cn){ + Gdx.app.error(TAG, CLASS_NAME + ".run() :: InvalidClassException during reception: " + cn.getMessage(), cn); + break; + + }catch(ClassCastException cc){ + Gdx.app.error(TAG, CLASS_NAME + ".run() :: InvalidClassException during reception: " + cc.getMessage(), cc); + break; + + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".run() :: InvalidClassException during reception: " + io.getMessage(), io); + break; + } + + }else{ + // Clean and continue. + ack = null; + message = null; + continue; + } + } + + + try{ + client.close(); + }catch(IOException io){ + Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error closing client: " + io.getMessage(), io); } } } diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/ServiceDiscoveryThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/ServiceDiscoveryThread.java index 305cb49..e740513 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/ServiceDiscoveryThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/ServiceDiscoveryThread.java @@ -31,7 +31,7 @@ import com.badlogic.gdx.Gdx; *

This thread performs an ad hoc service discovery protocol. A multicast datagram packet is sent every * 250 miliseconds carrying the string "NxtAR server is here!" on the multicast address defined * in {@link ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants#MULTICAST_ADDRESS}. The port defined in - * {@link ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants#SERVER_UDP_PORT} is used for the transmissions. The server stops + * {@link ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants#SERVICE_DISCOVERY_PORT} is used for the transmissions. The server stops * when another thread calls the {@link #finish()} method or the server fails to transmit {@link #MAX_RETRIES} packets in * a row, whichever happens first.

* @@ -89,7 +89,7 @@ public class ServiceDiscoveryThread extends Thread { // Create a UDP socket at the port defined in ProjectConstants.SERVER_UDP_PORT. Gdx.app.debug(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Creating multicast server."); try{ - udpServer = new DatagramSocket(ProjectConstants.SERVER_UDP_PORT); + udpServer = new DatagramSocket(ProjectConstants.SERVICE_DISCOVERY_PORT); }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".ServiceDiscoveryThread() :: Error creating UDP socket: " + io.getMessage()); udpServer = null; @@ -150,10 +150,11 @@ public class ServiceDiscoveryThread extends Thread { break; } // Send the packet and reset the retry counter. - DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, ProjectConstants.SERVER_UDP_PORT); + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, group, ProjectConstants.SERVICE_DISCOVERY_PORT); udpServer.send(packet); retries = 0; try{ sleep(250L); }catch(InterruptedException ie){ } + }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".run() :: Error sending packet: " + io.getMessage()); retries += 1; diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java index df9d6c0..a8c12f2 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java +++ b/src/ve/ucv/ciens/ccg/nxtar/network/VideoStreamingThread.java @@ -29,7 +29,7 @@ import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import com.badlogic.gdx.Gdx; -public class VideoStreamingThread extends Thread { +public class VideoStreamingThread extends Thread{ public static final String THREAD_NAME = "VideoStreamingThread"; private static final String TAG = "NXTAR_CORE_VIDEOTHREAD"; private static final String CLASS_NAME = VideoStreamingThread.class.getSimpleName(); @@ -65,7 +65,7 @@ public class VideoStreamingThread extends Thread { frameMonitor = VideoFrameMonitor.getInstance(); try{ - socket = new DatagramSocket(ProjectConstants.SERVER_TCP_PORT_1); + socket = new DatagramSocket(ProjectConstants.VIDEO_STREAMING_PORT); }catch(IOException io){ Gdx.app.error(TAG, CLASS_NAME + ".VideoStreamingThread() :: Error creating server: " + io.getMessage(), io); } diff --git a/src/ve/ucv/ciens/ccg/nxtar/network/monitors/MotorEventQueue.java b/src/ve/ucv/ciens/ccg/nxtar/network/monitors/MotorEventQueue.java new file mode 100644 index 0000000..0a72a8d --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtar/network/monitors/MotorEventQueue.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.network.monitors; + +import java.util.LinkedList; +import java.util.Queue; + +import ve.ucv.ciens.ccg.networkdata.MotorEvent; + +/** + *

A simple monitor class that encapsulates a queue.

+ *

As it name says it stores motor events to be forwarded to the NXT robot.

+ *

This class implements the singleton design pattern.

+ * + * @author Miguel Angel Astor Romero + */ +public class MotorEventQueue{ + /** + * The event queue implemented as a linked list. + */ + private Queue motorEvents; + + private MotorEventQueue(){ + motorEvents = new LinkedList(); + } + + private static class SingletonHolder{ + public static final MotorEventQueue instance = new MotorEventQueue(); + } + + /** + * Return the singleton instance of this class. + * @return The singleton instance. + */ + public static MotorEventQueue getInstance(){ + return SingletonHolder.instance; + } + + /** + *

Get the first event on the queue.

+ *

If there are no events to return this method blocks until some thread calls the addEvent() method.

+ * @return The event at the front of the queue. + */ + public synchronized MotorEvent getNextEvent(){ + while(motorEvents.size() == 0){ + try{ wait(); }catch(InterruptedException ie){ } + } + return motorEvents.poll(); + } + + /** + *

Adds an event to the back of the queue.

+ * @param event The event to add. + */ + public synchronized void addEvent(MotorEvent event){ + motorEvents.add(event); + notifyAll(); + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java index c1a3b0f..9b063a5 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java @@ -17,9 +17,11 @@ package ve.ucv.ciens.ccg.nxtar.states; import java.util.Arrays; +import ve.ucv.ciens.ccg.networkdata.MotorEvent; +import ve.ucv.ciens.ccg.networkdata.MotorEvent.motor_t; import ve.ucv.ciens.ccg.nxtar.NxtARCore; import ve.ucv.ciens.ccg.nxtar.NxtARCore.game_states_t; -import ve.ucv.ciens.ccg.nxtar.exceptions.ImageTooBigException; +import ve.ucv.ciens.ccg.nxtar.network.monitors.MotorEventQueue; import ve.ucv.ciens.ccg.nxtar.network.monitors.VideoFrameMonitor; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import ve.ucv.ciens.ccg.nxtar.utils.Size; @@ -76,11 +78,14 @@ public class InGameState extends BaseState{ private boolean[] motorButtonsTouched; private int[] motorButtonsPointers; + // Monitors. private VideoFrameMonitor frameMonitor; + private MotorEventQueue queue; public InGameState(final NxtARCore core){ this.core = core; frameMonitor = VideoFrameMonitor.getInstance(); + queue = MotorEventQueue.getInstance(); // Set up rendering fields; videoFrame = null; @@ -126,8 +131,7 @@ public class InGameState extends BaseState{ } @Override - public void render(float delta) { - Pixmap temp; + public void render(float delta){ byte[] frame; byte[] prevFrame = null; Size dimensions = null; @@ -148,20 +152,10 @@ public class InGameState extends BaseState{ frame = frameMonitor.getCurrentFrame(); if(frame != null && !Arrays.equals(frame, prevFrame)){ dimensions = frameMonitor.getFrameDimensions(); - temp = new Pixmap(frame, 0, dimensions.getWidth() * dimensions.getHeight()); - if(videoFrame == null){ - try{ - videoFrame = new Pixmap(getOptimalTextureSize(dimensions.getWidth()), getOptimalTextureSize(dimensions.getHeight()), temp.getFormat()); - }catch(ImageTooBigException e){ - core.toast("Cannot display received frame.\n" + e.getMessage(), true); - Gdx.app.exit(); - return; - } - } - videoFrame.drawPixmap(temp, 0, 0); - temp.dispose(); + videoFrame = new Pixmap(frame, 0, dimensions.getWidth() * dimensions.getHeight()); videoFrameTexture = new Texture(videoFrame); videoFrameTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear); + videoFrame.dispose(); TextureRegion region = new TextureRegion(videoFrameTexture, 0, 0, dimensions.getWidth(), dimensions.getHeight()); @@ -199,59 +193,38 @@ public class InGameState extends BaseState{ motorD.draw(core.batch); } }core.batch.end(); - + prevFrame = frame; } @Override - public void resize(int width, int height) { + public void resize(int width, int height){ // TODO Auto-generated method stub } @Override - public void show() { - // TODO Auto-generated method stub - - } + public void show(){ } @Override - public void hide() { - // TODO Auto-generated method stub - - } + public void hide(){ } @Override - public void pause() { - // TODO Auto-generated method stub - - } + public void pause(){ } @Override - public void resume() { - // TODO Auto-generated method stub - - } + public void resume(){ } @Override - public void dispose() { + public void dispose(){ if(videoFrameTexture != null) videoFrameTexture.dispose(); if(buttonTexture != null) buttonTexture.dispose(); - if(videoFrame != null) - videoFrame.dispose(); backgroundTexture.dispose(); if(backgroundShader != null) backgroundShader.dispose(); } - private int getOptimalTextureSize(int imageSideLength) throws ImageTooBigException{ - for(int po2: ProjectConstants.POWERS_OF_2){ - if(imageSideLength < po2) return po2; - } - throw new ImageTooBigException("No valid texture size found. Image too large."); - } - /*;;;;;;;;;;;;;;;;;; ; HELPER METHODS ; ;;;;;;;;;;;;;;;;;;*/ @@ -301,28 +274,9 @@ public class InGameState extends BaseState{ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ @Override - public boolean keyDown(int keycode) { - if(keycode == Input.Keys.BACK){ - core.nextState = game_states_t.MAIN_MENU; - return true; - } - return false; - } + public boolean touchDown(int screenX, int screenY, int pointer, int button){ + MotorEvent event; - @Override - public boolean keyUp(int keycode) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean keyTyped(char character) { - // TODO Auto-generated method stub - return false; - } - - @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button) { if(!Ouya.runningOnOuya){ win2world.set(screenX, screenY, 0.0f); camera.unproject(win2world); @@ -333,27 +287,69 @@ public class InGameState extends BaseState{ if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); - motorButtonsTouched[0] = true; - motorButtonsPointers[0] = pointer; + + // Enqueue the event corresponding to this button if the opposing button is not pressed already. + if(!motorButtonsTouched[1]){ + motorButtonsTouched[0] = true; + motorButtonsPointers[0] = pointer; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte)100); + queue.addEvent(event); + } + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); - motorButtonsTouched[1] = true; - motorButtonsPointers[1] = pointer; + + // Enqueue the event corresponding to this button if the opposing button is not pressed already. + if(!motorButtonsTouched[0]){ + motorButtonsTouched[1] = true; + motorButtonsPointers[1] = pointer; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte)-100); + queue.addEvent(event); + } + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); - motorButtonsTouched[2] = true; - motorButtonsPointers[2] = pointer; + + // Enqueue the event corresponding to this button if the opposing button is not pressed already. + if(!motorButtonsTouched[3]){ + motorButtonsTouched[2] = true; + motorButtonsPointers[2] = pointer; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte)-100); + queue.addEvent(event); + } + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); - motorButtonsTouched[3] = true; - motorButtonsPointers[3] = pointer; + + // Enqueue the event corresponding to this button if the opposing button is not pressed already. + if(!motorButtonsTouched[2]){ + motorButtonsTouched[3] = true; + motorButtonsPointers[3] = pointer; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte)100); + queue.addEvent(event); + } + } } return true; } @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button) { + public boolean touchUp(int screenX, int screenY, int pointer, int button){ + MotorEvent event; + if(!Ouya.runningOnOuya){ win2world.set(screenX, screenY, 0.0f); camera.unproject(win2world); @@ -364,27 +360,70 @@ public class InGameState extends BaseState{ if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; + + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[1]){ + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte) 0); + queue.addEvent(event); + } + }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[0]){ + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte) 0); + queue.addEvent(event); + } + }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[3]){ + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte) 0); + queue.addEvent(event); + } + }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[2]){ + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte) 0); + queue.addEvent(event); + } + } } return true; } @Override - public boolean touchDragged(int screenX, int screenY, int pointer) { + public boolean touchDragged(int screenX, int screenY, int pointer){ + MotorEvent event; + if(!Ouya.runningOnOuya){ win2world.set(screenX, screenY, 0.0f); camera.unproject(win2world); @@ -392,28 +431,71 @@ public class InGameState extends BaseState{ if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[1]){ + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte) 0); + queue.addEvent(event); + } + }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[0]){ + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte) 0); + queue.addEvent(event); + } + }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[3]){ + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte) 0); + queue.addEvent(event); + } + }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[2]){ + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte) 0); + queue.addEvent(event); + } + } } return true; } @Override - public boolean mouseMoved(int screenX, int screenY) { - // TODO Auto-generated method stub + public boolean keyDown(int keycode){ + if(keycode == Input.Keys.BACK){ + core.nextState = game_states_t.MAIN_MENU; + return true; + } return false; } @@ -422,7 +504,7 @@ public class InGameState extends BaseState{ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ @Override - public boolean buttonDown(Controller controller, int buttonCode) { + public boolean buttonDown(Controller controller, int buttonCode){ if(stateActive){ Gdx.app.log(TAG, CLASS_NAME + ".buttonDown() :: " + controller.getName() + " :: " + Integer.toString(buttonCode)); return true; @@ -432,7 +514,7 @@ public class InGameState extends BaseState{ } @Override - public boolean buttonUp(Controller controller, int buttonCode) { + public boolean buttonUp(Controller controller, int buttonCode){ if(stateActive){ Gdx.app.log(TAG, CLASS_NAME + ".buttonDown() :: " + controller.getName() + " :: " + Integer.toString(buttonCode)); return true; @@ -442,7 +524,7 @@ public class InGameState extends BaseState{ } @Override - public boolean axisMoved(Controller controller, int axisCode, float value) { + public boolean axisMoved(Controller controller, int axisCode, float value){ if(stateActive){ if(value >= Ouya.STICK_DEADZONE){ if(axisCode == Ouya.AXIS_LEFT_TRIGGER){ @@ -459,47 +541,62 @@ public class InGameState extends BaseState{ } @Override - public boolean scrolled(int amount) { + public void connected(Controller controller){ } + + @Override + public void disconnected(Controller controller){ } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; UNUSED LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean mouseMoved(int screenX, int screenY){ + return false; + } + + @Override + public boolean keyUp(int keycode){ // TODO Auto-generated method stub return false; } @Override - public void connected(Controller controller) { + public boolean keyTyped(char character){ // TODO Auto-generated method stub - - } - - @Override - public void disconnected(Controller controller) { - // TODO Auto-generated method stub - + return false; } @Override public boolean povMoved(Controller controller, int povCode, - PovDirection value) { + PovDirection value){ // TODO Auto-generated method stub return false; } @Override public boolean xSliderMoved(Controller controller, int sliderCode, - boolean value) { + boolean value){ // TODO Auto-generated method stub return false; } @Override public boolean ySliderMoved(Controller controller, int sliderCode, - boolean value) { + boolean value){ // TODO Auto-generated method stub return false; } @Override public boolean accelerometerMoved(Controller controller, - int accelerometerCode, Vector3 value) { + int accelerometerCode, Vector3 value){ + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean scrolled(int amount){ // TODO Auto-generated method stub return false; } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java index 923bf95..13b5af2 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/MainMenuStateBase.java @@ -15,6 +15,7 @@ */ package ve.ucv.ciens.ccg.nxtar.states; +import ve.ucv.ciens.ccg.nxtar.NxtARCore.game_states_t; import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import com.badlogic.gdx.Gdx; @@ -23,6 +24,7 @@ import com.badlogic.gdx.controllers.Controller; import com.badlogic.gdx.controllers.PovDirection; import com.badlogic.gdx.controllers.mappings.Ouya; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.Texture.TextureFilter; import com.badlogic.gdx.graphics.Texture.TextureWrap; @@ -34,6 +36,7 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; import com.badlogic.gdx.graphics.g2d.freetype.FreeTypeFontGenerator; import com.badlogic.gdx.graphics.glutils.ShaderProgram; import com.badlogic.gdx.math.Rectangle; +import com.badlogic.gdx.math.Vector2; import com.badlogic.gdx.math.Vector3; import com.badlogic.gdx.scenes.scene2d.ui.TextButton; import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle; @@ -49,6 +52,7 @@ public abstract class MainMenuStateBase extends BaseState{ // Helper fields. protected boolean clientConnected; private float u_scaling[]; + protected OrthographicCamera pixelPerfectCamera; // Buttons and other gui components. protected TextButton startButton; @@ -72,9 +76,17 @@ public abstract class MainMenuStateBase extends BaseState{ private Texture backgroundTexture; private ShaderProgram backgroundShader; + // Button touch helper fields. + private Vector3 win2world; + protected Vector2 touchPointWorldCoords; + protected boolean startButtonTouched; + protected int startButtonTouchPointer; + public MainMenuStateBase(){ TextureRegion region; + this.pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + // Create the start button background. startButtonEnabledTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Pill_Button_Yellow.png")); startButtonEnabled9p = new NinePatch(new TextureRegion(startButtonEnabledTexture, 0, 0, startButtonEnabledTexture.getWidth(), startButtonEnabledTexture.getHeight()), 49, 49, 45, 45); @@ -131,6 +143,12 @@ public abstract class MainMenuStateBase extends BaseState{ u_scaling[0] = Gdx.graphics.getWidth() > Gdx.graphics.getHeight() ? 16.0f : 9.0f; u_scaling[1] = Gdx.graphics.getHeight() > Gdx.graphics.getWidth() ? 16.0f : 9.0f; + + win2world = new Vector3(0.0f, 0.0f, 0.0f); + touchPointWorldCoords = new Vector2(); + startButtonTouched = false; + startButtonTouchPointer = -1; + clientConnected = false; stateActive = false; } @@ -139,18 +157,18 @@ public abstract class MainMenuStateBase extends BaseState{ public abstract void render(float delta); @Override - public abstract void resize(int width, int height); + public void resize(int width, int height){ } @Override - public abstract void show(); + public void show(){ } @Override - public abstract void hide(); + public void hide(){ } @Override - public abstract void pause(); + public void pause(){ } @Override - public abstract void resume(); + public void resume(){ } @Override public void dispose(){ @@ -194,19 +212,82 @@ public abstract class MainMenuStateBase extends BaseState{ startButton.setDisabled(false); } - /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; INPUT LISTENER METHOD STUBS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + /*;;;;;;;;;;;;;;;;;; + ; HELPER METHODS ; + ;;;;;;;;;;;;;;;;;;*/ + + protected void unprojectTouch(int screenX, int screenY){ + win2world.set(screenX, screenY, 0.0f); + pixelPerfectCamera.unproject(win2world); + touchPointWorldCoords.set(win2world.x, win2world.y); + } + + /*;;;;;;;;;;;;;;;;;;;;;;;;;; + ; INPUT LISTENER METHODS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + + @Override + public boolean touchDown(int screenX, int screenY, int pointer, int button){ + unprojectTouch(screenX, screenY); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ + startButton.setChecked(true); + startButtonTouched = true; + startButtonTouchPointer = pointer; + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button pressed."); + } + + return true; + } + + @Override + public boolean touchUp(int screenX, int screenY, int pointer, int button){ + unprojectTouch(screenX, screenY); + + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); + Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); + + if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ + startButton.setChecked(false); + startButtonTouched = false; + startButtonTouchPointer = -1; + core.nextState = game_states_t.IN_GAME; + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button released."); + } + + return true; + } + + @Override + public boolean touchDragged(int screenX, int screenY, int pointer){ + unprojectTouch(screenX, screenY); + + if(!startButton.isDisabled() && startButtonTouched && pointer == startButtonTouchPointer && !startButtonBBox.contains(touchPointWorldCoords)){ + startButtonTouchPointer = -1; + startButtonTouched = false; + startButton.setChecked(false); + Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Start button released."); + } + + return true; + } @Override public boolean keyDown(int keycode){ if(keycode == Input.Keys.BACK){ - // TODO: Go to pause state. + // Ignore. return true; } return false; } + /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + ; INPUT LISTENER METHOD STUBS ; + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ + @Override public boolean keyUp(int keycode){ return false; @@ -217,21 +298,6 @@ public abstract class MainMenuStateBase extends BaseState{ return false; } - @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button){ - return false; - } - - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button){ - return false; - } - - @Override - public boolean touchDragged(int screenX, int screenY, int pointer){ - return false; - } - @Override public boolean mouseMoved(int screenX, int screenY){ return false; diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java index def2202..ac1be8a 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/OuyaMainMenuState.java @@ -22,7 +22,6 @@ import com.badlogic.gdx.Gdx; import com.badlogic.gdx.controllers.Controller; import com.badlogic.gdx.controllers.mappings.Ouya; import com.badlogic.gdx.graphics.GL10; -import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.Texture; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.graphics.g2d.TextureRegion; @@ -30,14 +29,12 @@ import com.badlogic.gdx.graphics.g2d.TextureRegion; public class OuyaMainMenuState extends MainMenuStateBase{ private static final String CLASS_NAME = OuyaMainMenuState.class.getSimpleName(); - private OrthographicCamera pixelPerfectCamera; private Texture ouyaOButtonTexture; private Sprite ouyaOButton; private boolean oButtonPressed; public OuyaMainMenuState(final NxtARCore core){ this.core = core; - this.pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); startButton.setPosition(-(startButton.getWidth() / 2), -(startButton.getHeight() / 2)); startButtonBBox.setPosition(startButton.getX(), startButton.getY()); @@ -53,7 +50,7 @@ public class OuyaMainMenuState extends MainMenuStateBase{ TextureRegion region = new TextureRegion(ouyaOButtonTexture, ouyaOButtonTexture.getWidth(), ouyaOButtonTexture.getHeight()); ouyaOButton = new Sprite(region); ouyaOButton.setSize(ouyaOButton.getWidth() * 0.6f, ouyaOButton.getHeight() * 0.6f); - ouyaOButton.setPosition(startButton.getX() - ouyaOButton.getWidth() - 20, startButton.getY()); + ouyaOButton.setPosition(startButton.getX() - ouyaOButton.getWidth() - 20, startButton.getY() + (ouyaOButton.getHeight() / 2)); oButtonPressed = false; } @@ -78,36 +75,6 @@ public class OuyaMainMenuState extends MainMenuStateBase{ }core.batch.end(); } - @Override - public void resize(int width, int height) { - // TODO Auto-generated method stub - - } - - @Override - public void show() { - // TODO Auto-generated method stub - - } - - @Override - public void hide() { - // TODO Auto-generated method stub - - } - - @Override - public void pause() { - // TODO Auto-generated method stub - - } - - @Override - public void resume() { - // TODO Auto-generated method stub - - } - @Override public void dispose(){ super.dispose(); diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java index 2d3043f..13bcfbb 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/TabletMainMenuState.java @@ -16,37 +16,16 @@ package ve.ucv.ciens.ccg.nxtar.states; import ve.ucv.ciens.ccg.nxtar.NxtARCore; -import ve.ucv.ciens.ccg.nxtar.NxtARCore.game_states_t; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.GL10; -import com.badlogic.gdx.graphics.OrthographicCamera; -import com.badlogic.gdx.math.Vector2; -import com.badlogic.gdx.math.Vector3; public class TabletMainMenuState extends MainMenuStateBase{ - private static final String CLASS_NAME = TabletMainMenuState.class.getSimpleName(); - - private OrthographicCamera pixelPerfectCamera; - - // Button touch helper fields. - private Vector3 win2world; - private Vector2 touchPointWorldCoords; - private boolean startButtonTouched; - private int startButtonTouchPointer; - public TabletMainMenuState(final NxtARCore core){ this.core = core; - pixelPerfectCamera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); startButton.setPosition(-(startButton.getWidth() / 2), -(startButton.getHeight() / 2)); startButtonBBox.setPosition(startButton.getX(), startButton.getY()); - win2world = new Vector3(0.0f, 0.0f, 0.0f); - touchPointWorldCoords = new Vector2(); - - startButtonTouched = false; - startButtonTouchPointer = -1; - float ledYPos = (-(Gdx.graphics.getHeight() / 2) * 0.5f) + (startButton.getY() * 0.5f); clientConnectedLedOn.setSize(clientConnectedLedOn.getWidth() * 0.5f, clientConnectedLedOn.getHeight() * 0.5f); clientConnectedLedOn.setPosition(-(clientConnectedLedOn.getWidth() / 2), ledYPos); @@ -74,87 +53,4 @@ public class TabletMainMenuState extends MainMenuStateBase{ startButton.draw(core.batch, 1.0f); }core.batch.end(); } - - @Override - public void resize(int width, int height){ } - - @Override - public void show(){ } - - @Override - public void hide(){ } - - @Override - public void pause(){ } - - @Override - public void resume(){ } - - @Override - public void dispose(){ - super.dispose(); - } - - /*;;;;;;;;;;;;;;;;;; - ; HELPER METHODS ; - ;;;;;;;;;;;;;;;;;;*/ - - private void unprojectTouch(int screenX, int screenY){ - win2world.set(screenX, screenY, 0.0f); - pixelPerfectCamera.unproject(win2world); - touchPointWorldCoords.set(win2world.x, win2world.y); - } - - /*;;;;;;;;;;;;;;;;;;;;;;;;;;; - ; INPUT LISTENER METHODS ; - ;;;;;;;;;;;;;;;;;;;;;;;;;;;*/ - - @Override - public boolean touchDown(int screenX, int screenY, int pointer, int button){ - unprojectTouch(screenX, screenY); - - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchDown() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - - if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ - startButton.setChecked(true); - startButtonTouched = true; - startButtonTouchPointer = pointer; - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button pressed."); - } - - return true; - } - - @Override - public boolean touchUp(int screenX, int screenY, int pointer, int button){ - unprojectTouch(screenX, screenY); - - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp(%d, %d, %d, %d)", screenX, screenY, pointer, button)); - Gdx.app.log(TAG, CLASS_NAME + String.format(".touchUp() :: Unprojected touch point: (%f, %f)", touchPointWorldCoords.x, touchPointWorldCoords.y)); - - if(!startButton.isDisabled() && startButtonBBox.contains(touchPointWorldCoords)){ - startButton.setChecked(false); - startButtonTouched = false; - startButtonTouchPointer = -1; - core.nextState = game_states_t.IN_GAME; - Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Start button released."); - } - - return true; - } - - @Override - public boolean touchDragged(int screenX, int screenY, int pointer){ - unprojectTouch(screenX, screenY); - - if(!startButton.isDisabled() && startButtonTouched && pointer == startButtonTouchPointer && !startButtonBBox.contains(touchPointWorldCoords)){ - startButtonTouchPointer = -1; - startButtonTouched = false; - startButton.setChecked(false); - Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Start button released."); - } - - return true; - } } diff --git a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java index e0d15ab..d53873a 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java +++ b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java @@ -17,11 +17,15 @@ package ve.ucv.ciens.ccg.nxtar.utils; import com.badlogic.gdx.controllers.mappings.Ouya; -public abstract class ProjectConstants { - public static final int SERVER_UDP_PORT = 8889; - public static final int SERVER_TCP_PORT_1 = 9989; - public static final int SERVER_TCP_PORT_2 = 9990; +public abstract class ProjectConstants{ + public static final int SERVICE_DISCOVERY_PORT = 9988; + public static final int VIDEO_STREAMING_PORT = 9989; + public static final int MOTOR_CONTROL_PORT = 9990; + public static final int SENSOR_REPORT_PORT = 9991; + public static final int APP_CONTROL_PORT = 9992; + public static final String MULTICAST_ADDRESS = "230.0.0.1"; + public static final int EXIT_SUCCESS = 0; public static final int EXIT_FAILURE = 1; @@ -31,8 +35,8 @@ public abstract class ProjectConstants { public static final float OVERSCAN; - public static final String FONT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.,:;!?"; - + public static final String FONT_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; + static{ OVERSCAN = Ouya.runningOnOuya ? 0.9f : 1.0f; } From 97b27f736aee6f849ff1dd9168c72b3578dbdebe Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 11 Feb 2014 17:44:54 -0430 Subject: [PATCH 16/16] Fixed robot control logic. Added gamepad support (not tested). --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 4 +- .../ciens/ccg/nxtar/states/InGameState.java | 332 ++++++++++++++---- 2 files changed, 264 insertions(+), 72 deletions(-) diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index eb633f3..e90ad5f 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -204,8 +204,8 @@ public class NxtARCore extends Game implements NetworkConnectionListener{ Controllers.addListener(states[currState.getValue()]); // Anything else. - //Gdx.app.setLogLevel(Application.LOG_INFO); - Gdx.app.setLogLevel(Application.LOG_DEBUG); + Gdx.app.setLogLevel(Application.LOG_INFO); + //Gdx.app.setLogLevel(Application.LOG_DEBUG); //Gdx.app.setLogLevel(Application.LOG_NONE); } diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java index 9b063a5..dfd5ea2 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java @@ -67,16 +67,21 @@ public class InGameState extends BaseState{ // Interface buttons. private Texture buttonTexture; + private Texture buttonTexture2; private Sprite motorA; private Sprite motorB; private Sprite motorC; private Sprite motorD; + private Sprite headA; + private Sprite headB; // Button touch helper fields. private Vector3 win2world; private Vector2 touchPointWorldCoords; private boolean[] motorButtonsTouched; private int[] motorButtonsPointers; + private boolean[] motorGamepadButtonPressed; + private boolean[] axisStopSent; // Monitors. private VideoFrameMonitor frameMonitor; @@ -99,17 +104,32 @@ public class InGameState extends BaseState{ // Set up input handling support fields. win2world = new Vector3(0.0f, 0.0f, 0.0f); touchPointWorldCoords = new Vector2(); - motorButtonsTouched = new boolean[4]; + + motorButtonsTouched = new boolean[6]; motorButtonsTouched[0] = false; motorButtonsTouched[1] = false; motorButtonsTouched[2] = false; motorButtonsTouched[3] = false; + motorButtonsTouched[4] = false; + motorButtonsTouched[5] = false; - motorButtonsPointers = new int[4]; + motorButtonsPointers = new int[6]; motorButtonsPointers[0] = -1; motorButtonsPointers[1] = -1; motorButtonsPointers[2] = -1; motorButtonsPointers[3] = -1; + motorButtonsPointers[4] = -1; + motorButtonsPointers[5] = -1; + + motorGamepadButtonPressed = new boolean[2]; + motorGamepadButtonPressed[0] = false; + motorGamepadButtonPressed[1] = false; + + axisStopSent = new boolean[4]; + axisStopSent[0] = true; + axisStopSent[1] = true; + axisStopSent[2] = true; + axisStopSent[3] = true; backgroundTexture = new Texture(Gdx.files.internal("data/gfx/textures/tile_aqua.png")); backgroundTexture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat); @@ -191,6 +211,8 @@ public class InGameState extends BaseState{ motorB.draw(core.batch); motorC.draw(core.batch); motorD.draw(core.batch); + headA.draw(core.batch); + headB.draw(core.batch); } }core.batch.end(); @@ -221,6 +243,8 @@ public class InGameState extends BaseState{ videoFrameTexture.dispose(); if(buttonTexture != null) buttonTexture.dispose(); + if(buttonTexture2 != null) + buttonTexture2.dispose(); backgroundTexture.dispose(); if(backgroundShader != null) backgroundShader.dispose(); } @@ -267,6 +291,17 @@ public class InGameState extends BaseState{ motorB.setPosition(-(Gdx.graphics.getWidth() / 2) + 20 + (motorA.getWidth() / 2), -(Gdx.graphics.getHeight() / 2) + 10); motorC.setPosition((Gdx.graphics.getWidth() / 2) - (1.5f * (motorD.getWidth())) - 20, -(Gdx.graphics.getHeight() / 2) + 10); motorD.setPosition((Gdx.graphics.getWidth() / 2) - motorD.getWidth() - 10, -(Gdx.graphics.getHeight() / 2) + 20 + motorC.getHeight()); + + buttonTexture2 = new Texture(Gdx.files.internal("data/gfx/gui/orange_glowy_button.png")); + + headA = new Sprite(buttonTexture2); + headA.setSize(headA.getWidth() * 0.3f, headA.getHeight() * 0.6f); + + headB = new Sprite(buttonTexture2); + headB.setSize(headB.getWidth() * 0.3f, headB.getHeight() * 0.6f); + + headA.setPosition(-headA.getWidth() - 10, motorA.getY() + (headA.getHeight() / 2)); + headB.setPosition(10, motorA.getY() + (headA.getHeight() / 2)); } /*;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -288,58 +323,69 @@ public class InGameState extends BaseState{ if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor A button pressed"); - // Enqueue the event corresponding to this button if the opposing button is not pressed already. - if(!motorButtonsTouched[1]){ - motorButtonsTouched[0] = true; - motorButtonsPointers[0] = pointer; + motorButtonsTouched[0] = true; + motorButtonsPointers[0] = pointer; - event = new MotorEvent(); - event.setMotor(motor_t.MOTOR_C); - event.setPower((byte)100); - queue.addEvent(event); - } + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte)100); + queue.addEvent(event); }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor B button pressed"); - // Enqueue the event corresponding to this button if the opposing button is not pressed already. - if(!motorButtonsTouched[0]){ - motorButtonsTouched[1] = true; - motorButtonsPointers[1] = pointer; - event = new MotorEvent(); - event.setMotor(motor_t.MOTOR_C); - event.setPower((byte)-100); - queue.addEvent(event); - } + motorButtonsTouched[1] = true; + motorButtonsPointers[1] = pointer; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte)-100); + queue.addEvent(event); }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor C button pressed"); - // Enqueue the event corresponding to this button if the opposing button is not pressed already. - if(!motorButtonsTouched[3]){ - motorButtonsTouched[2] = true; - motorButtonsPointers[2] = pointer; + motorButtonsTouched[2] = true; + motorButtonsPointers[2] = pointer; - event = new MotorEvent(); - event.setMotor(motor_t.MOTOR_A); - event.setPower((byte)-100); - queue.addEvent(event); - } + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte)-100); + queue.addEvent(event); }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Motor D button pressed"); - // Enqueue the event corresponding to this button if the opposing button is not pressed already. - if(!motorButtonsTouched[2]){ - motorButtonsTouched[3] = true; - motorButtonsPointers[3] = pointer; + motorButtonsTouched[3] = true; + motorButtonsPointers[3] = pointer; - event = new MotorEvent(); - event.setMotor(motor_t.MOTOR_A); - event.setPower((byte)100); - queue.addEvent(event); - } + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte)100); + queue.addEvent(event); + + }else if(headA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Head A button pressed"); + + motorButtonsTouched[4] = true; + motorButtonsPointers[4] = pointer; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte)-40); + queue.addEvent(event); + + }else if(headB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchDown() :: Head B button pressed"); + + motorButtonsTouched[5] = true; + motorButtonsPointers[5] = pointer; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte)40); + queue.addEvent(event); } } @@ -361,12 +407,11 @@ public class InGameState extends BaseState{ if(motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. if(!motorButtonsTouched[1]){ - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; - event = new MotorEvent(); event.setMotor(motor_t.MOTOR_C); event.setPower((byte) 0); @@ -376,11 +421,11 @@ public class InGameState extends BaseState{ }else if(motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. if(!motorButtonsTouched[0]){ - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; - event = new MotorEvent(); event.setMotor(motor_t.MOTOR_C); event.setPower((byte) 0); @@ -390,11 +435,11 @@ public class InGameState extends BaseState{ }else if(motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. if(!motorButtonsTouched[3]){ - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; - event = new MotorEvent(); event.setMotor(motor_t.MOTOR_A); event.setPower((byte) 0); @@ -404,17 +449,45 @@ public class InGameState extends BaseState{ }else if(motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. if(!motorButtonsTouched[2]){ - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; - event = new MotorEvent(); event.setMotor(motor_t.MOTOR_A); event.setPower((byte) 0); queue.addEvent(event); } + }else if(headA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Head A button released"); + + motorButtonsPointers[4] = -1; + motorButtonsTouched[4] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[5]){ + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte) 0); + queue.addEvent(event); + } + + }else if(headB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Head B button released"); + + motorButtonsPointers[5] = -1; + motorButtonsTouched[5] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[4]){ + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte) 0); + queue.addEvent(event); + } + } } return true; @@ -432,11 +505,11 @@ public class InGameState extends BaseState{ if(pointer == motorButtonsPointers[0] && !motorA.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor A button released"); + motorButtonsPointers[0] = -1; + motorButtonsTouched[0] = false; + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. if(!motorButtonsTouched[1]){ - motorButtonsPointers[0] = -1; - motorButtonsTouched[0] = false; - event = new MotorEvent(); event.setMotor(motor_t.MOTOR_C); event.setPower((byte) 0); @@ -446,11 +519,11 @@ public class InGameState extends BaseState{ }else if(pointer == motorButtonsPointers[1] && !motorB.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor B button released"); + motorButtonsPointers[1] = -1; + motorButtonsTouched[1] = false; + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. if(!motorButtonsTouched[0]){ - motorButtonsPointers[1] = -1; - motorButtonsTouched[1] = false; - event = new MotorEvent(); event.setMotor(motor_t.MOTOR_C); event.setPower((byte) 0); @@ -460,11 +533,11 @@ public class InGameState extends BaseState{ }else if(pointer == motorButtonsPointers[2] && !motorC.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor C button released"); + motorButtonsPointers[2] = -1; + motorButtonsTouched[2] = false; + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. if(!motorButtonsTouched[3]){ - motorButtonsPointers[2] = -1; - motorButtonsTouched[2] = false; - event = new MotorEvent(); event.setMotor(motor_t.MOTOR_A); event.setPower((byte) 0); @@ -474,17 +547,45 @@ public class InGameState extends BaseState{ }else if(pointer == motorButtonsPointers[3] && !motorD.getBoundingRectangle().contains(touchPointWorldCoords)){ Gdx.app.log(TAG, CLASS_NAME + ".touchDragged() :: Motor D button released"); + motorButtonsPointers[3] = -1; + motorButtonsTouched[3] = false; + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. if(!motorButtonsTouched[2]){ - motorButtonsPointers[3] = -1; - motorButtonsTouched[3] = false; - event = new MotorEvent(); event.setMotor(motor_t.MOTOR_A); event.setPower((byte) 0); queue.addEvent(event); } + }else if(pointer == motorButtonsPointers[4] && headA.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Head A button released"); + + motorButtonsPointers[4] = -1; + motorButtonsTouched[4] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[5]){ + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte) 0); + queue.addEvent(event); + } + + }else if(pointer == motorButtonsPointers[5] && headB.getBoundingRectangle().contains(touchPointWorldCoords)){ + Gdx.app.log(TAG, CLASS_NAME + ".touchUp() :: Head B button released"); + + motorButtonsPointers[5] = -1; + motorButtonsTouched[5] = false; + + // Enqueue the event corresponding to releasing this button if the opposing button is not pressed already. + if(!motorButtonsTouched[4]){ + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte) 0); + queue.addEvent(event); + } + } } return true; @@ -493,6 +594,7 @@ public class InGameState extends BaseState{ @Override public boolean keyDown(int keycode){ if(keycode == Input.Keys.BACK){ + // TODO: Go to pause state. core.nextState = game_states_t.MAIN_MENU; return true; } @@ -505,8 +607,33 @@ public class InGameState extends BaseState{ @Override public boolean buttonDown(Controller controller, int buttonCode){ - if(stateActive){ + MotorEvent event; + + if(stateActive && Ouya.runningOnOuya){ Gdx.app.log(TAG, CLASS_NAME + ".buttonDown() :: " + controller.getName() + " :: " + Integer.toString(buttonCode)); + + if(buttonCode == Ouya.BUTTON_L1){ + motorGamepadButtonPressed[0] = true; + + if(!motorGamepadButtonPressed[1]){ + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte)100); + queue.addEvent(event); + } + + }else if(buttonCode == Ouya.BUTTON_R1){ + motorGamepadButtonPressed[1] = true; + + if(!motorGamepadButtonPressed[0]){ + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte)-100); + queue.addEvent(event); + } + + } + return true; }else{ return false; @@ -515,8 +642,33 @@ public class InGameState extends BaseState{ @Override public boolean buttonUp(Controller controller, int buttonCode){ - if(stateActive){ + MotorEvent event; + + if(stateActive && Ouya.runningOnOuya){ Gdx.app.log(TAG, CLASS_NAME + ".buttonDown() :: " + controller.getName() + " :: " + Integer.toString(buttonCode)); + + if(buttonCode == Ouya.BUTTON_L1){ + motorGamepadButtonPressed[0] = false; + + if(!motorGamepadButtonPressed[1]){ + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte)0); + queue.addEvent(event); + } + + }else if(buttonCode == Ouya.BUTTON_R1){ + motorGamepadButtonPressed[1] = false; + + if(!motorGamepadButtonPressed[0]){ + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_B); + event.setPower((byte)0); + queue.addEvent(event); + } + + } + return true; }else{ return false; @@ -525,13 +677,53 @@ public class InGameState extends BaseState{ @Override public boolean axisMoved(Controller controller, int axisCode, float value){ - if(stateActive){ - if(value >= Ouya.STICK_DEADZONE){ - if(axisCode == Ouya.AXIS_LEFT_TRIGGER){ - Gdx.app.log(TAG, CLASS_NAME + ".axisMoved() :: LEFT TRIGGER pressed."); + MotorEvent event; + + if(stateActive && Ouya.runningOnOuya){ + if(Math.abs(value) >= Ouya.STICK_DEADZONE * 3.0f){ + + if(axisCode == Ouya.AXIS_LEFT_Y){ + Gdx.app.log(TAG, CLASS_NAME + ".axisMoved() :: LEFT Y moved: "+ Float.toString(value)); + + axisStopSent[0] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte)(100.0f * -value)); + queue.addEvent(event); + + }else if(axisCode == Ouya.AXIS_RIGHT_Y){ + Gdx.app.log(TAG, CLASS_NAME + ".axisMoved() :: RIGHT Y moved: "+ Float.toString(value)); + + axisStopSent[1] = false; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte)(100.0f * -value)); + queue.addEvent(event); + } - if(axisCode == Ouya.AXIS_RIGHT_TRIGGER){ - Gdx.app.log(TAG, CLASS_NAME + ".axisMoved() :: RIGHT TRIGGER pressed."); + + }else{ + + if(axisCode == Ouya.AXIS_LEFT_Y && !axisStopSent[0]){ + + axisStopSent[0] = true; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_A); + event.setPower((byte)0); + queue.addEvent(event); + + }else if(axisCode == Ouya.AXIS_RIGHT_Y && !axisStopSent[1]){ + + axisStopSent[1] = true; + + event = new MotorEvent(); + event.setMotor(motor_t.MOTOR_C); + event.setPower((byte)0); + queue.addEvent(event); + } } return true;