Skip to content

Commit

Permalink
added data structures to support gameplay
Browse files Browse the repository at this point in the history
  • Loading branch information
AlmasB committed Dec 26, 2021
1 parent fb6c51a commit eadcde9
Show file tree
Hide file tree
Showing 22 changed files with 231 additions and 136 deletions.
11 changes: 0 additions & 11 deletions TowerDefense/src/main/java/com/almasb/fxglgames/td/Config.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,22 @@
import com.almasb.fxgl.app.ApplicationMode;
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.app.scene.GameView;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxglgames.td.collision.BulletEnemyHandler;
import com.almasb.fxglgames.td.event.EnemyKilledEvent;
import com.almasb.fxglgames.td.ui.EnemiesIcon;
import com.almasb.fxglgames.td.ui.MoneyIcon;
import com.almasb.fxglgames.td.ui.TowerSelectionBox;
import com.almasb.fxglgames.td.ui.WaveIcon;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.geometry.Point2D;
import com.almasb.fxglgames.td.data.*;
import com.almasb.fxglgames.td.ui.*;
import javafx.scene.input.KeyCode;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.text.Text;
import javafx.util.Duration;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.almasb.fxgl.dsl.FXGL.*;
import static com.almasb.fxglgames.td.data.Config.STARTING_HP;
import static com.almasb.fxglgames.td.data.Config.STARTING_MONEY;
import static com.almasb.fxglgames.td.data.Vars.CURRENT_WAVE;

/**
* This is an example of a tower defense game.
Expand All @@ -41,10 +34,10 @@
*/
public class TowerDefenseApp extends GameApplication {

// TODO: read from level data
private int levelEnemies = 10;

private List<TowerData> towerData;
private List<LevelData> levelData;

private LevelData currentLevel;

private TowerSelectionBox towerSelectionBox;
private WaveIcon waveIcon;
Expand All @@ -68,34 +61,24 @@ protected void initInput() {

@Override
protected void initGameVars(Map<String, Object> vars) {
vars.put("numEnemies", levelEnemies);
vars.put("money", 1000);
vars.put("playerHP", 10);
vars.put("currentWave", 1);
vars.put("numEnemies", 0);
vars.put("money", STARTING_MONEY);
vars.put("playerHP", STARTING_HP);
vars.put(CURRENT_WAVE, 0);
}

@Override
protected void initGame() {
loadTowerData();
loadLevelData();

getGameWorld().addEntityFactory(new TowerDefenseFactory());

setLevelFromMap("td1.tmx");

BooleanProperty enemiesLeft = new SimpleBooleanProperty();
enemiesLeft.bind(getip("numEnemies").greaterThan(0));

getGameTimer().runAtIntervalWhile(this::spawnEnemy, Duration.seconds(1), enemiesLeft);

// getEventBus().addEventHandler(EnemyKilledEvent.ANY, this::onEnemyKilled);
// getEventBus().addEventHandler(EnemyReachedGoalEvent.ANY, e -> gameOver());
// construct UI objects
towerSelectionBox = new TowerSelectionBox(towerData);
waveIcon = new WaveIcon();

getGameWorld().getEntitiesFiltered(e -> e.isType("TiledMapLayer"))
.forEach(e -> {
e.getViewComponent().addOnClickHandler(event -> {
towerSelectionBox.setVisible(false);
});
});
nextLevel();
}

private void loadTowerData() {
Expand All @@ -113,9 +96,79 @@ private void loadTowerData() {
.collect(Collectors.toList());
}

@Override
protected void initPhysics() {
//getPhysicsWorld().addCollisionHandler(new BulletEnemyHandler());
private void loadLevelData() {
List<String> levelNames = List.of(
"level1.json"
);

levelData = levelNames.stream()
.map(name -> getAssetLoader().loadJSON("levels/" + name, LevelData.class).get())
.collect(Collectors.toList());
}

private void nextLevel() {
if (levelData.isEmpty()) {
gameOver();
return;
}

currentLevel = levelData.remove(0);
set(CURRENT_WAVE, 0);

waveIcon.setMaxWave(currentLevel.maxWaveIndex());

setLevelFromMap("tmx/" + currentLevel.map());

getGameWorld().getEntitiesFiltered(e -> e.isType("TiledMapLayer"))
.forEach(e -> {
e.getViewComponent().addOnClickHandler(event -> {
towerSelectionBox.setVisible(false);
});
});

nextWave();
}

private void nextWave() {
if (geti(CURRENT_WAVE) < currentLevel.maxWaveIndex()) {
inc(CURRENT_WAVE, 1);

currentLevel.waves()
.stream()
.filter(w -> w.index() == geti(CURRENT_WAVE))
.forEach(wave -> {
spawnWave(wave);

inc("numEnemies", wave.amount());
});
} else {
nextLevel();
}
}

private void spawnWave(WaveData wave) {
for (int i = 0; i < wave.amount(); i++) {
runOnce(() -> {

var wayEntity = getGameWorld().getSingleton(e ->
e.isType(EntityType.WAY) && e.getString("name").equals(wave.way())
);

EnemyData data = getAssetLoader().loadJSON("enemies/" + wave.enemy(), EnemyData.class).get();

Polygon p = wayEntity.getObject("polygon");

spawnWithScale(
"Enemy",
new SpawnData()
.put("way", Way.fromPolygon(p, wayEntity.getX(), wayEntity.getY()))
.put("enemyData", data),
Duration.seconds(0.45),
Interpolators.ELASTIC.EASE_OUT()
);

}, Duration.seconds(i));
}
}

public void onCellClicked(Entity cell) {
Expand All @@ -138,53 +191,24 @@ public void onTowerSelected(Entity cell, TowerData data) {

@Override
protected void initUI() {
towerSelectionBox = new TowerSelectionBox(towerData);
towerSelectionBox.setVisible(false);

addUINode(towerSelectionBox);

var moneyIcon = new MoneyIcon();
addUINode(new MoneyIcon(), 10, 10);
addUINode(new HPIcon(), 10, 90);

addUINode(moneyIcon, 10, 10);

waveIcon = new WaveIcon();
// TODO: read from data
waveIcon.setMaxWave(5);

addUINode(waveIcon, 10, 90);
addUINode(waveIcon, 10, 250);

addUINode(new EnemiesIcon(), 10, 170);
}

private void spawnEnemy() {
public void onEnemyKilled(Entity enemy) {
inc("numEnemies", -1);

var wayEntity = getGameWorld().getSingleton(EntityType.WAY);
Polygon p = wayEntity.getObject("polygon");

spawnWithScale(
"Enemy",
new SpawnData().put("way", Way.fromPolygon(p, wayEntity.getX(), wayEntity.getY())),
Duration.seconds(0.45),
Interpolators.ELASTIC.EASE_OUT()
);
}

private void onEnemyKilled(EnemyKilledEvent event) {
levelEnemies--;

if (levelEnemies == 0) {
gameOver();
if (geti("numEnemies") == 0) {
nextWave();
}

Entity enemy = event.getEnemy();
Point2D position = enemy.getPosition();

Text xMark = getUIFactoryService().newText("X", Color.RED, 24);
xMark.setTranslateX(position.getX());
xMark.setTranslateY(position.getY() + 20);

getGameScene().addGameView(new GameView(xMark, 1000));
}

private void gameOver() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@
import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.dsl.components.AutoRotationComponent;
import com.almasb.fxgl.dsl.components.HealthIntComponent;
import com.almasb.fxgl.dsl.components.OffscreenCleanComponent;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.EntityFactory;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.Spawns;
import com.almasb.fxgl.entity.components.CollidableComponent;
import com.almasb.fxgl.ui.ProgressBar;
import com.almasb.fxglgames.td.components.BulletComponent;
import com.almasb.fxglgames.td.components.EnemyComponent;
import com.almasb.fxglgames.td.components.TowerComponent;
import com.almasb.fxglgames.td.data.EnemyData;
import com.almasb.fxglgames.td.data.TowerData;
import javafx.beans.binding.Bindings;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Polygon;
import javafx.scene.shape.Rectangle;

import static com.almasb.fxgl.dsl.FXGL.*;
Expand All @@ -29,7 +28,9 @@ public class TowerDefenseFactory implements EntityFactory {

@Spawns("Enemy")
public Entity spawnEnemy(SpawnData data) {
var hp = new HealthIntComponent(150);
EnemyData enemyData = data.get("enemyData");

var hp = new HealthIntComponent(enemyData.hp());

var hpBar = new ProgressBar(false);
hpBar.setTranslateY(64);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
import com.almasb.fxgl.dsl.components.HealthIntComponent;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxglgames.td.Config;
import com.almasb.fxglgames.td.TowerDefenseApp;
import com.almasb.fxglgames.td.data.Config;
import com.almasb.fxglgames.td.event.EnemyKilledEvent;

/**
Expand Down Expand Up @@ -45,7 +46,7 @@ private void onTargetHit() {
hp.damage(data.getDamage());

if (hp.isZero()) {
FXGL.getEventBus().fireEvent(new EnemyKilledEvent(target));
FXGL.<TowerDefenseApp>getAppCast().onEnemyKilled(target);
target.removeFromWorld();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxglgames.td.Way;
import com.almasb.fxglgames.td.data.Way;
import com.almasb.fxglgames.td.event.EnemyReachedGoalEvent;
import javafx.geometry.Point2D;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package com.almasb.fxglgames.td.components;

import com.almasb.fxgl.dsl.FXGL;
import com.almasb.fxgl.dsl.components.ProjectileComponent;
import com.almasb.fxgl.entity.Entity;
import com.almasb.fxgl.entity.SpawnData;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxgl.time.LocalTimer;
import com.almasb.fxglgames.td.EntityType;
import com.almasb.fxglgames.td.Config;
import com.almasb.fxglgames.td.TowerData;
import com.almasb.fxglgames.td.data.TowerData;
import javafx.geometry.Point2D;
import javafx.util.Duration;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.almasb.fxglgames.td.data;

/**
* @author Almas Baimagambetov (almaslvl@gmail.com)
*/
public class Config {

public static final double BULLET_SPEED = 15 * 60;

public static final int STARTING_MONEY = 1000;
public static final int MAX_MONEY = 9999;
public static final int PERFECT_CLEAR_REWARD = 100;

public static final int STARTING_HP = 15;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.almasb.fxglgames.td.data;

/**
* @author Almas Baimagambetov (almaslvl@gmail.com)
*/
public record EnemyData(
int hp,
int reward,
double moveSpeed
) { }
Loading

0 comments on commit eadcde9

Please sign in to comment.