From d92730db132d11ad95528834056365bf1c7779eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laure=CE=B7t?= Date: Mon, 5 Apr 2021 23:14:56 +0200 Subject: [PATCH] feat: Player's Bow can now shoot Arrows (physics need adjusting) --- core/build.gradle | 2 +- core/src/bzh/fainsin/sagittarius/Arrow.java | 89 +++++++++++++++++++ core/src/bzh/fainsin/sagittarius/Bow.java | 63 +++++++++++++ core/src/bzh/fainsin/sagittarius/Entity.java | 23 +---- .../bzh/fainsin/sagittarius/GameScreen.java | 18 +++- core/src/bzh/fainsin/sagittarius/HUD.java | 7 ++ core/src/bzh/fainsin/sagittarius/Player.java | 30 +++++-- .../fainsin/sagittarius/SagittariusGame.java | 26 ++++-- desktop/build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 10 files changed, 221 insertions(+), 41 deletions(-) create mode 100644 core/src/bzh/fainsin/sagittarius/Arrow.java create mode 100644 core/src/bzh/fainsin/sagittarius/Bow.java diff --git a/core/build.gradle b/core/build.gradle index d192d04..4019af1 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -1,4 +1,4 @@ -sourceCompatibility = 1.7 +sourceCompatibility = 1.15 [compileJava, compileTestJava]*.options*.encoding = 'UTF-8' sourceSets.main.java.srcDirs = [ "src/" ] diff --git a/core/src/bzh/fainsin/sagittarius/Arrow.java b/core/src/bzh/fainsin/sagittarius/Arrow.java new file mode 100644 index 0000000..1f1f067 --- /dev/null +++ b/core/src/bzh/fainsin/sagittarius/Arrow.java @@ -0,0 +1,89 @@ +package bzh.fainsin.sagittarius; + +import com.badlogic.gdx.graphics.g2d.Batch; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.math.Vector2; + +class Arrow extends Entity { + +// ---------- ATTRIBUTEs ---------- + + private Vector2 velocity = new Vector2(); + private Vector2 acceleration = new Vector2(); + private Vector2 force = new Vector2(); + + float TTL = 20; + private final float length = 100; + +// ---------- CONSTRUCTORs ---------- + + Arrow(float angle, float power, Player shooter) { + super(shooter.position, 1); + this.velocity = new Vector2(power, 0).setAngleDeg(angle); + this.acceleration = new Vector2(); + this.force = computeForce(); + } + +// ---------- METHODs ---------- + + private Vector2 computeForce() { + Vector2 force = new Vector2(); + for (Planet attractor : SagittariusGame.planetList) { + Vector2 diff = attractor.position.cpy().sub(this.position); + Vector2 attraction = diff.scl( SagittariusGame.G * attractor.mass / diff.len2() ); + force.add(attraction); + } + return force; + } + + private boolean hasLanded() { + for (Planet planet : SagittariusGame.planetList) { + if (this.distanceTo(planet) < planet.getRadius()) { + return true; + } + } + return false; + } + + void update(float deltaTime) { + + if (!this.hasLanded()) { + integrationVerlet(deltaTime); + this.TTL -= deltaTime; + this.angle = this.velocity.angleRad(); + } + } + + private void integrationVerlet(float deltaTime) { + // Verlet integration + // https://gamedev.stackexchange.com/questions/15708/how-can-i-implement-gravity/41917#41917 + + // TODO : vectorialiser + + this.acceleration = this.force.cpy(); + + this.position.x += deltaTime * ( this.velocity.x + deltaTime * this.acceleration.x / 2 ); + this.position.y += deltaTime * ( this.velocity.y + deltaTime * this.acceleration.y / 2 ); + + this.force = computeForce(); + + this.velocity.x += deltaTime * ( this.acceleration.x + this.force.x ) / 2; + this.velocity.y += deltaTime * ( this.acceleration.y + this.force.y ) / 2; + } + + void render(ShapeRenderer shapeRenderer) { + Vector2 tail = new Vector2(-this.length, 0).rotateRad(this.angle).add(this.position); + shapeRenderer.line(this.position, tail); + } + + void renderDebug(Batch batch, BitmapFont font) { + font.draw(batch, "TTL = " + this.TTL, this.position.x, this.position.y + font.getCapHeight()*5); + font.draw(batch, "pos = " + this.position, this.position.x, this.position.y + font.getCapHeight()*4); + font.draw(batch, "speed = " + this.velocity, this.position.x, this.position.y + font.getCapHeight()*3); + font.draw(batch, "accel = " + this.acceleration, this.position.x, this.position.y + font.getCapHeight()*2); + font.draw(batch, "force = " + this.force, this.position.x, this.position.y + font.getCapHeight()*1); + font.draw(batch, "angle = " + this.angle, this.position.x, this.position.y); + } + +} diff --git a/core/src/bzh/fainsin/sagittarius/Bow.java b/core/src/bzh/fainsin/sagittarius/Bow.java new file mode 100644 index 0000000..f60c6fb --- /dev/null +++ b/core/src/bzh/fainsin/sagittarius/Bow.java @@ -0,0 +1,63 @@ +package bzh.fainsin.sagittarius; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Input.Buttons; +import com.badlogic.gdx.graphics.glutils.ShapeRenderer; +import com.badlogic.gdx.math.MathUtils; +import com.badlogic.gdx.math.Vector2; + +class Bow { + +// ---------- ATTRIBUTEs ---------- + + private Player shooter; + private boolean aimAssist = false; + private boolean pressed = false; + private float angle; + + private Vector2 anchor; + private Vector2 aim; + + private float power; + +// ---------- CONSTRUCTORs ---------- + + Bow(Player shooter, boolean aimAssist) { + this.shooter = shooter; + this.aimAssist = aimAssist; + } + +// ---------- METHODs ---------- + + void update(double deltaTime) { + + if (Gdx.input.isButtonJustPressed(Buttons.LEFT) && !pressed) { + this.anchor = SagittariusGame.worldCursor.cpy(); + pressed = true; + } else if (Gdx.input.isButtonPressed(Buttons.LEFT) && pressed) { + computeArrow(); + } else if (pressed) { + SagittariusGame.arrowList.add(getArrow()); + pressed = false; + } + + } + + private Arrow getArrow() { + return new Arrow(angle, power, shooter); + } + + private void computeArrow() { + aim = this.anchor.cpy().sub(SagittariusGame.worldCursor); + angle = aim.angleDeg(); + power = MathUtils.clamp(aim.len(), 0, 1000); + } + + public void render(ShapeRenderer shapeRenderer) { + if (pressed) { + shapeRenderer.line(this.anchor, SagittariusGame.worldCursor); + //shapeRenderer.polyline(traj); + } + } + +} diff --git a/core/src/bzh/fainsin/sagittarius/Entity.java b/core/src/bzh/fainsin/sagittarius/Entity.java index 3015922..6cd19d0 100644 --- a/core/src/bzh/fainsin/sagittarius/Entity.java +++ b/core/src/bzh/fainsin/sagittarius/Entity.java @@ -16,29 +16,10 @@ abstract class Entity { // ---------- CONSTRUCTORs ---------- protected Entity(Vector2 position, float mass) { - this.position = position; + this.position = position.cpy(); this.mass = mass; } -// ---------- GETs ---------- - - - Vector2 getPosition() { - return this.position; - } - - float getMass() { - return this.mass; - } - - float getAngle() { - return this.angle; - } - - Color getColor() { - return this.color; - } - // ---------- METHODs ---------- /** @@ -47,7 +28,7 @@ abstract class Entity { * @return distance to entity */ float distanceTo(Entity entity) { - return this.position.sub(entity.getPosition()).len(); + return this.position.cpy().sub(entity.position).len(); } } diff --git a/core/src/bzh/fainsin/sagittarius/GameScreen.java b/core/src/bzh/fainsin/sagittarius/GameScreen.java index 9185ae2..f502eaa 100644 --- a/core/src/bzh/fainsin/sagittarius/GameScreen.java +++ b/core/src/bzh/fainsin/sagittarius/GameScreen.java @@ -39,17 +39,17 @@ class GameScreen extends ScreenAdapter { Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); } - private void update(float delta) { - SagittariusGame.update(delta); + private void update(float deltaTime) { + SagittariusGame.update(deltaTime); hud.update(); camera.position.set(WIDTH / 2, HEIGHT / 2, 0); camera.update(); } @Override - public void render(float delta) { + public void render(float deltaTime) { - update(delta); + update(deltaTime); clearScreen(); @@ -67,6 +67,11 @@ class GameScreen extends ScreenAdapter { player.renderDebug(batch, font); } + // arrows + for (Arrow arrow : SagittariusGame.arrowList) { + arrow.renderDebug(batch, font); + } + batch.end(); // ---------- shapeRenderer ---------- @@ -83,6 +88,11 @@ class GameScreen extends ScreenAdapter { player.render(shapeRenderer); } + // arrows + for (Arrow arrow : SagittariusGame.arrowList) { + arrow.render(shapeRenderer); + } + shapeRenderer.end(); // HUD diff --git a/core/src/bzh/fainsin/sagittarius/HUD.java b/core/src/bzh/fainsin/sagittarius/HUD.java index 2321b33..0c25da1 100644 --- a/core/src/bzh/fainsin/sagittarius/HUD.java +++ b/core/src/bzh/fainsin/sagittarius/HUD.java @@ -23,7 +23,14 @@ class HUD implements Disposable { public void render() { batch.begin(); + + // framerate font.draw(batch, frameRate + " fps", 3, Gdx.graphics.getHeight() - 3); + + // cursor positions + font.draw(batch, "x_r = " + (int) SagittariusGame.screenCursor.x + ", y_r = " + (int) SagittariusGame.screenCursor.y, SagittariusGame.screenCursor.x + 5, Gdx.graphics.getHeight() - SagittariusGame.screenCursor.y + 5); + font.draw(batch, "x_g = " + (int) SagittariusGame.worldCursor.x + ", y_g = " + (int) SagittariusGame.worldCursor.y, SagittariusGame.screenCursor.x + 5, Gdx.graphics.getHeight() - SagittariusGame.screenCursor.y + 20); + batch.end(); } diff --git a/core/src/bzh/fainsin/sagittarius/Player.java b/core/src/bzh/fainsin/sagittarius/Player.java index 6e85e82..0406923 100644 --- a/core/src/bzh/fainsin/sagittarius/Player.java +++ b/core/src/bzh/fainsin/sagittarius/Player.java @@ -6,45 +6,59 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; -public class Player extends Entity { +class Player extends Entity { // ---------- ATTRIBUTEs ---------- private Planet home; private final float width = 50; private final float height = 100; + private Bow bow; + + private Vector2 positionBottom = new Vector2(); // TODO : reorganize, center of mass.... // ---------- CONSTRUCTORs ---------- Player(Planet home) { - super(new Vector2(), 1); + super(home.position, 1); this.home = home; + this.bow = new Bow(this, false); + this.angle = 45; // TODO : tmp } // ---------- METHODs ---------- void render(ShapeRenderer shapeRenderer) { shapeRenderer.setColor(color); - shapeRenderer.rect(position.x, position.y, width/2, 0, width, height, 1, 1, angle-90); + shapeRenderer.rect(positionBottom.x - width/2, positionBottom.y, width/2, 0, width, height, 1, 1, angle-90); + this.bow.render(shapeRenderer); } void renderDebug(Batch batch, BitmapFont font) { font.draw(batch, "x = " + (int) position.x + ", y = " + (int) position.y, position.x, position.y); } - void update(float delta) { + void update(float deltaTime) { computePosition(); - this.angle += 100.0f / home.getRadius(); + bow.update(deltaTime); + + // this.angle += 100.0f / home.getRadius(); // TODO : debug, remove later } void computePosition() { - Vector2 homePosition = this.home.getPosition(); + Vector2 homePosition = this.home.position; float homeRadius = this.home.getRadius(); - this.position.x = homePosition.x + homeRadius*MathUtils.cosDeg(angle) - width/2; - this.position.y = homePosition.y + homeRadius*MathUtils.sinDeg(angle); + this.position.x = homePosition.x + (homeRadius + height/2)*MathUtils.cosDeg(angle); + this.position.y = homePosition.y + (homeRadius + height/2)*MathUtils.sinDeg(angle); // TODO, faire des opérations vectorielles ? + this.positionBottom.x = homePosition.x + homeRadius*MathUtils.cosDeg(angle); + this.positionBottom.y = homePosition.y + homeRadius*MathUtils.sinDeg(angle); + } + + Planet getHome() { + return this.home; } } diff --git a/core/src/bzh/fainsin/sagittarius/SagittariusGame.java b/core/src/bzh/fainsin/sagittarius/SagittariusGame.java index 807731b..79ecffc 100644 --- a/core/src/bzh/fainsin/sagittarius/SagittariusGame.java +++ b/core/src/bzh/fainsin/sagittarius/SagittariusGame.java @@ -1,6 +1,7 @@ package bzh.fainsin.sagittarius; import java.util.ArrayList; +import java.util.Iterator; import com.badlogic.gdx.Game; import com.badlogic.gdx.Gdx; @@ -12,6 +13,9 @@ public class SagittariusGame extends Game { // ---------- ATTRIBUTEs ---------- + // Constants + static final int G = 100; + // Vectors static Vector2 screenCursor; static Vector2 worldCursor; @@ -19,6 +23,7 @@ public class SagittariusGame extends Game { // Entities static ArrayList planetList; static ArrayList playerList; + static ArrayList arrowList; // ---------- METHODs ---------- @@ -27,15 +32,17 @@ public class SagittariusGame extends Game { setScreen(new GameScreen()); planetList = new ArrayList(); - planetList.add( new Planet(new Vector2(100, 100), 1, 50) ); - planetList.add( new Planet(new Vector2(400, 400), 1, 100, Color.CYAN) ); + planetList.add( new Planet(new Vector2(400, 400), 1000, 50) ); + planetList.add( new Planet(new Vector2(1000, 400), 1000, 100, Color.CYAN) ); playerList = new ArrayList(); playerList.add( new Player(planetList.get(0)) ); - playerList.add( new Player(planetList.get(1)) ); + + arrowList = new ArrayList(); + } - static void update(float delta) { + static void update(float deltaTime) { // cursors screenCursor = new Vector2(Gdx.input.getX(), Gdx.input.getY()); @@ -44,7 +51,16 @@ public class SagittariusGame extends Game { // players for (Player player : playerList) { - player.update(delta); + player.update(deltaTime); + } + + // arrows + for (Iterator it = arrowList.iterator(); it.hasNext(); ) { + Arrow arrow = it.next(); + arrow.update(deltaTime); + if (arrow.TTL <= 0) { + it.remove(); + } } } diff --git a/desktop/build.gradle b/desktop/build.gradle index 9254fca..9587af5 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -1,4 +1,4 @@ -sourceCompatibility = 1.7 +sourceCompatibility = 1.15 sourceSets.main.java.srcDirs = [ "src/" ] sourceSets.main.resources.srcDirs = ["../core/assets"] diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 4d9ca16..1f3fdbc 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists