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:

+ * + * @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; }