diff --git a/core/src/main/java/io/github/annabeths/Boats/AttackBoat.java b/core/src/main/java/io/github/annabeths/Boats/AttackBoat.java index 9f08dbf..de90a43 100644 --- a/core/src/main/java/io/github/annabeths/Boats/AttackBoat.java +++ b/core/src/main/java/io/github/annabeths/Boats/AttackBoat.java @@ -34,8 +34,14 @@ public AttackBoat(GameController controller, Vector2 initialPosition, String tex @Override public void Shoot() { - Projectile projLeft = createProjectile(projectileType, -90, 1, 1); - Projectile projRight = createProjectile(projectileType, 90, 1, 1); + + float damageMul = 1; + if (this instanceof EnemyBoat) { + damageMul = controller.getGameDifficulty().getEnemyDmgMul(); + } + + Projectile projLeft = createProjectile(projectileType, -90, damageMul, 1); + Projectile projRight = createProjectile(projectileType, 90, damageMul, 1); // Add the projectile to the GameController's physics objects list so it // receives updates @@ -68,26 +74,28 @@ public void updateAIState() { @Override public void Update(float delta) { - if (isDead()) Destroy(); + if (isDead()) + Destroy(); timeSinceLastShot += delta; updateAIState(); switch (state) { - case APPROACH: + case APPROACH : approach(delta); break; - case ATTACK: + case ATTACK : attack(delta); break; - case IDLE: + case IDLE : idle(delta); break; - default: + default : break; } - if (destination != null) MoveToDestination(delta); + if (destination != null) + MoveToDestination(delta); } public void approach(float delta) { @@ -115,7 +123,8 @@ public void attack(float delta) { adjustedAng = MathHelper.normalizeAngle(adjustedAng); adjustedAng -= adjustedAng > 270 ? 180 : 0; - // If the angle to the player is within acceptable angle range, shoot + // If the angle to the player is within acceptable angle range, + // shoot if (adjustedAng > 80 && adjustedAng < 100) { Shoot(); timeSinceLastShot = 0; diff --git a/core/src/main/java/io/github/annabeths/Boats/EnemyBoat.java b/core/src/main/java/io/github/annabeths/Boats/EnemyBoat.java index 86c8b8f..ea4a0de 100644 --- a/core/src/main/java/io/github/annabeths/Boats/EnemyBoat.java +++ b/core/src/main/java/io/github/annabeths/Boats/EnemyBoat.java @@ -22,8 +22,8 @@ public EnemyBoat(GameController controller, Vector2 position) { xpValue = 150; plunderValue = 100; - this.HP = 100; - this.maxHP = 100; + this.maxHP = 100 * controller.getGameDifficulty().getEnemyHpMul(); + this.HP = this.maxHP; this.speed = 75; this.turnSpeed = 150; // uncomment for fun @@ -77,7 +77,8 @@ public void OnCollision(PhysicsObject other) { Destroy(); } - if (objWasPlayer) controller.addXp((dmgToInflict / maxHP) * xpValue); + if (objWasPlayer) + controller.addXp((dmgToInflict / maxHP) * xpValue); damage(dmgToInflict); } diff --git a/core/src/main/java/io/github/annabeths/Boats/NeutralBoat.java b/core/src/main/java/io/github/annabeths/Boats/NeutralBoat.java index 8346471..7a1197d 100644 --- a/core/src/main/java/io/github/annabeths/Boats/NeutralBoat.java +++ b/core/src/main/java/io/github/annabeths/Boats/NeutralBoat.java @@ -14,7 +14,7 @@ public class NeutralBoat extends AIBoat { public NeutralBoat(GameController controller, Vector2 initialPosition) { super(controller, initialPosition, "img/entity/boat_neutral.png"); - xpValue = 20; + xpValue = 20 * controller.getGameDifficulty().getPlayerXpMul(); plunderValue = 25; this.HP = 100; diff --git a/core/src/main/java/io/github/annabeths/Boats/PlayerBoat.java b/core/src/main/java/io/github/annabeths/Boats/PlayerBoat.java index 97015a2..852bb3e 100644 --- a/core/src/main/java/io/github/annabeths/Boats/PlayerBoat.java +++ b/core/src/main/java/io/github/annabeths/Boats/PlayerBoat.java @@ -64,8 +64,9 @@ public class PlayerBoat extends Boat { public PlayerBoat(GameController controller, Vector2 initialPosition) { super(controller, initialPosition, "img/entity/boat1.png"); - this.HP = 100; + this.maxHP = 100; + this.HP = this.maxHP; this.speed = 200; this.turnSpeed = 150; @@ -231,9 +232,9 @@ public void shootStock(float dmgMul) { } public float getDamageMul() { - float dmgMul = activePowerups.containsKey(PowerupType.DAMAGE) ? 3 : 1; + float dmgMul = activePowerups.containsKey(PowerupType.DAMAGE) ? 2 : 1; // multiply by the overall damage multiplier - return dmgMul * projDmgMul; + return dmgMul * projDmgMul * controller.getGameDifficulty().getPlayerDmgMul(); } @Override diff --git a/core/src/main/java/io/github/annabeths/Colleges/EnemyCollege.java b/core/src/main/java/io/github/annabeths/Colleges/EnemyCollege.java index 7e81520..4c1b45f 100644 --- a/core/src/main/java/io/github/annabeths/Colleges/EnemyCollege.java +++ b/core/src/main/java/io/github/annabeths/Colleges/EnemyCollege.java @@ -19,8 +19,8 @@ public class EnemyCollege extends College { /** * The inaccuracy when firing cannonballs. Measured in degrees and reflected - * about the center. i.e. the cannon could be fired anywhere between -x and x - * where x is the inaccuracy. + * about the center. i.e. the cannon could be fired anywhere between -x and + * x where x is the inaccuracy. */ public float shootingInaccuracy = 10f; public float timeSinceLastShot = 0; @@ -38,7 +38,7 @@ public EnemyCollege(Vector2 position, String aliveTexture, String islandTexture, deadSprite = initSprite("img/world/castle/castle_dead.png", position, new Vector2(100, 100)); - this.maxHP = maxHP; + this.maxHP = maxHP * controller.getGameDifficulty().getEnemyHpMul(); HP = maxHP; range = 500; fireRate = 1.5f; @@ -69,7 +69,8 @@ public void OnCollision(PhysicsObject other) { p.kill(); if (!isInvulnerable()) { damage(p.getDamage()); - if (isDead()) gc.CollegeDestroyed(this); + if (isDead()) + gc.CollegeDestroyed(this); updateHpText(); } else { hpText.setText(font, "RESISTED, destroy other colleges first!"); @@ -110,21 +111,26 @@ public void Draw(SpriteBatch batch) { void ShootAt(Vector2 target) { // If fire is disabled, skip calculation. - if (!DebugUtils.ENEMY_COLLEGE_FIRE) return; + if (!DebugUtils.ENEMY_COLLEGE_FIRE) + return; /* - * calculate the shot angle by getting a vector from the center of the college - * to the target. Convert to degrees for the inaccuracy calculation. + * calculate the shot angle by getting a vector from the center of the + * college to the target. Convert to degrees for the inaccuracy + * calculation. */ Vector2 directionVec = target.cpy().sub(getCenter()); float shotAngle = directionVec.angleDeg(); shotAngle += MathUtils.random(-shootingInaccuracy, shootingInaccuracy); + float dmgMul = gc.getGameDifficulty().getEnemyDmgMul(); + /* - * instantiate a new bullet and pass a reference to the gamecontroller so it can - * be updated and drawn + * instantiate a new bullet and pass a reference to the gamecontroller + * so it can be updated and drawn */ - gc.NewPhysicsObject(new Projectile(getCenter(), shotAngle, projectileType, false)); + gc.NewPhysicsObject( + new Projectile(getCenter(), shotAngle, projectileType, false, dmgMul, 1)); } diff --git a/core/src/main/java/io/github/annabeths/GameScreens/GameController.java b/core/src/main/java/io/github/annabeths/GameScreens/GameController.java index 8bb98b7..f4f7b61 100644 --- a/core/src/main/java/io/github/annabeths/GameScreens/GameController.java +++ b/core/src/main/java/io/github/annabeths/GameScreens/GameController.java @@ -1,8 +1,6 @@ package io.github.annabeths.GameScreens; import static io.github.annabeths.Level.GameMap.BORDER_BRIM; -import static io.github.annabeths.Level.GameMap.MAP_HEIGHT; -import static io.github.annabeths.Level.GameMap.MAP_WIDTH; import java.util.ArrayList; import java.util.Arrays; @@ -33,6 +31,7 @@ import io.github.annabeths.GameGenerics.GameObject; import io.github.annabeths.GameGenerics.PhysicsObject; import io.github.annabeths.GeneralControl.DebugUtils; +import io.github.annabeths.GeneralControl.Difficulty; import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; import io.github.annabeths.Obstacles.Kraken; @@ -54,6 +53,8 @@ public class GameController implements Screen { public EnemyCollege bossCollege; public Powerup powerUp; + private Difficulty gameDifficulty = Difficulty.MEDIUM; + public static final float PLAY_TIME = 10 * 60 + 0; public float timer = PLAY_TIME; @@ -72,14 +73,23 @@ public class GameController implements Screen { float xpTick = 1f; float xpTickMultiplier = 1f; - // passes the game class so that we can change scene back later - public GameController(eng1game game) { + public GameController(eng1game game, Difficulty diff) { this(); this.game = game; + this.setDifficulty(diff); + generateGameObjects(); } + /** + * Creates a GameController with a default difficulty of + * {@link Difficulty#MEDIUM} + */ + public GameController(eng1game game) { + this(game, Difficulty.MEDIUM); + } + private GameController() { gameObjects = new ArrayList(); physicsObjects = new ArrayList(); @@ -104,7 +114,7 @@ public void show() { } final int weatherPerGeneration = 5; - final int timeBetweenWeatherGeneration = 5; + float timeBetweenWeatherGeneration = 5; float timeSinceLastWeather = 0; public void generateWeather() { @@ -191,19 +201,19 @@ private void generateGameObjects() { new Vector2(2 * GameMap.getMapWidth() / 3, 2 * GameMap.getMapHeight() / 3))); // add a kraken - // TODO: Make the kraken only appear on higher difficulties - physicsObjects.add(new Kraken(this, new Vector2(1500, 1500))); + if (getGameDifficulty().doesKrakenSpawn()) + physicsObjects.add(new Kraken(this, new Vector2(1500, 1500))); - for (int i = 0; i < 75; i++) { - physicsObjects.add(new Mine(this, - new Vector2(MathUtils.random() * MAP_WIDTH, MathUtils.random() * MAP_HEIGHT))); + for (int i = 0; i < getGameDifficulty().getNumMines(); i++) { + physicsObjects.add(new Mine(this, GameMap.getRandomPointInBounds())); } } public void logic(float delta) { timer -= delta; - if (timer <= 0) gameOver(); + if (timer <= 0) + gameOver(); // give the player XP and Plunder each frame, normalized using delta xpTick -= delta * xpTickMultiplier; @@ -219,7 +229,8 @@ public void logic(float delta) { UpdateObjects(delta); // update all physicsobjects ClearKilledObjects(); // clear any 'killed' objects - if (bossCollege.isDead()) { // if the boss college is dead, the game is won + if (bossCollege.isDead()) { // if the boss college is dead, the game is + // won game.gameScore = (int) getGameScore(); game.gotoScreen(Screens.gameWinScreen); } @@ -252,7 +263,8 @@ public void render(float delta) { physicsObject.Draw(batch); } - if (DebugUtils.DRAW_DEBUG_TEXT) DebugUtils.drawEntityDebugText(this, batch); + if (DebugUtils.DRAW_DEBUG_TEXT) + DebugUtils.drawEntityDebugText(this, batch); // end the sprite batch batch.end(); @@ -261,8 +273,10 @@ public void render(float delta) { sr.setProjectionMatrix(camera.combined); renderRays(); - // this should be off during normal gameplay, but can be on to debug collisions - if (DebugUtils.DRAW_DEBUG_COLLISIONS) DebugUtils.drawDebugCollisions(this, sr); + // this should be off during normal gameplay, but can be on to debug + // collisions + if (DebugUtils.DRAW_DEBUG_COLLISIONS) + DebugUtils.drawDebugCollisions(this, sr); } /** Renders ProjectileRay objects */ @@ -287,7 +301,8 @@ public void renderRays() { /** * Updates all physics objects in the {@link #physicsObjects} list * - * @param delta time since last frame + * @param delta + * time since last frame */ public void UpdateObjects(float delta) { for (int i = 0; i < physicsObjects.size(); i++) { @@ -297,7 +312,8 @@ public void UpdateObjects(float delta) { for (int j = 0; j < physicsObjects.size(); j++) { PhysicsObject other = physicsObjects.get(j); - if (i == j) continue; + if (i == j) + continue; if (current.CheckCollisionWith(other)) { current.OnCollision(other); @@ -313,8 +329,8 @@ public void UpdateObjects(float delta) { } /** - * Tests if player is in danger. The player is in danger if it is in range of an - * {@link EnemyCollege} or an {@link EnemyBoat}. + * Tests if player is in danger. The player is in danger if it is in range + * of an {@link EnemyCollege} or an {@link EnemyBoat}. * * @return {@code true} if within range of an enemy college or boat, * {@code false} otherwise or player is invincible. @@ -350,11 +366,12 @@ public boolean isEnemyCollegeNearPlayer() { } /** - * Called when a college is destroyed Makes sure the boss college will be made - * vulnerable after the rest of the colleges are destroyed, and spawns a - * friendly college in the place of the enemy college. + * Called when a college is destroyed Makes sure the boss college will be + * made vulnerable after the rest of the colleges are destroyed, and spawns + * a friendly college in the place of the enemy college. * - * @param oldCollege the college that was destroyed + * @param oldCollege + * the college that was destroyed */ public void CollegeDestroyed(EnemyCollege oldCollege) { addXp(100); @@ -376,8 +393,8 @@ public void CollegeDestroyed(EnemyCollege oldCollege) { /** * Goes through all the {@link PhysicsObject} and removes ones from the list - * that have had the flag set ({@link GameObject#removeOnNextTick()}) in a safe - * manner + * that have had the flag set ({@link GameObject#removeOnNextTick()}) in a + * safe manner */ public void ClearKilledObjects() { Iterator p = physicsObjects.iterator(); @@ -435,13 +452,15 @@ public void gameOver() { } /** - * Calculates the overall game score to be presented to the player at the end of - * the game. + * Calculates the overall game score to be presented to the player at the + * end of the game. */ public float getGameScore() { float powerupScore = playerBoat.collectedPowerups.values().stream().reduce(0, Integer::sum); - float healthScore = playerBoat.getHealth() - 100; // penalty for losing health - float timeScore = (timer - PLAY_TIME); // the shorter the play, the more points + float healthScore = playerBoat.getHealth() - 100; // penalty for losing + // health + float timeScore = (timer - PLAY_TIME); // the shorter the play, the more + // points return getTotalPlunder() * 5 + getTotalXp() + timeScore + healthScore + powerupScore * 25; } @@ -449,10 +468,12 @@ public float getGameScore() { * Called to give a reference to a new {@link PhysicsObject} to the * {@link #physicsObjects} list * - * @param obj the object to add + * @param obj + * the object to add */ public void NewPhysicsObject(PhysicsObject obj) { - // A new PhysicsObject has been created, add it to the list so it receives + // A new PhysicsObject has been created, add it to the list so it + // receives // updates physicsObjects.add(obj); } @@ -460,17 +481,19 @@ public void NewPhysicsObject(PhysicsObject obj) { /** * Add XP to the player's amount. * - * @param amount the amount of XP to add + * @param amount + * the amount of XP to add */ public void addXp(float amount) { - xp += amount; - totalXp += amount; + xp += amount * getGameDifficulty().getPlayerXpMul(); + totalXp += amount * getGameDifficulty().getPlayerXpMul(); } /** * Add plunder to the player's amount. * - * @param amount the amount of plunder to add + * @param amount + * the amount of plunder to add */ public void addPlunder(float amount) { plunder += amount; @@ -480,7 +503,8 @@ public void addPlunder(float amount) { /** * Remove plunder from the player's amount. * - * @param amount the amount of plunder to remove + * @param amount + * the amount of plunder to remove */ public void subtractPlunder(float amount) { plunder -= amount; @@ -497,8 +521,8 @@ public int getXpLevel() { } /** - * Get how much XP the player has in this current level. i.e. the amount of XP - * excluding the XP contributing to whole levels + * Get how much XP the player has in this current level. i.e. the amount of + * XP excluding the XP contributing to whole levels * * @return the xp in the current level * @see #getXpLevel() @@ -511,7 +535,8 @@ public float getXpInLevel() { /** * Subtract a number of levels from the xp * - * @param levels the number of levels to remove + * @param levels + * the number of levels to remove */ public void subtractXpLevels(int levels) { int curr = getXpLevel(); @@ -523,7 +548,8 @@ public void subtractXpLevels(int levels) { /** * The the XP required to go from {@code level-1} to {@code level}. * - * @param level the target level + * @param level + * the target level * @return the XP difference between previous level and this one */ public static int getXpRequiredForLevel(int level) { @@ -531,8 +557,8 @@ public static int getXpRequiredForLevel(int level) { } /** - * The total XP the needs to level up. Note this is NOT the remaining amount, - * but the total amount to be able to level up. + * The total XP the needs to level up. Note this is NOT the remaining + * amount, but the total amount to be able to level up. * * @return the xp required to level up */ @@ -548,7 +574,8 @@ public float getXp() { } /** - * @param xp the xp to set + * @param xp + * the xp to set */ public void setXp(float xp) { this.xp = xp; @@ -562,7 +589,8 @@ public int getPlunder() { } /** - * @param plunder the plunder to set + * @param plunder + * the plunder to set */ public void setPlunder(int plunder) { this.plunder = plunder; @@ -583,18 +611,29 @@ public int getTotalPlunder() { } /** - * Returns a game controller instance with minimal data filled out to allow the - * HUD to function without taking up a lot of data. + * Returns a game controller instance with minimal data filled out to allow + * the HUD to function without taking up a lot of data. * * @return The new GameController instance */ public static GameController getMockForHUD() { GameController gc = new GameController(); -// gc.playerBoat.activePowerups.put(PowerupType.DAMAGE, 7f); -// gc.playerBoat.activePowerups.put(PowerupType.RAPIDFIRE, 2f); + // gc.playerBoat.activePowerups.put(PowerupType.DAMAGE, 7f); + // gc.playerBoat.activePowerups.put(PowerupType.RAPIDFIRE, 2f); gc.playerBoat.damage(13); gc.addXp(50); return gc; } + public void setDifficulty(Difficulty difficulty) { + this.gameDifficulty = difficulty; + } + + /** + * @return the gameDifficulty + */ + public Difficulty getGameDifficulty() { + return gameDifficulty; + } + } diff --git a/core/src/main/java/io/github/annabeths/GameScreens/GameDifScreen.java b/core/src/main/java/io/github/annabeths/GameScreens/GameDifScreen.java new file mode 100644 index 0000000..a4274a3 --- /dev/null +++ b/core/src/main/java/io/github/annabeths/GameScreens/GameDifScreen.java @@ -0,0 +1,167 @@ +package io.github.annabeths.GameScreens; + +import static io.github.annabeths.GeneralControl.Difficulty.EASY; +import static io.github.annabeths.GeneralControl.Difficulty.HARD; +import static io.github.annabeths.GeneralControl.Difficulty.MEDIUM; + +import java.util.function.Consumer; + +import com.badlogic.gdx.Gdx; +import com.badlogic.gdx.Screen; +import com.badlogic.gdx.graphics.Color; +import com.badlogic.gdx.graphics.Texture; +import com.badlogic.gdx.graphics.g2d.BitmapFont; +import com.badlogic.gdx.graphics.g2d.SpriteBatch; +import com.badlogic.gdx.math.Vector2; +import com.badlogic.gdx.scenes.scene2d.Actor; +import com.badlogic.gdx.scenes.scene2d.InputEvent; +import com.badlogic.gdx.scenes.scene2d.Stage; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton; +import com.badlogic.gdx.scenes.scene2d.ui.TextButton.TextButtonStyle; +import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; +import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable; +import com.badlogic.gdx.utils.ScreenUtils; + +import io.github.annabeths.GeneralControl.Difficulty; +import io.github.annabeths.GeneralControl.eng1game; + +/** + * The menu where the game difficulty is selected + * + * @author James Burnell + * @author Jiahao Shang + */ +public class GameDifScreen implements Screen { + + private Stage stage; + + private SpriteBatch batch; + private eng1game game; + + /** Array of the menu buttons */ + private TextButton[] buttons = new TextButton[4]; + + private BitmapFont font; + + public GameDifScreen(eng1game g) { + batch = new SpriteBatch(); + game = g; + + stage = new Stage(); + Gdx.input.setInputProcessor(stage); + + font = new BitmapFont(Gdx.files.internal("fonts/bobcat.fnt"), false); + + setupButtons(); + } + + private void setupButtons() { + // Size of each button + Vector2 btnSize = new Vector2(150, 350); + // Array of colors the text should be + Color[] textColors = {Color.GREEN, Color.ORANGE, Color.RED, Color.BLACK}; + // Array of text to display on the buttons + String[] buttonText = {"EASY", "MEDIUM", "HARD", "RETURN\nTO MENU"}; + Difficulty[] buttonDiff = {EASY, MEDIUM, HARD}; + + // y position of the buttons + float btnY = (Gdx.graphics.getHeight() - btnSize.y) / 2; + // horizontal margin of each button + float btnXMarg = 50; + // Total width of buttons + float menuWidth = (btnSize.x + btnXMarg) * 4 - btnXMarg; + // left-most x position of menu + float menuXPos = (Gdx.graphics.getWidth() - menuWidth) / 2; + + // Set up the styles of the buttons + for (int i = 0; i < 4; i++) { + // Define style for the button + TextButtonStyle style = new TextButtonStyle(); + style.font = font; + style.fontColor = textColors[i]; + style.up = new TextureRegionDrawable(new Texture("ui/upgradebutton.png")); + + // Define the button + buttons[i] = new TextButton(buttonText[i], style); + buttons[i].setSize(btnSize.x, btnSize.y); + float x = menuXPos + i * (btnSize.x + btnXMarg); + buttons[i].setPosition(x, btnY); + + // Define button click actions + if (i < buttonDiff.length) { + final int index = i; + clickListener(buttons[i], event -> { + game.setDifficulty(buttonDiff[index]); + game.gotoScreen(Screens.gameScreen); + }); + } + + // Add button to stage + stage.addActor(buttons[i]); + } + + // Return to menu + clickListener(buttons[3], event -> game.gotoScreen(Screens.menuScreen)); + } + + /** + * Created a new click listener based on the action given and assigns it as + * a new listener to the actor. Used to make code cleaner elsewhere. + * + * @param act + * the actor to apply the listener to + * @param actions + * the actions to run upon clicking the actor + * @author James Burnell + */ + private void clickListener(Actor act, Consumer actions) { + act.addListener(new ClickListener() { + @Override + public void clicked(InputEvent event, float x, float y) { + actions.accept(event); + } + }); + } + + @Override + public void show() { + + } + + @Override + public void render(float delta) { + ScreenUtils.clear(Color.DARK_GRAY); + + batch.begin(); + stage.draw(); + batch.end(); + } + + @Override + public void resize(int width, int height) { + + } + + @Override + public void pause() { + + } + + @Override + public void resume() { + + } + + @Override + public void hide() { + + } + + @Override + public void dispose() { + stage.dispose(); + batch.dispose(); + font.dispose(); + } + +} diff --git a/core/src/main/java/io/github/annabeths/GameScreens/Menu.java b/core/src/main/java/io/github/annabeths/GameScreens/Menu.java index 2130e68..0d2fc3e 100644 --- a/core/src/main/java/io/github/annabeths/GameScreens/Menu.java +++ b/core/src/main/java/io/github/annabeths/GameScreens/Menu.java @@ -53,8 +53,8 @@ public void render(float delta) { } else if (Gdx.input.isKeyJustPressed(Keys.ENTER)) { // Ensure the player has seen the instructions if (instructionsBeenShown) { - // if the ENTER key is pressed, switch to the game screen - game.gotoScreen(Screens.gameScreen); + // if the ENTER key is pressed, switch to the difficulty screen + game.gotoScreen(Screens.gameDifScreen); } else { toggleInstructions(); } diff --git a/core/src/main/java/io/github/annabeths/GameScreens/Screens.java b/core/src/main/java/io/github/annabeths/GameScreens/Screens.java index 3f03a8d..fee536a 100644 --- a/core/src/main/java/io/github/annabeths/GameScreens/Screens.java +++ b/core/src/main/java/io/github/annabeths/GameScreens/Screens.java @@ -2,5 +2,5 @@ /** All the screens the game can switch to */ public enum Screens { - splashScreen, menuScreen, gameScreen, gameOverScreen, gameWinScreen + splashScreen, menuScreen, gameScreen, gameOverScreen, gameWinScreen, gameDifScreen } \ No newline at end of file diff --git a/core/src/main/java/io/github/annabeths/GeneralControl/Difficulty.java b/core/src/main/java/io/github/annabeths/GeneralControl/Difficulty.java new file mode 100644 index 0000000..81b2ad8 --- /dev/null +++ b/core/src/main/java/io/github/annabeths/GeneralControl/Difficulty.java @@ -0,0 +1,93 @@ +package io.github.annabeths.GeneralControl; + +/** + * Used to define multipliers to different game variables depending on the + * selected difficulty. Based on the difficulty, other changes may be defined + * elsewhere in other classes. + * + * @author James Burnell + * @author Hector Woods + */ +public enum Difficulty { + + /** + * Kraken does not spawn on easy, very few mines and ships are much weaker + */ + EASY(0.75f, 0.75f, 1.1f, 1.5f, 40, false, 9), + /** Medium will be the standard difficulty, i.e. no changes */ + MEDIUM(1, 1, 1, 1, 50, true, 7), + /** + * On hard difficulty there are significantly more mines and enemies are a + * lot stronger + */ + HARD(2f, 2f, 0.8f, 0.75f, 75, true, 5); + + float enemyDmgMul; + float enemyHpMul; + float playerDmgMul; + float playerXpMul; + float numMines; + boolean krakenSpawns; + float timeBetweenWeather; + + private Difficulty(float enemyDmgMul, float enemyHpMul, float playerDmgMul, float playerXpMul, + float numMines, boolean krakenSpawns, float timeBetweenWeather) { + this.enemyDmgMul = enemyDmgMul; + this.enemyHpMul = enemyHpMul; + this.playerDmgMul = playerDmgMul; + this.playerXpMul = playerXpMul; + this.numMines = numMines; + this.krakenSpawns = krakenSpawns; + this.timeBetweenWeather = timeBetweenWeather; + } + + /** + * @return the enemyDmgMul + */ + public float getEnemyDmgMul() { + return enemyDmgMul; + } + + /** + * @return the enemyHpMul + */ + public float getEnemyHpMul() { + return enemyHpMul; + } + + /** + * @return the playerDmgMul + */ + public float getPlayerDmgMul() { + return playerDmgMul; + } + + /** + * @return the playerXpMul + */ + public float getPlayerXpMul() { + return playerXpMul; + } + + /** + * @return whether the Kraken spawns or not + */ + public boolean doesKrakenSpawn() { + return krakenSpawns; + } + + /** + * @return the number of mines that should spawn + */ + public float getNumMines() { + return numMines; + } + + /** + * @return the time between weather spawns + */ + public float getTimeBetweenWeather() { + return timeBetweenWeather; + } + +} diff --git a/core/src/main/java/io/github/annabeths/GeneralControl/eng1game.java b/core/src/main/java/io/github/annabeths/GeneralControl/eng1game.java index 722287c..de78797 100644 --- a/core/src/main/java/io/github/annabeths/GeneralControl/eng1game.java +++ b/core/src/main/java/io/github/annabeths/GeneralControl/eng1game.java @@ -13,6 +13,7 @@ import io.github.annabeths.GameScreens.Menu; import io.github.annabeths.GameScreens.Screens; import io.github.annabeths.GameScreens.Splash; +import io.github.annabeths.GameScreens.GameDifScreen; public class eng1game extends Game { @@ -21,14 +22,20 @@ public class eng1game extends Game { Menu menuScreen; GameController gameScreen; + /** + * A placeholder for the difficulty so the gamecontroller can be + * instantiated + */ + private Difficulty diff = Difficulty.MEDIUM; + public boolean timeUp = false; /** @see GameController#getGameScore() */ public int gameScore = 0; /** - * This debug value is controlled by arguments passed to the game. This value - * must NOT be changed manually from FALSE. + * This debug value is controlled by arguments passed to the game. This + * value must NOT be changed manually from FALSE. */ private boolean debug = false; @@ -42,10 +49,11 @@ public eng1game() { @Override public void create() { ResourceManager.init(new AssetManager()); - if (!debug) DebugUtils.initDebugSettings(); + if (!debug) + DebugUtils.initDebugSettings(); // create a menu and game screen, then switch to a new splash screen menuScreen = new Menu(this); - gameScreen = new GameController(this); + gameScreen = new GameController(this, diff); if (DebugUtils.SKIP_SPLASH) { gotoScreen(Screens.menuScreen); } else { @@ -53,33 +61,51 @@ public void create() { } } + /** + * Disposes of an old game screen so that we don't have multiple running at + * once + */ + public void removeGameScreen() { + gameScreen.dispose(); + gameScreen = null; + } + /** * Uses the {@link Screens} enumeration to change between any screen. * - * @param s the screen to switch to + * @param s + * the screen to switch to */ public void gotoScreen(Screens s) { switch (s) { - case splashScreen: // creates a new splash screen + case splashScreen : // creates a new splash screen Splash splashScreen = new Splash(this); setScreen(splashScreen); break; - case menuScreen: // switch back to the menu screen + case menuScreen : // switch back to the menu screen setScreen(menuScreen); break; - case gameScreen: // switch back to the game screen - gameScreen = new GameController(this); + case gameScreen : // switch back to the game screen + gameScreen = new GameController(this, diff); setScreen(gameScreen); break; - case gameOverScreen: + case gameOverScreen : + removeGameScreen(); GameOverScreen gameOverScreen = new GameOverScreen(this, - timeUp ? "Time Up! ENTER to go to menu, R to restart" + timeUp + ? "Time Up! ENTER to go to menu, R to restart" : "You Died! ENTER to go to menu, R to restart"); setScreen(gameOverScreen); break; - case gameWinScreen: + case gameWinScreen : + removeGameScreen(); GameWinScreen gameWinScreen = new GameWinScreen(this); setScreen(gameWinScreen); + break; + case gameDifScreen : + GameDifScreen gameDifScreen = new GameDifScreen(this); + setScreen(gameDifScreen); + break; } } @@ -89,4 +115,10 @@ public void setFullscreen() { Gdx.app.log("eng1game", "Switched to Fullscreen"); } + public void setDifficulty(Difficulty difficulty) { + System.out.printf("Set game difficulty to %s\n", difficulty.toString()); + if (gameScreen != null) + gameScreen.setDifficulty(difficulty); + this.diff = difficulty; + } } diff --git a/core/src/main/java/io/github/annabeths/Obstacles/Kraken.java b/core/src/main/java/io/github/annabeths/Obstacles/Kraken.java index 659c49c..39f2826 100644 --- a/core/src/main/java/io/github/annabeths/Obstacles/Kraken.java +++ b/core/src/main/java/io/github/annabeths/Obstacles/Kraken.java @@ -20,8 +20,8 @@ public class Kraken extends ObstacleEntity implements IHealth { final float timeBetweenDirectionChanges = 0.25f; final float speed = 75; private float attackRange = 1000; - protected float maxHealth = 500; - protected float health = maxHealth; + protected float maxHealth; + protected float health; private ProjectileData projectileType = ProjectileData.KRAKEN; private float plunderValue = 500; private float xpValue = 250; @@ -38,11 +38,14 @@ public class Kraken extends ObstacleEntity implements IHealth { public Kraken(GameController controller, Vector2 position) { super(controller, position, "img/entity/kraken1.png", new Vector2(200, 200)); - Polygon poly = new Polygon(new float[] { 0, 75, 75, 150, 150, 75, 75, 0 }); + Polygon poly = new Polygon(new float[]{0, 75, 75, 150, 150, 75, 75, 0}); poly.setPosition(position.x - getLocalCenterX(), position.y); poly.setOrigin(0, 0); poly.setRotation(rotation - 90); setCenter(position); + this.maxHealth = 500 * controller.getGameDifficulty().getEnemyHpMul(); + this.health = maxHealth; + this.collisionPolygon = poly; } @@ -85,14 +88,14 @@ public void Move(float delta) { String newFrame = null; switch (frameCounter) { - case 1: - newFrame = frame1; - break; - case 2: - newFrame = frame2; - break; - case 3: - newFrame = frame3; + case 1 : + newFrame = frame1; + break; + case 2 : + newFrame = frame2; + break; + case 3 : + newFrame = frame3; } setSprite(newFrame, position, new Vector2(200, 200)); @@ -124,10 +127,12 @@ public void ShotgunShot() { origin.y - controller.playerBoat.position.y).angleDeg(); for (int i = 0; i < 6; i++) { - Projectile proj = createProjectile(projectileType, direction + (15 * i) + 135, 1, 1, + Projectile proj = createProjectile(projectileType, direction + (15 * i) + 135, + controller.getGameDifficulty().getEnemyDmgMul(), 1, new Vector2(origin.x + i, origin.y + i)); - // Add the projectile to the GameController's physics objects list so it + // Add the projectile to the GameController's physics objects list + // so it // receives updates controller.NewPhysicsObject(proj); } diff --git a/core/src/main/java/io/github/annabeths/Obstacles/Weather.java b/core/src/main/java/io/github/annabeths/Obstacles/Weather.java index 6c66bf5..11494e5 100644 --- a/core/src/main/java/io/github/annabeths/Obstacles/Weather.java +++ b/core/src/main/java/io/github/annabeths/Obstacles/Weather.java @@ -25,7 +25,8 @@ public class Weather extends ObstacleEntity { Vector2 direction; float timeOnCurrentDirection = 0; /** - * The weather starts on one side of the map and "trends" to the other side.
+ * The weather starts on one side of the map and "trends" to the other + * side.
*
    *
  • 0 means it starts north, trends south
  • *
  • 1 means south-north
  • @@ -44,7 +45,7 @@ public class Weather extends ObstacleEntity { public Weather(GameController controller, Vector2 position, int dir) { super(controller, position, "img/entity/weather1.png", new Vector2(100, 100)); - Polygon poly = new Polygon(new float[] { 0, 50, 50, 100, 100, 50, 50, 0 }); + Polygon poly = new Polygon(new float[]{0, 50, 50, 100, 100, 50, 50, 0}); poly.setPosition(position.x - getLocalCenterX(), position.y); poly.setOrigin(0, 0); poly.setRotation(rotation - 90); @@ -77,22 +78,22 @@ public void OnCollision(PhysicsObject other) { return; // Only deal damage when lightning frames are showing } if (other instanceof Boat) { - ((Boat) other).damage(1f); + ((Boat) other).damage(1f * controller.getGameDifficulty().getEnemyDmgMul()); } } public void ChangeDirection() { switch (directionTrend) { - case 0: // North -> South + case 0 : // North -> South direction = new Vector2(Math.random() < 0.5 ? -1 : 1, -1); break; - case 1: // South -> North + case 1 : // South -> North direction = new Vector2(Math.random() < 0.5 ? -1 : 1, 1); break; - case 2: // East -> West + case 2 : // East -> West direction = new Vector2(1, Math.random() < 0.5 ? -1 : 1); break; - case 3: // West -> East + case 3 : // West -> East direction = new Vector2(-1, Math.random() < 0.5 ? -1 : 1); } } diff --git a/core/src/test/java/io/github/annabeths/Boats/AIBoatTest.java b/core/src/test/java/io/github/annabeths/Boats/AIBoatTest.java index ee28c70..e37894f 100644 --- a/core/src/test/java/io/github/annabeths/Boats/AIBoatTest.java +++ b/core/src/test/java/io/github/annabeths/Boats/AIBoatTest.java @@ -13,17 +13,17 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.withSettings; -import java.util.ArrayList; - +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; -import io.github.annabeths.Colleges.College; import io.github.annabeths.Colleges.EnemyCollege; import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; import io.github.annabeths.Projectiles.ProjectileData; @@ -32,11 +32,17 @@ public class AIBoatTest { public GameController gc; public AIBoat b; + @BeforeAll + public static void init() { + TestHelper.setupEnv(); + } + @BeforeEach public void setup() { - gc = mock(GameController.class); + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); + gc.physicsObjects.clear(); initColleges(); gc.playerBoat = new PlayerBoat(gc, new Vector2(0, 0)); @@ -144,7 +150,8 @@ public void testUpdateDestination() { b.updateDestination(); assertEquals(old, b.GetDestination()); - b.destinationThreshold = 100000; // ensure boat is within threshold to force update + b.destinationThreshold = 100000; // ensure boat is within threshold to + // force update b.updateDestination(); assertNotEquals(old, b.GetDestination()); } diff --git a/core/src/test/java/io/github/annabeths/Boats/EnemyBoatTest.java b/core/src/test/java/io/github/annabeths/Boats/EnemyBoatTest.java index cb38faf..35edf7d 100644 --- a/core/src/test/java/io/github/annabeths/Boats/EnemyBoatTest.java +++ b/core/src/test/java/io/github/annabeths/Boats/EnemyBoatTest.java @@ -1,49 +1,49 @@ package io.github.annabeths.Boats; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.atLeast; -import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.withSettings; -import java.util.ArrayList; import java.util.Iterator; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.badlogic.gdx.math.Vector2; import io.github.annabeths.Collectables.Powerup; -import io.github.annabeths.Colleges.College; import io.github.annabeths.GameGenerics.PhysicsObject; import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; import io.github.annabeths.Projectiles.Projectile; import io.github.annabeths.Projectiles.ProjectileData; -import io.github.annabeths.Projectiles.ProjectileRay; public class EnemyBoatTest { public GameController gc; public EnemyBoat b; + @BeforeAll + public static void init() { + TestHelper.setupEnv(); + } + @BeforeEach public void setup() { - gc = mock(GameController.class, withSettings().defaultAnswer(CALLS_REAL_METHODS)); + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); - gc.physicsObjects = new ArrayList(); - gc.rays = new ArrayList(); - doCallRealMethod().when(gc).NewPhysicsObject(any(PhysicsObject.class)); - gc.playerBoat = new PlayerBoat(gc, new Vector2(0, 0)); b = mock(EnemyBoat.class, withSettings().useConstructor(gc, new Vector2(0, 0)) .defaultAnswer(CALLS_REAL_METHODS)); @@ -92,6 +92,7 @@ public void testOnCollisionProjectileNonPlayer() { @Test public void testGetNearestTargetPlayerNear() { + gc.playerBoat = new PlayerBoat(gc, new Vector2(1, 0)); for (int i = 10; i < 200; i += 50) { gc.NewPhysicsObject(new FriendlyBoat(gc, new Vector2(i, 0))); } @@ -106,6 +107,7 @@ public void testGetNearestTargetNothing() { @Test public void testGetNearestTargetFriendlyBoat() { + gc.physicsObjects.clear(); gc.playerBoat = new PlayerBoat(gc, new Vector2(1000, 0)); for (int i = 10; i < 200; i += 50) { gc.NewPhysicsObject(new FriendlyBoat(gc, new Vector2(i, 0))); diff --git a/core/src/test/java/io/github/annabeths/Boats/FriendlyBoatTest.java b/core/src/test/java/io/github/annabeths/Boats/FriendlyBoatTest.java index fddfb1e..be71fe7 100644 --- a/core/src/test/java/io/github/annabeths/Boats/FriendlyBoatTest.java +++ b/core/src/test/java/io/github/annabeths/Boats/FriendlyBoatTest.java @@ -1,47 +1,46 @@ package io.github.annabeths.Boats; -import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.CALLS_REAL_METHODS; -import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.withSettings; -import java.util.ArrayList; import java.util.Iterator; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.badlogic.gdx.math.Vector2; -import io.github.annabeths.Colleges.College; import io.github.annabeths.GameGenerics.PhysicsObject; import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; import io.github.annabeths.Projectiles.Projectile; import io.github.annabeths.Projectiles.ProjectileData; -import io.github.annabeths.Projectiles.ProjectileRay; public class FriendlyBoatTest { public GameController gc; public FriendlyBoat b; + @BeforeAll + public static void init() { + TestHelper.setupEnv(); + } + @BeforeEach public void setup() { - gc = mock(GameController.class); + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); - gc.physicsObjects = new ArrayList(); - gc.rays = new ArrayList(); - doCallRealMethod().when(gc).NewPhysicsObject(any(PhysicsObject.class)); - gc.playerBoat = new PlayerBoat(gc, new Vector2(0, 0)); b = mock(FriendlyBoat.class, withSettings().useConstructor(gc, new Vector2(0, 0)) .defaultAnswer(CALLS_REAL_METHODS)); @@ -51,6 +50,7 @@ public void setup() { @Test public void testGetNearestTarget() { + gc.physicsObjects.clear(); for (int i = 10; i < 200; i += 50) { gc.NewPhysicsObject(new EnemyBoat(gc, new Vector2(i, 0))); } diff --git a/core/src/test/java/io/github/annabeths/Boats/GeneralBoatTests.java b/core/src/test/java/io/github/annabeths/Boats/GeneralBoatTests.java index 712f9e1..6fe5383 100644 --- a/core/src/test/java/io/github/annabeths/Boats/GeneralBoatTests.java +++ b/core/src/test/java/io/github/annabeths/Boats/GeneralBoatTests.java @@ -1,18 +1,20 @@ package io.github.annabeths.Boats; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.mock; - -import java.util.ArrayList; +import static org.mockito.Mockito.withSettings; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.badlogic.gdx.math.Vector2; -import io.github.annabeths.Colleges.College; import io.github.annabeths.GameGenerics.PhysicsObject; import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; /** @@ -24,9 +26,14 @@ public class GeneralBoatTests { @BeforeAll public static void init() { - gc = mock(GameController.class); + TestHelper.setupEnv(); + } + + @BeforeEach + public void setup() { + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); } @Test diff --git a/core/src/test/java/io/github/annabeths/Boats/NeutralBoatTest.java b/core/src/test/java/io/github/annabeths/Boats/NeutralBoatTest.java index 6e3baa9..e5a0122 100644 --- a/core/src/test/java/io/github/annabeths/Boats/NeutralBoatTest.java +++ b/core/src/test/java/io/github/annabeths/Boats/NeutralBoatTest.java @@ -4,23 +4,19 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.CALLS_REAL_METHODS; -import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.withSettings; -import java.util.ArrayList; - import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.badlogic.gdx.math.Vector2; -import io.github.annabeths.Colleges.College; -import io.github.annabeths.GameGenerics.PhysicsObject; import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; import io.github.annabeths.Projectiles.Projectile; import io.github.annabeths.Projectiles.ProjectileData; @@ -32,15 +28,15 @@ public class NeutralBoatTest { @BeforeAll public static void init() { - gc = mock(GameController.class, withSettings().defaultAnswer(CALLS_REAL_METHODS)); - gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); - gc.physicsObjects = new ArrayList(); - doCallRealMethod().when(gc).NewPhysicsObject(any(PhysicsObject.class)); + TestHelper.setupEnv(); } @BeforeEach public void setup() { + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); + gc.map = mock(GameMap.class); + nb = new NeutralBoat(gc, new Vector2(0, 0)); } @@ -53,7 +49,8 @@ public void testDestroyKills() { @Test public void testDestroyDropsPowerupRandomly() { - // The number of powerups should be less than the number of destroy calls + // The number of powerups should be less than the number of destroy + // calls int runs = 10000; for (int i = 0; i < runs; i++) { nb.Destroy(); diff --git a/core/src/test/java/io/github/annabeths/Boats/PlayerBoatTest.java b/core/src/test/java/io/github/annabeths/Boats/PlayerBoatTest.java index 499671d..dcaff09 100644 --- a/core/src/test/java/io/github/annabeths/Boats/PlayerBoatTest.java +++ b/core/src/test/java/io/github/annabeths/Boats/PlayerBoatTest.java @@ -15,8 +15,7 @@ import static org.mockito.Mockito.when; import static org.mockito.Mockito.withSettings; -import java.util.ArrayList; - +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -24,22 +23,19 @@ import com.badlogic.gdx.Graphics; import com.badlogic.gdx.Input; import com.badlogic.gdx.Input.Keys; -import com.badlogic.gdx.graphics.OrthographicCamera; import com.badlogic.gdx.graphics.g2d.Sprite; import com.badlogic.gdx.math.Polygon; import com.badlogic.gdx.math.Vector2; import io.github.annabeths.Collectables.PowerupType; -import io.github.annabeths.Colleges.College; import io.github.annabeths.Colleges.EnemyCollege; -import io.github.annabeths.GameGenerics.PhysicsObject; import io.github.annabeths.GameGenerics.Upgrades; import io.github.annabeths.GameScreens.GameController; import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; import io.github.annabeths.Projectiles.Projectile; import io.github.annabeths.Projectiles.ProjectileData; -import io.github.annabeths.Projectiles.ProjectileRay; import io.github.annabeths.UI.HUD; public class PlayerBoatTest { @@ -47,20 +43,19 @@ public class PlayerBoatTest { public GameController gc; public PlayerBoat b; + @BeforeAll + public static void init() { + TestHelper.setupEnv(); + } + @BeforeEach public void setup() { - TestHelper.setupEnv(); setupInput(); - gc = mock(GameController.class); + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); - gc.physicsObjects = new ArrayList(); - gc.rays = new ArrayList(); - doCallRealMethod().when(gc).NewPhysicsObject(any(PhysicsObject.class)); setupColleges(); - gc.playerBoat = new PlayerBoat(gc, new Vector2(0, 0)); - gc.camera = new OrthographicCamera(); gc.hud = mock(HUD.class); @@ -90,7 +85,7 @@ private void setupColleges() { doCallRealMethod().when(c).setCenter(any(Vector2.class)); c.sprite = new Sprite(); - Polygon collisionPolygon = new Polygon(new float[] { 0, 0, 100, 0, 100, 100, 0, 100 }); + Polygon collisionPolygon = new Polygon(new float[]{0, 0, 100, 0, 100, 100, 0, 100}); collisionPolygon.setPosition(pos.x, pos.y); c.setCenter(pos); c.collisionPolygon = collisionPolygon; @@ -132,8 +127,10 @@ public void testUpdatePowerupRemove() { b.receivePower(p); b.activatePowerup(p); assertFalse(b.activePowerups.isEmpty()); - b.updatePowerups(p.getDefaultTime() / 2f); // skip half way through powerup - assertFalse(b.activePowerups.isEmpty()); // powerup should still be present + b.updatePowerups(p.getDefaultTime() / 2f); // skip half way through + // powerup + assertFalse(b.activePowerups.isEmpty()); // powerup should still be + // present b.updatePowerups(p.getDefaultTime()); // skip past end of powerup assertTrue(b.activePowerups.isEmpty()); // powerup should be removed } @@ -161,19 +158,23 @@ public void testGetDamageMul() throws IllegalArgumentException, IllegalAccessExc public void testGetAngleBetweenMouseAndBoat() { b.setCenter(new Vector2(0, 0)); when(Gdx.input.getX()).thenReturn(1280 / 2); - when(Gdx.input.getY()).thenReturn(720 / 2 - 100); // point above the player + when(Gdx.input.getY()).thenReturn(720 / 2 - 100); // point above the + // player assertEquals(90, b.getAngleBetweenMouseAndBoat()); - when(Gdx.input.getY()).thenReturn(720 / 2 + 100); // point below the player + when(Gdx.input.getY()).thenReturn(720 / 2 + 100); // point below the + // player assertEquals(270, b.getAngleBetweenMouseAndBoat()); - when(Gdx.input.getX()).thenReturn(1280 / 2 - 100); // point left of the player + when(Gdx.input.getX()).thenReturn(1280 / 2 - 100); // point left of the + // player when(Gdx.input.getY()).thenReturn(720 / 2); assertEquals(180, b.getAngleBetweenMouseAndBoat()); } @Test public void testShootStockNormal() { + gc.physicsObjects.clear(); b.shootStock(1); // Shoot 2 projectiles assertEquals(2, gc.physicsObjects.size()); @@ -185,6 +186,7 @@ public void testShootStockNormal() { @Test public void testShootStockBurst() { + gc.physicsObjects.clear(); b.receivePower(PowerupType.STARBURSTFIRE); b.activatePowerup(PowerupType.STARBURSTFIRE); b.shootStock(1); diff --git a/core/src/test/java/io/github/annabeths/Colleges/CollegeTest.java b/core/src/test/java/io/github/annabeths/Colleges/CollegeTest.java index aa074a6..7ea9b4b 100644 --- a/core/src/test/java/io/github/annabeths/Colleges/CollegeTest.java +++ b/core/src/test/java/io/github/annabeths/Colleges/CollegeTest.java @@ -3,9 +3,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.mock; - -import java.util.ArrayList; +import static org.mockito.Mockito.withSettings; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -16,6 +16,8 @@ import io.github.annabeths.Boats.NeutralBoat; import io.github.annabeths.GameGenerics.PhysicsObject; import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; public class CollegeTest { @@ -26,9 +28,10 @@ public class CollegeTest { @BeforeAll public static void init() { - gc = mock(GameController.class); + TestHelper.setupEnv(); + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); } @BeforeEach diff --git a/core/src/test/java/io/github/annabeths/Colleges/EnemyCollegeTest.java b/core/src/test/java/io/github/annabeths/Colleges/EnemyCollegeTest.java index 41c8e74..0a2b4c8 100644 --- a/core/src/test/java/io/github/annabeths/Colleges/EnemyCollegeTest.java +++ b/core/src/test/java/io/github/annabeths/Colleges/EnemyCollegeTest.java @@ -7,15 +7,12 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.CALLS_REAL_METHODS; -import static org.mockito.Mockito.doCallRealMethod; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.withSettings; -import java.util.ArrayList; - import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,7 +27,8 @@ import io.github.annabeths.GameGenerics.PhysicsObject; import io.github.annabeths.GameScreens.GameController; import io.github.annabeths.GeneralControl.DebugUtils; -import io.github.annabeths.GeneralControl.ResourceManager; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; import io.github.annabeths.Projectiles.Projectile; import io.github.annabeths.Projectiles.ProjectileData; @@ -46,18 +44,16 @@ public class EnemyCollegeTest { @BeforeAll public static void init() { - ResourceManager.font = mock(BitmapFont.class); + TestHelper.setupEnv(); } @BeforeEach public void setup() { - gc = mock(GameController.class); + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); - gc.physicsObjects = new ArrayList(); + gc.playerBoat = new PlayerBoat(gc, new Vector2(0, 0)); - doCallRealMethod().when(gc).CollegeDestroyed(any(EnemyCollege.class)); - doCallRealMethod().when(gc).NewPhysicsObject(any(PhysicsObject.class)); col = mock(EnemyCollege.class, withSettings() diff --git a/core/src/test/java/io/github/annabeths/Colleges/GenericCollegeTests.java b/core/src/test/java/io/github/annabeths/Colleges/GenericCollegeTests.java index 6d4afc3..bddf53f 100644 --- a/core/src/test/java/io/github/annabeths/Colleges/GenericCollegeTests.java +++ b/core/src/test/java/io/github/annabeths/Colleges/GenericCollegeTests.java @@ -1,23 +1,35 @@ package io.github.annabeths.Colleges; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.withSettings; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import com.badlogic.gdx.graphics.g2d.BitmapFont; import com.badlogic.gdx.math.Vector2; import io.github.annabeths.GameGenerics.PhysicsObject; -import io.github.annabeths.GeneralControl.ResourceManager; +import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Projectiles.ProjectileData; public class GenericCollegeTests { + GameController gc; + @BeforeAll public static void init() { - ResourceManager.font = mock(BitmapFont.class); + TestHelper.setupEnv(); + } + + @BeforeEach + public void setup() { + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); } @Test @@ -32,7 +44,7 @@ public void OnCollision(PhysicsObject other) { }); assertDoesNotThrow(() -> { new College(new Vector2(0, 0), "img/world/castle/castle_dead.png", - "img/world/castle/castle_dead.png", null) { + "img/world/castle/castle_dead.png", gc) { @Override public void OnCollision(PhysicsObject other) { @@ -46,7 +58,7 @@ public void testEnemyCollegeInstantiation() { ProjectileData pd = ProjectileData.STOCK; assertDoesNotThrow(() -> { new EnemyCollege(new Vector2(0, 0), "img/world/castle/castle_dead.png", - "img/world/castle/castle_dead.png", null, pd, 100); + "img/world/castle/castle_dead.png", gc, pd, 100); }); } @@ -54,7 +66,7 @@ public void testEnemyCollegeInstantiation() { public void testPlayerCollegeInstantiation() { assertDoesNotThrow(() -> { new PlayerCollege(new Vector2(0, 0), "img/world/castle/castle_dead.png", - "img/world/castle/castle_dead.png", null,false); + "img/world/castle/castle_dead.png", gc, false); }); } diff --git a/core/src/test/java/io/github/annabeths/GameGenerics/PhysicsObjectTest.java b/core/src/test/java/io/github/annabeths/GameGenerics/PhysicsObjectTest.java index 39215ee..eaaab47 100644 --- a/core/src/test/java/io/github/annabeths/GameGenerics/PhysicsObjectTest.java +++ b/core/src/test/java/io/github/annabeths/GameGenerics/PhysicsObjectTest.java @@ -2,18 +2,20 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.mock; - -import java.util.ArrayList; +import static org.mockito.Mockito.withSettings; import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.badlogic.gdx.math.Vector2; import io.github.annabeths.Boats.NeutralBoat; -import io.github.annabeths.Colleges.College; import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; public class PhysicsObjectTest { @@ -22,9 +24,14 @@ public class PhysicsObjectTest { @BeforeAll public static void init() { - gc = mock(GameController.class); + TestHelper.setupEnv(); + } + + @BeforeEach + public void setup() { + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); } @Test diff --git a/core/src/test/java/io/github/annabeths/GeneralControl/DifficultyTest.java b/core/src/test/java/io/github/annabeths/GeneralControl/DifficultyTest.java new file mode 100644 index 0000000..f7f0b5b --- /dev/null +++ b/core/src/test/java/io/github/annabeths/GeneralControl/DifficultyTest.java @@ -0,0 +1,60 @@ +package io.github.annabeths.GeneralControl; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.github.annabeths.GameGenerics.PhysicsObject; +import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.Obstacles.Kraken; +import io.github.annabeths.Obstacles.Mine; + +public class DifficultyTest { + + public static GameController easyG; + public GameController mediumG; + public GameController hardG; + public static eng1game game; + + @BeforeAll + public static void init() { + TestHelper.setupEnv(); + game = new eng1game(); + } + + @BeforeEach + public void setup() { + easyG = new GameController(game, Difficulty.EASY); + mediumG = new GameController(game, Difficulty.MEDIUM); + hardG = new GameController(game, Difficulty.HARD); + } + + public long countMines(GameController g) { + return g.physicsObjects.stream().filter(o -> o instanceof Mine).count(); + } + + public boolean isKrakenPresent(GameController g) { + for (PhysicsObject obj : g.physicsObjects) { + if (obj instanceof Kraken) { + return true; + } + } + return false; + } + + @Test + public void testNumMinesCorrect() { + assertEquals(Difficulty.EASY.getNumMines(), countMines(easyG)); + assertEquals(Difficulty.MEDIUM.getNumMines(), countMines(mediumG)); + assertEquals(Difficulty.HARD.getNumMines(), countMines(hardG)); + } + + @Test + public void testIfKrakenIsPresent() { + assertEquals(isKrakenPresent(easyG), false); + assertEquals(isKrakenPresent(mediumG), true); + assertEquals(isKrakenPresent(hardG), true); + } + +} diff --git a/core/src/test/java/io/github/annabeths/Projectiles/ProjectileRayTest.java b/core/src/test/java/io/github/annabeths/Projectiles/ProjectileRayTest.java index 13d9a4b..eb36bec 100644 --- a/core/src/test/java/io/github/annabeths/Projectiles/ProjectileRayTest.java +++ b/core/src/test/java/io/github/annabeths/Projectiles/ProjectileRayTest.java @@ -4,7 +4,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.withSettings; import java.util.ArrayList; import java.util.Collections; @@ -20,9 +22,10 @@ import io.github.annabeths.Boats.NeutralBoat; import io.github.annabeths.Boats.PlayerBoat; -import io.github.annabeths.Colleges.College; import io.github.annabeths.GameGenerics.PhysicsObject; import io.github.annabeths.GameScreens.GameController; +import io.github.annabeths.GeneralControl.TestHelper; +import io.github.annabeths.GeneralControl.eng1game; import io.github.annabeths.Level.GameMap; public class ProjectileRayTest { @@ -35,13 +38,15 @@ public class ProjectileRayTest { @BeforeAll public static void init() { - gc = mock(GameController.class); - gc.map = mock(GameMap.class); - gc.colleges = new ArrayList(); + TestHelper.setupEnv(); } @BeforeEach public void setupWorld() { + gc = mock(GameController.class, withSettings().useConstructor(mock(eng1game.class)) + .defaultAnswer(CALLS_REAL_METHODS)); + gc.map = mock(GameMap.class); + objects = new ArrayList(); // line of boats