diff --git a/android/assets/machinegunPlanes.json b/android/assets/machinegunPlanes.json new file mode 100644 index 0000000..6e442d6 --- /dev/null +++ b/android/assets/machinegunPlanes.json @@ -0,0 +1,65 @@ +{ + "j_scout01": { + "collisionModel": "orig/j_scout01.n/collide.obj", + "normal": { + "minSpeed": 40, + "maxSpeed": 70, + "acceleration": 3.5, + "decceleration": 5 + }, + "displayModels": [ + { + "displayModel": "orig/j_scout01.n/wings.obj", + "displayTexture": "orig/j_scout01.n/texture_wingnone.ktx", + "children": [ + { + "displayModel": "orig/j_scout01.n/aileronl.obj", + "displayTexture": "orig/j_scout01.n/texture_wingnone.ktx", + "animationChannel": "wingVert", + "relativeTransform": { + "translation": [ + -6.154, + 2.943, + 0.887 + ], + "rotation": [ + 0.0, + 0.0, + 0.030538492, + -0.9995336 + ], + "scale": [ + 1, + 1, + 1 + ] + } + }, + { + "displayModel": "orig/j_scout01.n/aileronr.obj", + "displayTexture": "orig/j_scout01.n/texture_wingnone.ktx", + "animationChannel": "wingVert", + "relativeTransform": { + "translation": [ + 6.0, + 2.943, + 0.887 + ], + "rotation": [ + 0.0, + 0.0, + 0.030538514, + 0.9995336 + ], + "scale": [ + 1, + 1, + 1 + ] + } + } + ] + } + ] + } +} diff --git a/core/src/me/vinceh121/wanderer/IMeta.java b/core/src/me/vinceh121/wanderer/IMeta.java index bfaa475..6f881b7 100644 --- a/core/src/me/vinceh121/wanderer/IMeta.java +++ b/core/src/me/vinceh121/wanderer/IMeta.java @@ -2,6 +2,9 @@ import me.vinceh121.wanderer.entity.AbstractEntity; +/** + * TODO rename to prototype, that's more semantically correct + */ public interface IMeta { /** * Returns a new instance of the concerned entity meta. Perhaps a default if diff --git a/core/src/me/vinceh121/wanderer/MetaRegistry.java b/core/src/me/vinceh121/wanderer/MetaRegistry.java index 00f93e1..1aca0bd 100644 --- a/core/src/me/vinceh121/wanderer/MetaRegistry.java +++ b/core/src/me/vinceh121/wanderer/MetaRegistry.java @@ -22,6 +22,7 @@ import me.vinceh121.wanderer.character.CharacterMeta; import me.vinceh121.wanderer.entity.PropMeta; import me.vinceh121.wanderer.entity.guntower.MachineGunGuntowerMeta; +import me.vinceh121.wanderer.entity.plane.MachineGunPlaneMeta; public final class MetaRegistry { private static final Logger LOG = LogManager.getLogger(MetaRegistry.class); @@ -50,6 +51,7 @@ public void loadDefaults() throws StreamReadException, DatabindException, IOExce this.readMetas(Gdx.files.internal("characters.json"), CharacterMeta.class); this.readMetas(Gdx.files.internal("props.json"), PropMeta.class); this.readMetas(Gdx.files.internal("machinegunGuntowers.json"), MachineGunGuntowerMeta.class); + this.readMetas(Gdx.files.internal("machinegunPlanes.json"), MachineGunPlaneMeta.class); } public void clear() { diff --git a/core/src/me/vinceh121/wanderer/building/AbstractBuilding.java b/core/src/me/vinceh121/wanderer/building/AbstractBuilding.java index aab3f27..b0ee9f8 100644 --- a/core/src/me/vinceh121/wanderer/building/AbstractBuilding.java +++ b/core/src/me/vinceh121/wanderer/building/AbstractBuilding.java @@ -65,6 +65,7 @@ protected void onInteractContact(final btCollisionObject colObj0, final btCollis if (!(this.game.getControlledEntity() instanceof CharacterW)) { return; } + final CharacterW chara = (CharacterW) this.game.getControlledEntity(); // if collided objects are interaction zone and player character @@ -81,6 +82,7 @@ protected void onInteractStop(final btCollisionObject colObj0, final btCollision if (!(this.game.getControlledEntity() instanceof CharacterW)) { return; } + final CharacterW chara = (CharacterW) this.game.getControlledEntity(); // if collided objects are interaction zone and player character @@ -172,6 +174,7 @@ public void enterBtWorld(final btDiscreteDynamicsWorld world) { @Override public void leaveBtWorld(final btDiscreteDynamicsWorld world) { super.leaveBtWorld(world); + if (this.interactZone != null && !this.interactZone.isDisposed()) { world.removeCollisionObject(this.interactZone); } @@ -205,6 +208,7 @@ public void dispose() { if (this.island != null) { this.island.removeBuilding(this); } + this.game.getPhysicsManager().removeContactListener(this.interactListener); Gdx.app.postRunnable(() -> this.interactZone.dispose()); super.dispose(); diff --git a/core/src/me/vinceh121/wanderer/entity/plane/AbstractPlane.java b/core/src/me/vinceh121/wanderer/entity/plane/AbstractPlane.java new file mode 100644 index 0000000..7376f8a --- /dev/null +++ b/core/src/me/vinceh121/wanderer/entity/plane/AbstractPlane.java @@ -0,0 +1,107 @@ +package me.vinceh121.wanderer.entity.plane; + +import com.badlogic.gdx.math.MathUtils; +import com.badlogic.gdx.math.Vector3; +import com.badlogic.gdx.utils.Array; + +import me.vinceh121.wanderer.Wanderer; +import me.vinceh121.wanderer.building.ExplosionPart; +import me.vinceh121.wanderer.entity.AbstractClanLivingEntity; +import me.vinceh121.wanderer.entity.DisplayModel; +import me.vinceh121.wanderer.entity.IControllableEntity; +import me.vinceh121.wanderer.input.Input; +import me.vinceh121.wanderer.input.InputListener; +import me.vinceh121.wanderer.input.InputListenerAdapter; + +public abstract class AbstractPlane extends AbstractClanLivingEntity implements IControllableEntity { + private final Array explosionParts = new Array<>(); + private final PlaneSpeedProfile normal, turbo; + private boolean controlled; + private float speedUpTime; + + public AbstractPlane(Wanderer game, AbstractPlaneMeta meta) { + super(game); + + this.setCollideModel(meta.getCollisionModel()); + + for (final DisplayModel m : meta.getDisplayModels()) { + this.getModels().add(new DisplayModel(m)); + } + + for (final DisplayModel m : meta.getExplosionParts()) { + this.explosionParts.add(new DisplayModel(m)); + } + + this.normal = new PlaneSpeedProfile(meta.getNormal()); + this.turbo = new PlaneSpeedProfile(meta.getTurbo()); + } + + @Override + public void tick(final float delta) { + super.tick(delta); + + if (this.controlled) { + if (this.game.getInputManager().isPressed(Input.FLY_BOOST)) { + this.speedUpTime += delta; // FIXME upper clamp + } else { + this.speedUpTime = Math.max(0, this.speedUpTime - delta); + } + } + + final float speedUpProgress = this.speedUpTime / this.normal.getAcceleration(); + final float speed = MathUtils.lerp(this.normal.getMinSpeed(), this.normal.getMaxSpeed(), speedUpProgress); + + this.translate(0, 0, -speed * delta); + + if (this.controlled) { + this.moveCamera(); + + if (this.game.getInputManager().isPressed(Input.FIRE)) { + this.fire(); + } + } + } + + protected void moveCamera() { + final Vector3 arm = new Vector3(0, 6, 17); + arm.mul(this.getRotation()); + arm.add(this.getTranslation()); + + final Vector3 watch = new Vector3(0, 0, -50); + watch.mul(this.getRotation()); + watch.add(this.getTranslation()); + + this.game.getCamera().position.set(arm); + this.game.getCamera().lookAt(watch); + } + + public abstract void fire(); + + @Override + public void onDeath() { + this.game.removeEntity(this); + this.dispose(); + + for (final DisplayModel m : this.explosionParts) { + final ExplosionPart part = new ExplosionPart(this.game, m); + part.translate(this.getTranslation()); + part.addEventListener("collideModelLoaded", e -> part.thrust(10)); + this.game.addEntity(part); + } + } + + @Override + public void onTakeControl() { + this.controlled = true; + } + + @Override + public void onRemoveControl() { + this.controlled = false; + } + + @Override + public InputListener getInputProcessor() { + return new InputListenerAdapter(50); + } +} diff --git a/core/src/me/vinceh121/wanderer/entity/plane/AbstractPlaneMeta.java b/core/src/me/vinceh121/wanderer/entity/plane/AbstractPlaneMeta.java new file mode 100644 index 0000000..6888234 --- /dev/null +++ b/core/src/me/vinceh121/wanderer/entity/plane/AbstractPlaneMeta.java @@ -0,0 +1,54 @@ +package me.vinceh121.wanderer.entity.plane; + +import com.badlogic.gdx.utils.Array; + +import me.vinceh121.wanderer.IMeta; +import me.vinceh121.wanderer.entity.DisplayModel; + +public abstract class AbstractPlaneMeta implements IMeta { + private Array displayModels = new Array<>(); + private Array explosionParts = new Array<>(); + private String collisionModel; + private final PlaneSpeedProfile normal = new PlaneSpeedProfile(), turbo = new PlaneSpeedProfile(); + private float turboTime; + + public Array getDisplayModels() { + return displayModels; + } + + public void setDisplayModels(Array displayModels) { + this.displayModels = displayModels; + } + + public Array getExplosionParts() { + return explosionParts; + } + + public void setExplosionParts(Array explosionParts) { + this.explosionParts = explosionParts; + } + + public String getCollisionModel() { + return collisionModel; + } + + public void setCollisionModel(String collisionModel) { + this.collisionModel = collisionModel; + } + + public PlaneSpeedProfile getNormal() { + return this.normal; + } + + public PlaneSpeedProfile getTurbo() { + return this.turbo; + } + + public float getTurboTime() { + return turboTime; + } + + public void setTurboTime(float turboTime) { + this.turboTime = turboTime; + } +} diff --git a/core/src/me/vinceh121/wanderer/entity/plane/MachineGunPlane.java b/core/src/me/vinceh121/wanderer/entity/plane/MachineGunPlane.java new file mode 100644 index 0000000..2687071 --- /dev/null +++ b/core/src/me/vinceh121/wanderer/entity/plane/MachineGunPlane.java @@ -0,0 +1,14 @@ +package me.vinceh121.wanderer.entity.plane; + +import me.vinceh121.wanderer.Wanderer; + +public class MachineGunPlane extends AbstractPlane { + + public MachineGunPlane(Wanderer game, MachineGunPlaneMeta meta) { + super(game, meta); + } + + @Override + public void fire() { + } +} diff --git a/core/src/me/vinceh121/wanderer/entity/plane/MachineGunPlaneMeta.java b/core/src/me/vinceh121/wanderer/entity/plane/MachineGunPlaneMeta.java new file mode 100644 index 0000000..8c98228 --- /dev/null +++ b/core/src/me/vinceh121/wanderer/entity/plane/MachineGunPlaneMeta.java @@ -0,0 +1,12 @@ +package me.vinceh121.wanderer.entity.plane; + +import me.vinceh121.wanderer.Wanderer; +import me.vinceh121.wanderer.entity.AbstractEntity; + +public class MachineGunPlaneMeta extends AbstractPlaneMeta { + + @Override + public AbstractEntity create(Wanderer game) { + return new MachineGunPlane(game, this); + } +} diff --git a/core/src/me/vinceh121/wanderer/entity/plane/PlaneSpeedProfile.java b/core/src/me/vinceh121/wanderer/entity/plane/PlaneSpeedProfile.java new file mode 100644 index 0000000..c7d2796 --- /dev/null +++ b/core/src/me/vinceh121/wanderer/entity/plane/PlaneSpeedProfile.java @@ -0,0 +1,103 @@ +package me.vinceh121.wanderer.entity.plane; + +public class PlaneSpeedProfile { + private float minSpeed = Float.NaN, maxSpeed = Float.NaN, acceleration = Float.NaN, decceleration = Float.NaN, + maxPitch = Float.NaN, pitchSpeed = Float.NaN, maxYaw = Float.NaN, yawSpeed = Float.NaN, maxRoll = Float.NaN, + rollTime = Float.NaN; + + public PlaneSpeedProfile() { + } + + public PlaneSpeedProfile(PlaneSpeedProfile from) { + this.minSpeed = from.minSpeed; + this.maxSpeed = from.maxSpeed; + this.acceleration = from.acceleration; + this.decceleration = from.decceleration; + this.maxPitch = from.maxPitch; + this.pitchSpeed = from.pitchSpeed; + this.maxYaw = from.maxYaw; + this.yawSpeed = from.yawSpeed; + this.maxRoll = from.maxRoll; + this.rollTime = from.rollTime; + } + + public float getMinSpeed() { + return minSpeed; + } + + public void setMinSpeed(float minSpeed) { + this.minSpeed = minSpeed; + } + + public float getMaxSpeed() { + return maxSpeed; + } + + public void setMaxSpeed(float maxSpeed) { + this.maxSpeed = maxSpeed; + } + + public float getAcceleration() { + return acceleration; + } + + public void setAcceleration(float acceleration) { + this.acceleration = acceleration; + } + + public float getDecceleration() { + return decceleration; + } + + public void setDecceleration(float decceleration) { + this.decceleration = decceleration; + } + + public float getMaxPitch() { + return maxPitch; + } + + public void setMaxPitch(float maxPitch) { + this.maxPitch = maxPitch; + } + + public float getPitchSpeed() { + return pitchSpeed; + } + + public void setPitchSpeed(float pitchSpeed) { + this.pitchSpeed = pitchSpeed; + } + + public float getMaxYaw() { + return maxYaw; + } + + public void setMaxYaw(float maxYaw) { + this.maxYaw = maxYaw; + } + + public float getYawSpeed() { + return yawSpeed; + } + + public void setYawSpeed(float yawSpeed) { + this.yawSpeed = yawSpeed; + } + + public float getMaxRoll() { + return maxRoll; + } + + public void setMaxRoll(float maxRoll) { + this.maxRoll = maxRoll; + } + + public float getRollTime() { + return rollTime; + } + + public void setRollTime(float rollTime) { + this.rollTime = rollTime; + } +} diff --git a/core/src/me/vinceh121/wanderer/input/InputListenerAdapter.java b/core/src/me/vinceh121/wanderer/input/InputListenerAdapter.java index bfae5b3..0590b3e 100644 --- a/core/src/me/vinceh121/wanderer/input/InputListenerAdapter.java +++ b/core/src/me/vinceh121/wanderer/input/InputListenerAdapter.java @@ -3,6 +3,16 @@ public class InputListenerAdapter implements InputListener { private final int priority; + /** + * Priorities typical ranges are: + *
    + *
  • 0 : general, available all the time in game
  • + *
  • 50 : currently controlled character/gun tower/plane
  • + *
  • -1000 : NOOP
  • + *
+ * + * @param priority + */ public InputListenerAdapter(final int priority) { this.priority = priority; }