Added freeInstance to network. Modelling game logic.

This commit is contained in:
2014-06-11 11:18:12 -04:30
parent 8abf594c8a
commit 36eea36c15
15 changed files with 251 additions and 67 deletions

View File

@@ -425,8 +425,14 @@ public class NxtARCore extends Game implements ApplicationEventsListener{
*/
public void dispose(){
// Finish network threads.
serviceDiscoveryThread.finish();
videoThread.finish();
robotThread.finish();
sensorThread.finish();
ServiceDiscoveryThread.freeInstance();
VideoStreamingThread.freeInstance();
RobotControlThread.freeInstance();
SensorReportThread.freeInstance();
// Dispose graphic objects.
fadeTexture.dispose();

View File

@@ -24,11 +24,16 @@ import com.badlogic.gdx.graphics.g3d.utils.AnimationController;
public class AnimationComponent extends Component {
public AnimationController controller;
public AnimationController collisionController;
public List<String> animationsIds;
public int current;
public int next;
public boolean loop;
public AnimationComponent(ModelInstance instance, ModelInstance collisionInstance){
this(instance, -1, false, collisionInstance);
}
public AnimationComponent(ModelInstance instance) throws IllegalArgumentException{
this(instance, -1, false);
}
@@ -40,12 +45,11 @@ public class AnimationComponent extends Component {
public AnimationComponent(ModelInstance instance, int next, boolean loop) throws IllegalArgumentException{
if(instance == null)
throw new IllegalArgumentException("Instance is null.");
else if(next < 0)
throw new IllegalArgumentException("Next is less than 0.");
else if(next > instance.animations.size)
throw new IllegalArgumentException("Next is greater than the number of animations for this model.");
controller = new AnimationController(instance);
collisionController = null;
animationsIds = new LinkedList<String>();
current = -1;
this.next = next;
@@ -55,4 +59,18 @@ public class AnimationComponent extends Component {
animationsIds.add(instance.animations.get(i).id);
}
}
public AnimationComponent(ModelInstance instance, int next, boolean loop, ModelInstance collisionInstance) throws IllegalArgumentException{
this(instance, next, loop);
if(instance.animations.size != collisionInstance.animations.size)
throw new IllegalArgumentException("Animation number doesn't match between render model and collision model.");
for(int i = 0; i < instance.animations.size; i++){
if(!instance.animations.get(i).id.contentEquals(collisionInstance.animations.get(i).id))
throw new IllegalArgumentException("Animations don't match between render model and collision model.");
}
collisionController = new AnimationController(collisionInstance);
}
}

View File

@@ -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.components;
import com.artemis.Component;
public class BombGameObjectTypeComponent extends Component {
public static final int BOMB_WIRE_1 = 10;
public static final int BOMB_WIRE_2 = 11;
public static final int BOMB_WIRE_3 = 12;
public static final int BIG_BUTTON = 20;
public static final int COM_BUTTON_1 = 30;
public static final int COM_BUTTON_2 = 31;
public static final int COM_BUTTON_3 = 32;
public static final int COM_BUTTON_4 = 33;
public static final int DOOR = 40;
public int type;
public BombGameObjectTypeComponent(int type){
this.type = type;
}
}

View File

@@ -19,10 +19,17 @@ import com.artemis.Component;
public class MarkerCodeComponent extends Component {
public int code;
public boolean enabled;
public MarkerCodeComponent(int code) throws IllegalArgumentException{
if(code < 0 || code > 1024)
throw new IllegalArgumentException("Marker code must be between [0, 1024].");
this.code = code;
this.enabled = true;
}
public MarkerCodeComponent(int code, boolean enabled){
this(code);
this.enabled = enabled;
}
}

View File

@@ -19,6 +19,7 @@ import ve.ucv.ciens.ccg.nxtar.components.AnimationComponent;
import ve.ucv.ciens.ccg.nxtar.components.AutomaticMovementComponent;
import ve.ucv.ciens.ccg.nxtar.components.BombComponent;
import ve.ucv.ciens.ccg.nxtar.components.BombComponent.bomb_type_t;
import ve.ucv.ciens.ccg.nxtar.components.BombGameObjectTypeComponent;
import ve.ucv.ciens.ccg.nxtar.components.CollisionDetectionComponent;
import ve.ucv.ciens.ccg.nxtar.components.CollisionModelComponent;
import ve.ucv.ciens.ccg.nxtar.components.EnvironmentComponent;
@@ -182,7 +183,7 @@ public class BombGameEntityCreator extends EntityCreatorBase{
addBomb(parameters, bomb_type_t.WIRES);
// Add doors.
parameters.nextAnimation = 1;
parameters.nextAnimation = -1;
parameters.loopAnimation = false;
parameters.markerCode = 89;
@@ -293,7 +294,10 @@ public class BombGameEntityCreator extends EntityCreatorBase{
button3 = addBombParaphernalia(combinationButton3Model, combinationButton3CollisionModel, bomb, parameters);
button4 = addBombParaphernalia(combinationButton4Model, combinationButton4CollisionModel, bomb, parameters);
// TODO: Add button parameters.
button1.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.COM_BUTTON_1));
button2.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.COM_BUTTON_2));
button3.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.COM_BUTTON_3));
button4.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.COM_BUTTON_4));
button1.addToWorld();
button2.addToWorld();
@@ -305,9 +309,7 @@ public class BombGameEntityCreator extends EntityCreatorBase{
Entity button;
button = addBombParaphernalia(inclinationBombButtonModel, inclinationBombButtonCollisionModel, bomb, parameters);
// TODO: Add button parameters.
button.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.BIG_BUTTON));
button.addToWorld();
}
@@ -318,7 +320,9 @@ public class BombGameEntityCreator extends EntityCreatorBase{
wire2 = addBombParaphernalia(wiresBombModelWire2, wiresBombCollisionModelWire2, bomb, parameters);
wire3 = addBombParaphernalia(wiresBombModelWire3, wiresBombCollisionModelWire3, bomb, parameters);
// TODO: Add Wire parameters.
wire1.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.BOMB_WIRE_1));
wire2.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.BOMB_WIRE_2));
wire3.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.BOMB_WIRE_3));
wire1.addToWorld();
wire2.addToWorld();
@@ -337,6 +341,7 @@ public class BombGameEntityCreator extends EntityCreatorBase{
thing.addComponent(new BombComponent(bomb));
thing.addComponent(new VisibilityComponent());
thing.addComponent(new MarkerCodeComponent(parameters.markerCode));
thing.addComponent(new CollisionDetectionComponent());
groupManager.add(thing, CollisionDetectionSystem.COLLIDABLE_OBJECT);
if(DEBUG_RENDER_PARAPHERNALIA_COLLISION_MODELS)
@@ -346,7 +351,7 @@ public class BombGameEntityCreator extends EntityCreatorBase{
}
private void addDoor(EntityParameters parameters){
ModelInstance doorInstance;
ModelInstance doorInstance, doorColInstance;
Entity frame, door;
frame = world.createEntity();
@@ -368,7 +373,10 @@ public class BombGameEntityCreator extends EntityCreatorBase{
door.addComponent(new MarkerCodeComponent(parameters.markerCode));
door.addComponent(new VisibilityComponent());
doorInstance = door.getComponent(RenderModelComponent.class).instance;
door.addComponent(new AnimationComponent(doorInstance, parameters.nextAnimation, parameters.loopAnimation));
doorColInstance = door.getComponent(CollisionModelComponent.class).instance;
door.addComponent(new AnimationComponent(doorInstance, parameters.nextAnimation, parameters.loopAnimation, doorColInstance));
door.addComponent(new CollisionDetectionComponent());
door.addComponent(new BombGameObjectTypeComponent(BombGameObjectTypeComponent.DOOR));
groupManager.add(door, CollisionDetectionSystem.COLLIDABLE_OBJECT);
door.addToWorld();

View File

@@ -34,6 +34,7 @@ public class RobotControlThread extends Thread {
public static final String THREAD_NAME = "RobotControlThread";
private static final String TAG = "NXTAR_CORE_ROBOTTHREAD";
private static final String CLASS_NAME = RobotControlThread.class.getSimpleName();
private static int refCount = 0;
private ApplicationEventsListener netListener;
private ServerSocket server;
@@ -62,13 +63,21 @@ public class RobotControlThread extends Thread {
}
private static class SingletonHolder{
public static final RobotControlThread INSTANCE = new RobotControlThread();
public static RobotControlThread INSTANCE;
}
public static RobotControlThread getInstance(){
if(refCount == 0)
SingletonHolder.INSTANCE = new RobotControlThread();
refCount++;
return SingletonHolder.INSTANCE;
}
public static void freeInstance(){
refCount--;
if(refCount == 0) SingletonHolder.INSTANCE = null;
}
public void addNetworkConnectionListener(ApplicationEventsListener listener){
netListener = listener;
}

View File

@@ -29,6 +29,7 @@ public class SensorReportThread extends Thread {
public static final String THREAD_NAME = "SensorReportThread";
private static final String TAG = "NXTAR_CORE_ROBOTTHREAD";
private static final String CLASS_NAME = SensorReportThread.class.getSimpleName();
private static int refCount = 0;
private ApplicationEventsListener netListener;
private ServerSocket server;
@@ -56,13 +57,21 @@ public class SensorReportThread extends Thread {
}
private static class SingletonHolder{
public final static SensorReportThread INSTANCE = new SensorReportThread();
public static SensorReportThread INSTANCE;
}
public static SensorReportThread getInstance(){
if(refCount == 0)
SingletonHolder.INSTANCE = new SensorReportThread();
refCount++;
return SingletonHolder.INSTANCE;
}
public static void freeInstance(){
refCount--;
if(refCount == 0) SingletonHolder.INSTANCE = null;
}
public void addNetworkConnectionListener(ApplicationEventsListener listener){
netListener = listener;
}

View File

@@ -38,35 +38,28 @@ import com.badlogic.gdx.Gdx;
* @author miky
*/
public class ServiceDiscoveryThread extends Thread {
/**
* The name used to identify this thread.
*/
public static final String THREAD_NAME = "ServiceDiscoveryThread";
/**
* Tag used for logging.
*/
private static final String TAG = "NXTAR_CORE_UDPTHREAD";
/**
* Class name used for logging.
*/
private static final String CLASS_NAME = ServiceDiscoveryThread.class.getSimpleName();
/**
* Maximum number of transmission attempts before ending the thread abruptly.
*/
private static final int MAX_RETRIES = 5;
private static int refCount = 0;
/**
* A semaphore object used to synchronize acces to this thread finish flag.
*/
private Object semaphore;
/**
* The finish flag.
*/
private boolean done;
/**
* The UDP server socket used for the ad hoc service discovery protocol.
*/
private DatagramSocket udpServer;
/**
* Holder for the multicast address used in the protocol.
*/
@@ -101,7 +94,7 @@ public class ServiceDiscoveryThread extends Thread {
* Singleton holder for this class.
*/
private static class SingletonHolder{
public static final ServiceDiscoveryThread INSTANCE = new ServiceDiscoveryThread();
public static ServiceDiscoveryThread INSTANCE;
}
/**
@@ -110,9 +103,17 @@ public class ServiceDiscoveryThread extends Thread {
* @return The singleton instance.
*/
public static ServiceDiscoveryThread getInstance(){
if(refCount == 0)
SingletonHolder.INSTANCE = new ServiceDiscoveryThread();
refCount++;
return SingletonHolder.INSTANCE;
}
public static void freeInstance(){
refCount--;
if(refCount == 0) SingletonHolder.INSTANCE = null;
}
/**
* This thread's run method.
*
@@ -138,6 +139,7 @@ public class ServiceDiscoveryThread extends Thread {
// Verify if the thread should end. If that is the case, close the server.
synchronized(semaphore){
if(done){
Gdx.app.log(TAG, CLASS_NAME + ".run(): Closing.");
udpServer.close();
break;
}

View File

@@ -32,6 +32,7 @@ public class VideoStreamingThread extends Thread{
public static final String THREAD_NAME = "VideoStreamingThread";
private static final String TAG = "NXTAR_CORE_VIDEOTHREAD";
private static final String CLASS_NAME = VideoStreamingThread.class.getSimpleName();
private static int refCount = 0;
private ApplicationEventsListener netListener;
private DatagramSocket socket;
@@ -70,13 +71,21 @@ public class VideoStreamingThread extends Thread{
}
private static class SingletonHolder{
public static final VideoStreamingThread INSTANCE = new VideoStreamingThread();
public static VideoStreamingThread INSTANCE;
}
public static VideoStreamingThread getInstance(){
if(refCount == 0)
SingletonHolder.INSTANCE = new VideoStreamingThread();
refCount++;
return SingletonHolder.INSTANCE;
}
public static void freeInstance(){
refCount--;
if(refCount == 0) SingletonHolder.INSTANCE = null;
}
public void addNetworkConnectionListener(ApplicationEventsListener listener){
netListener = listener;
}
@@ -139,6 +148,7 @@ public class VideoStreamingThread extends Thread{
//Gdx.app.debug(TAG, CLASS_NAME + ".receiveUdp() :: Reading message size from socket.");
try{
packet = new DatagramPacket(size, size.length);
socket.setSoTimeout(1000);
socket.receive(packet);
}catch(IOException io){
Gdx.app.error(TAG, CLASS_NAME + ".receiveUdp() :: IOException receiving size " + io.getMessage());

View File

@@ -193,7 +193,7 @@ public class InGameState extends BaseState{
gameWorld.setSystem(new GeometrySystem());
gameWorld.setSystem(new AnimationSystem());
gameWorld.setSystem(new CollisionDetectionSystem());
//gameWorld.setSystem(GameSettings.gameLogicSystem);
//gameWorld.setSystem(GameSettings.getGameLogicSystem());
gameWorld.setSystem(markerRenderingSystem, true);
gameWorld.setSystem(objectRenderingSystem, true);

View File

@@ -46,9 +46,20 @@ public class AnimationSystem extends EntityProcessingSystem {
}else{
animation.controller.animate(animation.animationsIds.get(animation.next), loopCount, 1, null, 0.1f);
}
if(animation.collisionController != null){
if(animation.collisionController.current == null){
animation.collisionController.setAnimation(animation.animationsIds.get(animation.next), loopCount, 1, null);
}else{
animation.collisionController.animate(animation.animationsIds.get(animation.next), loopCount, 1, null, 0.1f);
}
}
}
if(visibility.visible)
if(visibility.visible){
animation.controller.update(Gdx.graphics.getDeltaTime());
if(animation.collisionController != null)
animation.collisionController.update(Gdx.graphics.getDeltaTime());
}
}
}

View File

@@ -15,17 +15,64 @@
*/
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.MarkerCodeComponent;
import ve.ucv.ciens.ccg.nxtar.components.VisibilityComponent;
import com.artemis.Aspect;
import com.artemis.ComponentMapper;
import com.artemis.Entity;
import com.artemis.annotations.Mapper;
import com.badlogic.gdx.Gdx;
public class BombGameLogicSystem extends GameLogicSystemBase {
private static final String TAG = "BOMB_GAME_LOGIC";
private static final String CLASS_NAME = BombGameLogicSystem.class.getSimpleName();
@Mapper ComponentMapper<BombGameObjectTypeComponent> typeMapper;
@Mapper ComponentMapper<AnimationComponent> animationMapper;
@Mapper ComponentMapper<VisibilityComponent> visibilityMapper;
@Mapper ComponentMapper<MarkerCodeComponent> markerMapper;
@Mapper ComponentMapper<CollisionDetectionComponent> collisionMapper;
@SuppressWarnings("unchecked")
public BombGameLogicSystem(){
super(Aspect.getAspectForAll(null));
super(Aspect.getAspectForAll(BombGameObjectTypeComponent.class));
}
@Override
protected void process(Entity e){
BombGameObjectTypeComponent typeComponent;
typeComponent = typeMapper.get(e);
switch(typeComponent.type){
case BombGameObjectTypeComponent.DOOR:
processDoor(e);
break;
default: break;
}
}
private void processDoor(Entity d){
CollisionDetectionComponent collision = collisionMapper.getSafe(d);
AnimationComponent animation = animationMapper.getSafe(d);
VisibilityComponent visibility = visibilityMapper.getSafe(d);
MarkerCodeComponent marker = markerMapper.getSafe(d);
if(marker == null || collision == null || animation == null || visibility == null){
Gdx.app.log(TAG, CLASS_NAME + ".processDoor(): Door is missing some components.");
return;
}
if(marker.enabled && visibility.visible && collision.colliding && animation.current != 1){
animation.next = 1;
animation.loop = false;
Gdx.app.log(TAG, CLASS_NAME + ".processDoor(): Animating door.");
}
return;
}
}

View File

@@ -15,6 +15,7 @@
*/
package ve.ucv.ciens.ccg.nxtar.systems;
import ve.ucv.ciens.ccg.nxtar.components.BombGameObjectTypeComponent;
import ve.ucv.ciens.ccg.nxtar.components.CollisionDetectionComponent;
import ve.ucv.ciens.ccg.nxtar.components.CollisionModelComponent;
import ve.ucv.ciens.ccg.nxtar.components.MarkerCodeComponent;
@@ -35,6 +36,7 @@ public class CollisionDetectionSystem extends EntityProcessingSystem {
@Mapper ComponentMapper<CollisionModelComponent> collisionModelMapper;
@Mapper ComponentMapper<CollisionDetectionComponent> collisionDetectionMapper;
@Mapper ComponentMapper<VisibilityComponent> visibilityMapper;
@Mapper ComponentMapper<BombGameObjectTypeComponent> typeMapper;
private GroupManager groupManager;
@@ -45,12 +47,11 @@ public class CollisionDetectionSystem extends EntityProcessingSystem {
@Override
protected void process(Entity e) {
VisibilityComponent visibility;
CollisionModelComponent collision;
CollisionModelComponent target;
CollisionDetectionComponent onCollision;
CollisionDetectionComponent onCollisionTarget;
BoundingBox colBB = new BoundingBox();
BoundingBox targetBB = new BoundingBox();
ImmutableBag<Entity> collidables;
@@ -64,8 +65,9 @@ public class CollisionDetectionSystem extends EntityProcessingSystem {
for(int i = 0; i < collidables.size(); ++i){
target = collisionModelMapper.getSafe(collidables.get(i));
visibility = visibilityMapper.getSafe(collidables.get(i));
onCollisionTarget = collisionDetectionMapper.getSafe(collidables.get(i));
if(target == null || visibility == null) continue;
if(target == null || visibility == null || onCollisionTarget == null) continue;
if(visibility.visible){
collision.instance.calculateBoundingBox(colBB);
@@ -73,8 +75,10 @@ public class CollisionDetectionSystem extends EntityProcessingSystem {
if(colBB.contains(targetBB)){
onCollision.colliding = true;
onCollisionTarget.colliding = true;
}else{
onCollision.colliding = false;
onCollisionTarget.colliding = false;
}
}
}

View File

@@ -37,6 +37,7 @@ public class RobotArmPositioningSystem extends EntityProcessingSystem {
private static final String TAG = "ROBOT_ARM_POSITIONING_SYSTEM";
private static final String CLASS_NAME = RobotArmPositioningSystem.class.getSimpleName();
private static final float STEP_SIZE = 0.05f;
private static final Vector3 END_POINT = new Vector3(-1.0f, 0.0f, 0.0f);
@Mapper ComponentMapper<GeometryComponent> geometryMapper;
@Mapper ComponentMapper<AutomaticMovementComponent> autoMapper;
@@ -81,20 +82,36 @@ public class RobotArmPositioningSystem extends EntityProcessingSystem {
}else if(input instanceof GamepadUserInput){
tempGP = (GamepadUserInput) input;
geometry.position.x += !collision.colliding ? tempGP.axisLeftY * STEP_SIZE : 0.0f;
geometry.position.y += !collision.colliding ? tempGP.axisLeftX * STEP_SIZE : 0.0f;
geometry.position.z += !collision.colliding ? tempGP.axisRightY * STEP_SIZE : 0.0f;
if(!collision.colliding && !auto.moving){
geometry.position.x += tempGP.axisLeftY * STEP_SIZE;
geometry.position.y += tempGP.axisLeftX * STEP_SIZE;
geometry.position.z += tempGP.axisRightY * STEP_SIZE;
clampPosition(geometry);
}else{
auto.moving = true;
auto.forward = false;
auto.startPoint.set(geometry.position);
auto.endPoint.set(END_POINT);
}
}else if(input instanceof KeyboardUserInput){
tempKey = (KeyboardUserInput) input;
geometry.position.x -= tempKey.keyUp && !collision.colliding ? STEP_SIZE : 0.0f;
geometry.position.x += tempKey.keyDown && !collision.colliding ? STEP_SIZE : 0.0f;
geometry.position.y -= tempKey.keyLeft && !collision.colliding ? STEP_SIZE : 0.0f;
geometry.position.y += tempKey.keyRight && !collision.colliding ? STEP_SIZE : 0.0f;
geometry.position.z -= tempKey.keyZ && !collision.colliding ? STEP_SIZE : 0.0f;
geometry.position.z += tempKey.keyA && !collision.colliding ? STEP_SIZE : 0.0f;
if(!collision.colliding && !auto.moving){
geometry.position.x -= tempKey.keyUp ? STEP_SIZE : 0.0f;
geometry.position.x += tempKey.keyDown ? STEP_SIZE : 0.0f;
geometry.position.y -= tempKey.keyLeft ? STEP_SIZE : 0.0f;
geometry.position.y += tempKey.keyRight ? STEP_SIZE : 0.0f;
geometry.position.z -= tempKey.keyZ ? STEP_SIZE : 0.0f;
geometry.position.z += tempKey.keyA ? STEP_SIZE : 0.0f;
clampPosition(geometry);
}else{
auto.moving = true;
auto.forward = false;
auto.startPoint.set(geometry.position);
auto.endPoint.set(END_POINT);
}
}else
throw new ClassCastException("Input is not a valid UserInput instance.");

View File

@@ -15,14 +15,15 @@
*/
package ve.ucv.ciens.ccg.nxtar.utils;
import com.artemis.World;
import com.artemis.managers.GroupManager;
import ve.ucv.ciens.ccg.nxtar.NxtARCore;
import ve.ucv.ciens.ccg.nxtar.entities.BombGameEntityCreator;
import ve.ucv.ciens.ccg.nxtar.entities.EntityCreatorBase;
import ve.ucv.ciens.ccg.nxtar.systems.BombGameLogicSystem;
import ve.ucv.ciens.ccg.nxtar.systems.GameLogicSystemBase;
import com.artemis.World;
import com.artemis.managers.GroupManager;
public abstract class GameSettings{
private static EntityCreatorBase entityCreator = null;
private static GameLogicSystemBase gameLogicSystem = null;
@@ -44,8 +45,7 @@ public abstract class GameSettings{
}
if(getGameLogicSystem() == null)
gameLogicSystem = null;
//gameLogicSystem = new BombGameLogicSystem();
gameLogicSystem = new BombGameLogicSystem();
}
/**