diff --git a/core/src/com/me/asteroids/Constants.java b/core/src/com/me/asteroids/Constants.java index 3cee301..8f7b847 100644 --- a/core/src/com/me/asteroids/Constants.java +++ b/core/src/com/me/asteroids/Constants.java @@ -15,5 +15,6 @@ public class Constants { public static final int HALF_HEIGHT = HEIGHT / 2; public static final float ASTEROID_SPAWN_DELAY = 1f; + public static final int ASTEROID_SPAWN_COUNT = 4; } diff --git a/core/src/com/me/asteroids/EntityFactory.java b/core/src/com/me/asteroids/EntityFactory.java index 97a4957..a0d2d4c 100644 --- a/core/src/com/me/asteroids/EntityFactory.java +++ b/core/src/com/me/asteroids/EntityFactory.java @@ -1,6 +1,7 @@ package com.me.asteroids; import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import com.me.asteroids.components.AccelerationComponent; import com.me.asteroids.components.AsteroidComponent; @@ -16,6 +17,8 @@ import com.me.asteroids.components.model.PolygonModel; import com.me.common.ecs.Engine; import com.me.common.ecs.Entity; +import java.util.Arrays; + import static com.me.asteroids.Constants.rand; public class EntityFactory { @@ -94,10 +97,10 @@ public class EntityFactory { return models; } - public static Entity[] createPlayerDebris(Engine engine, Entity player) { - Vector2 playerVelocity = player.getComponent(VelocityComponent.class).velocity; - PositionComponent playerPosition = player.getComponent(PositionComponent.class); - LineModel[] models = getLineModels(player.getComponent(ModelComponent.class).model); + public static Entity[] createDebris(Engine engine, Entity entity) { + Vector2 playerVelocity = entity.getComponent(VelocityComponent.class).velocity; + PositionComponent playerPosition = entity.getComponent(PositionComponent.class); + LineModel[] models = getLineModels(entity.getComponent(ModelComponent.class).model); Vector2 explosionCenter = tmp.set(playerPosition.position).sub(Utils.setUnitVectorAngle(tmp2, playerPosition.rotation).scl(5)); Entity[] entities = new Entity[models.length]; @@ -118,12 +121,12 @@ public class EntityFactory { .add(tmp2.set(playerVelocity).scl(0.75f)); // Maintain 75% of the player's velocity at impact velocity.angularVelocity = rand.nextFloat(-60, 60); // Make each piece spin at a different rate - Entity entity = createEntity(engine); - entity.addComponent(position); - entity.addComponent(velocity); - entity.addComponent(model); - entity.addComponent(new DebrisComponent()); - entities[i] = entity; + Entity debris = createEntity(engine); + debris.addComponent(position); + debris.addComponent(velocity); + debris.addComponent(model); + debris.addComponent(new DebrisComponent()); + entities[i] = debris; } return entities; } @@ -170,11 +173,11 @@ public class EntityFactory { ModelComponent model = new ModelComponent(); model.model = new PolygonModel(Color.WHITE); - int size = rand.nextInt(30, 60); + int size = rand.nextInt(45, 75); model.model.setVertices(new AsteroidFactory() - .setVertexCount(rand.nextInt(16, 24)) + .setVertexCount(32) .setSize(size) - .setSizeVariation(size * 0.7f) + .setSizeVariation(size * 0.5f) .sizeRelativeToLast() .generate()); @@ -186,4 +189,57 @@ public class EntityFactory { return asteroid; } + private static float[] scaleAndRelativizeVertices(Vector2 position, float[] vertices, float scale) { + float[] ret = new float[vertices.length]; + for (int j = 0, n = vertices.length; j < n; j += 2) { + ret[j] = (vertices[j] - position.x) * scale; + ret[j + 1] = (vertices[j + 1] - position.y) * scale; + } + return ret; + } + + public static Entity[] splitAsteroidIntoChunks(Engine engine, Entity asteroid, int chunkCount, float chunkScale) { + Vector2 asteroidVelocity = asteroid.getComponent(VelocityComponent.class).velocity; + Model asteroidModel = asteroid.getComponent(ModelComponent.class).model; + Vector2 asteroidPosition = asteroidModel.getPosition(); + float[] scaledVertices = scaleAndRelativizeVertices(asteroidPosition, asteroidModel.getVertices(), chunkScale); + + float angle = rand.nextFloat() * MathUtils.PI2; + float angleStep = MathUtils.PI2 / chunkCount; + Utils.setUnitVectorAngleRad(tmp, angle); + + Entity[] entities = new Entity[chunkCount]; + for (int i = 0; i < chunkCount; i++) { + Vector2 chunkPosition = tmp2.set(asteroidPosition).add(tmp.scl(25)); + + ModelComponent model = new ModelComponent(); + model.model = new PolygonModel(asteroidModel.getColor()); + model.model.setVertices(Arrays.copyOf(scaledVertices, scaledVertices.length)); + model.model.setPosition(chunkPosition); + + PositionComponent position = new PositionComponent(); + position.position = new Vector2(chunkPosition); + position.rotation = 90; + + VelocityComponent velocity = new VelocityComponent(); + velocity.velocity = new Vector2(tmp).nor().rotate(rand.nextFloat(-45, 45)).scl(asteroidVelocity.len() * 1.10f); + velocity.angularVelocity = rand.nextFloat(-30, 30); + + AsteroidComponent asteroidComponent = new AsteroidComponent(); + asteroidComponent.generation = asteroid.getComponent(AsteroidComponent.class).generation + 1; + + angle += angleStep; + Utils.setUnitVectorAngleRad(tmp, angle); + + Entity split = createEntity(engine); + split.addComponent(model); + split.addComponent(position); + split.addComponent(velocity); + split.addComponent(asteroidComponent); + entities[i] = split; + } + + return entities; + } + } diff --git a/core/src/com/me/asteroids/components/AsteroidComponent.java b/core/src/com/me/asteroids/components/AsteroidComponent.java index 68a5eb3..2b93f38 100644 --- a/core/src/com/me/asteroids/components/AsteroidComponent.java +++ b/core/src/com/me/asteroids/components/AsteroidComponent.java @@ -3,5 +3,7 @@ package com.me.asteroids.components; import com.me.common.ecs.Component; public class AsteroidComponent implements Component { - // TODO: See PlayerComponent's TODO + + public int generation; + } diff --git a/core/src/com/me/asteroids/screens/GameScreen.java b/core/src/com/me/asteroids/screens/GameScreen.java index b8f1842..81d5ff0 100644 --- a/core/src/com/me/asteroids/screens/GameScreen.java +++ b/core/src/com/me/asteroids/screens/GameScreen.java @@ -101,12 +101,14 @@ public class GameScreen extends Screen implements Listener { ComponentMapper modelMapper; ComponentMapper bulletMapper; ComponentMapper debrisMapper; + ComponentMapper asteroidMapper; EventListener(Engine engine) { this.positionMapper = engine.getComponentMapper(PositionComponent.class); this.modelMapper = engine.getComponentMapper(ModelComponent.class); this.bulletMapper = engine.getComponentMapper(BulletComponent.class); this.debrisMapper = engine.getComponentMapper(DebrisComponent.class); + this.asteroidMapper = engine.getComponentMapper(AsteroidComponent.class); } @EventHandler @@ -127,7 +129,18 @@ public class GameScreen extends Screen implements Listener { // AABBs intersect but let's only consider it a hit if the bullet's position // is actually inside the asteroid event.getBullet().remove(); + int generation = asteroidMapper.get(event.getAsteroid()).generation; + if (generation < 2) { + for (Entity shard : EntityFactory.splitAsteroidIntoChunks(engine, event.getAsteroid(), 2, 2/3f)) { + shard.activate(); + } + } else { + for (Entity debris : EntityFactory.createDebris(engine, event.getAsteroid())) { + debris.activate(); + } + } event.getAsteroid().remove(); + } } @@ -138,7 +151,7 @@ public class GameScreen extends Screen implements Listener { if (asteroid.contains(player.getVertices()) || player.contains(asteroid.getVertices())) { event.getPlayer().deactivate(); - for (Entity debris : EntityFactory.createPlayerDebris(engine, event.getPlayer())) { + for (Entity debris : EntityFactory.createDebris(engine, event.getPlayer())) { debris.activate(); } } diff --git a/core/src/com/me/asteroids/systems/AsteroidSpawningSystem.java b/core/src/com/me/asteroids/systems/AsteroidSpawningSystem.java index 94a5e9b..c7a073b 100644 --- a/core/src/com/me/asteroids/systems/AsteroidSpawningSystem.java +++ b/core/src/com/me/asteroids/systems/AsteroidSpawningSystem.java @@ -64,7 +64,7 @@ public class AsteroidSpawningSystem extends BaseSystem { model.setPosition(position); VelocityComponent velocityComponent = velocityMapper.get(asteroid); - velocityComponent.velocity = new Vector2().setToRandomDirection().scl(rand.nextFloat(125, 175)); + velocityComponent.velocity = new Vector2().setToRandomDirection().scl(rand.nextFloat(75, 125)); velocityComponent.angularVelocity = rand.nextFloat(-30, 30); asteroid.activate(); @@ -83,7 +83,7 @@ public class AsteroidSpawningSystem extends BaseSystem { } } - if (asteroidCount++ < 6 && (asteroidSpawnDelay -= dt) <= 0) { + if (asteroidCount++ < Constants.ASTEROID_SPAWN_COUNT && (asteroidSpawnDelay -= dt) <= 0) { spawnAsteroid(); asteroidSpawnDelay = Constants.ASTEROID_SPAWN_DELAY; }