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{