diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 000000000..27221ab51 --- /dev/null +++ b/.github/workflows/maven.yml @@ -0,0 +1,26 @@ +# This workflow will build a Java project with Maven, and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven + +name: Java CI with Maven + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 11 + uses: actions/setup-java@v2 + with: + java-version: '11' + distribution: 'adopt' + cache: maven + - name: Build with Maven + run: mvn -B package --file pom.xml diff --git a/.gitignore b/.gitignore index aeed73a98..7f72f0bf9 100644 --- a/.gitignore +++ b/.gitignore @@ -167,5 +167,7 @@ pip-log.txt ############# log* -*.ttf -.checkstyle \ No newline at end of file +.checkstyle +*.class +.idea/ +out/ \ No newline at end of file diff --git a/README.md b/README.md index 48d20a1b2..46ad64bc8 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,33 @@ Invaders = -[Space Invaders](http://en.wikipedia.org/wiki/Space_Invaders) clone, written in Java. -###Screenshots -![](http://i.minus.com/ijt8HhaA8laZq.png) +Welcome to our Space Invaders java project developed as part of our Software Development Practices class at Hanyang University. We were tasked with adding features onto a previously developed space invaders game. -###Download -[Dropbox](https://dl.dropboxusercontent.com/u/23829102/invaders.zip) +### Team -Mirror: [Mediafire](http://www.mediafire.com/download/kwv9s90j9i1o4kc/invaders.zip) +Our team is called Team Aliens, it comprises of 5 members. -###Installation -After downloading the file above, unpack it and save it to an appropiate location. + * Elias - https://github.com/eliasb1 + * Luca - https://github.com/56luca + * Janae - https://github.com/jfarinas96 + * Sophie - https://github.com/sibylle221 + * Josh - https://github.com/Josholeary -Open the directory and double-click invaders.jar. In some systems (i.e. Ubuntu) you may need to select 'Open with OpenJDK 7 Runtime' or similar from the context menu. +### Features -If the Java path is not set correctly, you can also navigate to the directory from the command line and execute +The following is a list of the features we added. ->java -jar invaders.jar + - Add dying effect (screen shake) + - Add SFX & BGM (background music and sound effects) + - Add various monsters (making higher hp monsters and different monster formations) + - Display HP Color (coordinating colours to reflect monster hp) + - Add Setting function (screen resizing, game speed selecting etc) + - Add game summary (controls/manual) + - Add pause function -###System Requirements -Requires Java 7 or better. + ### CI/CD +We used Github Actions for CI/CD, these are the specific tools we are using for this project: + + - Maven to build the project + - CodeFactor for code checking -###Resources -[Space Invaders Regular (font)](http://www.fonts2u.com/space-invaders-regular.font) - © kylemaoin 2010 \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..59dd58c35 --- /dev/null +++ b/pom.xml @@ -0,0 +1,33 @@ + + + 4.0.0 + + com.setb + Invaders + 1.0-SNAPSHOT + + + + + src/main/resources + + + + + + + org.junit.jupiter + junit-jupiter-api + 5.8.2 + test + + + + + 11 + 11 + + + \ No newline at end of file diff --git a/src/engine/Cooldown.java b/src/main/java/engine/Cooldown.java similarity index 100% rename from src/engine/Cooldown.java rename to src/main/java/engine/Cooldown.java diff --git a/src/engine/Core.java b/src/main/java/engine/Core.java similarity index 86% rename from src/engine/Core.java rename to src/main/java/engine/Core.java index 35cc8274c..f63b50b5e 100644 --- a/src/engine/Core.java +++ b/src/main/java/engine/Core.java @@ -8,11 +8,7 @@ import java.util.logging.Level; import java.util.logging.Logger; -import screen.GameScreen; -import screen.HighScoreScreen; -import screen.ScoreScreen; -import screen.Screen; -import screen.TitleScreen; +import screen.*; /** * Implements core game logic. @@ -23,9 +19,9 @@ public final class Core { /** Width of current screen. */ - private static final int WIDTH = 448; + private static int WIDTH = 448; /** Height of current screen. */ - private static final int HEIGHT = 520; + private static int HEIGHT = 520; /** Max fps of current screen. */ private static final int FPS = 60; @@ -59,7 +55,7 @@ public final class Core { new GameSettings(8, 7, 2, 500); /** Frame to draw the screen on. */ - private static Frame frame; + public static Frame frame; /** Screen currently shown. */ private static Screen currentScreen; /** Difficulty settings list. */ @@ -114,6 +110,8 @@ public static void main(final String[] args) { GameState gameState; + Sound.playMusic(); + int returnCode = 1; do { gameState = new GameState(1, 0, MAX_LIVES, 0, 0); @@ -121,6 +119,12 @@ public static void main(final String[] args) { switch (returnCode) { case 1: // Main menu. + frame.setVisible(false); // This makes the old window disappear + frame = new Frame(WIDTH, HEIGHT); // This creates a new window with new width & height values + DrawManager.getInstance().setFrame(frame); + width = frame.getWidth(); + height = frame.getHeight(); + currentScreen = new TitleScreen(width, height, FPS); LOGGER.info("Starting " + WIDTH + "x" + HEIGHT + " title screen at " + FPS + " fps."); @@ -172,6 +176,22 @@ public static void main(final String[] args) { returnCode = frame.setScreen(currentScreen); LOGGER.info("Closing high score screen."); break; + case 4: + // Help. + currentScreen = new HelpScreen(width, height, FPS); + LOGGER.info("Starting " + WIDTH + "x" + HEIGHT + + " help screen at " + FPS + " fps."); + returnCode = frame.setScreen(currentScreen); + LOGGER.info("Closing help screen."); + break; + case 5: + // Settings. + currentScreen = new SettingsScreen(width, height, FPS); + LOGGER.info("Starting " + WIDTH + "x" + HEIGHT + + " settings screen at " + FPS + " fps."); + returnCode = frame.setScreen(currentScreen); + LOGGER.info("Closing settings screen."); + break; default: break; } @@ -250,4 +270,9 @@ public static Cooldown getVariableCooldown(final int milliseconds, final int variance) { return new Cooldown(milliseconds, variance); } + + public static void setSize(int width, int height) { + WIDTH = width; + HEIGHT = height; + } } \ No newline at end of file diff --git a/src/engine/DrawManager.java b/src/main/java/engine/DrawManager.java similarity index 71% rename from src/engine/DrawManager.java rename to src/main/java/engine/DrawManager.java index 3d61ca503..eabd865cf 100644 --- a/src/engine/DrawManager.java +++ b/src/main/java/engine/DrawManager.java @@ -283,15 +283,18 @@ public void drawHorizontalLine(final Screen screen, final int positionY) { */ public void drawTitle(final Screen screen) { String titleString = "Invaders"; - String instructionsString = - "select with w+s / arrows, confirm with space"; + String[] instructionsStrings = {"Select with w+s / arrows", "Confirm with space"}; + int i = 0; backBufferGraphics.setColor(Color.GRAY); - drawCenteredRegularString(screen, instructionsString, - screen.getHeight() / 2); + for (String instructionString : instructionsStrings) { + drawCenteredRegularString(screen, instructionString, + screen.getHeight() * 4 / 15 + fontRegularMetrics.getHeight() * 2 * i); + i++; + } backBufferGraphics.setColor(Color.GREEN); - drawCenteredBigString(screen, titleString, screen.getHeight() / 3); + drawCenteredBigString(screen, titleString, screen.getHeight() / 6); } /** @@ -305,26 +308,40 @@ public void drawTitle(final Screen screen) { public void drawMenu(final Screen screen, final int option) { String playString = "Play"; String highScoresString = "High scores"; - String exitString = "exit"; + String helpString = "Help"; + String settingsString = "Settings"; + String exitString = "Exit"; if (option == 2) backBufferGraphics.setColor(Color.GREEN); else backBufferGraphics.setColor(Color.WHITE); drawCenteredRegularString(screen, playString, - screen.getHeight() / 3 * 2); + screen.getHeight() * 11 / 20); if (option == 3) backBufferGraphics.setColor(Color.GREEN); else backBufferGraphics.setColor(Color.WHITE); - drawCenteredRegularString(screen, highScoresString, screen.getHeight() - / 3 * 2 + fontRegularMetrics.getHeight() * 2); + drawCenteredRegularString(screen, highScoresString, + screen.getHeight() * 11 / 20 + fontRegularMetrics.getHeight() * 2); + if (option == 4) + backBufferGraphics.setColor(Color.GREEN); + else + backBufferGraphics.setColor(Color.WHITE); + drawCenteredRegularString(screen, helpString, + screen.getHeight() * 11 / 20 + fontRegularMetrics.getHeight() * 4); + if (option == 5) + backBufferGraphics.setColor(Color.GREEN); + else + backBufferGraphics.setColor(Color.WHITE); + drawCenteredRegularString(screen, settingsString, + screen.getHeight() * 11 / 20 + fontRegularMetrics.getHeight() * 6); if (option == 0) backBufferGraphics.setColor(Color.GREEN); else backBufferGraphics.setColor(Color.WHITE); - drawCenteredRegularString(screen, exitString, screen.getHeight() / 3 - * 2 + fontRegularMetrics.getHeight() * 4); + drawCenteredRegularString(screen, exitString, + screen.getHeight() * 11 / 20 + fontRegularMetrics.getHeight() * 8); } /** @@ -488,15 +505,169 @@ public void drawHighScores(final Screen screen, } /** - * Draws a centered string on regular font. - * + * Draws help screen + * + * @param screen + * Screen to draw on. + */ + public void drawHelp(final Screen screen) { + String helpString = "Help"; + String instructionsString = "Press Space to return"; + String[] rule1 = {"Press the arrow keys", "(or the A or D keys)", "to move your ship"}; + String[] rule2 = {"Press space to shoot", "missiles at the enemy ships"}; + String[] rule3 = {"Avoid the missiles shot", "by the enemy ships"}; + String[] rule4 = {"The color of an enemy ship", "depends on their remaining", "health points"}; + String[][] rules = {rule1, rule2, rule3, rule4}; + int i = 0; + int j = 0; + + backBufferGraphics.setColor(Color.GREEN); + drawCenteredBigString(screen, helpString, screen.getHeight() / 8); + + backBufferGraphics.setColor(Color.GRAY); + drawCenteredRegularString(screen, instructionsString, + screen.getHeight() / 5); + + backBufferGraphics.setColor(Color.WHITE); + for (String[] rule : rules) { + for (String ruleString : rule) { + drawCenteredRegularString(screen, ruleString, + screen.getHeight() * 3 / 10 + + fontRegularMetrics.getHeight() * i + + fontRegularMetrics.getHeight() * 2 * j); + i++; + } + j++; + } + } + + /** + * Draws settings screen + * + * @param screen + * Screen to draw on. + */ + public void drawSettings(final Screen screen) { + String settingsString = "Settings"; + String[] instructionsString1 = {"Use A+D / Arrows", "to change settings", "", "Press space to return", + "and apply changes"}; + int i = 0; + + backBufferGraphics.setColor(Color.GREEN); + drawCenteredBigString(screen, settingsString, screen.getHeight() / 8); + + backBufferGraphics.setColor(Color.GRAY); + for (String instructionsString : instructionsString1) { + drawCenteredRegularString(screen, instructionsString, + (int) (screen.getHeight() / 5 + Math.round(fontRegularMetrics.getHeight() * 1.5 * i))); + i++; + } + + backBufferGraphics.setColor(Color.WHITE); + } + + /** + * Draws settings options + * * @param screen * Screen to draw on. - * @param string - * String to draw. - * @param height - * Height of the drawing. */ + public void drawSettingsOptions(final Screen screen, final int option) { + String screenSizeString = "Screen size"; + String difficultyString = "Difficulty"; + String volumeString = "Volume"; + + if (option == 1) + backBufferGraphics.setColor(Color.GREEN); + else + backBufferGraphics.setColor(Color.WHITE); + drawCenteredRegularString(screen, screenSizeString, + screen.getHeight() * 11 / 20 + fontRegularMetrics.getHeight() * 4); + if (option == 2) + backBufferGraphics.setColor(Color.GREEN); + else + backBufferGraphics.setColor(Color.WHITE); + drawCenteredRegularString(screen, difficultyString, + screen.getHeight() * 11 / 20 + fontRegularMetrics.getHeight() * 6); + if (option == 3) + backBufferGraphics.setColor(Color.GREEN); + else + backBufferGraphics.setColor(Color.WHITE); + drawCenteredRegularString(screen, volumeString, + screen.getHeight() * 11 / 20 + fontRegularMetrics.getHeight() * 8); + } + + /** + * Draws settings options to change + * + * @param screen + * Screen to draw on. + */ + public void drawSettingsChange(final Screen screen, final int option, final int change) { + String screenSizeOption1 = "Standard"; + String screenSizeOption2 = "Extended"; + String screenSizeOption3 = "Full screen"; + String difficultyOption1 = "Easy"; + String difficultyOption2 = "Medium"; + String difficultyOption3 = "Hard"; + String volumeOption1 = "25%"; + String volumeOption2 = "50%"; + String volumeOption3 = "75%"; + String volumeOption4 = "100%"; + String volumeOption5 = "Mute"; + String displayOption = "Nothing to display"; + + + // Screen size + if (option == 1) { + if (change == 1) + displayOption = screenSizeOption1; + if (change == 2) + displayOption = screenSizeOption2; + if (change == 3) + displayOption = screenSizeOption3; + } + // Difficulty + else if (option == 2) { + if (change == 1) + displayOption = difficultyOption1; + if (change == 2) + displayOption = difficultyOption2; + if (change == 3) + displayOption = difficultyOption3; + } + // Volume + else if (option == 3) { + if (change == 1) + displayOption = volumeOption1; + if (change == 2) + displayOption = volumeOption2; + if (change == 3) + displayOption = volumeOption3; + if (change == 4) + displayOption = volumeOption4; + if (change == 5) + displayOption = volumeOption5; + } + // Default + else { + displayOption = "Nothing to display"; + } + + backBufferGraphics.setColor(Color.darkGray); + drawCenteredBigString(screen, displayOption, screen.getHeight() / 2 + fontRegularMetrics.getHeight() * 2); + } + + /** + * Draws a centered string on regular font. + * + * @param screen + * Screen to draw on. + * @param string + * String to draw. + * @param height + * Height of the drawing. + */ public void drawCenteredRegularString(final Screen screen, final String string, final int height) { backBufferGraphics.setFont(fontRegular); @@ -559,4 +730,21 @@ else if (number != 0) drawCenteredBigString(screen, "GO!", screen.getHeight() / 2 + fontBigMetrics.getHeight() / 3); } + + /** + * Shows a pause screen when the game is paused + * + * @param screen + * Screen to draw on. + */ + public void drawPaused(final Screen screen) { + int rectWidth = screen.getWidth(); + int rectHeight = screen.getHeight() / 6; + backBufferGraphics.setColor(Color.BLACK); + backBufferGraphics.fillRect(0, screen.getHeight() / 2 - rectHeight / 2, + rectWidth, rectHeight); + backBufferGraphics.setColor(Color.GREEN); + + drawCenteredBigString(screen, "Paused",screen.getHeight() / 2 + fontBigMetrics.getHeight() / 3); + } } diff --git a/src/engine/FileManager.java b/src/main/java/engine/FileManager.java similarity index 100% rename from src/engine/FileManager.java rename to src/main/java/engine/FileManager.java diff --git a/src/engine/Frame.java b/src/main/java/engine/Frame.java similarity index 84% rename from src/engine/Frame.java rename to src/main/java/engine/Frame.java index b52997a8c..c4183348b 100644 --- a/src/engine/Frame.java +++ b/src/main/java/engine/Frame.java @@ -6,6 +6,8 @@ import screen.Screen; + + /** * Implements a frame to show screens on. * @@ -15,20 +17,24 @@ @SuppressWarnings("serial") public class Frame extends JFrame { - /** Frame width. */ + /** + * Frame width. + */ private int width; - /** Frame height. */ + /** + * Frame height. + */ private int height; - /** Screen currently shown. */ + /** + * Screen currently shown. + */ private Screen currentScreen; /** * Initializes the new frame. - * - * @param width - * Frame width. - * @param height - * Frame height. + * + * @param width Frame width. + * @param height Frame height. */ public Frame(final int width, final int height) { setSize(width, height); @@ -48,9 +54,8 @@ public Frame(final int width, final int height) { /** * Sets current screen. - * - * @param screen - * Screen to show. + * + * @param screen Screen to show. * @return Return code of the finished screen. */ public final int setScreen(final Screen screen) { @@ -61,7 +66,7 @@ public final int setScreen(final Screen screen) { /** * Getter for frame width. - * + * * @return Frame width. */ public final int getWidth() { @@ -70,11 +75,13 @@ public final int getWidth() { /** * Getter for frame height. - * + * * @return Frame height. */ public final int getHeight() { return this.height; } + + } diff --git a/src/engine/GameSettings.java b/src/main/java/engine/GameSettings.java similarity index 100% rename from src/engine/GameSettings.java rename to src/main/java/engine/GameSettings.java diff --git a/src/engine/GameState.java b/src/main/java/engine/GameState.java similarity index 100% rename from src/engine/GameState.java rename to src/main/java/engine/GameState.java diff --git a/src/engine/InputManager.java b/src/main/java/engine/InputManager.java similarity index 100% rename from src/engine/InputManager.java rename to src/main/java/engine/InputManager.java diff --git a/src/engine/MinimalFormatter.java b/src/main/java/engine/MinimalFormatter.java similarity index 100% rename from src/engine/MinimalFormatter.java rename to src/main/java/engine/MinimalFormatter.java diff --git a/src/engine/Score.java b/src/main/java/engine/Score.java similarity index 100% rename from src/engine/Score.java rename to src/main/java/engine/Score.java diff --git a/src/main/java/engine/Sound.java b/src/main/java/engine/Sound.java new file mode 100644 index 000000000..480bc352f --- /dev/null +++ b/src/main/java/engine/Sound.java @@ -0,0 +1,135 @@ +package engine; + +//Responsible for the sounds of the game + +import javax.sound.sampled.*; +import java.io.File; + +public class Sound +{ + + private static float decibels = 0; + + private static Clip musicClip; + + public static void playMusic() //background music class + { + File musicfile = new File("src/main/resources/sounds/music.wav"); + try + { + AudioInputStream Audio = AudioSystem.getAudioInputStream(musicfile); + Clip clip = AudioSystem.getClip(); + clip.open(Audio); + setGain(clip); + clip.start(); + clip.loop(Clip.LOOP_CONTINUOUSLY); + + musicClip = clip; + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + public static void shoot() //shooting sound effect + { + File shot = new File("src/main/resources/sounds/shot.wav"); + try + { + AudioInputStream Audio = AudioSystem.getAudioInputStream(shot); + Clip clip = AudioSystem.getClip(); + clip.open(Audio); + setGain(clip); + clip.start(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + public static void death() //shooting sound effect + { + File dead = new File("src/main/resources/sounds/death.wav"); + try + { + AudioInputStream Audio = AudioSystem.getAudioInputStream(dead); + Clip clip = AudioSystem.getClip(); + clip.open(Audio); + setGain(clip); + clip.start(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + + + public static void enemydeath() //shooting sound effect + { + File bang = new File("src/main/resources/sounds/boom.wav"); + try + { + AudioInputStream Audio = AudioSystem.getAudioInputStream(bang); + Clip clip = AudioSystem.getClip(); + clip.open(Audio); + setGain(clip); + clip.start(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + public static void enemyshot() //shooting sound effect + { + File zap = new File("src/main/resources/sounds/zap.wav"); + try + { + AudioInputStream Audio = AudioSystem.getAudioInputStream(zap); + Clip clip = AudioSystem.getClip(); + clip.open(Audio); + setGain(clip); + clip.start(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + public static void gameover() //shooting sound effect + { + File over = new File("src/main/resources/sounds/go.wav"); + try + { + AudioInputStream Audio = AudioSystem.getAudioInputStream(over); + Clip clip = AudioSystem.getClip(); + clip.open(Audio); + setGain(clip); + clip.start(); + } + catch(Exception e) + { + e.printStackTrace(); + } + } + + public static void stop() { + musicClip.stop(); + } + + public static void setGain(Clip clip) { + FloatControl gainControl = (FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN); + gainControl.setValue(-decibels); // Reduce volume by decibels + } + + public static void setDecibels(float newDecibels) { + decibels = newDecibels; + } + +} diff --git a/src/entity/Bullet.java b/src/main/java/entity/Bullet.java similarity index 100% rename from src/entity/Bullet.java rename to src/main/java/entity/Bullet.java diff --git a/src/entity/BulletPool.java b/src/main/java/entity/BulletPool.java similarity index 98% rename from src/entity/BulletPool.java rename to src/main/java/entity/BulletPool.java index ae74e5606..04abdcfbe 100644 --- a/src/entity/BulletPool.java +++ b/src/main/java/entity/BulletPool.java @@ -1,5 +1,7 @@ package entity; +import engine.Sound; + import java.util.HashSet; import java.util.Set; diff --git a/src/entity/EnemyShip.java b/src/main/java/entity/EnemyShip.java similarity index 77% rename from src/entity/EnemyShip.java rename to src/main/java/entity/EnemyShip.java index 19d9958ad..862d37338 100644 --- a/src/entity/EnemyShip.java +++ b/src/main/java/entity/EnemyShip.java @@ -1,10 +1,12 @@ package entity; import java.awt.Color; +import java.util.HashMap; import engine.Cooldown; import engine.Core; import engine.DrawManager.SpriteType; +import engine.Sound; /** * Implements a enemy ship, to be destroyed by the player. @@ -22,6 +24,13 @@ public class EnemyShip extends Entity { private static final int C_TYPE_POINTS = 30; /** Point value of a bonus enemy. */ private static final int BONUS_TYPE_POINTS = 100; + /** Different health values with their corresponding colors. */ + private static final HashMap HEALTH_COLOR_CODES = + new HashMap(){{ + put(1, Color.WHITE); + put(3, Color.YELLOW); + put(5, Color.BLUE); + }}; /** Cooldown between sprite changes. */ private Cooldown animationCooldown; @@ -29,6 +38,8 @@ public class EnemyShip extends Entity { private boolean isDestroyed; /** Values of the ship, in points, when destroyed. */ private int pointValue; + /** Health value of the ship, when spawned */ + private int health; /** * Constructor, establishes the ship's properties. @@ -39,14 +50,17 @@ public class EnemyShip extends Entity { * Initial position of the ship in the Y axis. * @param spriteType * Sprite type, image corresponding to the ship. + * @param health + * Initial health of the ship. */ public EnemyShip(final int positionX, final int positionY, - final SpriteType spriteType) { - super(positionX, positionY, 12 * 2, 8 * 2, Color.WHITE); + final SpriteType spriteType, final int health) { + super(positionX, positionY, 12 * 2, 8 * 2, HEALTH_COLOR_CODES.get(health)); this.spriteType = spriteType; this.animationCooldown = Core.getCooldown(500); this.isDestroyed = false; + this.health = health; switch (this.spriteType) { case EnemyShipA1: @@ -137,10 +151,21 @@ public final void update() { * Destroys the ship, causing an explosion. */ public final void destroy() { + Sound.enemydeath(); this.isDestroyed = true; this.spriteType = SpriteType.Explosion; } + /** + * Reduces the health of the ship by 1 and changes the + * color of the ship when a specific health was reached. + */ + public final void reduceHealth() { + this.health--; + if (HEALTH_COLOR_CODES.containsKey(this.health)) + this.setColor(HEALTH_COLOR_CODES.get(this.health)); + } + /** * Checks if the ship has been destroyed. * @@ -149,4 +174,13 @@ public final void destroy() { public final boolean isDestroyed() { return this.isDestroyed; } -} + + /** + * Returns the current remaining health. + * + * @return Integer value of the health field. + */ + public final int getHealth() { + return this.health; + } +} \ No newline at end of file diff --git a/src/entity/EnemyShipFormation.java b/src/main/java/entity/EnemyShipFormation.java similarity index 93% rename from src/entity/EnemyShipFormation.java rename to src/main/java/entity/EnemyShipFormation.java index 04bf96326..a8954e386 100644 --- a/src/entity/EnemyShipFormation.java +++ b/src/main/java/entity/EnemyShipFormation.java @@ -7,12 +7,9 @@ import java.util.Set; import java.util.logging.Logger; +import engine.*; import screen.Screen; -import engine.Cooldown; -import engine.Core; -import engine.DrawManager; import engine.DrawManager.SpriteType; -import engine.GameSettings; /** * Groups enemy ships into a formation that moves together. @@ -94,6 +91,14 @@ public class EnemyShipFormation implements Iterable { private List shooters; /** Number of not destroyed ships. */ private int shipCount; + /** Set health of enemy ships. */ + private static int health; + /** Health of enemy ships type A. */ + private static int A_health = 1; + /** Health of enemy ships type B. */ + private static int B_health = 3; + /** Health of enemy ships type C. */ + private static int C_health = 5; /** Directions the formation can move. */ private enum Direction { @@ -103,7 +108,7 @@ private enum Direction { LEFT, /** Movement to the bottom of the screen. */ DOWN - }; + } /** * Constructor, sets the initial conditions. @@ -138,18 +143,24 @@ public EnemyShipFormation(final GameSettings gameSettings) { for (List column : this.enemyShips) { for (int i = 0; i < this.nShipsHigh; i++) { - if (i / (float) this.nShipsHigh < PROPORTION_C) + if (i / (float) this.nShipsHigh < PROPORTION_C) { spriteType = SpriteType.EnemyShipC1; + health = C_health; + } else if (i / (float) this.nShipsHigh < PROPORTION_B - + PROPORTION_C) + + PROPORTION_C) { spriteType = SpriteType.EnemyShipB1; - else + health = B_health; + } + else { spriteType = SpriteType.EnemyShipA1; + health = A_health; + } column.add(new EnemyShip((SEPARATION_DISTANCE * this.enemyShips.indexOf(column)) + positionX, (SEPARATION_DISTANCE * i) - + positionY, spriteType)); + + positionY, spriteType, health)); this.shipCount++; } } @@ -336,6 +347,7 @@ public final void shoot(final Set bullets) { EnemyShip shooter = this.shooters.get(index); if (this.shootingCooldown.checkFinished()) { + Sound.enemyshot(); this.shootingCooldown.reset(); bullets.add(BulletPool.getBullet(shooter.getPositionX() + shooter.width / 2, shooter.getPositionY(), BULLET_SPEED)); @@ -426,4 +438,25 @@ public final Iterator iterator() { public final boolean isEmpty() { return this.shipCount <= 0; } + + /** + * Set health for enemy ships type A. + */ + public static void setA_Health(int newHealth) { + A_health = newHealth; + } + + /** + * Set health for enemy ships type A. + */ + public static void setB_Health(int newHealth) { + B_health = newHealth; + } + + /** + * Set health for enemy ships type A. + */ + public static void setC_Health(int newHealth) { + C_health = newHealth; + } } diff --git a/src/entity/Entity.java b/src/main/java/entity/Entity.java similarity index 94% rename from src/entity/Entity.java rename to src/main/java/entity/Entity.java index 9fe604fdf..7183cd1ba 100644 --- a/src/entity/Entity.java +++ b/src/main/java/entity/Entity.java @@ -57,6 +57,14 @@ public final Color getColor() { return color; } + /** + * Setter for the color of the entity. + * + * @param color + * New color of the entity. + */ + public final void setColor(Color color) { this.color = color; } + /** * Getter for the X axis position of the entity. * diff --git a/src/entity/Ship.java b/src/main/java/entity/Ship.java similarity index 96% rename from src/entity/Ship.java rename to src/main/java/entity/Ship.java index fd007fde1..0f62b2ec6 100644 --- a/src/entity/Ship.java +++ b/src/main/java/entity/Ship.java @@ -6,6 +6,8 @@ import engine.Cooldown; import engine.Core; import engine.DrawManager.SpriteType; +import engine.Sound; +import screen.Shakeframe; /** * Implements a ship, to be controlled by the player. @@ -68,6 +70,7 @@ public final void moveLeft() { */ public final boolean shoot(final Set bullets) { if (this.shootingCooldown.checkFinished()) { + Sound.shoot(); this.shootingCooldown.reset(); bullets.add(BulletPool.getBullet(positionX + this.width / 2, positionY, BULLET_SPEED)); @@ -91,6 +94,9 @@ public final void update() { */ public final void destroy() { this.destructionCooldown.reset(); + + Sound.death(); + Shakeframe.vibrate(); } /** diff --git a/src/screen/GameScreen.java b/src/main/java/screen/GameScreen.java similarity index 72% rename from src/screen/GameScreen.java rename to src/main/java/screen/GameScreen.java index 4e76259d0..9b0589863 100644 --- a/src/screen/GameScreen.java +++ b/src/main/java/screen/GameScreen.java @@ -71,6 +71,10 @@ public class GameScreen extends Screen { /** Checks if a bonus life is received. */ private boolean bonusLife; + boolean paused = false; + private static final int SELECTION_TIME = 200; + private Cooldown selectionCooldown; + /** * Constructor, establishes the properties of the screen. * @@ -78,7 +82,7 @@ public class GameScreen extends Screen { * Current game state. * @param gameSettings * Current game settings. - * @param bonnusLife + * @param bonusLife * Checks if a bonus life is awarded this level. * @param width * Screen width. @@ -101,6 +105,9 @@ public GameScreen(final GameState gameState, this.lives++; this.bulletsShot = gameState.getBulletsShot(); this.shipsDestroyed = gameState.getShipsDestroyed(); + + this.selectionCooldown = Core.getCooldown(SELECTION_TIME); + this.selectionCooldown.reset(); } /** @@ -125,6 +132,10 @@ public final void initialize() { this.gameStartTime = System.currentTimeMillis(); this.inputDelay = Core.getCooldown(INPUT_DELAY); this.inputDelay.reset(); + + this.gameStartTime = System.currentTimeMillis(); + this.inputDelay = Core.getCooldown(INPUT_DELAY); + this.inputDelay.reset(); } /** @@ -141,73 +152,100 @@ public final int run() { return this.returnCode; } + public final boolean isPaused() { + return this.paused; + } + + public final void pause() { + this.paused = !paused; + } /** * Updates the elements on screen and checks for events. */ protected final void update() { super.update(); - if (this.inputDelay.checkFinished() && !this.levelFinished) { + if (this.selectionCooldown.checkFinished() && this.inputDelay.checkFinished()) { + if (inputManager.isKeyDown(KeyEvent.VK_P) && this.isPaused()) { + pause(); + this.logger.info("Game unpaused"); + this.selectionCooldown.reset(); + } else if (inputManager.isKeyDown(KeyEvent.VK_P)) { + pause(); + this.logger.info("Game paused"); + this.selectionCooldown.reset(); + + drawManager.drawPaused(this); + drawManager.drawHorizontalLine(this, this.height / 2 - this.height / 12); + drawManager.drawHorizontalLine(this, this.height / 2 + this.height / 12); + drawManager.completeDrawing(this); + } + } - if (!this.ship.isDestroyed()) { - boolean moveRight = inputManager.isKeyDown(KeyEvent.VK_RIGHT) - || inputManager.isKeyDown(KeyEvent.VK_D); - boolean moveLeft = inputManager.isKeyDown(KeyEvent.VK_LEFT) - || inputManager.isKeyDown(KeyEvent.VK_A); + if(!this.isPaused()) + { + if (this.inputDelay.checkFinished() && !this.levelFinished) { - boolean isRightBorder = this.ship.getPositionX() - + this.ship.getWidth() + this.ship.getSpeed() > this.width - 1; - boolean isLeftBorder = this.ship.getPositionX() - - this.ship.getSpeed() < 1; + if (!this.ship.isDestroyed()) { + boolean moveRight = inputManager.isKeyDown(KeyEvent.VK_RIGHT) + || inputManager.isKeyDown(KeyEvent.VK_D); + boolean moveLeft = inputManager.isKeyDown(KeyEvent.VK_LEFT) + || inputManager.isKeyDown(KeyEvent.VK_A); - if (moveRight && !isRightBorder) { - this.ship.moveRight(); - } - if (moveLeft && !isLeftBorder) { - this.ship.moveLeft(); + boolean isRightBorder = this.ship.getPositionX() + + this.ship.getWidth() + this.ship.getSpeed() > this.width - 1; + boolean isLeftBorder = this.ship.getPositionX() + - this.ship.getSpeed() < 1; + + if (moveRight && !isRightBorder) { + this.ship.moveRight(); + } + if (moveLeft && !isLeftBorder) { + this.ship.moveLeft(); + } + if (inputManager.isKeyDown(KeyEvent.VK_SPACE)) + if (this.ship.shoot(this.bullets)) + this.bulletsShot++; } - if (inputManager.isKeyDown(KeyEvent.VK_SPACE)) - if (this.ship.shoot(this.bullets)) - this.bulletsShot++; - } - if (this.enemyShipSpecial != null) { - if (!this.enemyShipSpecial.isDestroyed()) - this.enemyShipSpecial.move(2, 0); - else if (this.enemyShipSpecialExplosionCooldown.checkFinished()) - this.enemyShipSpecial = null; + if (this.enemyShipSpecial != null) { + if (!this.enemyShipSpecial.isDestroyed()) + this.enemyShipSpecial.move(2, 0); - } - if (this.enemyShipSpecial == null - && this.enemyShipSpecialCooldown.checkFinished()) { - this.enemyShipSpecial = new EnemyShip(); - this.enemyShipSpecialCooldown.reset(); - this.logger.info("A special ship appears"); - } - if (this.enemyShipSpecial != null - && this.enemyShipSpecial.getPositionX() > this.width) { - this.enemyShipSpecial = null; - this.logger.info("The special ship has escaped"); - } + else if (this.enemyShipSpecialExplosionCooldown.checkFinished()) + this.enemyShipSpecial = null; - this.ship.update(); - this.enemyShipFormation.update(); - this.enemyShipFormation.shoot(this.bullets); - } + } + if (this.enemyShipSpecial == null + && this.enemyShipSpecialCooldown.checkFinished()) { + this.enemyShipSpecial = new EnemyShip(); + this.enemyShipSpecialCooldown.reset(); + this.logger.info("A special ship appears"); + } + if (this.enemyShipSpecial != null + && this.enemyShipSpecial.getPositionX() > this.width) { + this.enemyShipSpecial = null; + this.logger.info("The special ship has escaped"); + } - manageCollisions(); - cleanBullets(); - draw(); + this.ship.update(); + this.enemyShipFormation.update(); + this.enemyShipFormation.shoot(this.bullets); + } - if ((this.enemyShipFormation.isEmpty() || this.lives == 0) - && !this.levelFinished) { - this.levelFinished = true; - this.screenFinishedCooldown.reset(); - } + manageCollisions(); + cleanBullets(); + draw(); - if (this.levelFinished && this.screenFinishedCooldown.checkFinished()) - this.isRunning = false; + if ((this.enemyShipFormation.isEmpty() || this.lives == 0) + && !this.levelFinished) { + this.levelFinished = true; + this.screenFinishedCooldown.reset(); + } + if (this.levelFinished && this.screenFinishedCooldown.checkFinished()) + this.isRunning = false; + }//pause } /** @@ -285,9 +323,12 @@ private void manageCollisions() { for (EnemyShip enemyShip : this.enemyShipFormation) if (!enemyShip.isDestroyed() && checkCollision(bullet, enemyShip)) { - this.score += enemyShip.getPointValue(); - this.shipsDestroyed++; - this.enemyShipFormation.destroy(enemyShip); + enemyShip.reduceHealth(); + if (enemyShip.getHealth() == 0) { + this.score += enemyShip.getPointValue(); + this.shipsDestroyed++; + this.enemyShipFormation.destroy(enemyShip); + } recyclable.add(bullet); } if (this.enemyShipSpecial != null diff --git a/src/main/java/screen/HelpScreen.java b/src/main/java/screen/HelpScreen.java new file mode 100644 index 000000000..e78c66bac --- /dev/null +++ b/src/main/java/screen/HelpScreen.java @@ -0,0 +1,64 @@ +package screen; + +import java.awt.event.KeyEvent; +import java.io.IOException; +import java.util.List; + +import engine.Core; +import engine.Score; + +/** + * Implements the help screen, it shows the player instructions on how to play the game. + */ + +public class HelpScreen extends Screen { + /** + * Constructor, establishes the properties of the screen. + * + * @param width + * Screen width. + * @param height + * Screen height. + * @param fps + * Frames per second, frame rate at which the game is run. + */ + public HelpScreen(final int width, final int height, final int fps) { + super(width, height, fps); + + this.returnCode = 1; + } + + /** + * Starts the action. + * + * @return Next screen code. + */ + public final int run() { + super.run(); + + return this.returnCode; + } + + /** + * Updates the elements on screen and checks for events. + */ + protected final void update() { + super.update(); + + draw(); + if (inputManager.isKeyDown(KeyEvent.VK_SPACE) + && this.inputDelay.checkFinished()) + this.isRunning = false; + } + + /** + * Draws the elements associated with the screen. + */ + private void draw() { + drawManager.initDrawing(this); + + drawManager.drawHelp(this); + + drawManager.completeDrawing(this); + } +} \ No newline at end of file diff --git a/src/screen/HighScoreScreen.java b/src/main/java/screen/HighScoreScreen.java similarity index 100% rename from src/screen/HighScoreScreen.java rename to src/main/java/screen/HighScoreScreen.java diff --git a/src/screen/ScoreScreen.java b/src/main/java/screen/ScoreScreen.java similarity index 98% rename from src/screen/ScoreScreen.java rename to src/main/java/screen/ScoreScreen.java index ff215715d..6ec2ee833 100644 --- a/src/screen/ScoreScreen.java +++ b/src/main/java/screen/ScoreScreen.java @@ -5,10 +5,7 @@ import java.util.Collections; import java.util.List; -import engine.Cooldown; -import engine.Core; -import engine.GameState; -import engine.Score; +import engine.*; /** * Implements the score screen. @@ -61,7 +58,7 @@ public class ScoreScreen extends Screen { public ScoreScreen(final int width, final int height, final int fps, final GameState gameState) { super(width, height, fps); - + Sound.gameover(); this.score = gameState.getScore(); this.livesRemaining = gameState.getLivesRemaining(); this.bulletsShot = gameState.getBulletsShot(); diff --git a/src/screen/Screen.java b/src/main/java/screen/Screen.java similarity index 100% rename from src/screen/Screen.java rename to src/main/java/screen/Screen.java diff --git a/src/main/java/screen/SettingsScreen.java b/src/main/java/screen/SettingsScreen.java new file mode 100644 index 000000000..1d3015499 --- /dev/null +++ b/src/main/java/screen/SettingsScreen.java @@ -0,0 +1,243 @@ +package screen; + +import java.awt.*; +import java.awt.event.KeyEvent; +import engine.Cooldown; +import engine.Core; +import engine.Sound; +import entity.EnemyShipFormation; + +import javax.sound.sampled.Clip; + +/** + * Implements the Settings screen, it shows the options to change the settings of the game. + */ + +public class SettingsScreen extends Screen { + /** Number of options in the settings menu. */ + private static final int NO_OF_OPTIONS = 3; + /** Current settings option. */ + private static int settingsOption; + /** Change settings. */ + private static int change; + /** Milliseconds between changes in user selection. */ + private static final int SELECTION_TIME = 200; + /** Time between changes in user selection. */ + private Cooldown selectionCooldown; + /** Get screen size using the Toolkit class */ + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + /** + * Constructor, establishes the properties of the screen. + * + * @param width + * Screen width. + * @param height + * Screen height. + * @param fps + * Frames per second, frame rate at which the game is run. + */ + public SettingsScreen(final int width, final int height, final int fps) { + super(width, height, fps); + + this.returnCode = 1; + this.settingsOption = 1; + this.change = 1; + + this.selectionCooldown = Core.getCooldown(SELECTION_TIME); + this.selectionCooldown.reset(); + } + + /** + * Starts the action. + * + * @return Next screen code. + */ + public final int run() { + super.run(); + + return this.returnCode; + } + + /** + * Updates the elements on screen and checks for events. + */ + protected final void update() { + super.update(); + + draw(); + + if (this.selectionCooldown.checkFinished() + && this.inputDelay.checkFinished()) { + if (inputManager.isKeyDown(KeyEvent.VK_UP) + || inputManager.isKeyDown(KeyEvent.VK_W)) { + previousMenuItem(); + this.change = 1; + this.selectionCooldown.reset(); + } + if (inputManager.isKeyDown(KeyEvent.VK_DOWN) + || inputManager.isKeyDown(KeyEvent.VK_S)) { + nextMenuItem(); + this.change = 1; + this.selectionCooldown.reset(); + } + if (inputManager.isKeyDown(KeyEvent.VK_LEFT) + || inputManager.isKeyDown(KeyEvent.VK_A)) { + previousMenuChange(); + this.selectionCooldown.reset(); + } + if (inputManager.isKeyDown(KeyEvent.VK_RIGHT) + || inputManager.isKeyDown(KeyEvent.VK_D)) { + nextMenuChange(); + this.selectionCooldown.reset(); + } + if (inputManager.isKeyDown(KeyEvent.VK_SPACE)) { + Sound.stop(); + Sound.playMusic(); + this.isRunning = false; + } + + // Change screen size + if (this.settingsOption == 1) { + changeScreenSize(); + } + + // Change difficulty + if (this.settingsOption == 2) { + changeDifficulty(); + } + + // Adjust volume + if (this.settingsOption == 3) { + adjustVolume(); + } + } + } + + /** + * Change difficulty level + */ + private void changeDifficulty() { + if (this.change == 1) { // Easy + EnemyShipFormation.setA_Health(1); + EnemyShipFormation.setB_Health(1); + EnemyShipFormation.setC_Health(1); + } + + if (this.change == 2) { // Medium + EnemyShipFormation.setA_Health(1); + EnemyShipFormation.setB_Health(3); + EnemyShipFormation.setC_Health(5); + } + + if (this.change == 3) { // Hard + EnemyShipFormation.setA_Health(5); + EnemyShipFormation.setB_Health(5); + EnemyShipFormation.setC_Health(5); + } + + } + + /** + * Adjust volume + */ + private void adjustVolume() { + if (this.change == 1) // 25% volume + Sound.setDecibels(40); + if (this.change == 2) // 50% volume + Sound.setDecibels(35); + if (this.change == 3) // 75% volume + Sound.setDecibels(30); + if (this.change == 4) // 100% volume + Sound.setDecibels(0); + if (this.change == 5) // Mute + Sound.setDecibels(100); + } + + /** + * Changes the screen size + */ + private void changeScreenSize() { + if (this.change == 1) // Standard + Core.setSize(448, 520); + else if (this.change == 2) // Extended + Core.setSize(1020,520); + else if (this.change == 3) // Full Screen + Core.setSize(screenSize.width, screenSize.height); + } + + /** + * Shifts the focus to the next menu item. + */ + private void nextMenuItem() { + if (this.settingsOption == NO_OF_OPTIONS) + this.settingsOption = 1; + else if (this.settingsOption == 1) + this.settingsOption = 2; + else + this.settingsOption++; + } + + /** + * Shifts the focus to the previous menu item. + */ + private void previousMenuItem() { + if (this.settingsOption == 1) + this.settingsOption = NO_OF_OPTIONS; + else if (this.settingsOption == 2) + this.settingsOption = 1; + else + this.settingsOption--; + } + + /** + * Shifts the focus to the next change in the settings option. + */ + private void nextMenuChange() { + int no_of_changes = 3; + + if(this.settingsOption == 3) + no_of_changes = 5; + + if (this.change == no_of_changes) + this.change = 1; + else if (this.change == 1) + this.change = 2; + else + this.change++; + } + + /** + * Shifts the focus to the previous change in the settings option. + */ + private void previousMenuChange() { + int no_of_changes; + + if(this.settingsOption == 3) + no_of_changes = 5; + else + no_of_changes = 3; + + if (this.change == 1) + this.change = no_of_changes; + else if (this.change == 2) + this.change = 1; + else + this.change--; + } + + /** + * Draws the elements associated with the screen. + */ + private void draw() { + drawManager.initDrawing(this); + drawManager.drawSettings(this); + drawManager.drawSettingsChange(this, settingsOption, change); + drawManager.drawSettingsOptions(this, settingsOption); + drawManager.completeDrawing(this); + } + + public static int getChange() { + return change; + } +} \ No newline at end of file diff --git a/src/main/java/screen/Shakeframe.java b/src/main/java/screen/Shakeframe.java new file mode 100644 index 000000000..7c994e007 --- /dev/null +++ b/src/main/java/screen/Shakeframe.java @@ -0,0 +1,41 @@ +package screen; + +import static engine.Core.frame; + +public class Shakeframe extends Screen { + + private final static int VIB_LENGTH = 20; + private final static int VIB_VEL = 5; + + /** + * Constructor, establishes the properties of the screen. + * + * @param width Screen width. + * @param height Screen height. + * @param fps + */ + public Shakeframe(int width, int height, int fps) { + super(width, height, fps); + } + + + public static void vibrate() { + try { + final int originalX = frame.getLocationOnScreen().x; + final int originalY = frame.getLocationOnScreen().y; + for(int i = 0; i < VIB_LENGTH; i++) { + Thread.sleep(10); + frame.setLocation(originalX, originalY + VIB_VEL); + Thread.sleep(10); + frame.setLocation(originalX, originalY - VIB_VEL); + Thread.sleep(10); + frame.setLocation(originalX + VIB_VEL, originalY); + Thread.sleep(10); + frame.setLocation(originalX, originalY); + } + } + catch (Exception err) { + err.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/src/screen/TitleScreen.java b/src/main/java/screen/TitleScreen.java similarity index 96% rename from src/screen/TitleScreen.java rename to src/main/java/screen/TitleScreen.java index a8229b463..43e0c7aef 100644 --- a/src/screen/TitleScreen.java +++ b/src/main/java/screen/TitleScreen.java @@ -1,6 +1,7 @@ package screen; import java.awt.event.KeyEvent; +import engine.Sound; import engine.Cooldown; import engine.Core; @@ -77,7 +78,7 @@ protected final void update() { * Shifts the focus to the next menu item. */ private void nextMenuItem() { - if (this.returnCode == 3) + if (this.returnCode == 5) this.returnCode = 0; else if (this.returnCode == 0) this.returnCode = 2; @@ -90,7 +91,7 @@ else if (this.returnCode == 0) */ private void previousMenuItem() { if (this.returnCode == 0) - this.returnCode = 3; + this.returnCode = 5; else if (this.returnCode == 2) this.returnCode = 0; else @@ -108,4 +109,5 @@ private void draw() { drawManager.completeDrawing(this); } + } diff --git a/src/main/resources/font.ttf b/src/main/resources/font.ttf new file mode 100644 index 000000000..4730e4458 Binary files /dev/null and b/src/main/resources/font.ttf differ diff --git a/res/graphics b/src/main/resources/graphics similarity index 100% rename from res/graphics rename to src/main/resources/graphics diff --git a/res/scores b/src/main/resources/scores similarity index 100% rename from res/scores rename to src/main/resources/scores diff --git a/src/main/resources/sounds/boom.wav b/src/main/resources/sounds/boom.wav new file mode 100644 index 000000000..a7ebe875f Binary files /dev/null and b/src/main/resources/sounds/boom.wav differ diff --git a/src/main/resources/sounds/death.wav b/src/main/resources/sounds/death.wav new file mode 100644 index 000000000..a9959c595 Binary files /dev/null and b/src/main/resources/sounds/death.wav differ diff --git a/src/main/resources/sounds/go.wav b/src/main/resources/sounds/go.wav new file mode 100644 index 000000000..3ed6a9d48 Binary files /dev/null and b/src/main/resources/sounds/go.wav differ diff --git a/src/main/resources/sounds/music.wav b/src/main/resources/sounds/music.wav new file mode 100644 index 000000000..54f1819b9 Binary files /dev/null and b/src/main/resources/sounds/music.wav differ diff --git a/src/main/resources/sounds/shot.wav b/src/main/resources/sounds/shot.wav new file mode 100644 index 000000000..1d9d9c3de Binary files /dev/null and b/src/main/resources/sounds/shot.wav differ diff --git a/src/main/resources/sounds/zap.wav b/src/main/resources/sounds/zap.wav new file mode 100644 index 000000000..64db3f0d0 Binary files /dev/null and b/src/main/resources/sounds/zap.wav differ diff --git a/src/test/java/entity/EnemyShipTest.java b/src/test/java/entity/EnemyShipTest.java new file mode 100644 index 000000000..6ef8cf05c --- /dev/null +++ b/src/test/java/entity/EnemyShipTest.java @@ -0,0 +1,40 @@ +package entity; + +import engine.DrawManager.SpriteType; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.awt.*; + +import static org.junit.jupiter.api.Assertions.*; + +class EnemyShipTest { + + EnemyShip testShip; + + @BeforeEach + void setUp() { + // positionX, positionY and spriteType are just placeholders + // they are not necessary for our tests + testShip = new EnemyShip(0, 0, SpriteType.EnemyShipA1, 5); + } + + @Test + void getHealth() { + assertEquals(5, testShip.getHealth()); + } + + @Test + void reduceHealthWithoutColorChange() { + testShip.reduceHealth(); + assertEquals(4, testShip.getHealth()); + } + + @Test + void reduceHealthWithColorChange() { + testShip.reduceHealth(); + testShip.reduceHealth(); + assertEquals(3, testShip.getHealth()); + assertEquals(Color.YELLOW, testShip.getColor()); + } +} \ No newline at end of file diff --git a/src/test/java/entity/EntityTest.java b/src/test/java/entity/EntityTest.java new file mode 100644 index 000000000..614cf5556 --- /dev/null +++ b/src/test/java/entity/EntityTest.java @@ -0,0 +1,31 @@ +package entity; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.awt.*; + +import static org.junit.jupiter.api.Assertions.*; + +class EntityTest { + + Entity testEntity; + + @BeforeEach + void setUp() { + // positionX, positionY, width and height are just placeholders + // they are not necessary for our tests + testEntity = new Entity(0,0,0,0, Color.WHITE); + } + + @Test + void getColor() { + assertEquals(Color.WHITE, testEntity.getColor()); + } + + @Test + void setColor() { + testEntity.setColor(Color.GREEN); + assertEquals(Color.GREEN, testEntity.getColor()); + } +} \ No newline at end of file diff --git a/target/classes/graphics b/target/classes/graphics new file mode 100644 index 000000000..ea318b6a5 --- /dev/null +++ b/target/classes/graphics @@ -0,0 +1,12 @@ +00001111000111110001111100011111000111110111111111111111011111110001111100011111000111110001111100001111 +00000100000000010001001100000011000001111011001100001111001011110000001100101111010010010000010000000011 +100001111110000 +000011111100001 +001110010111100101111010011011101110110011111010111110101110110001101110011110100111100100111001 +001110000111101001111111011011011110110011111010111110101110110001101101011111110111101000111000 +000000000000111000011000101111100110110100111101001111000011110101101101101111100001100000001110 +000000000111100000011101101111100110110000111100001111000011110001101100101111100001110101111000 +000000000000000000011010001111010110100011111100111111000110100000111101000110100000000000000000 +000000000000000000011001001110100110110111111010111110100110110100111010000110010000000000000000 +0000100000110000111100110111011111011111001110100111111011111101110100111110001111100110111001111000011000000100 +0001000100100101000100010100100000101000100000000010001010000010010100010001010010010001000 \ No newline at end of file diff --git a/target/classes/scores b/target/classes/scores new file mode 100644 index 000000000..a4cc05c7a --- /dev/null +++ b/target/classes/scores @@ -0,0 +1,8 @@ +ROB +6500 +PAT +6000 +KOF +5500 +BYR +5000 \ No newline at end of file diff --git a/target/classes/sounds/boom.wav b/target/classes/sounds/boom.wav new file mode 100644 index 000000000..a7ebe875f Binary files /dev/null and b/target/classes/sounds/boom.wav differ diff --git a/target/classes/sounds/death.wav b/target/classes/sounds/death.wav new file mode 100644 index 000000000..a9959c595 Binary files /dev/null and b/target/classes/sounds/death.wav differ diff --git a/target/classes/sounds/go.wav b/target/classes/sounds/go.wav new file mode 100644 index 000000000..3ed6a9d48 Binary files /dev/null and b/target/classes/sounds/go.wav differ diff --git a/target/classes/sounds/music.wav b/target/classes/sounds/music.wav new file mode 100644 index 000000000..54f1819b9 Binary files /dev/null and b/target/classes/sounds/music.wav differ diff --git a/target/classes/sounds/shot.wav b/target/classes/sounds/shot.wav new file mode 100644 index 000000000..1d9d9c3de Binary files /dev/null and b/target/classes/sounds/shot.wav differ diff --git a/target/classes/sounds/zap.wav b/target/classes/sounds/zap.wav new file mode 100644 index 000000000..64db3f0d0 Binary files /dev/null and b/target/classes/sounds/zap.wav differ