From b937b93767d10049b07ece7cc03fd15f5809fd93 Mon Sep 17 00:00:00 2001 From: Miguel Astor Date: Mon, 20 Jan 2014 13:00:29 -0430 Subject: [PATCH 1/6] 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 2/6] 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 3/6] 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 4/6] 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 5/6] 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 6/6] 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; + } }