package net.mostlyoriginal.ns2d.system.active; import com.artemis.Aspect; import com.artemis.ComponentMapper; import com.artemis.Entity; import com.artemis.annotations.Wire; import com.artemis.systems.EntityProcessingSystem; import net.mostlyoriginal.ns2d.component.*; import net.mostlyoriginal.ns2d.system.passive.AssetSystem; import net.mostlyoriginal.ns2d.system.passive.CameraSystem; import net.mostlyoriginal.ns2d.system.passive.MapSystem; import net.mostlyoriginal.ns2d.util.MapMask; /** * Constrain movement to map collision. * <p/> * Inteded to clamp physics calculations. * * @author Daan van Yperen */ @Wire public class MapCollisionSystem extends EntityProcessingSystem { private static boolean DEBUG = false; private MapSystem mapSystem; private AssetSystem assetSystem; private CameraSystem cameraSystem; private boolean initialized; private MapMask solidMask; private ComponentMapper<Physics> ym; private ComponentMapper<Pos> pm; private ComponentMapper<Bounds> bm; public MapCollisionSystem() { super(Aspect.getAspectForAll(Physics.class, Pos.class, Bounds.class)); } @Override protected void begin() { if (!initialized) { initialized = true; solidMask = mapSystem.getMask("solid"); } } @Override protected void end() { } @Override protected void process(Entity e) { final Physics physics = ym.get(e); final Pos pos = pm.get(e); final Bounds bounds = bm.get(e); // no math required here. if (physics.vx != 0 || physics.vy != 0) { float px = pos.x + physics.vx * world.delta; float py = pos.y + physics.vy * world.delta; if ((physics.vx > 0 && collides(px + bounds.x2, py + bounds.y1 + (bounds.y2 - bounds.y1) * 0.5f)) || (physics.vx < 0 && collides(px + bounds.x1, py + bounds.y1 + (bounds.y2 - bounds.y1) * 0.5f))) { physics.vx = physics.bounce > 0 ? -physics.vx * physics.bounce : 0; px = pos.x; } if ((physics.vy > 0 && collides(px + bounds.x1 + (bounds.x2 - bounds.x1) * 0.5f, py + bounds.y2)) || (physics.vy < 0 && collides(px + bounds.x1 + (bounds.x2 - bounds.x1) * 0.5f, py + bounds.y1))) { physics.vy = physics.bounce > 0 ? -physics.vy * physics.bounce : 0; } } } private boolean collides(final float x, final float y) { if (DEBUG) { world.createEntity() .edit() .add(new Pos(x - 1, y - 1)) .add(new Anim("debug-marker")) .add(new Terminal(1)) ; } return solidMask.atScreen(x, y); } }