From 8bd799f146d8bdf296b85bc298038598b927f723 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jun 2014 17:57:57 -0430 Subject: [PATCH] All bombs sucessfully implemented. --- src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java | 7 +- .../BombGameObjectTypeComponent.java | 1 + .../nxtar/components/FadeEffectComponent.java | 72 +++++ .../nxtar/entities/BombGameEntityCreator.java | 2 +- .../ciens/ccg/nxtar/states/InGameState.java | 101 ++++++- .../nxtar/systems/BombGameLogicSystem.java | 259 ++++++++++++++---- .../systems/FadeEffectRenderingSystem.java | 57 ++++ .../systems/RobotArmPositioningSystem.java | 1 + .../ccg/nxtar/utils/ProjectConstants.java | 3 +- 9 files changed, 441 insertions(+), 62 deletions(-) create mode 100644 src/ve/ucv/ciens/ccg/nxtar/components/FadeEffectComponent.java create mode 100644 src/ve/ucv/ciens/ccg/nxtar/systems/FadeEffectRenderingSystem.java diff --git a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java index fac2280..14f25f5 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java +++ b/src/ve/ucv/ciens/ccg/nxtar/NxtARCore.java @@ -390,10 +390,11 @@ public class NxtARCore extends Game implements ApplicationEventsListener{ batch.setProjectionMatrix(pixelPerfectCamera.combined); batch.begin();{ // Draw the FPS overlay. - font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), overlayX, overlayY); - font.draw(batch, String.format("Total stream FPS: %d", videoThread.getFps()), overlayX, overlayY - font.getCapHeight() - 5); - font.draw(batch, String.format("Lost stream FPS: %d", videoThread.getLostFrames()), overlayX, overlayY - (2 * font.getCapHeight()) - 10); + font.draw(batch, String.format("Render FPS: %d", Gdx.graphics.getFramesPerSecond()), overlayX, overlayY); + font.draw(batch, String.format("Total stream FPS: %d", videoThread.getFps()), overlayX, overlayY - font.getCapHeight() - 5); + font.draw(batch, String.format("Lost stream FPS: %d", videoThread.getLostFrames()), overlayX, overlayY - (2 * font.getCapHeight()) - 10); font.draw(batch, String.format("Light sensor data: %d", sensorThread.getLightSensorReading()), overlayX, overlayY - (3 * font.getCapHeight()) - 15); + font.draw(batch, String.format("Device roll: %f", Gdx.input.getRoll()), overlayX, overlayY - (4 * font.getCapHeight()) - 20); }batch.end(); } } diff --git a/src/ve/ucv/ciens/ccg/nxtar/components/BombGameObjectTypeComponent.java b/src/ve/ucv/ciens/ccg/nxtar/components/BombGameObjectTypeComponent.java index a0c923f..5fd7862 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/components/BombGameObjectTypeComponent.java +++ b/src/ve/ucv/ciens/ccg/nxtar/components/BombGameObjectTypeComponent.java @@ -28,6 +28,7 @@ public class BombGameObjectTypeComponent extends Component { public static final int COM_BUTTON_4 = 33; public static final int DOOR = 40; public static final int DOOR_FRAME = 41; + public static final int FADE_EFFECT = 90; public int type; diff --git a/src/ve/ucv/ciens/ccg/nxtar/components/FadeEffectComponent.java b/src/ve/ucv/ciens/ccg/nxtar/components/FadeEffectComponent.java new file mode 100644 index 0000000..1490354 --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtar/components/FadeEffectComponent.java @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014 Miguel Angel Astor Romero + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package ve.ucv.ciens.ccg.nxtar.components; + +import aurelienribon.tweenengine.Tween; +import aurelienribon.tweenengine.TweenEquations; +import aurelienribon.tweenengine.primitives.MutableFloat; + +import com.artemis.Component; + +public class FadeEffectComponent extends Component{ + private MutableFloat alpha; + private Tween fadeIn; + private Tween fadeOut; + + public FadeEffectComponent(boolean fadeIn){ + if(fadeIn){ + this.alpha = new MutableFloat(1.0f); + this.fadeIn = Tween.to(alpha, 0, 2.0f).target(0.0f).ease(TweenEquations.easeInQuint); + this.fadeOut = null; + }else{ + this.alpha = new MutableFloat(0.0f); + this.fadeOut = Tween.to(alpha, 0, 2.5f).target(1.0f).ease(TweenEquations.easeInQuint); + this.fadeIn = null; + } + } + + public float getFloatValue(){ + return alpha.floatValue(); + } + + public void update(float delta){ + if(fadeIn != null) + fadeIn.update(delta); + + if(fadeOut != null) + fadeOut.update(delta); + } + + public void startEffect(){ + if(fadeIn != null) + fadeIn.start(); + + if(fadeOut != null) + fadeOut.start(); + } + + public boolean isEffectStarted(){ + return fadeIn != null ? fadeIn.isStarted() : fadeOut.isStarted(); + } + + public boolean isEffectFadeIn(){ + return fadeIn != null; + } + + public boolean isEffectFinished(){ + return fadeIn != null ? fadeIn.isFinished() : fadeOut.isFinished(); + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/entities/BombGameEntityCreator.java b/src/ve/ucv/ciens/ccg/nxtar/entities/BombGameEntityCreator.java index 2182716..fc4e6f4 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/entities/BombGameEntityCreator.java +++ b/src/ve/ucv/ciens/ccg/nxtar/entities/BombGameEntityCreator.java @@ -56,7 +56,7 @@ public class BombGameEntityCreator extends EntityCreatorBase{ public static final String DOORS_GROUP = "DOORS"; public static final Vector3 ROBOT_ARM_START_POINT = new Vector3(0.0f, 0.0f, -1.0f); public static final int DOOR_OPEN_ANIMATION = 1; - public static final int DOOR_CLOSE_ANIMATION = 1; + public static final int DOOR_CLOSE_ANIMATION = 0; private class EntityParameters{ public Environment environment; diff --git a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java index f4a3338..ab8529a 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java +++ b/src/ve/ucv/ciens/ccg/nxtar/states/InGameState.java @@ -29,6 +29,7 @@ import ve.ucv.ciens.ccg.nxtar.network.monitors.MotorEventQueue; import ve.ucv.ciens.ccg.nxtar.network.monitors.VideoFrameMonitor; import ve.ucv.ciens.ccg.nxtar.systems.AnimationSystem; import ve.ucv.ciens.ccg.nxtar.systems.CollisionDetectionSystem; +import ve.ucv.ciens.ccg.nxtar.systems.FadeEffectRenderingSystem; import ve.ucv.ciens.ccg.nxtar.systems.GeometrySystem; import ve.ucv.ciens.ccg.nxtar.systems.MarkerPositioningSystem; import ve.ucv.ciens.ccg.nxtar.systems.MarkerRenderingSystem; @@ -61,6 +62,7 @@ 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 BACKGROUND_SHADER_PATH = "shaders/bckg/bckg"; + private static final String ALPHA_SHADER_PREFIX = "shaders/alphaSprite/alpha"; private static final float NEAR = 0.01f; private static final float FAR = 100.0f; @@ -91,12 +93,16 @@ public class InGameState extends BaseState{ private ModelBatch modelBatch; private FrameBuffer frameBuffer; private Sprite frameBufferSprite; + private FrameBuffer robotArmFrameBuffer; + private Sprite robotArmFrameBufferSprite; + private ShaderProgram alphaShader; // Game related fields. private World gameWorld; private MarkerRenderingSystem markerRenderingSystem; private ObjectRenderingSystem objectRenderingSystem; private RobotArmPositioningSystem robotArmPositioningSystem; + private FadeEffectRenderingSystem fadeEffectRenderingSystem; private robot_control_mode_t controlMode; // Cameras. @@ -114,6 +120,8 @@ public class InGameState extends BaseState{ private Texture headControlButtonTexture; private Texture wheelControlButtonTexture; private Texture armControlButtonTexture; + private Texture correctAngleLedOnTexture; + private Texture correctAngleLedOffTexture; private Sprite motorAButton; private Sprite motorBButton; private Sprite motorCButton; @@ -123,6 +131,8 @@ public class InGameState extends BaseState{ private Sprite headCButton; private Sprite wheelControlButton; private Sprite armControlButton; + private Sprite correctAngleLedOnSprite; + private Sprite correctAngleLedOffSprite; // Button touch helper fields. private boolean[] buttonsTouched; @@ -192,7 +202,7 @@ public class InGameState extends BaseState{ // Set up the shader. backgroundShader = new ShaderProgram(Gdx.files.internal(BACKGROUND_SHADER_PATH + "_vert.glsl"), Gdx.files.internal(BACKGROUND_SHADER_PATH + "_frag.glsl")); if(!backgroundShader.isCompiled()){ - Gdx.app.error(TAG, CLASS_NAME + ".MainMenuStateBase() :: Failed to compile the background shader."); + Gdx.app.error(TAG, CLASS_NAME + ".InGameState() :: Failed to compile the background shader."); Gdx.app.error(TAG, CLASS_NAME + backgroundShader.getLog()); backgroundShader = null; } @@ -201,11 +211,21 @@ public class InGameState extends BaseState{ uScaling[0] = Gdx.graphics.getWidth() > Gdx.graphics.getHeight() ? 16.0f : 9.0f; uScaling[1] = Gdx.graphics.getHeight() > Gdx.graphics.getWidth() ? 16.0f : 9.0f; + // Set up the alpha shader. + alphaShader = new ShaderProgram(Gdx.files.internal(ALPHA_SHADER_PREFIX + "_vert.glsl"), Gdx.files.internal(ALPHA_SHADER_PREFIX + "_frag.glsl")); + if(!alphaShader.isCompiled()){ + Gdx.app.error(TAG, CLASS_NAME + ".InGameState() :: Failed to compile the alpha shader."); + Gdx.app.error(TAG, CLASS_NAME + alphaShader.getLog()); + alphaShader = null; + } + // Set up the 3D rendering. modelBatch = new ModelBatch(); frameBuffer = null; perspectiveCamera = null; frameBufferSprite = null; + robotArmFrameBuffer = null; + robotArmFrameBufferSprite = null; // Set up the game world. gameWorld = GameSettings.getGameWorld(); @@ -213,6 +233,7 @@ public class InGameState extends BaseState{ robotArmPositioningSystem = new RobotArmPositioningSystem(); markerRenderingSystem = new MarkerRenderingSystem(modelBatch); objectRenderingSystem = new ObjectRenderingSystem(modelBatch); + fadeEffectRenderingSystem = new FadeEffectRenderingSystem(); gameWorld.setSystem(new MarkerPositioningSystem()); gameWorld.setSystem(robotArmPositioningSystem, Ouya.runningOnOuya); @@ -222,6 +243,7 @@ public class InGameState extends BaseState{ gameWorld.setSystem(GameSettings.getGameLogicSystem()); gameWorld.setSystem(markerRenderingSystem, true); gameWorld.setSystem(objectRenderingSystem, true); + gameWorld.setSystem(fadeEffectRenderingSystem, true); gameWorld.initialize(); } @@ -263,6 +285,9 @@ public class InGameState extends BaseState{ frameBuffer = new FrameBuffer(Format.RGBA8888, w, h, true); frameBuffer.getColorBufferTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear); + robotArmFrameBuffer = new FrameBuffer(Format.RGBA8888, w, h, true); + robotArmFrameBuffer.getColorBufferTexture().setFilter(TextureFilter.Linear, TextureFilter.Linear); + perspectiveCamera = new CustomPerspectiveCamera(67, w, h); perspectiveCamera.translate(0.0f, 0.0f, 0.0f); perspectiveCamera.near = NEAR; @@ -315,12 +340,19 @@ public class InGameState extends BaseState{ markerRenderingSystem.begin(perspectiveCamera); markerRenderingSystem.process(); markerRenderingSystem.end(); + }frameBuffer.end(); + robotArmFrameBuffer.begin();{ + // Set OpenGL state. + Gdx.gl.glClearColor(0, 0, 0, 0); + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT); + Gdx.gl.glDisable(GL20.GL_TEXTURE_2D); + + // Call rendering systems. objectRenderingSystem.begin(perspectiveCamera); objectRenderingSystem.process(); objectRenderingSystem.end(); - - }frameBuffer.end(); + }robotArmFrameBuffer.end(); // Set the frame buffer object texture to a renderable sprite. region = new TextureRegion(frameBuffer.getColorBufferTexture(), 0, 0, frameBuffer.getWidth(), frameBuffer.getHeight()); @@ -332,6 +364,16 @@ public class InGameState extends BaseState{ frameBufferSprite.setOrigin(frameBufferSprite.getWidth() / 2, frameBufferSprite.getHeight() / 2); frameBufferSprite.setPosition(0, 0); + // Set the other frame buffer object texture to a renderable sprite. + region = new TextureRegion(robotArmFrameBuffer.getColorBufferTexture(), 0, 0, robotArmFrameBuffer.getWidth(), robotArmFrameBuffer.getHeight()); + region.flip(false, true); + if(robotArmFrameBufferSprite == null) + robotArmFrameBufferSprite = new Sprite(region); + else + robotArmFrameBufferSprite.setRegion(region); + robotArmFrameBufferSprite.setOrigin(robotArmFrameBuffer.getWidth() / 2, robotArmFrameBuffer.getHeight() / 2); + robotArmFrameBufferSprite.setPosition(0, 0); + // Set the position and orientation of the renderable video frame and the frame buffer. if(!Ouya.runningOnOuya){ renderableVideoFrame.setSize(1.0f, renderableVideoFrame.getHeight() / renderableVideoFrame.getWidth() ); @@ -341,6 +383,10 @@ public class InGameState extends BaseState{ frameBufferSprite.setSize(1.0f, frameBufferSprite.getHeight() / frameBufferSprite.getWidth() ); frameBufferSprite.rotate90(true); frameBufferSprite.translate(-frameBufferSprite.getWidth() / 2, 0.5f - frameBufferSprite.getHeight()); + + robotArmFrameBufferSprite.setSize(1.0f, robotArmFrameBufferSprite.getHeight() / robotArmFrameBufferSprite.getWidth() ); + robotArmFrameBufferSprite.rotate90(true); + robotArmFrameBufferSprite.translate(-robotArmFrameBufferSprite.getWidth() / 2, 0.5f - robotArmFrameBufferSprite.getHeight()); }else{ float xSize = Gdx.graphics.getHeight() * (w / h); renderableVideoFrame.setSize(xSize * ProjectConstants.OVERSCAN, Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN); @@ -350,6 +396,10 @@ public class InGameState extends BaseState{ frameBufferSprite.setSize(xSize * ProjectConstants.OVERSCAN, Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN); frameBufferSprite.rotate90(true); frameBufferSprite.translate(-frameBufferSprite.getWidth() / 2, -frameBufferSprite.getHeight() / 2); + + robotArmFrameBufferSprite.setSize(xSize * ProjectConstants.OVERSCAN, Gdx.graphics.getHeight() * ProjectConstants.OVERSCAN); + robotArmFrameBufferSprite.rotate90(true); + robotArmFrameBufferSprite.translate(-robotArmFrameBufferSprite.getWidth() / 2, -robotArmFrameBufferSprite.getHeight() / 2); } // Set the correct camera for the device. @@ -363,6 +413,13 @@ public class InGameState extends BaseState{ core.batch.begin();{ renderableVideoFrame.draw(core.batch); frameBufferSprite.draw(core.batch); + + if(alphaShader != null){ + core.batch.setShader(alphaShader); + } + robotArmFrameBufferSprite.draw(core.batch); + if(alphaShader != null) core.batch.setShader(null); + }core.batch.end(); // Clear the video frame from memory. @@ -389,9 +446,16 @@ public class InGameState extends BaseState{ throw new IllegalStateException("Unrecognized control mode: " + Integer.toString(controlMode.getValue())); } + if(Math.abs(Gdx.input.getRoll()) < ProjectConstants.MAX_ABS_ROLL){ + correctAngleLedOnSprite.draw(core.batch); + }else{ + correctAngleLedOffSprite.draw(core.batch); + } }core.batch.end(); } + fadeEffectRenderingSystem.process(); + data = null; } @@ -421,8 +485,22 @@ public class InGameState extends BaseState{ if(backgroundShader != null) backgroundShader.dispose(); + if(alphaShader != null) + alphaShader.dispose(); + if(frameBuffer != null) frameBuffer.dispose(); + + if(robotArmFrameBuffer != null) + robotArmFrameBuffer.dispose(); + + if(correctAngleLedOffTexture != null) + correctAngleLedOffTexture.dispose(); + + if(correctAngleLedOnTexture != null) + correctAngleLedOnTexture.dispose(); + + fadeEffectRenderingSystem.dispose(); } /*;;;;;;;;;;;;;;;;;; @@ -454,10 +532,13 @@ public class InGameState extends BaseState{ motorAButton = new Sprite(region); motorAButton.setSize(motorAButton.getWidth() * 0.7f, motorAButton.getHeight() * 0.7f); + motorBButton = new Sprite(region); motorBButton.setSize(motorBButton.getWidth() * 0.7f, motorBButton.getHeight() * 0.7f); + motorCButton = new Sprite(region); motorCButton.setSize(motorCButton.getWidth() * 0.7f, motorCButton.getHeight() * 0.7f); + motorDButton = new Sprite(region); motorDButton.setSize(motorDButton.getWidth() * 0.7f, motorDButton.getHeight() * 0.7f); @@ -487,11 +568,25 @@ public class InGameState extends BaseState{ wheelControlButton = new Sprite(wheelControlButtonTexture); wheelControlButton.setSize(wheelControlButton.getWidth() * 0.3f, wheelControlButton.getHeight() * 0.3f); + armControlButton = new Sprite(armControlButtonTexture); armControlButton.setSize(armControlButton.getWidth() * 0.3f, armControlButton.getHeight() * 0.3f); wheelControlButton.setPosition(-(wheelControlButton.getWidth() / 2), headCButton.getY() - headCButton.getHeight() - 15); armControlButton.setPosition(-(armControlButton.getWidth() / 2), headCButton.getY() - headCButton.getHeight() - 15); + + // Set up the correct angle leds. + correctAngleLedOnTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Button_Green.png")); + correctAngleLedOffTexture = new Texture(Gdx.files.internal("data/gfx/gui/Anonymous_Button_Red.png")); + + correctAngleLedOnSprite = new Sprite(correctAngleLedOnTexture); + correctAngleLedOffSprite = new Sprite(correctAngleLedOffTexture); + + correctAngleLedOnSprite.setSize(correctAngleLedOnSprite.getWidth() * 0.25f, correctAngleLedOnSprite.getHeight() * 0.25f); + correctAngleLedOffSprite.setSize(correctAngleLedOffSprite.getWidth() * 0.25f, correctAngleLedOffSprite.getHeight() * 0.25f); + + correctAngleLedOnSprite.setPosition(Gdx.graphics.getWidth() / 2 - correctAngleLedOnSprite.getWidth() - 5, Gdx.graphics.getHeight() / 2 - correctAngleLedOnSprite.getHeight() - 5); + correctAngleLedOffSprite.setPosition(Gdx.graphics.getWidth() / 2 - correctAngleLedOffSprite.getWidth() - 5, Gdx.graphics.getHeight() / 2 - correctAngleLedOffSprite.getHeight() - 5); } /*;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/src/ve/ucv/ciens/ccg/nxtar/systems/BombGameLogicSystem.java b/src/ve/ucv/ciens/ccg/nxtar/systems/BombGameLogicSystem.java index 8f2d6e7..79eb391 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/systems/BombGameLogicSystem.java +++ b/src/ve/ucv/ciens/ccg/nxtar/systems/BombGameLogicSystem.java @@ -18,42 +18,66 @@ package ve.ucv.ciens.ccg.nxtar.systems; import ve.ucv.ciens.ccg.nxtar.components.AnimationComponent; import ve.ucv.ciens.ccg.nxtar.components.BombGameObjectTypeComponent; import ve.ucv.ciens.ccg.nxtar.components.CollisionDetectionComponent; +import ve.ucv.ciens.ccg.nxtar.components.FadeEffectComponent; import ve.ucv.ciens.ccg.nxtar.components.MarkerCodeComponent; import ve.ucv.ciens.ccg.nxtar.components.VisibilityComponent; import ve.ucv.ciens.ccg.nxtar.entities.BombGameEntityCreator; +import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants; import com.artemis.Aspect; import com.artemis.ComponentMapper; import com.artemis.Entity; +import com.artemis.World; import com.artemis.annotations.Mapper; import com.artemis.managers.GroupManager; import com.artemis.utils.ImmutableBag; import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input.Peripheral; public class BombGameLogicSystem extends GameLogicSystemBase { private static final String TAG = "BOMB_GAME_LOGIC"; private static final String CLASS_NAME = BombGameLogicSystem.class.getSimpleName(); + private enum combination_button_state_t{ + CORRECT(0), INCORRECT(1), DISABLED(2); + + private int value; + + private combination_button_state_t(int value){ + this.value = value; + } + + public int getValue(){ + return this.value; + } + } + @Mapper ComponentMapper typeMapper; @Mapper ComponentMapper animationMapper; @Mapper ComponentMapper visibilityMapper; @Mapper ComponentMapper markerMapper; @Mapper ComponentMapper collisionMapper; + @Mapper ComponentMapper fadeMapper; private MarkerCodeComponent tempMarker; private BombGameObjectTypeComponent tempType; private GroupManager manager; + private int then; @SuppressWarnings("unchecked") public BombGameLogicSystem(){ super(Aspect.getAspectForAll(BombGameObjectTypeComponent.class)); - manager = world.getManager(GroupManager.class); + manager = null; + then = 0; } @Override protected void process(Entity e){ BombGameObjectTypeComponent typeComponent; + if(manager == null) + manager = world.getManager(GroupManager.class); + typeComponent = typeMapper.get(e); switch(typeComponent.type){ @@ -78,6 +102,10 @@ public class BombGameLogicSystem extends GameLogicSystemBase { processDoor(e); break; + case BombGameObjectTypeComponent.FADE_EFFECT: + processFade(e); + break; + default: break; } @@ -89,11 +117,9 @@ public class BombGameLogicSystem extends GameLogicSystemBase { * @param b An Artemis {@link Entity} that possibly represents any of a Wire Bomb's wires. */ private void processWireBomb(Entity b){ - int relatedWires = 0; CollisionDetectionComponent collision; MarkerCodeComponent marker; BombGameObjectTypeComponent wireType; - ImmutableBag related; // Get this wire's parameters. collision = collisionMapper.getSafe(b); @@ -107,27 +133,22 @@ public class BombGameLogicSystem extends GameLogicSystemBase { } // If this bomb is still enabled and it's door is already open then process it. - if(marker.enabled && isDoorOpen(marker.code, manager) && collision.colliding){ - manager.remove(b, CollisionDetectionSystem.COLLIDABLE_OBJECTS_GROUP); - manager.remove(b, Integer.toString(marker.code)); - b.deleteFromWorld(); - related = manager.getEntities(Integer.toString(marker.code)); + try{ + if(marker.enabled && isDoorOpen(marker.code, manager) && collision.colliding){ + manager.remove(b, CollisionDetectionSystem.COLLIDABLE_OBJECTS_GROUP); + manager.remove(b, Integer.toString(marker.code)); + b.deleteFromWorld(); - // Check the state of the other wires associated with this bomb. - for(int i = 0; i < related.size(); i++){ - tempType = typeMapper.getSafe(related.get(i)); - - if(tempType == null) continue; - - if(tempType.type >= BombGameObjectTypeComponent.BOMB_WIRE_1 && tempType.type <= BombGameObjectTypeComponent.BOMB_WIRE_3){ - if(tempType.type != wireType.type){ - relatedWires++; - } + if(wireType.type != BombGameObjectTypeComponent.BOMB_WIRE_1){ + Gdx.app.log(TAG, CLASS_NAME + ".processWireBomb(): Wire bomb exploded."); + createFadeOutEffect(); } - } - if(relatedWires == 0) disableBomb(marker.code); + Gdx.app.log(TAG, CLASS_NAME + ".processWireBomb(): Wire bomb disabled."); + } + }catch(IllegalArgumentException e){ + Gdx.app.error(TAG, CLASS_NAME + ".processWireBomb(): IllegalArgumentException caught: " + e.getMessage()); } } @@ -137,16 +158,15 @@ public class BombGameLogicSystem extends GameLogicSystemBase { * @param b An Artemis {@link Entity} that possibly represents any of a Combination Bomb's buttons. */ private void processCombinationBomb(Entity b){ - int relatedButtons = 0; + combination_button_state_t state; CollisionDetectionComponent collision; MarkerCodeComponent marker; BombGameObjectTypeComponent buttonType; - ImmutableBag related; // Get this wire's parameters. collision = collisionMapper.getSafe(b); marker = markerMapper.getSafe(b); - buttonType = typeMapper.getSafe(b); + buttonType = typeMapper.getSafe(b); // if any of the parameters is missing then skip. if(marker == null || collision == null || buttonType == null){ @@ -155,27 +175,27 @@ public class BombGameLogicSystem extends GameLogicSystemBase { } // If this bomb is still enabled and it's door is already open then process it. - if(marker.enabled && isDoorOpen(marker.code, manager) && collision.colliding){ - manager.remove(b, CollisionDetectionSystem.COLLIDABLE_OBJECTS_GROUP); - manager.remove(b, Integer.toString(marker.code)); - b.deleteFromWorld(); - related = manager.getEntities(Integer.toString(marker.code)); + try{ + if(marker.enabled && isDoorOpen(marker.code, manager) && collision.colliding){ + manager.remove(b, CollisionDetectionSystem.COLLIDABLE_OBJECTS_GROUP); + manager.remove(b, Integer.toString(marker.code)); + b.deleteFromWorld(); - // Check the state of the other wires associated with this bomb. - for(int i = 0; i < related.size(); i++){ - tempType = typeMapper.getSafe(related.get(i)); + // Check the state of the other buttons associated with this bomb. - if(tempType == null) continue; + state = checkCombinationBombButtons(buttonType.type, marker.code); - if(tempType.type >= BombGameObjectTypeComponent.COM_BUTTON_1 && tempType.type <= BombGameObjectTypeComponent.COM_BUTTON_4){ - if(tempType.type != buttonType.type){ - relatedButtons++; - } + if(state.getValue() == combination_button_state_t.INCORRECT.getValue()){ + Gdx.app.log(TAG, CLASS_NAME + ".processCombinationBomb(): Combination bomb exploded."); + createFadeOutEffect(); + disableBomb(marker.code); + }else if(state.getValue() == combination_button_state_t.DISABLED.getValue()){ + Gdx.app.log(TAG, CLASS_NAME + ".processCombinationBomb(): Combination bomb disabled."); + disableBomb(marker.code); } } - - if(relatedButtons == 0) - disableBomb(marker.code); + }catch(IllegalArgumentException e){ + Gdx.app.error(TAG, CLASS_NAME + ".processCombinationBomb(): IllegalArgumentException caught: " + e.getMessage()); } } @@ -188,6 +208,7 @@ public class BombGameLogicSystem extends GameLogicSystemBase { // Get the components of the big button. CollisionDetectionComponent collision = collisionMapper.getSafe(b); MarkerCodeComponent marker = markerMapper.getSafe(b); + float angle; // If any of the components is missing, skip this entity. if(marker == null || collision == null ){ @@ -196,17 +217,29 @@ public class BombGameLogicSystem extends GameLogicSystemBase { } // If this bomb is still enabled and it's door is already open then process it. - if(marker.enabled && isDoorOpen(marker.code, manager) && collision.colliding){ - // Disable the bomb and remove it from collision detection. - marker.enabled = false; - manager.remove(b, CollisionDetectionSystem.COLLIDABLE_OBJECTS_GROUP); - manager.remove(b, Integer.toString(marker.code)); - b.deleteFromWorld(); + try{ + if(marker.enabled && isDoorOpen(marker.code, manager) && collision.colliding){ + // Disable the bomb and remove it from collision detection. + marker.enabled = false; + manager.remove(b, CollisionDetectionSystem.COLLIDABLE_OBJECTS_GROUP); + manager.remove(b, Integer.toString(marker.code)); + b.deleteFromWorld(); - // Disable all related entities. - disableBomb(marker.code); + angle = Gdx.input.getRoll(); + Gdx.app.log("ROTATION", "Roll: " + Float.toString(angle)); - Gdx.app.log(TAG, CLASS_NAME + ".processInclinationBomb(): Inclination bomb disabled."); + if(Gdx.input.isPeripheralAvailable(Peripheral.Accelerometer) && Math.abs(angle) > ProjectConstants.MAX_ABS_ROLL){ + Gdx.app.log(TAG, CLASS_NAME + ".processInclinationBomb(): Inclination bomb exploded."); + createFadeOutEffect(); + } + + // Disable all related entities. + disableBomb(marker.code); + + Gdx.app.log(TAG, CLASS_NAME + ".processInclinationBomb(): Inclination bomb disabled."); + } + }catch(IllegalArgumentException e){ + Gdx.app.error(TAG, CLASS_NAME + ".processInclinationBomb(): IllegalArgumentException caught: " + e.getMessage()); } } @@ -241,7 +274,7 @@ public class BombGameLogicSystem extends GameLogicSystemBase { } }else{ // If the door is disabled and open, then set it's closing animation. - if(animation.current != 0){ + if(animation.current != BombGameEntityCreator.DOOR_CLOSE_ANIMATION){ animation.next = BombGameEntityCreator.DOOR_CLOSE_ANIMATION; animation.loop = false; Gdx.app.log(TAG, CLASS_NAME + ".processDoor(): Closing door."); @@ -256,12 +289,16 @@ public class BombGameLogicSystem extends GameLogicSystemBase { * @param markerCode The code of the door to check. Must be between 0 and 1023. * @param manager An Artemis {@link GroupManager} to use to get all related entities. * @return true if the opening animation of the door has finished playing. + * @throws IllegalArgumentException If marker code is not in the range [0, 1023], inclusive. */ - private boolean isDoorOpen(int markerCode, GroupManager manager){ + private boolean isDoorOpen(int markerCode, GroupManager manager) throws IllegalArgumentException{ AnimationComponent animation; boolean doorOpen = false; ImmutableBag doors = manager.getEntities(BombGameEntityCreator.DOORS_GROUP); + if(markerCode < 0 || markerCode > 1023) + throw new IllegalArgumentException("Marker code is not within range [0, 1023]: " + Integer.toString(markerCode)); + // For every door. for(int i = 0; i < doors.size(); i++){ tempMarker = markerMapper.getSafe(doors.get(i)); @@ -283,10 +320,14 @@ public class BombGameLogicSystem extends GameLogicSystemBase { *

Disables all entities associated with the corresponding marker code.

* * @param markerCode + * @throws IllegalArgumentException If marker code is not in the range [0, 1023], inclusive. */ - private void disableBomb(int markerCode){ + private void disableBomb(int markerCode) throws IllegalArgumentException{ ImmutableBag related = manager.getEntities(Integer.toString(markerCode)); + if(markerCode < 0 || markerCode > 1023) + throw new IllegalArgumentException("Marker code is not within range [0, 1023]: " + Integer.toString(markerCode)); + // Disable every entity sharing this marker code except for the corresponding door frame. for(int i = 0; i < related.size(); i++){ tempMarker = markerMapper.getSafe(related.get(i)); @@ -295,14 +336,124 @@ public class BombGameLogicSystem extends GameLogicSystemBase { // Enable collisions with the corresponding door frame entity. Disable collisions with other related entities. if(tempMarker != null) tempMarker.enabled = false; if(tempType != null){ - if(tempType.type != BombGameObjectTypeComponent.DOOR_FRAME){ + if(tempType.type != BombGameObjectTypeComponent.DOOR_FRAME && tempType.type != BombGameObjectTypeComponent.DOOR){ manager.remove(related.get(i), CollisionDetectionSystem.COLLIDABLE_OBJECTS_GROUP); manager.remove(related.get(i), Integer.toString(markerCode)); - related.get(i).deleteFromWorld(); - }else{ + }else if(tempType.type != BombGameObjectTypeComponent.DOOR_FRAME){ manager.add(related.get(i), CollisionDetectionSystem.COLLIDABLE_OBJECTS_GROUP); } } } } + + /** + *

Checks if a combination bomb is being disabled in the correct sequence.

+ * + * @param buttonType A number between {@link BombGameObjectTypeComponent.COM_BUTTON_1} and {@link BombGameObjectTypeComponent.COM_BUTTON_4}. + * @param markerCode A marker code between [0, 1023], inclusive. + * @return The current state of the bomb. + * @throws IllegalArgumentException If marker code is not in range or if buttonType is not valid. + */ + private combination_button_state_t checkCombinationBombButtons(int buttonType, int markerCode) throws IllegalArgumentException{ + combination_button_state_t state; + boolean correctSequence = true; + int remainingButtons = 0; + ImmutableBag related; + + if(buttonType < BombGameObjectTypeComponent.COM_BUTTON_1 || buttonType > BombGameObjectTypeComponent.COM_BUTTON_4) + throw new IllegalArgumentException("Button is not a valid combination bomb button: " + Integer.toString(buttonType)); + + if(markerCode < 0 || markerCode > 1023) + throw new IllegalArgumentException("Marker code is not within range [0, 1023]: " + Integer.toString(markerCode)); + + related = manager.getEntities(Integer.toString(markerCode)); + + // Check the state of the other buttons associated with this bomb. + for(int i = 0; i < related.size(); i++){ + tempType = typeMapper.getSafe(related.get(i)); + + if(tempType == null) continue; + + if(tempType.type >= BombGameObjectTypeComponent.COM_BUTTON_1 && tempType.type <= BombGameObjectTypeComponent.COM_BUTTON_4){ + if(tempType.type >= buttonType){ + // If this remaining button is a correct one then skip it. + remainingButtons++; + continue; + }else{ + // If this remaining button is an incorrect one then the sequence is wrong. + correctSequence = false; + break; + } + }else continue; + } + + if(!correctSequence) + state = combination_button_state_t.INCORRECT; + else + if(remainingButtons == 0) + state = combination_button_state_t.DISABLED; + else + state = combination_button_state_t.CORRECT; + + return state; + } + + /** + *

Adds a new fade out entity to the {@link World}.

+ */ + private void createFadeOutEffect(){ + Entity effect = world.createEntity(); + effect.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.FADE_EFFECT)); + effect.addComponent(new FadeEffectComponent(false)); + effect.addToWorld(); + } + + /** + *

Adds a new fade in entity to the {@link World}.

+ */ + private void createFadeInEffect(){ + Entity effect = world.createEntity(); + effect.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.FADE_EFFECT)); + effect.addComponent(new FadeEffectComponent(true)); + effect.addToWorld(); + } + + /** + *

Updates a fade effect entity.

+ * + * @param f An Artemis {@link Entity} possibly referencing a fade effect. + */ + private void processFade(Entity f){ + FadeEffectComponent fade = fadeMapper.getSafe(f); + + if(fade != null){ + if(!fade.isEffectStarted()) + fade.startEffect(); + + if(!fade.isEffectFinished()){ + // If the fade has not finished then just update it. + Gdx.app.log(TAG, CLASS_NAME + ".processFade(): Updating fade."); + fade.update(Gdx.graphics.getDeltaTime()); + }else{ + // If the fade finished. + if(fade.isEffectFadeIn()){ + // If the effect was a fade in then just remove it. + Gdx.app.log(TAG, CLASS_NAME + ".processFade(): deleting fade in."); + f.deleteFromWorld(); + }else{ + // If the effect was a fade out then wait for one second and then remove it and start a fade in. + then += (int)(Gdx.graphics.getDeltaTime() * 1000.0f); + if(then >= 1500){ + Gdx.app.log(TAG, CLASS_NAME + ".processFade(): Deleting fade out."); + f.deleteFromWorld(); + Gdx.app.log(TAG, CLASS_NAME + ".processFade(): Creating fade in."); + createFadeInEffect(); + then = 0; + }else{ + Gdx.app.log(TAG, CLASS_NAME + ".processFade(): Waiting after fade out: " + Integer.toString(then)); + } + } + } + } + } } diff --git a/src/ve/ucv/ciens/ccg/nxtar/systems/FadeEffectRenderingSystem.java b/src/ve/ucv/ciens/ccg/nxtar/systems/FadeEffectRenderingSystem.java new file mode 100644 index 0000000..32b49bd --- /dev/null +++ b/src/ve/ucv/ciens/ccg/nxtar/systems/FadeEffectRenderingSystem.java @@ -0,0 +1,57 @@ +package ve.ucv.ciens.ccg.nxtar.systems; + +import ve.ucv.ciens.ccg.nxtar.components.FadeEffectComponent; + +import com.artemis.Aspect; +import com.artemis.ComponentMapper; +import com.artemis.Entity; +import com.artemis.annotations.Mapper; +import com.artemis.systems.EntityProcessingSystem; +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.graphics.OrthographicCamera; +import com.badlogic.gdx.graphics.Pixmap; +import com.badlogic.gdx.graphics.Pixmap.Format; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.utils.Disposable; + +public class FadeEffectRenderingSystem extends EntityProcessingSystem implements Disposable{ + @Mapper ComponentMapper fadeMapper; + + private SpriteBatch batch; + private Texture fadeTexture; + private OrthographicCamera camera; + + @SuppressWarnings("unchecked") + public FadeEffectRenderingSystem(){ + super(Aspect.getAspectForAll(FadeEffectComponent.class)); + + this.batch = new SpriteBatch(); + this.batch.enableBlending(); + this.camera = new OrthographicCamera(Gdx.graphics.getWidth(), Gdx.graphics.getHeight()); + + Pixmap pixmap = new Pixmap(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), Format.RGBA4444); + pixmap.setColor(1, 1, 1, 1); + pixmap.fill(); + fadeTexture = new Texture(pixmap); + pixmap.dispose(); + } + + @Override + public void dispose(){ + this.fadeTexture.dispose(); + this.batch.dispose(); + } + + @Override + protected void process(Entity e) { + FadeEffectComponent fade = fadeMapper.get(e); + + this.batch.setProjectionMatrix(this.camera.combined); + this.batch.begin();{ + this.batch.setColor(1, 1, 1, fade.getFloatValue()); + this.batch.draw(fadeTexture, -(Gdx.graphics.getWidth() / 2), -(Gdx.graphics.getHeight() / 2)); + this.batch.setColor(1, 1, 1, 1); + }this.batch.end(); + } +} diff --git a/src/ve/ucv/ciens/ccg/nxtar/systems/RobotArmPositioningSystem.java b/src/ve/ucv/ciens/ccg/nxtar/systems/RobotArmPositioningSystem.java index 8a5e612..c7171e7 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/systems/RobotArmPositioningSystem.java +++ b/src/ve/ucv/ciens/ccg/nxtar/systems/RobotArmPositioningSystem.java @@ -147,6 +147,7 @@ public class RobotArmPositioningSystem extends EntityProcessingSystem { Gdx.app.log(TAG, CLASS_NAME + ".autoMove(): Going forward now."); }else if(auto.distance >= 1.0f || collision.colliding){ auto.forward = false; + auto.startPoint.set(BombGameEntityCreator.ROBOT_ARM_START_POINT); Gdx.app.log(TAG, CLASS_NAME + ".autoMove(): Going backwards now."); } diff --git a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java index 8d3c2c6..7ed1fe1 100644 --- a/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java +++ b/src/ve/ucv/ciens/ccg/nxtar/utils/ProjectConstants.java @@ -28,9 +28,10 @@ public abstract class ProjectConstants{ public static final int EXIT_SUCCESS = 0; public static final int EXIT_FAILURE = 1; - public static final boolean DEBUG = true; + public static final boolean DEBUG = false; public static final int[] POWERS_OF_2 = {64, 128, 256, 512, 1024, 2048}; + public static final float MAX_ABS_ROLL = 60.0f; public static final float OVERSCAN; public static final int MENU_BUTTON_FONT_SIZE;