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 com.badlogic.gdx.Gdx; import com.badlogic.gdx.Input; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import net.mostlyoriginal.ns2d.component.*; import net.mostlyoriginal.ns2d.system.passive.AssetSystem; import net.mostlyoriginal.ns2d.system.render.DialogRenderSystem; /** * @author Daan van Yperen */ @Wire public class PlayerControlSystem extends EntityProcessingSystem { public static final int MOVEMENT_FACTOR = 1000; public static final int JUMP_FACTOR = 10000; public static final int JETPACK_THRUST = 1500; public static final int THRUST_VECTOR = 90; public static final float ROTATIONAL_SPEED_JETPACK_ON = 120f; public static final float ROTATIONAL_SPEED_JETPACK_OFF = 360f; private ComponentMapper<Physics> ym; private ComponentMapper<WallSensor> wm; private ComponentMapper<Pos> pm; private ComponentMapper<Weapon> wem; private ComponentMapper<Gravity> gm; private ComponentMapper<Inventory> im; private ComponentMapper<Anim> am; private ComponentMapper<Frozen> fm; private ComponentMapper<Bounds> bm; private ComponentMapper<Attached> attm; private EntitySpawnerSystem entitySpawnerSystem; private PhysicsSystem physicsSystem; private AssetSystem assetSystem; private boolean jetpackLooping; private ParticleSystem particleSystem; private float jetpackGasCooldown; private Vector2 vTmp = new Vector2(); private Vector2 vTmp2 = new Vector2(); private float lastPuffX; private float lastPuffY; private DialogRenderSystem dialogRenderSystem; private float jetPackMessageCooldown; public PlayerControlSystem() { super(Aspect.getAspectForAll(PlayerControlled.class, Physics.class, WallSensor.class, Anim.class)); } Vector2 tmp = new Vector2(); float jetPackUsageTime = 0; float jetPackRollingTime = 0; @Override protected void process(Entity player) { jetPackMessageCooldown -= world.delta; final Physics physics = ym.get(player); final Gravity gravity = gm.get(player); // frozen player does not act. if (fm.has(player)) { stopJetpackLooping(); player.getComponent(Anim.class).id = "player-respawning"; gravity.enabled = false; physics.vr = physics.vx = physics.vy = 0; return; } if (Gdx.input.isKeyPressed(Input.Keys.SPACE) || Gdx.input.isButtonPressed(0)) { Inventory inventory = im.get(player); if (inventory.weapon != null && inventory.weapon.isActive()) { Weapon weapon = wem.get(inventory.weapon); weapon.firing = true; } } final WallSensor wallSensor = wm.get(player); final Pos pos = pm.get(player); final Anim anim = am.get(player); gravity.enabled = true; if (wallSensor.onFloor) { stopJetpackLooping(); anim.id = "player-idle"; // handle player walking. move left and right, rotation always 0. anim.rotation = 0; physics.vr = 0; float dx = 0; float dy = 0; if (Gdx.input.isKeyPressed(Input.Keys.A)) { dx = -MOVEMENT_FACTOR; flip(player, true); } if (Gdx.input.isKeyPressed(Input.Keys.D)) { dx = MOVEMENT_FACTOR; flip(player, false); } if (Gdx.input.isKeyPressed(Input.Keys.W)) // jump { dy = JUMP_FACTOR; } ; if (dx != 0) { physics.vx += dx * world.delta; anim.id = "player-walk"; } if (dy != 0) physics.vy += dy * world.delta; } else { anim.id = "player-jetpack"; // handle player flying! :D boolean jetPackActive = Gdx.input.isKeyPressed(Input.Keys.W); float turningSpeed = jetPackActive ? ROTATIONAL_SPEED_JETPACK_ON : ROTATIONAL_SPEED_JETPACK_OFF; // slow turning. int rx = 0; if (Gdx.input.isKeyPressed(Input.Keys.A)) rx += turningSpeed; if (Gdx.input.isKeyPressed(Input.Keys.D)) rx -= turningSpeed; if (rx != 0) { if (!jetPackActive) { jetPackRollingTime += world.delta; if (jetPackRollingTime >= 1 && jetPackMessageCooldown <= 0) { jetPackMessageCooldown = 10; dialogRenderSystem.randomSay(DialogRenderSystem.JETPACK_ROLLING); } } else jetPackRollingTime=0; physics.vr += rx * world.delta * 10f; } else { jetPackRollingTime = 0; // not steering, not jetpack active? auto-straighten if (!jetPackActive) { float rotationClamped = ((anim.rotation % 360 + 360) % 360); if (rotationClamped < 180) physics.vr -= turningSpeed * world.delta * 1f; if (rotationClamped > 180) physics.vr += turningSpeed * world.delta * 1f; if (rotationClamped < 90) physics.vr -= turningSpeed * world.delta * 1f; if (rotationClamped > 180 + 90) physics.vr += turningSpeed * world.delta * 1f; } } if (jetPackActive) { startJetpackLooping(); jetpackGasCooldown -= world.delta; float distanceMoved = vTmp.set(lastPuffX, lastPuffY).dst(pos.x, pos.y); if ( distanceMoved <= 0.1f ) jetPackUsageTime=0; if (jetpackGasCooldown <= 0 || distanceMoved >= 4f) { lastPuffX = pos.x; lastPuffY = pos.y; jetpackGasCooldown = 1 / 15f; vTmp.set(anim.flippedX ? 8 : -8, 0).rotate(anim.rotation).add(pos.x + 16, pos.y + 16); particleSystem.setRotation(anim.rotation - (10f + MathUtils.random(-10f, 10f) * (anim.flippedX ? -1f : 1f))); particleSystem.spawnParticle((int) (vTmp.x), (int) (vTmp.y), "puff"); particleSystem.setRotation(anim.rotation - 10f * (anim.flippedX ? -1f : 1f)); vTmp.set(anim.flippedX ? 8 : -8, -13).rotate(anim.rotation).add(pos.x + 16, pos.y + 16); particleSystem.spawnParticle((int) (vTmp.x), (int) (vTmp.y), "gasburn"); particleSystem.setRotation(0); } gravity.enabled = false; physicsSystem.push(player, anim.rotation + THRUST_VECTOR, JETPACK_THRUST * world.delta); physicsSystem.clampVelocity(player, 0, 100); physics.vr = MathUtils.clamp(physics.vr, -ROTATIONAL_SPEED_JETPACK_ON * 2, ROTATIONAL_SPEED_JETPACK_ON * 2); // clamp our rotation while accelerating. } else { stopJetpackLooping(); gravity.enabled = true; physics.vr = MathUtils.clamp(physics.vr, -ROTATIONAL_SPEED_JETPACK_OFF * 2, ROTATIONAL_SPEED_JETPACK_OFF * 2); } } } private void startJetpackLooping() { jetPackUsageTime += world.delta; if (jetPackUsageTime > 2 && jetPackMessageCooldown <= 0) { jetPackMessageCooldown = 20; dialogRenderSystem.randomSay(DialogRenderSystem.JETPACK_USAGE); } if (!jetpackLooping) { jetpackLooping = true; assetSystem.getSfx("ns2d_sfx_jetpack_loop").loop(0.09f); assetSystem.getSfx("ns2d_sfx_jetpack_start").play(0.05f); } } private void stopJetpackLooping() { jetPackUsageTime = 0; if (jetpackLooping) { jetpackLooping = false; assetSystem.getSfx("ns2d_sfx_jetpack_loop").stop(); } } private void flip(Entity player, boolean flippedX) { final Anim anim = am.get(player); anim.flippedX = flippedX; /* Inventory inventory = im.get(player); if ( inventory.weapon != null && inventory.weapon.isActive() ) { Attached weaponAttached = attm.get(inventory.weapon); Anim weaponAnim = am.get(inventory.weapon); weaponAnim.flippedX = flippedX; } */ } }