package net.mostlyoriginal.game.system.ship; import com.artemis.Aspect; import com.artemis.ComponentMapper; import com.artemis.Entity; import com.artemis.annotations.Wire; import com.artemis.systems.EntityProcessingSystem; import com.badlogic.gdx.math.MathUtils; import net.mostlyoriginal.api.component.graphics.Anim; import net.mostlyoriginal.api.thirdparty.SimplexNoise; import net.mostlyoriginal.game.component.ship.ShipComponent; /** * @author Daan van Yperen */ @Wire public class HullSystem extends EntityProcessingSystem { private boolean dirty = true; ShipComponentSystem shipComponentSystem; protected ComponentMapper<Anim> mAnim; protected ComponentMapper<ShipComponent> mc; public HullSystem() { // @todo manual qualifiers. super(Aspect.getAspectForAll(ShipComponent.class, Anim.class)); } @Override protected void begin() { super.begin(); if (dirty) { dirty = false; generateMissingHullPieces(); connectHullPieces(); } } private static class Pattern { private final int[] layout; public final String[] animId; public final String[] animIdBuilding; private Pattern( String animId, int ... layout ) { this.layout = layout; this.animId = new String[] {animId}; this.animIdBuilding = new String[] {animId + "-building"}; } private Pattern( String[] animId, int ... layout ) { this.layout = layout; this.animId = animId; this.animIdBuilding = new String[animId.length]; for (int i=0;i<animId.length;i++) { this.animIdBuilding[i] = animId[i] + "-building"; } } public boolean matches(int[] pat) { for (int i = 0; i < 9; i++) { if ( layout[i] == 2 ) continue; // ignore! if ( pat[i] != layout[i] ) return false; } return true; } } // 0: empty // 1: wall (or engine, solar panel, scoop) // 2: ignore private static final Pattern[] patterns = { // top left new Pattern("hull-0", 2, 0, 2, 0, 1, 1, 2, 1, 1), new Pattern(new String[] {"hull-1","hull-1","hull-1","hull-1", "hull-1-solar", "hull-1-wing"}, 2, 0, 2, 1, 1, 1, 2, 1, 2), // top right, new Pattern("hull-2", 2, 0, 2, 1, 1, 0, 1, 1, 2), // left new Pattern("hull-3", 2, 1, 2, 0, 1, 1, 2, 1, 2), // right new Pattern("hull-4", 2, 1, 2, 1, 1, 0, 2, 1, 2), // b-left new Pattern("hull-5", 2, 1, 1, 0, 1, 1, 0, 0, 2), // b-middle new Pattern("hull-6", 2, 1, 2, 1, 1, 1, 2, 0, 2), // b-right new Pattern("hull-7", 1, 1, 2, 1, 1, 0, 2, 0, 0), // b-right new Pattern("hull-inny-0", 1, 1, 2, 1, 1, 1, 2, 1, 0), // b-left new Pattern("hull-inny-1", 2, 1, 1, 1, 1, 1, 0, 1, 2), // t-right new Pattern("hull-inny-2", 2, 1, 0, 1, 1, 1, 1, 1, 1), // t-left new Pattern("hull-inny-3", 0, 1, 2, 1, 1, 1, 2, 1, 1) }; private static final int[] pat = new int[9]; private void connectHullPieces() { for (int gridY = 0; gridY < ShipComponentSystem.MAX_Y; gridY++) { for (int gridX = 0; gridX < ShipComponentSystem.MAX_X; gridX++) { final Entity entity = shipComponentSystem.get(gridX, gridY); if ( entity != null ) { // try to find non hull pieces. ShipComponent shipComponent = mc.get(entity); if ( shipComponent != null && shipComponent.type == ShipComponent.Type.HULL ) { // attempt to place hull in all directions. // @todo what am i doing @_@ IN A HURRY DON'T CARE. pat[0] = structureAt(-1 + gridX, 1 + gridY); pat[1] = structureAt(0 + gridX, 1 + gridY); pat[2] = structureAt(1 + gridX, 1 + gridY); pat[3] = structureAt(-1 + gridX, 0 + gridY); pat[4] = 1; pat[5] = structureAt(1 + gridX, 0 + gridY); pat[6] = structureAt(-1 + gridX, -1 + gridY); pat[7] = structureAt(0 + gridX, -1 + gridY); pat[8] = structureAt(1 + gridX, -1 + gridY); final Anim anim = mAnim.get(entity); anim.id = "hull-missing"; for (Pattern pattern : patterns) { if ( pattern.matches(pat)) { final String[] newId = shipComponent.state == ShipComponent.State.UNDER_CONSTRUCTION ? pattern.animIdBuilding : pattern.animId; if ( !newId.equals(anim.id) ) { double index = (SimplexNoise.noise(gridX*100f,gridY*100f,0)+1.0)*0.5; anim.id = newId[Math.min(newId.length, (int)(index * newId.length))]; } break; } } } } } } } private int structureAt(int gridX, int gridY) { final Entity entity = shipComponentSystem.get(gridX, gridY); if ( entity != null ) { return 1; } // nothing here. return 0; } private void generateMissingHullPieces() { for (int gridY = 1; gridY < ShipComponentSystem.MAX_Y-1; gridY++) { for (int gridX = 1; gridX < ShipComponentSystem.MAX_X-1; gridX++) { final Entity entity = shipComponentSystem.get(gridX, gridY); if ( entity != null ) { // try to find non hull pieces. ShipComponent shipComponent = mc.get(entity); if ( shipComponent != null && !shipComponent.type.countsAsHull ) { // attempt to place hull in all directions. placeHull(-1 + gridX,-1 + gridY); placeHull( 0 + gridX,-1 + gridY); placeHull( 1 + gridX,-1 + gridY); placeHull(-1 + gridX, 0 + gridY); placeHull( 1 + gridX, 0 + gridY); placeHull(-1 + gridX, 1 + gridY); placeHull( 0 + gridX, 1 + gridY); placeHull( 1 + gridX, 1 + gridY); } } } } } // attempt to place hull at coordinates, if slot is empty. private void placeHull(int gridX, int gridY) { final Entity entity = shipComponentSystem.get(gridX, gridY); if ( entity == null ) { shipComponentSystem.createComponent(gridX, gridY, ShipComponent.Type.HULL, ShipComponent.State.UNDER_CONSTRUCTION); } } // regenerate walls. public void dirty() { dirty = true; } @Override protected void process(Entity e) { } }