feat: Player's Bow can now shoot Arrows
(physics need adjusting)
This commit is contained in:
parent
caa6c614eb
commit
d92730db13
|
@ -1,4 +1,4 @@
|
||||||
sourceCompatibility = 1.7
|
sourceCompatibility = 1.15
|
||||||
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
|
||||||
|
|
||||||
sourceSets.main.java.srcDirs = [ "src/" ]
|
sourceSets.main.java.srcDirs = [ "src/" ]
|
||||||
|
|
89
core/src/bzh/fainsin/sagittarius/Arrow.java
Normal file
89
core/src/bzh/fainsin/sagittarius/Arrow.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
63
core/src/bzh/fainsin/sagittarius/Bow.java
Normal file
63
core/src/bzh/fainsin/sagittarius/Bow.java
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -16,29 +16,10 @@ abstract class Entity {
|
||||||
// ---------- CONSTRUCTORs ----------
|
// ---------- CONSTRUCTORs ----------
|
||||||
|
|
||||||
protected Entity(Vector2 position, float mass) {
|
protected Entity(Vector2 position, float mass) {
|
||||||
this.position = position;
|
this.position = position.cpy();
|
||||||
this.mass = mass;
|
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 ----------
|
// ---------- METHODs ----------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,7 +28,7 @@ abstract class Entity {
|
||||||
* @return distance to entity
|
* @return distance to entity
|
||||||
*/
|
*/
|
||||||
float distanceTo(Entity entity) {
|
float distanceTo(Entity entity) {
|
||||||
return this.position.sub(entity.getPosition()).len();
|
return this.position.cpy().sub(entity.position).len();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,17 +39,17 @@ class GameScreen extends ScreenAdapter {
|
||||||
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void update(float delta) {
|
private void update(float deltaTime) {
|
||||||
SagittariusGame.update(delta);
|
SagittariusGame.update(deltaTime);
|
||||||
hud.update();
|
hud.update();
|
||||||
camera.position.set(WIDTH / 2, HEIGHT / 2, 0);
|
camera.position.set(WIDTH / 2, HEIGHT / 2, 0);
|
||||||
camera.update();
|
camera.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(float delta) {
|
public void render(float deltaTime) {
|
||||||
|
|
||||||
update(delta);
|
update(deltaTime);
|
||||||
|
|
||||||
clearScreen();
|
clearScreen();
|
||||||
|
|
||||||
|
@ -67,6 +67,11 @@ class GameScreen extends ScreenAdapter {
|
||||||
player.renderDebug(batch, font);
|
player.renderDebug(batch, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// arrows
|
||||||
|
for (Arrow arrow : SagittariusGame.arrowList) {
|
||||||
|
arrow.renderDebug(batch, font);
|
||||||
|
}
|
||||||
|
|
||||||
batch.end();
|
batch.end();
|
||||||
|
|
||||||
// ---------- shapeRenderer ----------
|
// ---------- shapeRenderer ----------
|
||||||
|
@ -83,6 +88,11 @@ class GameScreen extends ScreenAdapter {
|
||||||
player.render(shapeRenderer);
|
player.render(shapeRenderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// arrows
|
||||||
|
for (Arrow arrow : SagittariusGame.arrowList) {
|
||||||
|
arrow.render(shapeRenderer);
|
||||||
|
}
|
||||||
|
|
||||||
shapeRenderer.end();
|
shapeRenderer.end();
|
||||||
|
|
||||||
// HUD
|
// HUD
|
||||||
|
|
|
@ -23,7 +23,14 @@ class HUD implements Disposable {
|
||||||
|
|
||||||
public void render() {
|
public void render() {
|
||||||
batch.begin();
|
batch.begin();
|
||||||
|
|
||||||
|
// framerate
|
||||||
font.draw(batch, frameRate + " fps", 3, Gdx.graphics.getHeight() - 3);
|
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();
|
batch.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,45 +6,59 @@ import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||||
import com.badlogic.gdx.math.MathUtils;
|
import com.badlogic.gdx.math.MathUtils;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
|
|
||||||
public class Player extends Entity {
|
class Player extends Entity {
|
||||||
|
|
||||||
// ---------- ATTRIBUTEs ----------
|
// ---------- ATTRIBUTEs ----------
|
||||||
|
|
||||||
private Planet home;
|
private Planet home;
|
||||||
private final float width = 50;
|
private final float width = 50;
|
||||||
private final float height = 100;
|
private final float height = 100;
|
||||||
|
private Bow bow;
|
||||||
|
|
||||||
|
private Vector2 positionBottom = new Vector2(); // TODO : reorganize, center of mass....
|
||||||
|
|
||||||
// ---------- CONSTRUCTORs ----------
|
// ---------- CONSTRUCTORs ----------
|
||||||
|
|
||||||
Player(Planet home) {
|
Player(Planet home) {
|
||||||
super(new Vector2(), 1);
|
super(home.position, 1);
|
||||||
this.home = home;
|
this.home = home;
|
||||||
|
this.bow = new Bow(this, false);
|
||||||
|
this.angle = 45; // TODO : tmp
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------- METHODs ----------
|
// ---------- METHODs ----------
|
||||||
|
|
||||||
void render(ShapeRenderer shapeRenderer) {
|
void render(ShapeRenderer shapeRenderer) {
|
||||||
shapeRenderer.setColor(color);
|
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) {
|
void renderDebug(Batch batch, BitmapFont font) {
|
||||||
font.draw(batch, "x = " + (int) position.x + ", y = " + (int) position.y, position.x, position.y);
|
font.draw(batch, "x = " + (int) position.x + ", y = " + (int) position.y, position.x, position.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void update(float delta) {
|
void update(float deltaTime) {
|
||||||
|
|
||||||
computePosition();
|
computePosition();
|
||||||
|
|
||||||
this.angle += 100.0f / home.getRadius();
|
bow.update(deltaTime);
|
||||||
|
|
||||||
|
// this.angle += 100.0f / home.getRadius(); // TODO : debug, remove later
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void computePosition() {
|
void computePosition() {
|
||||||
Vector2 homePosition = this.home.getPosition();
|
Vector2 homePosition = this.home.position;
|
||||||
float homeRadius = this.home.getRadius();
|
float homeRadius = this.home.getRadius();
|
||||||
this.position.x = homePosition.x + homeRadius*MathUtils.cosDeg(angle) - width/2;
|
this.position.x = homePosition.x + (homeRadius + height/2)*MathUtils.cosDeg(angle);
|
||||||
this.position.y = homePosition.y + homeRadius*MathUtils.sinDeg(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;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package bzh.fainsin.sagittarius;
|
package bzh.fainsin.sagittarius;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import com.badlogic.gdx.Game;
|
import com.badlogic.gdx.Game;
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
@ -12,6 +13,9 @@ public class SagittariusGame extends Game {
|
||||||
|
|
||||||
// ---------- ATTRIBUTEs ----------
|
// ---------- ATTRIBUTEs ----------
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
static final int G = 100;
|
||||||
|
|
||||||
// Vectors
|
// Vectors
|
||||||
static Vector2 screenCursor;
|
static Vector2 screenCursor;
|
||||||
static Vector2 worldCursor;
|
static Vector2 worldCursor;
|
||||||
|
@ -19,6 +23,7 @@ public class SagittariusGame extends Game {
|
||||||
// Entities
|
// Entities
|
||||||
static ArrayList<Planet> planetList;
|
static ArrayList<Planet> planetList;
|
||||||
static ArrayList<Player> playerList;
|
static ArrayList<Player> playerList;
|
||||||
|
static ArrayList<Arrow> arrowList;
|
||||||
|
|
||||||
// ---------- METHODs ----------
|
// ---------- METHODs ----------
|
||||||
|
|
||||||
|
@ -27,15 +32,17 @@ public class SagittariusGame extends Game {
|
||||||
setScreen(new GameScreen());
|
setScreen(new GameScreen());
|
||||||
|
|
||||||
planetList = new ArrayList<Planet>();
|
planetList = new ArrayList<Planet>();
|
||||||
planetList.add( new Planet(new Vector2(100, 100), 1, 50) );
|
planetList.add( new Planet(new Vector2(400, 400), 1000, 50) );
|
||||||
planetList.add( new Planet(new Vector2(400, 400), 1, 100, Color.CYAN) );
|
planetList.add( new Planet(new Vector2(1000, 400), 1000, 100, Color.CYAN) );
|
||||||
|
|
||||||
playerList = new ArrayList<Player>();
|
playerList = new ArrayList<Player>();
|
||||||
playerList.add( new Player(planetList.get(0)) );
|
playerList.add( new Player(planetList.get(0)) );
|
||||||
playerList.add( new Player(planetList.get(1)) );
|
|
||||||
|
arrowList = new ArrayList<Arrow>();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void update(float delta) {
|
static void update(float deltaTime) {
|
||||||
|
|
||||||
// cursors
|
// cursors
|
||||||
screenCursor = new Vector2(Gdx.input.getX(), Gdx.input.getY());
|
screenCursor = new Vector2(Gdx.input.getX(), Gdx.input.getY());
|
||||||
|
@ -44,7 +51,16 @@ public class SagittariusGame extends Game {
|
||||||
|
|
||||||
// players
|
// players
|
||||||
for (Player player : playerList) {
|
for (Player player : playerList) {
|
||||||
player.update(delta);
|
player.update(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
// arrows
|
||||||
|
for (Iterator<Arrow> it = arrowList.iterator(); it.hasNext(); ) {
|
||||||
|
Arrow arrow = it.next();
|
||||||
|
arrow.update(deltaTime);
|
||||||
|
if (arrow.TTL <= 0) {
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
sourceCompatibility = 1.7
|
sourceCompatibility = 1.15
|
||||||
sourceSets.main.java.srcDirs = [ "src/" ]
|
sourceSets.main.java.srcDirs = [ "src/" ]
|
||||||
sourceSets.main.resources.srcDirs = ["../core/assets"]
|
sourceSets.main.resources.srcDirs = ["../core/assets"]
|
||||||
|
|
||||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,5 +1,5 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
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
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|
Loading…
Reference in a new issue