Implement asteroids breaking apart
Rename createPlayerDebris -> createDebris to make it clear it's not only for the player entity. Add Constants.ASTEROID_SPAWN_COUNT Slow down asteroids, tweak sizing
This commit is contained in:
parent
d140959fdc
commit
3b1c075102
@ -15,5 +15,6 @@ public class Constants {
|
|||||||
public static final int HALF_HEIGHT = HEIGHT / 2;
|
public static final int HALF_HEIGHT = HEIGHT / 2;
|
||||||
|
|
||||||
public static final float ASTEROID_SPAWN_DELAY = 1f;
|
public static final float ASTEROID_SPAWN_DELAY = 1f;
|
||||||
|
public static final int ASTEROID_SPAWN_COUNT = 4;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package com.me.asteroids;
|
package com.me.asteroids;
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.me.asteroids.components.AccelerationComponent;
|
import com.me.asteroids.components.AccelerationComponent;
|
||||||
import com.me.asteroids.components.AsteroidComponent;
|
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.Engine;
|
||||||
import com.me.common.ecs.Entity;
|
import com.me.common.ecs.Entity;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static com.me.asteroids.Constants.rand;
|
import static com.me.asteroids.Constants.rand;
|
||||||
|
|
||||||
public class EntityFactory {
|
public class EntityFactory {
|
||||||
@ -94,10 +97,10 @@ public class EntityFactory {
|
|||||||
return models;
|
return models;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Entity[] createPlayerDebris(Engine engine, Entity player) {
|
public static Entity[] createDebris(Engine engine, Entity entity) {
|
||||||
Vector2 playerVelocity = player.getComponent(VelocityComponent.class).velocity;
|
Vector2 playerVelocity = entity.getComponent(VelocityComponent.class).velocity;
|
||||||
PositionComponent playerPosition = player.getComponent(PositionComponent.class);
|
PositionComponent playerPosition = entity.getComponent(PositionComponent.class);
|
||||||
LineModel[] models = getLineModels(player.getComponent(ModelComponent.class).model);
|
LineModel[] models = getLineModels(entity.getComponent(ModelComponent.class).model);
|
||||||
Vector2 explosionCenter = tmp.set(playerPosition.position).sub(Utils.setUnitVectorAngle(tmp2, playerPosition.rotation).scl(5));
|
Vector2 explosionCenter = tmp.set(playerPosition.position).sub(Utils.setUnitVectorAngle(tmp2, playerPosition.rotation).scl(5));
|
||||||
|
|
||||||
Entity[] entities = new Entity[models.length];
|
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
|
.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
|
velocity.angularVelocity = rand.nextFloat(-60, 60); // Make each piece spin at a different rate
|
||||||
|
|
||||||
Entity entity = createEntity(engine);
|
Entity debris = createEntity(engine);
|
||||||
entity.addComponent(position);
|
debris.addComponent(position);
|
||||||
entity.addComponent(velocity);
|
debris.addComponent(velocity);
|
||||||
entity.addComponent(model);
|
debris.addComponent(model);
|
||||||
entity.addComponent(new DebrisComponent());
|
debris.addComponent(new DebrisComponent());
|
||||||
entities[i] = entity;
|
entities[i] = debris;
|
||||||
}
|
}
|
||||||
return entities;
|
return entities;
|
||||||
}
|
}
|
||||||
@ -170,11 +173,11 @@ public class EntityFactory {
|
|||||||
|
|
||||||
ModelComponent model = new ModelComponent();
|
ModelComponent model = new ModelComponent();
|
||||||
model.model = new PolygonModel(Color.WHITE);
|
model.model = new PolygonModel(Color.WHITE);
|
||||||
int size = rand.nextInt(30, 60);
|
int size = rand.nextInt(45, 75);
|
||||||
model.model.setVertices(new AsteroidFactory()
|
model.model.setVertices(new AsteroidFactory()
|
||||||
.setVertexCount(rand.nextInt(16, 24))
|
.setVertexCount(32)
|
||||||
.setSize(size)
|
.setSize(size)
|
||||||
.setSizeVariation(size * 0.7f)
|
.setSizeVariation(size * 0.5f)
|
||||||
.sizeRelativeToLast()
|
.sizeRelativeToLast()
|
||||||
.generate());
|
.generate());
|
||||||
|
|
||||||
@ -186,4 +189,57 @@ public class EntityFactory {
|
|||||||
return asteroid;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -3,5 +3,7 @@ package com.me.asteroids.components;
|
|||||||
import com.me.common.ecs.Component;
|
import com.me.common.ecs.Component;
|
||||||
|
|
||||||
public class AsteroidComponent implements Component {
|
public class AsteroidComponent implements Component {
|
||||||
// TODO: See PlayerComponent's TODO
|
|
||||||
|
public int generation;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -101,12 +101,14 @@ public class GameScreen extends Screen implements Listener {
|
|||||||
ComponentMapper<ModelComponent> modelMapper;
|
ComponentMapper<ModelComponent> modelMapper;
|
||||||
ComponentMapper<BulletComponent> bulletMapper;
|
ComponentMapper<BulletComponent> bulletMapper;
|
||||||
ComponentMapper<DebrisComponent> debrisMapper;
|
ComponentMapper<DebrisComponent> debrisMapper;
|
||||||
|
ComponentMapper<AsteroidComponent> asteroidMapper;
|
||||||
|
|
||||||
EventListener(Engine engine) {
|
EventListener(Engine engine) {
|
||||||
this.positionMapper = engine.getComponentMapper(PositionComponent.class);
|
this.positionMapper = engine.getComponentMapper(PositionComponent.class);
|
||||||
this.modelMapper = engine.getComponentMapper(ModelComponent.class);
|
this.modelMapper = engine.getComponentMapper(ModelComponent.class);
|
||||||
this.bulletMapper = engine.getComponentMapper(BulletComponent.class);
|
this.bulletMapper = engine.getComponentMapper(BulletComponent.class);
|
||||||
this.debrisMapper = engine.getComponentMapper(DebrisComponent.class);
|
this.debrisMapper = engine.getComponentMapper(DebrisComponent.class);
|
||||||
|
this.asteroidMapper = engine.getComponentMapper(AsteroidComponent.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@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
|
// AABBs intersect but let's only consider it a hit if the bullet's position
|
||||||
// is actually inside the asteroid
|
// is actually inside the asteroid
|
||||||
event.getBullet().remove();
|
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();
|
event.getAsteroid().remove();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +151,7 @@ public class GameScreen extends Screen implements Listener {
|
|||||||
|
|
||||||
if (asteroid.contains(player.getVertices()) || player.contains(asteroid.getVertices())) {
|
if (asteroid.contains(player.getVertices()) || player.contains(asteroid.getVertices())) {
|
||||||
event.getPlayer().deactivate();
|
event.getPlayer().deactivate();
|
||||||
for (Entity debris : EntityFactory.createPlayerDebris(engine, event.getPlayer())) {
|
for (Entity debris : EntityFactory.createDebris(engine, event.getPlayer())) {
|
||||||
debris.activate();
|
debris.activate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ public class AsteroidSpawningSystem extends BaseSystem {
|
|||||||
model.setPosition(position);
|
model.setPosition(position);
|
||||||
|
|
||||||
VelocityComponent velocityComponent = velocityMapper.get(asteroid);
|
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);
|
velocityComponent.angularVelocity = rand.nextFloat(-30, 30);
|
||||||
|
|
||||||
asteroid.activate();
|
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();
|
spawnAsteroid();
|
||||||
asteroidSpawnDelay = Constants.ASTEROID_SPAWN_DELAY;
|
asteroidSpawnDelay = Constants.ASTEROID_SPAWN_DELAY;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user