Browse Source

It is now possible to see Projectiles created by other players

Tankernn 7 years ago
parent
commit
613af3e84a

+ 12 - 0
src/main/java/eu/tankernn/gameEngine/TankernnGame3D.java

@@ -10,6 +10,7 @@ import org.lwjgl.util.vector.Vector4f;
 
 import eu.tankernn.gameEngine.entities.Camera;
 import eu.tankernn.gameEngine.entities.Entity3D;
+import eu.tankernn.gameEngine.entities.EntityState;
 import eu.tankernn.gameEngine.entities.GameContext;
 import eu.tankernn.gameEngine.environmentMap.EnvironmentMapRenderer;
 import eu.tankernn.gameEngine.loader.Loader;
@@ -61,6 +62,12 @@ public class TankernnGame3D extends TankernnGame {
 
 	public void update() {
 		super.update();
+		while (player == null)
+			try {
+				Thread.sleep(100);
+			} catch (InterruptedException e) {
+				e.printStackTrace();
+			}
 
 		GameContext ctx = new GameContext(true, DisplayManager.getFrameTimeSeconds(),
 				world.getEntities().values().stream().map(Entity3D::getState).collect(Collectors.toSet())) {
@@ -79,6 +86,11 @@ public class TankernnGame3D extends TankernnGame {
 			public AABB getBoundingBox(int entityId) {
 				return world.getEntities().get(entityId).getBoundingBox();
 			}
+
+			@Override
+			public EntityState getEntity(int id) {
+				return world.getEntities().get(id).getState();
+			}
 		};
 
 		world.update(ctx);

+ 13 - 14
src/main/java/eu/tankernn/gameEngine/World.java

@@ -1,9 +1,9 @@
 package eu.tankernn.gameEngine;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import eu.tankernn.gameEngine.entities.Entity3D;
 import eu.tankernn.gameEngine.entities.EntityFactory;
@@ -17,7 +17,7 @@ import eu.tankernn.gameEngine.renderEngine.gui.floating.FloatingTexture;
 import eu.tankernn.gameEngine.terrains.TerrainPack;
 
 public class World {
-	private Map<Integer, Entity3D> entities = new HashMap<>();
+	private Map<Integer, Entity3D> entities = new ConcurrentHashMap<>();
 	private List<ILight> lights = new ArrayList<>();
 	private List<FloatingTexture> floatTextures = new ArrayList<>();
 	private TerrainPack terrainPack;
@@ -62,24 +62,23 @@ public class World {
 		for (EntityState s : state.getEntities()) {
 			updateEntityState(s);
 		}
-		this.lights = state.getLights();
+		this.lights = new ArrayList<>(state.getLights());
 	}
 
-	public void updateEntityState(EntityState s) {
-		if (entities.containsKey(s.getId()))
-			entities.get(s.getId()).setState(s);
-		else
-			spawnEntity(s);
+	public Entity3D updateEntityState(EntityState s) {
+		return updateEntityState(s, false);
 	}
 
-	public Entity3D spawnEntity(EntityState state) {
-		if (entities.containsKey(state.getId())) {
-			throw new RuntimeException("Entity with id " + state.getId() + " has already been spawned.");
+	public Entity3D updateEntityState(EntityState s, boolean forceRespawn) {
+		Entity3D e;
+		if (entities.containsKey(s.getId()) && !forceRespawn) {
+			e = entities.get(s.getId());
+			e.setState(s);
 		} else {
-			Entity3D e = entityFactory.getEntity(state);
-			entities.put(state.getId(), e);
-			return e;
+			e = entityFactory.getEntity(s);
+			entities.put(s.getId(), e);
 		}
+		return e;
 	}
 
 	public float getTerrainHeigh(float x, float z) {

+ 1 - 0
src/main/java/eu/tankernn/gameEngine/entities/Entity3D.java

@@ -26,6 +26,7 @@ public class Entity3D implements IPositionable {
 		this.model = model;
 		this.particleSystem = particleSystem;
 		this.boundingBox = boundingBox;
+		this.boundingBox.updatePosition(getPosition());
 		this.world = world;
 	}
 

+ 3 - 1
src/main/java/eu/tankernn/gameEngine/entities/EntityFactory.java

@@ -1,5 +1,7 @@
 package eu.tankernn.gameEngine.entities;
 
+import org.lwjgl.util.vector.Vector3f;
+
 import eu.tankernn.gameEngine.World;
 import eu.tankernn.gameEngine.loader.Loader;
 import eu.tankernn.gameEngine.loader.models.AABB;
@@ -24,7 +26,7 @@ public class EntityFactory {
 		ParticleSystem particleSystem = loader.getParticleSystem(state.getParticleSystemId());
 		if (particleSystem != null)
 			particleMaster.addSystem(particleSystem);
-		AABB boundingBox = loader.getBoundingBox(model.getModel().id);
+		AABB boundingBox = model != null ? loader.getBoundingBox(model.getModel().id) : new AABB(new Vector3f(0, 0, 0), new Vector3f(1, 1, 1));
 		return new Entity3D(state, model, particleSystem, boundingBox, world);
 	}
 }

+ 17 - 14
src/main/java/eu/tankernn/gameEngine/entities/EntityState.java

@@ -1,9 +1,9 @@
 package eu.tankernn.gameEngine.entities;
 
 import java.io.Serializable;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import org.lwjgl.util.vector.Vector3f;
@@ -20,27 +20,28 @@ public class EntityState implements Serializable {
 
 	protected static final AtomicInteger ID_GEN = new AtomicInteger();
 
-	private final int id;
-	private int modelId;
-	private int systemId;
+	private int id;
+	private int modelId = -1;
+	private int systemId = -1;
 	private final Vector3f position;
 	private final Vector3f rotation;
 	private final Vector3f velocity;
 	private final Vector3f scale;
 	protected boolean dead = false;
 
-	private List<Behavior> behaviors;
+	private Set<Behavior> behaviors;
 
 	public EntityState(int id, int modelId, int systemId, Vector3f position, Vector3f rotation, Vector3f velocity,
 			Vector3f scale, Behavior... behaviors) {
 		this.id = id;
 		this.modelId = modelId;
+		this.systemId = systemId;
 		this.position = new Vector3f(position);
-		this.rotation = rotation;
-		this.velocity = velocity;
-		this.scale = scale;
+		this.rotation = new Vector3f(rotation);
+		this.velocity = new Vector3f(velocity);
+		this.scale = new Vector3f(scale);
 
-		this.behaviors = new ArrayList<Behavior>(Arrays.asList(behaviors));
+		this.behaviors = new HashSet<>(Arrays.asList(behaviors));
 		this.behaviors.forEach(b -> b.setEntity(this));
 	}
 
@@ -79,8 +80,6 @@ public class EntityState implements Serializable {
 			position.y = terrainHeight;
 		}
 
-		System.out.println(this);
-
 		Vector3f.add(position, (Vector3f) new Vector3f(velocity).scale(ctx.getTickLengthSeconds()), position);
 	}
 
@@ -129,15 +128,19 @@ public class EntityState implements Serializable {
 		return systemId;
 	}
 
-	public List<Behavior> getBehaviors() {
+	public Set<Behavior> getBehaviors() {
 		return behaviors;
 	}
 
-	public void setBehaviors(List<Behavior> behaviors) {
+	public void setBehaviors(Set<Behavior> behaviors) {
 		this.behaviors = behaviors;
 	}
 
 	public String toString() {
 		return String.format("Entity with id %d, modelId %d and position %s. List of behaviors: %s", id, modelId, position.toString(), behaviors.toString());
 	}
+
+	public void resetId() {
+		this.id = ID_GEN.getAndIncrement();
+	}
 }

+ 2 - 0
src/main/java/eu/tankernn/gameEngine/entities/GameContext.java

@@ -33,4 +33,6 @@ public abstract class GameContext {
 	public abstract float getTerrainHeight(float x, float z);
 
 	public abstract AABB getBoundingBox(int entityId);
+
+	public abstract EntityState getEntity(int id);
 }

+ 6 - 0
src/main/java/eu/tankernn/gameEngine/entities/PlayerCamera.java

@@ -31,6 +31,8 @@ public class PlayerCamera extends Camera {
 	 */
 	@Override
 	public void update() {
+		if (player == null)
+			return;
 		Vector3f rot = player.getRotation();
 		calculateZoom();
 		if (Mouse.isButtonDown(0) || Mouse.isButtonDown(1)) {
@@ -146,4 +148,8 @@ public class PlayerCamera extends Camera {
 			e.printStackTrace();
 		}
 	}
+
+	public void setPlayer(Entity3D player) {
+		this.player = player;
+	}
 }

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/entities/ai/CollisionBehavior.java

@@ -18,6 +18,6 @@ public abstract class CollisionBehavior extends Behavior {
 				.forEach(this::onCollision);
 	}
 
-	public abstract void onCollision(EntityState entity);
+	public abstract void onCollision(EntityState other);
 
 }

+ 1 - 1
src/main/java/eu/tankernn/gameEngine/entities/ai/DieOnCollisionBehavior.java

@@ -11,7 +11,7 @@ public class DieOnCollisionBehavior extends CollisionBehavior {
 
 	@Override
 	public void onCollision(EntityState entity) {
-		entity.setDead(true);
+		this.entity.setDead(true);
 	}
 
 }

+ 18 - 4
src/main/java/eu/tankernn/gameEngine/entities/ai/FollowBehavior.java

@@ -2,8 +2,8 @@ package eu.tankernn.gameEngine.entities.ai;
 
 import org.lwjgl.util.vector.Vector3f;
 
+import eu.tankernn.gameEngine.entities.EntityState;
 import eu.tankernn.gameEngine.entities.GameContext;
-import eu.tankernn.gameEngine.util.IPositionable;
 
 public class FollowBehavior extends Behavior {
 	
@@ -12,18 +12,32 @@ public class FollowBehavior extends Behavior {
 	 */
 	private static final long serialVersionUID = 1890567568320815924L;
 	
-	private IPositionable target;
+	private Vector3f target;
 	private float speed;
+	private int targetId = -1;
 	
-	public FollowBehavior(IPositionable target, float speed) {
+	public FollowBehavior(Vector3f target, float speed) {
 		this.target = target;
 		this.speed = speed;
 	}
 	
+	public FollowBehavior(int targetEntity, float speed) {
+		this.targetId = targetEntity;
+		this.speed = speed;
+	}
+	
+	public FollowBehavior(EntityState targetEntity, float speed) {
+		this(targetEntity.getId(), speed);
+	}
+	
 	@Override
 	public void update(GameContext impl) {
+		if (targetId != -1)
+			this.target = impl.getEntity(targetId).getPosition();
 		// Store direction in velocity vector
-		Vector3f.sub(target.getPosition(), entity.getPosition(), entity.getVelocity());
+		Vector3f.sub(target, entity.getPosition(), entity.getVelocity());
+		if (entity.getVelocity().length() == 0)
+			return;
 		// Normalize and scale velocity vector
 		entity.getVelocity().normalise().scale(speed);
 	}

+ 62 - 47
src/main/java/eu/tankernn/gameEngine/loader/Loader.java

@@ -38,18 +38,19 @@ import eu.tankernn.gameEngine.util.InternalFile;
  */
 public class Loader {
 	public static final int MAX_WEIGHTS = 3;
-	
+
 	private List<Vao> vaos = new ArrayList<>();
 	private List<TextureAtlas> textures = new ArrayList<>();
 	private Map<Integer, TexturedModel> models = new HashMap<>();
 	private Map<Integer, AABB> boundingBoxes = new HashMap<>();
 	private Map<Integer, ParticleSystem> particleSystems = new HashMap<>();
-	
+
 	public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, int[] indices) {
 		return loadToVAO(vertices, textureCoords, normals, null, null, null, indices);
 	}
-	
-	public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, float[] tangents, int[] jointIds, float[] weights, int[] indices) {
+
+	public Vao loadToVAO(float[] vertices, float[] textureCoords, float[] normals, float[] tangents, int[] jointIds,
+			float[] weights, int[] indices) {
 		Vao model = Vao.create();
 		model.bind();
 		model.createIndexBuffer(indices);
@@ -66,7 +67,7 @@ public class Loader {
 		vaos.add(model);
 		return model;
 	}
-	
+
 	public Vao loadToVAO(float[] positions, float[] textureCoords) {
 		Vao vao = Vao.create();
 		vao.bind();
@@ -76,7 +77,7 @@ public class Loader {
 		vaos.add(vao);
 		return vao;
 	}
-	
+
 	public Vao loadToVAO(float[] positions, int dimensions) {
 		Vao vao = Vao.create(positions.length / 2);
 		vao.bind();
@@ -85,20 +86,23 @@ public class Loader {
 		vaos.add(vao);
 		return vao;
 	}
-	
+
 	public Vao loadToVAO(ModelData data) {
-		return loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getTangents(), null, null, data.getIndices());
+		return loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getTangents(), null, null,
+				data.getIndices());
 	}
-	
+
 	public Vao loadToVAO(MeshData data) {
-		return loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getTangents(), data.getJointIds(), data.getVertexWeights(), data.getIndices());
+		return loadToVAO(data.getVertices(), data.getTextureCoords(), data.getNormals(), data.getTangents(),
+				data.getJointIds(), data.getVertexWeights(), data.getIndices());
 	}
-	
+
 	/**
 	 * Loads a texture to the GPU.
 	 * 
-	 * @param filename The path, relative to the root of the jar file, of the
-	 *        file to load.
+	 * @param filename
+	 *            The path, relative to the root of the jar file, of the file to
+	 *            load.
 	 * @return The texture ID
 	 * @throws FileNotFoundException
 	 */
@@ -111,24 +115,26 @@ public class Loader {
 	public Texture loadTexture(InternalFile file) {
 		return new Texture(loadTextureAtlas(file));
 	}
-	
+
 	/**
 	 * Creates a new cube map from the images specified. File 0: Right face File
 	 * 1: Left face File 2: Top face File 3: Bottom face File 4: Back face File
 	 * 5: Front face
 	 * 
-	 * @param textureFiles Filenames of images that make up the cube map
+	 * @param textureFiles
+	 *            Filenames of images that make up the cube map
 	 * @return The ID of the new cube map
 	 */
-	
+
 	public Texture loadCubeMap(InternalFile[] textureFiles) {
 		Texture cubeMap = Texture.newCubeMap(textureFiles, 500);
 		textures.add(cubeMap.atlas);
 		return cubeMap;
 	}
-	
-	private static final int[] CUBE_INDICES = {0, 1, 3, 1, 2, 3, 1, 5, 2, 2, 5, 6, 4, 7, 5, 5, 7, 6, 0, 3, 4, 4, 3, 7, 7, 3, 6, 6, 3, 2, 4, 5, 0, 0, 5, 1};
-	
+
+	private static final int[] CUBE_INDICES = { 0, 1, 3, 1, 2, 3, 1, 5, 2, 2, 5, 6, 4, 7, 5, 5, 7, 6, 0, 3, 4, 4, 3, 7,
+			7, 3, 6, 6, 3, 2, 4, 5, 0, 0, 5, 1 };
+
 	public Vao generateCube(float size) {
 		Vao vao = Vao.create();
 		vao.bind();
@@ -138,32 +144,34 @@ public class Loader {
 		vaos.add(vao);
 		return vao;
 	}
-	
+
 	private static float[] getCubeVertexPositions(float size) {
-		return new float[] {-size, size, size, size, size, size, size, -size, size, -size, -size, size, -size, size, -size, size, size, -size, size, -size, -size, -size, -size, -size};
+		return new float[] { -size, size, size, size, size, size, size, -size, size, -size, -size, size, -size, size,
+				-size, size, size, -size, size, -size, -size, -size, -size, -size };
 	}
-	
+
 	@Override
 	public void finalize() {
-		for (TextureAtlas tex: textures)
+		for (TextureAtlas tex : textures)
 			tex.delete();
-		for (Vao model: vaos)
+		for (Vao model : vaos)
 			model.finalize();
 	}
-	
+
 	public Vao loadOBJ(InternalFile objFile) {
 		ModelData data = ObjLoader.loadOBJ(objFile);
 		Vao vao = this.loadToVAO(data);
 		boundingBoxes.put(vao.id, new AABB(data));
 		return vao;
 	}
-	
+
 	/**
 	 * Creates an AnimatedEntity from the data in an entity file. It loads up
 	 * the collada model data, stores the extracted data in a VAO, sets up the
 	 * joint hierarchy, and loads up the entity's texture.
 	 * 
-	 * @param entityFile - the file containing the data for the entity.
+	 * @param entityFile
+	 *            - the file containing the data for the entity.
 	 * @return The animated entity (no animation applied though)
 	 */
 	public AnimatedModel loadDAE(InternalFile modelFile, ModelTexture texture) {
@@ -174,21 +182,21 @@ public class Loader {
 		Joint headJoint = new Joint(skeletonData.headJoint);
 		return new AnimatedModel(model.id, model, texture, headJoint, skeletonData.jointCount);
 	}
-	
+
 	public void readModelSpecification(InternalFile file) throws IOException {
 		Map<InternalFile, Vao> cachedRawModels = new HashMap<InternalFile, Vao>();
 		Map<InternalFile, Texture> cachedTextures = new HashMap<InternalFile, Texture>();
 		JSONObject spec;
-		
+
 		JSONArray jsonArr = new JSONArray(file.readFile());
-		
+
 		for (int j = 0; j < jsonArr.length(); j++) {
 			spec = jsonArr.getJSONObject(j);
-			
+
 			int id;
 			Vao model;
 			ModelTexture modelTexture;
-			
+
 			id = spec.getInt("id");
 			InternalFile modelFile;
 			try {
@@ -196,9 +204,10 @@ public class Loader {
 			} catch (FileNotFoundException e) {
 				modelFile = new InternalFile("models/" + optFilename(spec, "model", ".dae"));
 			}
-			
-			String[] textureFiles = {optFilename(spec, "texture", ".png"), optFilename(spec, "specular", "S.png"), optFilename(spec, "normal", "N.png")};
-			
+
+			String[] textureFiles = { optFilename(spec, "texture", ".png"), optFilename(spec, "specular", "S.png"),
+					optFilename(spec, "normal", "N.png") };
+
 			Texture[] textures = Arrays.stream(textureFiles).map(fileName -> {
 				try {
 					InternalFile f = new InternalFile("textures/" + fileName);
@@ -215,19 +224,19 @@ public class Loader {
 					return null;
 				}
 			}).toArray(size -> new Texture[size]);
-			
+
 			modelTexture = new ModelTexture(textures[0]);
 			if (textures[1] != null)
 				modelTexture.setNormalMap(textures[2]);
 			if (textures[2] != null)
 				modelTexture.setSpecularMap(textures[1]);
-			
+
 			modelTexture.setShineDamper(optFloat(spec, "shinedamper", 10.0f));
 			modelTexture.setReflectivity(optFloat(spec, "reflectivity", 0f));
 			modelTexture.setRefractivity(optFloat(spec, "refractivity", 0f));
-			
+
 			modelTexture.setHasTransparency(spec.optBoolean("transparency"));
-			
+
 			if (cachedRawModels.containsKey(modelFile)) {
 				model = cachedRawModels.get(modelFile);
 				models.put(id, new TexturedModel(id, model, modelTexture));
@@ -241,7 +250,8 @@ public class Loader {
 				case "dae":
 					AnimatedModel animatedModel = loadDAE(modelFile, modelTexture);
 					String animations = spec.getString("animations");
-					animatedModel.registerAnimations(AnimationLoader.loadAnimations(modelFile, new InternalFile("models/" + animations)));
+					animatedModel.registerAnimations(
+							AnimationLoader.loadAnimations(modelFile, new InternalFile("models/" + animations)));
 					models.put(id, animatedModel);
 					break;
 				default:
@@ -250,15 +260,15 @@ public class Loader {
 			}
 		}
 	}
-	
+
 	private float optFloat(JSONObject spec, String key, float defaultValue) {
 		return BigDecimal.valueOf(spec.optDouble(key, (double) defaultValue)).floatValue();
 	}
-	
+
 	private String optFilename(JSONObject spec, String key, String extension) {
 		return spec.has(key) ? spec.getString(key) : spec.get("name") + extension;
 	}
-	
+
 	public TexturedModel getModel(int id) {
 		TexturedModel model = models.get(id);
 		if (model instanceof AnimatedModel)
@@ -266,7 +276,7 @@ public class Loader {
 		else
 			return model;
 	}
-	
+
 	public AABB getBoundingBox(int vaoId) {
 		if (vaoId == -1)
 			return new AABB(new Vector3f(0, 0, 0), new Vector3f(0.1f, 0.1f, 0.1f));
@@ -274,12 +284,17 @@ public class Loader {
 			throw new NullPointerException("Unable to find bounding box for vaoId " + vaoId);
 		return boundingBoxes.get(vaoId);
 	}
-	
+
 	public void registerParticleSystem(int id, ParticleSystem system) {
 		particleSystems.put(id, system);
 	}
-	
+
 	public ParticleSystem getParticleSystem(int particleSystemId) {
-		return particleSystems.get(particleSystemId);
+		if (particleSystemId == -1)
+			return null;
+		else if (particleSystems.containsKey(particleSystemId))
+			return new ParticleSystem(particleSystems.get(particleSystemId));
+		else
+			throw new NullPointerException("No particle system with id " + particleSystemId);
 	}
 }

+ 2 - 1
src/main/java/eu/tankernn/gameEngine/loader/models/AABB.java

@@ -50,8 +50,9 @@ public class AABB {
 		this.relativeMiddlePos.z /= 2;
 	}
 
-	public void updatePosition(Vector3f pos) {
+	public AABB updatePosition(Vector3f pos) {
 		this.position = pos;
+		return this;
 	}
 
 	public static boolean collides(AABB a, AABB b) {

+ 4 - 3
src/main/java/eu/tankernn/gameEngine/multiplayer/WorldState.java

@@ -2,6 +2,7 @@ package eu.tankernn.gameEngine.multiplayer;
 
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 
 import eu.tankernn.gameEngine.entities.EntityState;
@@ -21,9 +22,9 @@ public class WorldState implements Serializable {
 		this.seed = seed;
 	}
 	
-	public WorldState(int seed, List<ILight> lights, List<EntityState> entities) {
+	public WorldState(int seed, List<ILight> collection, List<EntityState> entities) {
 		this(seed);
-		this.lights = lights;
+		this.lights = collection;
 		this.entities = entities;
 	}
 
@@ -31,7 +32,7 @@ public class WorldState implements Serializable {
 		return seed;
 	}
 
-	public List<ILight> getLights() {
+	public Collection<ILight> getLights() {
 		return lights;
 	}
 

+ 2 - 2
src/main/java/eu/tankernn/gameEngine/renderEngine/Scene.java

@@ -19,10 +19,10 @@ public class Scene {
 	
 	private Texture environmentMap;
 	
-	public Scene(Collection<Entity3D> entities, TerrainPack terrainPack, List<ILight> lights, Camera camera, Skybox sky) {
+	public Scene(Collection<Entity3D> entities, TerrainPack terrainPack, List<ILight> collection, Camera camera, Skybox sky) {
 		this.entities = entities;
 		this.terrainPack = terrainPack;
-		this.lights = lights;
+		this.lights = collection;
 		this.camera = camera;
 		this.sky = sky;
 		this.environmentMap = Texture.newEmptyCubeMap(128);