Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions src/main/java/dk/sdu/mmmi/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import dk.sdu.mmmi.modulemon.Monster.MonsterRegistry;
import dk.sdu.mmmi.modulemon.NPC.NPCControlSystem;
import dk.sdu.mmmi.modulemon.NPC.NPCPlugin;
import dk.sdu.mmmi.modulemon.Player.Player;
import dk.sdu.mmmi.modulemon.Player.PlayerControlSystem;
import dk.sdu.mmmi.modulemon.Player.PlayerPlugin;
import dk.sdu.mmmi.modulemon.Settings.Settings;
Expand All @@ -37,7 +36,7 @@ public static void main(String[] args) throws IOException, URISyntaxException {
var simpleBattleAI = new dk.sdu.mmmi.modulemon.SimpleAI.BattleAIFactory(); // Uncomment for Simple AI

var battleSimulation = new BattleSimulation();
battleSimulation.setAIFactory(battleAI);
battleSimulation.setOpponentAIFactory(battleAI);
battleSimulation.setMonsterProcessor(battleMonsterProcessor);

var battle = new BattleView();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package dk.sdu.mmmi.modulemon.BattleScene;

import dk.sdu.mmmi.modulemon.common.drawing.MathUtils;

public class BattleSpeedController {

private static final int incrementAmount = 200;
private int speed = 1000;

public void increaseSpeed(){
speed +=incrementAmount;
}

public void decreaseSpeed(){
speed = Math.max(0, speed - incrementAmount);
}

public void setSpeed(int speed){
this.speed = Math.max(0, speed);
}

public int getSpeed(){
return speed;
}

@Override
public String toString() {
return "Battle delay: " + speed + "ms";
}
}
78 changes: 68 additions & 10 deletions src/main/java/dk/sdu/mmmi/modulemon/BattleScene/BattleView.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public class BattleView implements IGameViewService, IBattleView {
private Sound _winSound;
private Sound _loseSound;
private MenuState menuState = MenuState.DEFAULT;
private BattleSpeedController forcedAIDelay;
private Queue<BaseAnimation> blockingAnimations;
private Queue<BaseAnimation> backgroundAnimations;
private IMonsterRegistry monsterRegistry;
Expand Down Expand Up @@ -134,6 +135,7 @@ public void startBattle(List<IMonster> playerMonsters, List<IMonster> enemyMonst
_battleMusic.play();
_battleMusic.setLooping(true);
menuState = MenuState.DEFAULT;
forcedAIDelay = new BattleSpeedController();
_battleScene.setActionTitle("Your actions:");
_battleScene.setActions(this.defaultActions);

Expand All @@ -147,15 +149,16 @@ public void startBattle(List<IMonster> playerMonsters, List<IMonster> enemyMonst

private void setBattleAIFactory() {
IBattleAIFactory desiredAI;
if(settings.getSetting("AI").equals("MCTS")){
if (settings.getSetting("AI").equals("MCTS")) {
desiredAI = new MCTSBattleAIFactory();
} else if(settings.getSetting("AI").equals("Simple")){
} else if (settings.getSetting("AI").equals("Simple")) {
desiredAI = new dk.sdu.mmmi.modulemon.SimpleAI.BattleAIFactory();
} else {
} else {
desiredAI = new dk.sdu.mmmi.modulemon.BattleAI.BattleAIFactory();
((BattleAIFactory) desiredAI).setSettingsService(settings);
}
_battleSimulation.setAIFactory(desiredAI);
_battleSimulation.setOpponentAIFactory(desiredAI);
_battleSimulation.setPlayerAIFactory(null); // Null means the human controls the player.
}

@Override
Expand Down Expand Up @@ -220,6 +223,11 @@ public void update(GameData gameData, IGameViewManager gameViewManager) {
}
stuckSince = 0; // No longer stuck.

var enemyAi = _battleSimulation.getOpponentAIFactory();
var playerAi = _battleSimulation.getPlayerAIFactory();
_battleScene.setEnemyControllerName(enemyAi == null ? "No AI" : enemyAi.toString());
_battleScene.setPlayerControllerName(playerAi == null ? "Your monster" : playerAi.toString());

if (settings != null) {
if (_battleMusic.getVolume() != (int) settings.getSetting(SettingsRegistry.getInstance().getMusicVolumeSetting()) / 100f) {
_battleMusic.setVolume((int) settings.getSetting(SettingsRegistry.getInstance().getMusicVolumeSetting()) / 100f);
Expand Down Expand Up @@ -285,17 +293,27 @@ public void update(GameData gameData, IGameViewManager gameViewManager) {
if (event.getUsingParticipant().isPlayerControlled()) {
//Player attacked
PlayerBattleAttackAnimation battleAnimation = new PlayerBattleAttackAnimation(_battleScene, getAttackSound(event.getMove()), settings);
battleAnimation.setOnEventDone(() -> {
addEmptyAnimation(1000, true);
_battleScene.setTextToDisplay("...");
});
if (forcedAIDelay.getSpeed() > 0) {
battleAnimation.setOnEventDone(() -> {
var anim = addEmptyAnimation(forcedAIDelay.getSpeed(), true);
anim.setOnEventDone(() -> _battleScene.setShowEnemySpinner(false));
_battleScene.setShowEnemySpinner(true);
});
}
battleAnimation.start();
blockingAnimations.add(battleAnimation);
_battleScene.setHealthIndicatorText(String.format("-%d HP", event.getDamage()));
} else {
//Enemy attacked
EnemyBattleAttackAnimation battleAnimation = new EnemyBattleAttackAnimation(_battleScene, getAttackSound(event.getMove()), settings);
battleAnimation.start();
if (_battleSimulation.isPlayerControlledByAI() && forcedAIDelay.getSpeed() > 0) {
battleAnimation.setOnEventDone(() -> {
var anim = addEmptyAnimation(forcedAIDelay.getSpeed(), true);
anim.setOnEventDone(() -> _battleScene.setShowPlayerSpinner(false));
_battleScene.setShowPlayerSpinner(true);
});
}
blockingAnimations.add(battleAnimation);
_battleScene.setHealthIndicatorText(String.format("-%d HP", event.getDamage()));
}
Expand Down Expand Up @@ -419,11 +437,23 @@ public void draw(GameData gameData) {

@Override
public void handleInput(GameData gameData, IGameViewManager gameViewManager) {
if (!blockingAnimations.isEmpty() || !_isInitialized || (_battleSimulation != null && _battleSimulation.getState() != null && !_battleSimulation.getState().isPlayersTurn())) {
if (_battleSimulation != null && _battleSimulation.isPlayerControlledByAI()) {
menuState = MenuState.SPECTATOR;
}

if (
(
!blockingAnimations.isEmpty()
|| !_isInitialized
|| (_battleSimulation != null && _battleSimulation.getState() != null && !_battleSimulation.getState().isPlayersTurn())
)
&& menuState != MenuState.SPECTATOR // Always show the UI when spectating
) {
//If any blocking animations, don't allow any input.
_battleScene.setActionBoxAlpha(0.5f);
return;
}

_battleScene.setActionBoxAlpha(1f);
GameKeys keys = gameData.getKeys();

Expand Down Expand Up @@ -523,6 +553,33 @@ public void handleInput(GameData gameData, IGameViewManager gameViewManager) {
_battleScene.setTextToDisplay("This monster is already in battle.");
}
}
} else if (this.menuState == MenuState.SPECTATOR) {
_battleScene.setActionTitle("Spectating");
IBattleParticipant player = _battleSimulation.getState().getPlayer();
Object[] menuOptions = new Object[]{
forcedAIDelay,
"Quit spectating"
};

_battleScene.setActions(menuOptions);

//Get selected monster
Object selectedAction = menuOptions[this.selectedAction % menuOptions.length];
if (selectedAction instanceof String action) {
if (action.equalsIgnoreCase("Quit spectating")) {
if (keys.isPressed(GameKeys.ACTION)) {
handleBattleEnd(new VictoryBattleEvent("Player runs away", _battleSimulation.getState().getEnemy(), null));
}
}
} else if (selectedAction instanceof BattleSpeedController speed) {
if (keys.isPressed(GameKeys.RIGHT)) {
speed.increaseSpeed();
} else if (keys.isPressed(GameKeys.LEFT)) {
speed.decreaseSpeed();
} else if (keys.isPressed(GameKeys.DELETE)) {
speed.setSpeed(0);
}
}
}


Expand Down Expand Up @@ -560,11 +617,12 @@ public void dispose() {
this._isInitialized = false;
}

private void addEmptyAnimation(int duration, boolean autoStart) {
private EmptyAnimation addEmptyAnimation(int duration, boolean autoStart) {
EmptyAnimation emptyAnimation = new EmptyAnimation(duration);
if (autoStart)
emptyAnimation.start();
blockingAnimations.add(emptyAnimation);
return emptyAnimation;
}

public void setSettingsService(IGameSettings settings) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ public enum MenuState {
DEFAULT,
FIGHT,
SWITCH,
SPECTATOR,
NONE
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import dk.sdu.mmmi.modulemon.BattleScene.BattleView;
import dk.sdu.mmmi.modulemon.common.AssetLoader;
import dk.sdu.mmmi.modulemon.common.drawing.*;

Expand All @@ -15,6 +16,11 @@ public class BattleScene {
private Image _backdrop;
private Image _playerBase;
private Image _enemyBase;
private float _spinnerSpeed = -100f;
private Image _playerSpinner;
private Image _enemySpinner;
private boolean _showPlayerSpinner;
private boolean _showEnemySpinner;
private String _playerMonsterSpritePath = "";
private String _enemyMonsterSpritePath = "";
private Image _playerMonster;
Expand Down Expand Up @@ -43,11 +49,12 @@ public class BattleScene {
private Rectangle _playerHPBoxFillRect;
private Rectangle _playerHPBoxBorderRect;
private float _actionBoxAlpha = 1;

private String enemyControllerName;
private String enemyMonsterName;
private int enemyHP;
private float intermediateEnemyHP = 0f;
private int maxEnemyHP;
private String playerControllerName;
private String playerMonsterName;
private int playerHP;
private float intermediatePlayerHP = 0f;
Expand All @@ -70,6 +77,8 @@ public BattleScene() {
_backdrop = loader.getImageAsset("/battleart/backdrop1.png", this.getClass());
_playerBase = loader.getImageAsset("/battleart/playerbase1.png", this.getClass());
_enemyBase = loader.getImageAsset("/battleart/enemybase1.png", this.getClass());
_playerSpinner = loader.getImageAsset("/battleart/spinner.png", this.getClass());
_enemySpinner = loader.getImageAsset("/battleart/spinner.png", BattleView.class);
_textBoxRect = new Rectangle(-100,-100, 0,0); // All these values are dynamically calculated anyway
_actionBoxRect = new Rectangle(-100,-100, BattleSceneDefaults.actionBoxWidth(), BattleSceneDefaults.actionBoxHeight());
_enemyHealthRect = new Rectangle(-100,-100, BattleSceneDefaults.enemyHealthBoxWidth(), BattleSceneDefaults.enemyHealthBoxHeight());
Expand All @@ -80,6 +89,8 @@ public BattleScene() {
_enemyHPBoxFillRect = new Rectangle(-100,-100, 0, 0);
spriteBatch = new SpriteBatch();
shapeRenderer = new ShapeRenderer();
playerControllerName = "Your monster";
enemyControllerName = "Opponent";
resetPositions();
}

Expand All @@ -96,11 +107,17 @@ public void draw(float dt, OrthographicCamera camera) {
_playerMonster.setOrigin(_playerMonster.getImageWidth() / 2, _playerMonster.getImageHeight() / 2);
_playerMonster.setRotation(_playerMonsterRotation);
_playerMonsterPosition.updatePosition(_playerMonster);

_playerSpinner.setOrigin(_playerSpinner.getImageWidth() / 2, _playerSpinner.getImageHeight() / 2);
_playerSpinner.setPosition(_playerBasePosition.getX() + _playerBase.getImageWidth()/2f - _playerSpinner.getImageWidth()/2f, _playerBasePosition.getY()+160);
}
if(_enemyMonster != null) {
_enemyMonster.setOrigin(_enemyMonster.getImageWidth() / 2, _enemyMonster.getImageHeight() / 2);
_enemyMonster.setRotation(_enemyMonsterRotation);
_enemyMonsterPosition.updatePosition(_enemyMonster);

_enemySpinner.setOrigin(_enemySpinner.getImageWidth() / 2, _enemySpinner.getImageHeight() / 2);
_enemySpinner.setPosition(_enemyBasePosition.getX() + _enemyBase.getImageWidth()/2f - _enemySpinner.getImageWidth()/2f, _enemyBasePosition.getY()+100);
}

_backdrop.setSize(this.gameWidth, this.gameHeight);
Expand All @@ -114,6 +131,16 @@ public void draw(float dt, OrthographicCamera camera) {
if (_enemyMonster != null)
_enemyMonster.draw(spriteBatch, 1);

if(_showPlayerSpinner){
_playerSpinner.rotateBy(_spinnerSpeed * dt);
_playerSpinner.draw(spriteBatch, 1);
}

if(_showEnemySpinner){
_enemySpinner.rotateBy(_spinnerSpeed * dt);
_enemySpinner.draw(spriteBatch, 1);
}

spriteBatch.end();


Expand Down Expand Up @@ -170,10 +197,10 @@ public void draw(float dt, OrthographicCamera camera) {
spriteBatch.begin();

//Health box
textUtils.drawNormalRoboto(spriteBatch, "Opponent: " + this.enemyMonsterName, Color.BLACK, _enemyHealthBoxPosition.getX() + 10, _enemyHealthBoxPosition.getY() + 85);
textUtils.drawNormalRoboto(spriteBatch, this.enemyControllerName+": " + this.enemyMonsterName, Color.BLACK, _enemyHealthBoxPosition.getX() + 10, _enemyHealthBoxPosition.getY() + 85);
textUtils.drawNormalRoboto(spriteBatch, "HP:", Color.BLACK, _enemyHealthBoxPosition.getX() + 10, _enemyHealthBoxPosition.getY() + 55);
textUtils.drawNormalRoboto(spriteBatch, this.enemyHP+"/"+this.maxEnemyHP, Color.BLACK, _enemyHealthBoxPosition.getX() + 52, _enemyHealthBoxPosition.getY() + 28);
textUtils.drawNormalRoboto(spriteBatch, "Your monster: " + this.playerMonsterName, Color.BLACK, _playerHealthBoxPosition.getX() + 10, _playerHealthBoxPosition.getY() + 85);
textUtils.drawNormalRoboto(spriteBatch, this.playerControllerName+": " + this.playerMonsterName, Color.BLACK, _playerHealthBoxPosition.getX() + 10, _playerHealthBoxPosition.getY() + 85);
textUtils.drawNormalRoboto(spriteBatch, "HP:", Color.BLACK, _playerHealthBoxPosition.getX() + 10, _playerHealthBoxPosition.getY() + 55);
textUtils.drawNormalRoboto(spriteBatch, this.playerHP+"/"+this.maxPlayerHP, Color.BLACK, _playerHealthBoxPosition.getX() + 52, _playerHealthBoxPosition.getY() + 28);

Expand Down Expand Up @@ -231,7 +258,7 @@ private static void setHpBarDimentions(float hp, int maxHp, Position basePositio
float hpBarOffsetX = 58;
float hpBarOffsetY = 35;
float hpBarHeight = 20;
float hpBarFullWidth = 225;
float hpBarFullWidth = 290;

float hpBasedWidth = MathUtils.map(hp, 0, maxHp, 0, hpBarFullWidth);
fillRect.setX(basePosition.getX() + hpBarOffsetX);
Expand Down Expand Up @@ -279,6 +306,14 @@ public void setEnemyMonsterName(String enemyMonsterName) {
this.enemyMonsterName = enemyMonsterName;
}

public void setEnemyControllerName(String enemyControllerName) {
this.enemyControllerName = enemyControllerName;
}

public void setPlayerControllerName(String playerControllerName) {
this.playerControllerName = playerControllerName;
}

public void setEnemyHP(int enemyHP) {
this.enemyHP = enemyHP;
}
Expand Down Expand Up @@ -512,6 +547,14 @@ public void setTextBoxPosition(Position pos) {
this._textBoxPosition = pos;
}

public void setShowPlayerSpinner(boolean _showPlayerSpinner) {
this._showPlayerSpinner = _showPlayerSpinner;
}

public void setShowEnemySpinner(boolean _showEnemySpinner) {
this._showEnemySpinner = _showEnemySpinner;
}

public void resetPositions() {
_backdropPosition = BattleSceneDefaults.backdropPosition();
_playerBasePosition = BattleSceneDefaults.playerBasePosition();
Expand All @@ -526,5 +569,7 @@ public void resetPositions() {
_healthIndicatorColor = BattleSceneDefaults.healthIndicatorColor();
_enemyMonsterRotation = BattleSceneDefaults.enemyMonsterRotation();
_playerMonsterRotation = BattleSceneDefaults.playerMonsterRotation();
_showEnemySpinner = false;
_showPlayerSpinner = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ public class BattleSceneDefaults {
public static Position enemyBasePosition(){ return new Position(800, 400);}
public static Position enemyMonsterPosition(){return new Position(850, 450);}
public static Position playerMonsterPosition () {return new Position(320, 100);}
public static Position enemyHealthBoxPosition(){ return new Position(480, 550);}
public static float enemyHealthBoxWidth(){return 300f;}
public static Position enemyHealthBoxPosition(){ return new Position(430, 550);}
public static float enemyHealthBoxWidth(){return 380f;}
public static float enemyHealthBoxHeight(){return 100f;}
public static Position playerHealthBoxPosition(){ return new Position(100, 300);}
public static float playerHealthBoxWidth(){return 350f;}
public static Position playerHealthBoxPosition(){ return new Position(60, 300);}
public static float playerHealthBoxWidth(){return 400f;}
public static float playerHealthBoxHeight(){return 100f;}
public static Position actionBoxPosition(float gameWidth){return new Position(gameWidth - 300, 155); }
public static float actionBoxWidth(){return 250f;}
Expand Down
Loading