Add beginnings of game code.
This commit is contained in:
parent
909b50b47d
commit
89a7bc031c
121
core/src/com/me/asteroids/AsteroidFactory.java
Normal file
121
core/src/com/me/asteroids/AsteroidFactory.java
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
package com.me.asteroids;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
|
import com.badlogic.gdx.math.Polygon;
|
||||||
|
import com.badlogic.gdx.math.Vector2;
|
||||||
|
import com.me.common.Random;
|
||||||
|
|
||||||
|
public final class AsteroidFactory {
|
||||||
|
|
||||||
|
public static final Random rand = new Random();
|
||||||
|
|
||||||
|
int vertexCount;
|
||||||
|
float size;
|
||||||
|
|
||||||
|
float sizeVariation;
|
||||||
|
float angleVariation;
|
||||||
|
|
||||||
|
boolean sizeRelativeToLast;
|
||||||
|
|
||||||
|
public AsteroidFactory setVertexCount(int vertexCount) {
|
||||||
|
this.vertexCount = vertexCount;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsteroidFactory setSize(float size) {
|
||||||
|
this.size = size;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsteroidFactory setSizeVariation(float sizeVariation) {
|
||||||
|
this.sizeVariation = sizeVariation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsteroidFactory sizeRelativeToLast() {
|
||||||
|
this.sizeRelativeToLast = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsteroidFactory sizeRelativeToInitial() {
|
||||||
|
this.sizeRelativeToLast = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsteroidFactory setAngleVariation(float angleVariation) {
|
||||||
|
this.angleVariation = angleVariation;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validate() {
|
||||||
|
if (vertexCount <= 2) {
|
||||||
|
throw new IllegalStateException(String.format("Illegal vertexCount: %d. Must be >= 3.", vertexCount));
|
||||||
|
}
|
||||||
|
if (size <= 0) {
|
||||||
|
throw new IllegalStateException(String.format("Illegal vertexCount: %f. Must be > 0.", size));
|
||||||
|
}
|
||||||
|
if (sizeVariation < 0) {
|
||||||
|
throw new IllegalStateException(String.format("Illegal sizeVariation: %f. Must be >= 0.", sizeVariation));
|
||||||
|
}
|
||||||
|
if (sizeVariation > size) {
|
||||||
|
throw new IllegalStateException(String.format("Illegal sizeVariation: %f. Must be <= size.", sizeVariation));
|
||||||
|
}
|
||||||
|
if (angleVariation < 0) {
|
||||||
|
throw new IllegalStateException(String.format("Illegal angleVariation: %f. Must be >= 0.", angleVariation));
|
||||||
|
}
|
||||||
|
if (angleVariation > MathUtils.PI2 / vertexCount / 2) {
|
||||||
|
throw new IllegalStateException(String.format("Illegal angleVariation: %f. May cause vertexes positions to swap.", angleVariation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 applyAngleVariation(Vector2 vertex) {
|
||||||
|
if (angleVariation > 0) {
|
||||||
|
float half = angleVariation * 0.5f;
|
||||||
|
vertex.rotateRad(rand.nextFloat(-half, half));
|
||||||
|
}
|
||||||
|
return vertex;
|
||||||
|
}
|
||||||
|
|
||||||
|
private float applySizeVariation(float size) {
|
||||||
|
if (sizeVariation > 0) {
|
||||||
|
float half = sizeVariation * 0.5f;
|
||||||
|
float variation = rand.nextFloat(-half, half);
|
||||||
|
if (sizeRelativeToLast) {
|
||||||
|
size += variation;
|
||||||
|
size = MathUtils.clamp(size, this.size - half, this.size + half);
|
||||||
|
} else {
|
||||||
|
size = this.size + variation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Polygon generate() {
|
||||||
|
validate();
|
||||||
|
|
||||||
|
float angleStep = MathUtils.PI2 / vertexCount;
|
||||||
|
|
||||||
|
// Pick a random starting angle
|
||||||
|
float startAngle = rand.nextFloat() * MathUtils.PI2;
|
||||||
|
Vector2 dir = new Vector2(MathUtils.cos(startAngle), MathUtils.sin(startAngle));
|
||||||
|
|
||||||
|
float lastSize = size;
|
||||||
|
float[] vertices = new float[vertexCount * 2];
|
||||||
|
|
||||||
|
for (int i = 0; i < vertexCount; i++) {
|
||||||
|
Vector2 vertex = dir.cpy();
|
||||||
|
|
||||||
|
vertex = applyAngleVariation(vertex);
|
||||||
|
lastSize = applySizeVariation(lastSize);
|
||||||
|
|
||||||
|
vertex.scl(lastSize);
|
||||||
|
vertices[i * 2] = vertex.x;
|
||||||
|
vertices[(i * 2) + 1] = vertex.y;
|
||||||
|
|
||||||
|
dir.rotateRad(angleStep);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Polygon(vertices);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
39
core/src/com/me/asteroids/Asteroids.java
Normal file
39
core/src/com/me/asteroids/Asteroids.java
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
package com.me.asteroids;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.ApplicationAdapter;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.me.asteroids.screens.GameScreen;
|
||||||
|
import com.me.common.Game;
|
||||||
|
|
||||||
|
public class Asteroids extends ApplicationAdapter {
|
||||||
|
|
||||||
|
public Graphics graphics;
|
||||||
|
private Game game;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void create () {
|
||||||
|
graphics = new Graphics(Constants.WIDTH, Constants.HEIGHT);
|
||||||
|
graphics.initialize();
|
||||||
|
|
||||||
|
game = new Game();
|
||||||
|
game.setNextScreen(new GameScreen(graphics));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render () {
|
||||||
|
game.update(Gdx.graphics.getDeltaTime());
|
||||||
|
game.render();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose () {
|
||||||
|
graphics.dispose();
|
||||||
|
game.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resize(int width, int height) {
|
||||||
|
graphics.setScreenSize(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
11
core/src/com/me/asteroids/Constants.java
Normal file
11
core/src/com/me/asteroids/Constants.java
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package com.me.asteroids;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
public static final int WIDTH = 800;
|
||||||
|
public static final int HEIGHT = 600;
|
||||||
|
|
||||||
|
public static final int HALF_WIDTH = WIDTH / 2;
|
||||||
|
public static final int HALF_HEIGHT = HEIGHT / 2;
|
||||||
|
|
||||||
|
}
|
63
core/src/com/me/asteroids/Graphics.java
Normal file
63
core/src/com/me/asteroids/Graphics.java
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
package com.me.asteroids;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.graphics.Camera;
|
||||||
|
import com.badlogic.gdx.graphics.GL20;
|
||||||
|
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||||
|
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||||
|
import com.badlogic.gdx.utils.viewport.FitViewport;
|
||||||
|
import com.badlogic.gdx.utils.viewport.Viewport;
|
||||||
|
|
||||||
|
public class Graphics {
|
||||||
|
|
||||||
|
private int worldWidth, worldHeight;
|
||||||
|
private int screenWidth, screenHeight;
|
||||||
|
|
||||||
|
private Camera camera;
|
||||||
|
private Viewport viewport;
|
||||||
|
|
||||||
|
private ShapeRenderer shapeRenderer;
|
||||||
|
|
||||||
|
public Graphics(int worldWidth, int worldHeight) {
|
||||||
|
this.worldWidth = worldWidth;
|
||||||
|
this.worldHeight = worldHeight;
|
||||||
|
this.screenWidth = Gdx.graphics.getWidth();
|
||||||
|
this.screenHeight = Gdx.graphics.getHeight();
|
||||||
|
|
||||||
|
this.camera = new OrthographicCamera();
|
||||||
|
this.viewport = new FitViewport(worldHeight, worldWidth, camera);
|
||||||
|
|
||||||
|
this.shapeRenderer = new ShapeRenderer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize() {
|
||||||
|
Gdx.gl.glClearColor(0, 0, 0, 1);
|
||||||
|
updateDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScreenSize(int width, int height) {
|
||||||
|
screenWidth = width;
|
||||||
|
screenHeight = height;
|
||||||
|
updateDimensions();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
shapeRenderer.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapeRenderer getShapeRenderer() {
|
||||||
|
return shapeRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDimensions() {
|
||||||
|
viewport.setWorldSize(worldWidth, worldHeight);
|
||||||
|
viewport.update(screenWidth, screenHeight, true);
|
||||||
|
|
||||||
|
shapeRenderer.setProjectionMatrix(camera.combined);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
core/src/com/me/asteroids/Utils.java
Normal file
28
core/src/com/me/asteroids/Utils.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package com.me.asteroids;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
|
import com.badlogic.gdx.math.Vector2;
|
||||||
|
|
||||||
|
import java.lang.Math;
|
||||||
|
|
||||||
|
public final class Utils {
|
||||||
|
|
||||||
|
public static float rotate(float rotation, float degrees) {
|
||||||
|
rotation += degrees;
|
||||||
|
if (rotation < 0) {
|
||||||
|
rotation = 360 - rotation;
|
||||||
|
} else if (rotation > 360) {
|
||||||
|
rotation -= 360;
|
||||||
|
}
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 setUnitVectorAngle(Vector2 vector, float degrees) {
|
||||||
|
return vector.set((float) Math.cos(degrees * MathUtils.degreesToRadians), (float) Math.sin(degrees * MathUtils.degreesToRadians));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector2 setUnitVectorAngleRad(Vector2 vector, float radians) {
|
||||||
|
return vector.set((float) Math.cos(radians), (float) Math.sin(radians));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
29
core/src/com/me/asteroids/screens/GameScreen.java
Normal file
29
core/src/com/me/asteroids/screens/GameScreen.java
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package com.me.asteroids.screens;
|
||||||
|
|
||||||
|
import com.me.asteroids.Graphics;
|
||||||
|
import com.me.common.Screen;
|
||||||
|
|
||||||
|
public class GameScreen extends Screen {
|
||||||
|
|
||||||
|
Graphics graphics;
|
||||||
|
|
||||||
|
public GameScreen(Graphics graphics) {
|
||||||
|
this.graphics = graphics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setup() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(float dt) {
|
||||||
|
graphics.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
40
core/src/com/me/common/Game.java
Normal file
40
core/src/com/me/common/Game.java
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package com.me.common;
|
||||||
|
|
||||||
|
public class Game {
|
||||||
|
|
||||||
|
private Screen screen;
|
||||||
|
private Screen nextScreen;
|
||||||
|
|
||||||
|
public void update(float dt) {
|
||||||
|
if (nextScreen != null) {
|
||||||
|
handleScreeUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (screen != null) {
|
||||||
|
screen.update(dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render() {
|
||||||
|
if (screen != null) {
|
||||||
|
screen.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleScreeUpdate() {
|
||||||
|
if (screen != null) screen.dispose();
|
||||||
|
|
||||||
|
nextScreen.setup();
|
||||||
|
screen = nextScreen;
|
||||||
|
nextScreen = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNextScreen(Screen screen) {
|
||||||
|
nextScreen = screen;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
screen.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
8
core/src/com/me/common/MockRenderer.java
Normal file
8
core/src/com/me/common/MockRenderer.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package com.me.common;
|
||||||
|
|
||||||
|
public class MockRenderer implements Renderer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render() {}
|
||||||
|
|
||||||
|
}
|
13
core/src/com/me/common/MockScreen.java
Normal file
13
core/src/com/me/common/MockScreen.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package com.me.common;
|
||||||
|
|
||||||
|
public class MockScreen extends Screen {
|
||||||
|
|
||||||
|
public void setup() {
|
||||||
|
setRenderer(new MockRenderer());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(float dt) {}
|
||||||
|
|
||||||
|
public void dispose() {}
|
||||||
|
|
||||||
|
}
|
21
core/src/com/me/common/Random.java
Normal file
21
core/src/com/me/common/Random.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package com.me.common;
|
||||||
|
|
||||||
|
public class Random extends java.util.Random {
|
||||||
|
|
||||||
|
public Random() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Random(long seed) {
|
||||||
|
super(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public float nextFloat(float min, float max) {
|
||||||
|
return min + (nextFloat() * Math.abs(min - max));
|
||||||
|
}
|
||||||
|
|
||||||
|
public int nextInt(int min, int max) {
|
||||||
|
return min + nextInt(Math.abs(min - max));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
7
core/src/com/me/common/Renderer.java
Normal file
7
core/src/com/me/common/Renderer.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package com.me.common;
|
||||||
|
|
||||||
|
public interface Renderer {
|
||||||
|
|
||||||
|
void render();
|
||||||
|
|
||||||
|
}
|
23
core/src/com/me/common/Screen.java
Normal file
23
core/src/com/me/common/Screen.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.me.common;
|
||||||
|
|
||||||
|
public abstract class Screen {
|
||||||
|
|
||||||
|
private Renderer renderer;
|
||||||
|
|
||||||
|
public abstract void setup();
|
||||||
|
|
||||||
|
public abstract void update(float dt);
|
||||||
|
|
||||||
|
public abstract void dispose();
|
||||||
|
|
||||||
|
public void setRenderer(Renderer renderer) {
|
||||||
|
this.renderer = renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render() {
|
||||||
|
if (renderer != null) {
|
||||||
|
renderer.render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
5
core/src/com/me/common/ecs/Component.java
Normal file
5
core/src/com/me/common/ecs/Component.java
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
package com.me.common.ecs;
|
||||||
|
|
||||||
|
public abstract class Component {
|
||||||
|
|
||||||
|
}
|
41
core/src/com/me/common/ecs/ComponentBag.java
Normal file
41
core/src/com/me/common/ecs/ComponentBag.java
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package com.me.common.ecs;
|
||||||
|
|
||||||
|
public class ComponentBag {
|
||||||
|
|
||||||
|
private Component[] items;
|
||||||
|
private int size;
|
||||||
|
|
||||||
|
public ComponentBag() {
|
||||||
|
this.items = new Component[16];
|
||||||
|
this.size = items.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component get(int index) {
|
||||||
|
if (index > size) {
|
||||||
|
throw new IndexOutOfBoundsException("index > size");
|
||||||
|
}
|
||||||
|
return items[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void insert(int index, Component item) {
|
||||||
|
if (index >= size) {
|
||||||
|
grow((int) (index * 1.5f));
|
||||||
|
}
|
||||||
|
items[index] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(int index) {
|
||||||
|
if (index >= size) {
|
||||||
|
throw new IndexOutOfBoundsException("index must be < size");
|
||||||
|
}
|
||||||
|
items[index] = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void grow(int newSize) {
|
||||||
|
Component[] newItems = new Component[newSize];
|
||||||
|
System.arraycopy(this.items, 0, newItems, 0, size);
|
||||||
|
size = newSize;
|
||||||
|
this.items = newItems;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
78
core/src/com/me/common/ecs/ComponentType.java
Normal file
78
core/src/com/me/common/ecs/ComponentType.java
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
package com.me.common.ecs;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class ComponentType {
|
||||||
|
|
||||||
|
private static final Map<Class<? extends Component>, ComponentType> types = new HashMap<>();
|
||||||
|
private static final ComponentType[] typeById = new ComponentType[Long.SIZE];
|
||||||
|
|
||||||
|
private static long nextBit = 1l;
|
||||||
|
private static int nextId = 0;
|
||||||
|
|
||||||
|
private long bits;
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
private ComponentType() {
|
||||||
|
this.bits = nextBit;
|
||||||
|
this.id = nextId++;
|
||||||
|
|
||||||
|
this.nextBit <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long getBits() {
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static long getMaskBits(Class<? extends Component>... components) {
|
||||||
|
long mask = 0l;
|
||||||
|
for (Class<? extends Component> clazz : components) {
|
||||||
|
mask |= getTypeBits(clazz);
|
||||||
|
}
|
||||||
|
return mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static long getTypeBits(Class<? extends Component> component) {
|
||||||
|
return getComponentType(component).getBits();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int getTypeId(Class<? extends Component> component) {
|
||||||
|
return getComponentType(component).getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static ComponentType getById(int id) {
|
||||||
|
return typeById[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isTypeInMask(long mask) {
|
||||||
|
return (bits & mask) == mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static void registerComponentType(Class<? extends Component> component) {
|
||||||
|
ComponentType type = types.get(component);
|
||||||
|
if (type != null) {
|
||||||
|
throw new IllegalArgumentException(component.getName() + " has already been registered.");
|
||||||
|
}
|
||||||
|
type = new ComponentType();
|
||||||
|
types.put(component, type);
|
||||||
|
typeById[type.getId()] = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static ComponentType getComponentType(Class<? extends Component> component) {
|
||||||
|
ComponentType type = types.get(component);
|
||||||
|
if (type == null) {
|
||||||
|
throw new IllegalArgumentException(component.getName() + " has not been registered.");
|
||||||
|
}
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static int getRegisteredComponentTypeCount() {
|
||||||
|
return types.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
90
core/src/com/me/common/ecs/Engine.java
Normal file
90
core/src/com/me/common/ecs/Engine.java
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
package com.me.common.ecs;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
|
public class Engine {
|
||||||
|
|
||||||
|
private Array<Entity> entities;
|
||||||
|
private ComponentBag[] components;
|
||||||
|
private Array<EntitySystem> systems;
|
||||||
|
|
||||||
|
public Engine() {
|
||||||
|
this.entities = new Array<>();
|
||||||
|
this.systems = new Array<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerComponentClass(Class<? extends Component> clazz) {
|
||||||
|
ComponentType.registerComponentType(clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerSystem(EntitySystem system) {
|
||||||
|
this.systems.add(system);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ready() {
|
||||||
|
this.components = new ComponentBag[ComponentType.getRegisteredComponentTypeCount()];
|
||||||
|
for (int i = 0; i < components.length; i++) {
|
||||||
|
components[i] = new ComponentBag();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update(float dt) {
|
||||||
|
for (EntitySystem system : systems) {
|
||||||
|
system.preProcessing();
|
||||||
|
updateSystem(system, dt);
|
||||||
|
system.postProcessing();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity createEntity() {
|
||||||
|
Entity entity = new Entity(this);
|
||||||
|
entities.add(entity);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeEntity(Entity entity) {
|
||||||
|
removeAllEntityComponents(entity.getId());
|
||||||
|
entities.removeValue(entity, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeAllEntityComponents(int entityId) {
|
||||||
|
for (int i = 0; i < components.length; i++) {
|
||||||
|
components[i].insert(entityId, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addEntityComponent(Entity entity, Component component) {
|
||||||
|
ComponentType type = ComponentType.getComponentType(component.getClass());
|
||||||
|
components[type.getId()].insert(entity.getId(), component);
|
||||||
|
entity.addComponentType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeEntityComponent(Entity entity, Component component) {
|
||||||
|
ComponentType type = ComponentType.getComponentType(component.getClass());
|
||||||
|
components[type.getId()].remove(entity.getId());
|
||||||
|
entity.removeComponentType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T extends Component> T getEntityComponent(Entity entity, Class<T> clazz) {
|
||||||
|
ComponentType type = ComponentType.getComponentType(clazz);
|
||||||
|
return clazz.cast(components[type.getId()].get(entity.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void updateSystem(EntitySystem system, float dt) {
|
||||||
|
for (Entity entity : entities) {
|
||||||
|
if (!entity.isActive()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this system is interested in this entity
|
||||||
|
if ((entity.getComponentBits() & system.getTypeMask()) != system.getTypeMask()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If so, process the entity
|
||||||
|
system.processEntity(entity, dt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
60
core/src/com/me/common/ecs/Entity.java
Normal file
60
core/src/com/me/common/ecs/Entity.java
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package com.me.common.ecs;
|
||||||
|
|
||||||
|
public final class Entity {
|
||||||
|
|
||||||
|
private static int nextId = 0;
|
||||||
|
|
||||||
|
private Engine engine;
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
private boolean active;
|
||||||
|
|
||||||
|
private long componentBits;
|
||||||
|
|
||||||
|
protected Entity(Engine engine) {
|
||||||
|
this.engine = engine;
|
||||||
|
this.active = false;
|
||||||
|
this.id = nextId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void activate() {
|
||||||
|
this.active = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void deactivate() {
|
||||||
|
this.active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends Component> T getComponent(Class<T> clazz) {
|
||||||
|
return engine.getEntityComponent(this, clazz);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addComponent(Component component) {
|
||||||
|
engine.addEntityComponent(this, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeComponent(Component component) {
|
||||||
|
engine.removeEntityComponent(this, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void addComponentType(ComponentType type) {
|
||||||
|
componentBits |= type.getBits();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void removeComponentType(ComponentType type) {
|
||||||
|
componentBits &= ~type.getBits();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long getComponentBits() {
|
||||||
|
return componentBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
core/src/com/me/common/ecs/EntitySystem.java
Normal file
25
core/src/com/me/common/ecs/EntitySystem.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package com.me.common.ecs;
|
||||||
|
|
||||||
|
public abstract class EntitySystem {
|
||||||
|
|
||||||
|
private long typeBits;
|
||||||
|
|
||||||
|
public EntitySystem(Class<? extends Component>... components) {
|
||||||
|
typeBits = ComponentType.getMaskBits(components);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the type mask for this system. Only entities containing all component types specified
|
||||||
|
* by the mask will be processed by it.
|
||||||
|
*/
|
||||||
|
public long getTypeMask() {
|
||||||
|
return typeBits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void preProcessing() {}
|
||||||
|
|
||||||
|
public abstract void processEntity(Entity entity, float dt);
|
||||||
|
|
||||||
|
public void postProcessing() {}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user