Legger til en del fremdeles uimplementerte items

This commit is contained in:
Kristian Knarvik 2018-03-10 15:17:50 +01:00
parent 478a8f02a3
commit d1b4f4a316
25 changed files with 433 additions and 58 deletions

View File

@ -73,5 +73,10 @@ c)
# Del C
## Oversikt over designvalg og hva du har gjort
* ... blah, blah, er implementert i klassen [KurtMario](src/inf101/v18/rogue101/player/KurtMario.java), blah, blah `ITurtleShell` ...
*
### Tredjepartsfiler
* Bow Fire Arrow Sound fra http://soundbible.com av Stephan Schutze
* Sword Swing Sound fra http://soundbible.com av Mike Koenig
* Large Fireball Sound fra http://soundbible.com av Mike Koenig

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -88,7 +88,7 @@ public class Main extends Application {
printer.setTextMode(MAIN_TEXT_MODE, true);
// Font with emojis need separate download
// printer.setFont(Printer.FONT_SYMBOLA);
printer.setFont(Printer.FONT_SYMBOLA);
if (grid)
printer.drawCharCells();

View File

@ -14,17 +14,17 @@ import java.util.List;
import java.util.Random;
public class Girl implements INonPlayer {
private String name = randomName();
private Age age = Age.getRandom();
private Personality personality = Personality.getRandom();
private Occupation occupation = Occupation.getRandom();
private final String name = randomName();
private final Age age = Age.getRandom();
private final Personality personality = Personality.getRandom();
private final Occupation occupation = Occupation.getRandom();
private int maxhp;
private int hp;
private int attack;
private int defence;
private int visibility;
private IItem equipped;
private static Random random = new Random();
private static final Random random = new Random();
public Girl() {
setStats();
@ -94,7 +94,7 @@ public class Girl implements INonPlayer {
}
break;
case AFRAID:
if (!NPC.flee(game)) {
if (NPC.flee(game)) {
return;
} else {
attack = true;
@ -129,6 +129,10 @@ public class Girl implements INonPlayer {
}
}
public Occupation getOccupation() {
return occupation;
}
@Override
public int getAttack() {
return attack;
@ -164,6 +168,11 @@ public class Girl implements INonPlayer {
return 8;
}
@Override
public String getPrintSymbol() {
return "𓀠";
}
@Override
public String getSymbol() {
return "G";

View File

@ -5,9 +5,7 @@ import java.util.List;
import inf101.v18.gfx.gfxmode.ITurtle;
import inf101.v18.grid.GridDirection;
import inf101.v18.grid.ILocation;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.objects.IActor;
import inf101.v18.rogue101.objects.IItem;
import inf101.v18.rogue101.objects.INonPlayer;
import inf101.v18.rogue101.shared.NPC;

View File

@ -43,6 +43,12 @@ public class Game implements IGame {
* Useful random generator
*/
private Random random = new Random();
/**
* Saves the last three messages
*/
private List<String> lastMessages = new ArrayList<>();
/**
* The game map. {@link IGameMap} gives us a few more details than
* {@link IMapView} (write access to item lists); the game needs this but
@ -69,7 +75,7 @@ public class Game implements IGame {
// inputGrid will be filled with single-character strings indicating what (if
// anything)
// should be placed at that map square
IGrid<String> inputGrid = MapReader.readFile("maps/level1.txt");
IGrid<String> inputGrid = MapReader.readFile("maps/testmap.txt");
if (inputGrid == null) {
System.err.println("Map not found falling back to builtin map");
inputGrid = MapReader.readString(Main.BUILTIN_MAP);
@ -159,7 +165,7 @@ public class Game implements IGame {
}
// process actors one by one; for the IPlayer, we return and wait for keypresses
// Possible TODO: for INonPlayer, we could also return early (returning
// Possible for INonPlayer, we could also return early (returning
// *false*), and then insert a little timer delay between each non-player move
// (the timer
// is already set up in Main)
@ -179,6 +185,7 @@ public class Game implements IGame {
((INonPlayer) currentActor).doTurn(this);
// remove any dead items from current location
map.clean(currentLocation);
return false;
} else if (currentActor instanceof IPlayer) {
if (currentActor.isDestroyed()) {
// a dead human player gets removed from the game
@ -289,11 +296,23 @@ public class Game implements IGame {
@Override
public void displayMessage(String s) {
// it should be safe to print to lines Main.LINE_MSG1, Main.LINE_MSG2,
// Main.LINE_MSG3
// TODO: you can save the last three lines, and display/scroll them
if (lastMessages.size() >= 3) {
lastMessages.remove(2);
}
lastMessages.add(0, s);
printer.clearLine(Main.LINE_MSG1);
printer.printAt(1, Main.LINE_MSG1, s);
printer.clearLine(Main.LINE_MSG2);
printer.clearLine(Main.LINE_MSG3);
System.out.println(lastMessages.size());
if (lastMessages.size() > 0) {
printer.printAt(1, Main.LINE_MSG1, lastMessages.get(0));
}
if (lastMessages.size() > 1) {
printer.printAt(1, Main.LINE_MSG2, lastMessages.get(1));
}
if (lastMessages.size() > 2) {
printer.printAt(1, Main.LINE_MSG3, lastMessages.get(2));
}
System.out.println("Message: «" + s + "»");
}
@ -425,11 +444,19 @@ public class Game implements IGame {
@Override
public IItem pickUp(IItem item) {
if (item != null && map.has(currentLocation, item)) {
// TODO: bruk getAttack()/getDefence() til å avgjøre om man får til å plukke opp
// tingen
// evt.: en IActor kan bare plukkes opp hvis den har /ingen helsepoeng igjen
map.remove(currentLocation, item);
return item;
if (item instanceof IActor) {
if (item.getCurrentHealth() / item.getMaxHealth() < 3) {
map.remove(currentLocation, item);
return item;
} else {
return null;
}
} else if (currentActor.getAttack() > item.getDefence()) {
map.remove(currentLocation, item);
return item;
} else {
return null;
}
} else {
return null;
}
@ -440,13 +467,13 @@ public class Game implements IGame {
ILocation loc = currentLocation;
int damage = (currentActor.getAttack() + random.nextInt(20) + 1)
/ loc.gridDistanceTo(map.getLocation(target)); //Close attacks will take more damage.
if (damage >= target.getDefence() + 10) {
if (damage >= target.getDefence()) {
int actualDamage = target.handleDamage(this, target, damage);
formatMessage("%s hits %s for %d damage", currentActor.getName(), target.getName(), actualDamage);
} else {
displayMessage("The attack missed.");
}
map.clean(loc);
map.clean(map.getLocation(target));
if (target.isDestroyed() && map.has(currentLocation.go(dir), target)) {
return move(dir);
} else {

View File

@ -0,0 +1,52 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.objects.IItem;
import java.util.Random;
public class Bow implements IRangedWeapon {
private static final Random random = new Random();
private final int damage = 3 + random.nextInt(20);
private final int hp = getMaxHealth();
@Override
public int getWeaponDamage() {
return damage;
}
@Override
public int getCurrentHealth() {
return hp;
}
@Override
public int getDefence() {
return 0;
}
@Override
public int getMaxHealth() {
return 110;
}
@Override
public String getName() {
return "Unknown bow";
}
@Override
public int getSize() {
return 2;
}
@Override
public String getSymbol() {
return "B";
}
@Override
public int handleDamage(IGame game, IItem source, int amount) {
return 0;
}
}

View File

@ -0,0 +1,33 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.objects.IItem;
interface IBuffItem extends IItem {
/**
* Retrieve damage increase done by the buff item.
*
* @return An int, May be 0
*/
int getBuffDamage();
/**
* Retrieve defence increase done by the buff item.
*
* @return An int, May be 0
*/
int getBuffDefence();
/**
* Retrieve defence increase done by the buff item.
*
* @return An int, May be 0
*/
int getBuffDamageReduction();
/**
* Retrieve visibility increase done by the buff item.
*
* @return An int, May be 0
*/
int getBuffVisibility();
}

View File

@ -0,0 +1,9 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.objects.IItem;
public interface IConsumable extends IItem {
void hpIncrease();
void attackIncrease();
void defenceIncrease();
}

View File

@ -0,0 +1,12 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.objects.IItem;
interface IMagicWeapon extends IItem {
/**
* Retrieves the damage points of a weapon.
*
* @return
*/
int getWeaponDamage();
}

View File

@ -0,0 +1,12 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.objects.IItem;
interface IMeleeWeapon extends IItem {
/**
* Retrieves the damage points of a weapon.
*
* @return
*/
int getWeaponDamage();
}

View File

@ -0,0 +1,12 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.objects.IItem;
interface IRangedWeapon extends IItem {
/**
* Retrieves the damage points of a weapon.
*
* @return
*/
int getWeaponDamage();
}

View File

@ -1,12 +1,10 @@
package inf101.v18.rogue101.items;
import inf101.v18.gfx.gfxmode.ITurtle;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.objects.IItem;
import javafx.scene.paint.Color;
public class Manga implements IItem {
int hp = getMaxHealth();
private int hp = getMaxHealth();
/*@Override
public boolean draw(ITurtle painter, double w, double h) {

View File

@ -0,0 +1,63 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.objects.IItem;
public class Shield implements IBuffItem {
private final int hp = getMaxHealth();
@Override
public int getBuffDamage() {
return 0;
}
@Override
public int getBuffDefence() {
return 10;
}
@Override
public int getBuffDamageReduction() {
return 5;
}
@Override
public int getBuffVisibility() {
return 0;
}
@Override
public int getCurrentHealth() {
return hp;
}
@Override
public int getDefence() {
return 0;
}
@Override
public int getMaxHealth() {
return 150;
}
@Override
public String getName() {
return "Unknown shield";
}
@Override
public int getSize() {
return 2;
}
@Override
public String getSymbol() {
return "";
}
@Override
public int handleDamage(IGame game, IItem source, int amount) {
return 0;
}
}

View File

@ -0,0 +1,53 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.objects.IItem;
import java.util.Random;
public class Staff implements IMagicWeapon {
private static final Random random = new Random();
private final int damage = 5 + random.nextInt(25);
private int hp = getMaxHealth();
@Override
public int getWeaponDamage() {
return damage;
}
@Override
public int getCurrentHealth() {
return hp;
}
@Override
public int getDefence() {
return 0;
}
@Override
public int getMaxHealth() {
return 90;
}
@Override
public String getName() {
return "Unknown staff";
}
@Override
public int getSize() {
return 0;
}
@Override
public String getSymbol() {
return "s";
}
@Override
public int handleDamage(IGame game, IItem source, int amount) {
hp -= amount;
return amount;
}
}

View File

@ -0,0 +1,53 @@
package inf101.v18.rogue101.items;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.objects.IItem;
import java.util.Random;
public class Sword implements IMeleeWeapon {
private static final Random random = new Random();
private final int damage = 5 + random.nextInt(25);
private int hp = getMaxHealth();
@Override
public int getWeaponDamage() {
return damage;
}
@Override
public int getCurrentHealth() {
return hp;
}
@Override
public int getDefence() {
return 0;
}
@Override
public int getMaxHealth() {
return 100;
}
@Override
public String getName() {
return "Unknown sword";
}
@Override
public int getSize() {
return 2;
}
@Override
public String getSymbol() {
return "S";
}
@Override
public int handleDamage(IGame game, IItem source, int amount) {
hp -= amount;
return amount;
}
}

View File

@ -0,0 +1,21 @@
50 20
##################################################
# #
# #
# #
# G G #
# #
############### # #
# # #
# # #
# @ ####################### #
# # #
# # #
# # #
# G #
# G #
# #
# #
# #
# G #
##################################################

View File

@ -3,13 +3,14 @@ package inf101.v18.rogue101.objects;
import inf101.v18.grid.GridDirection;
import inf101.v18.grid.ILocation;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.shared.NPC;
import javafx.scene.input.KeyCode;
import java.util.ArrayList;
import java.util.List;
public class Player implements IPlayer {
private int hp = getMaxHealth();
private List<IItem> equipped = new ArrayList<>();
private final List<IItem> equipped = new ArrayList<>();
@Override
public void keyPressed(IGame game, KeyCode key) {
@ -93,6 +94,7 @@ public class Player implements IPlayer {
if (game.canGo(dir)) {
game.move(dir);
} else if (loc.canGo(dir) && game.getMap().hasActors(loc.go(dir))) {
NPC.playSound("audio/Sword Swing-SoundBible.com-639083727.wav");
game.attack(dir, game.getMap().getActors(loc.go(dir)).get(0));
} else {
game.displayMessage("Umm, it is not possible to move in that direction.");
@ -101,12 +103,12 @@ public class Player implements IPlayer {
@Override
public int getAttack() {
return 10;
return 50;
}
@Override
public int getDamage() {
return 10;
return 5;
}
@Override
@ -116,7 +118,7 @@ public class Player implements IPlayer {
@Override
public int getDefence() {
return 1;
return 10;
}
@Override

View File

@ -2,10 +2,15 @@ package inf101.v18.rogue101.shared;
import inf101.v18.grid.GridDirection;
import inf101.v18.grid.ILocation;
import inf101.v18.rogue101.enemies.Girl;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.objects.IActor;
import inf101.v18.rogue101.objects.IItem;
import inf101.v18.rogue101.states.Occupation;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import java.io.File;
import java.util.List;
public class NPC {
@ -24,6 +29,7 @@ public class NPC {
GridDirection dir = game.locationDirection(current, neighbour);
IActor actor = game.getMap().getActors(neighbour).get(0); //We assume there is only one actor.
if (current.gridDistanceTo(neighbour) <= 1 && current.canGo(dir) && game.getMap().has(current.go(dir), actor) && !actor.isDestroyed()) {
playSound("audio/Sword Swing-SoundBible.com-639083727.wav");
game.attack(dir, actor);
return true;
} else if (game.canGo(dir)) {
@ -51,6 +57,14 @@ public class NPC {
GridDirection dir = game.locationDirection(current, neighbour);
IActor actor = game.getMap().getActors(neighbour).get(0); //We assume there is only one actor.
if (current.gridDistanceTo(neighbour) <= range && !actor.isDestroyed()) {
if (game.getActor() instanceof Girl) {
Girl girl = (Girl)game.getActor();
if (girl.getOccupation() == Occupation.BOWSMAN) {
playSound("audio/Bow_Fire_Arrow-Stephan_Schutze-2133929391.wav");
} else if (girl.getOccupation() == Occupation.MAGE) {
playSound("audio/Large Fireball-SoundBible.com-301502490.wav");
}
}
game.rangedAttack(dir, actor);
return true;
} else if (game.canGo(dir)) {
@ -116,4 +130,10 @@ public class NPC {
return GridDirection.WEST;
}
}
public static void playSound(String filename) {
Media sound = new Media(new File(filename).toURI().toString());
MediaPlayer mediaPlayer = new MediaPlayer(sound);
mediaPlayer.play();
}
}

View File

@ -5,7 +5,7 @@ import java.util.Random;
public enum Age {
TODDLER, CHILD, TEEN, ADULT, ELDER;
private static Random random = new Random();
private static final Random random = new Random();
public static Age getRandom() {
return values()[random.nextInt(values().length)];

View File

@ -5,7 +5,7 @@ import java.util.Random;
public enum Occupation {
KNIGHT, MAGE, BOWSMAN;
private static Random random = new Random();
private static final Random random = new Random();
public static Occupation getRandom() {
return values()[random.nextInt(values().length)];

View File

@ -5,7 +5,7 @@ import java.util.Random;
public enum Personality {
AGRESSIVE, CALM, AFRAID;
private static Random random = new Random();
private static final Random random = new Random();
public static Personality getRandom() {
return values()[random.nextInt(values().length)];

View File

@ -11,34 +11,12 @@ import inf101.v18.rogue101.objects.IPlayer;
import javafx.scene.input.KeyCode;
public class PlayerTest {
//Tiny maps in collaboration with Stian J. Husum
private static String NO_WALLS_MAP = "1 1\n"
+ "@\n";
private static String EMPTY_MAP = "5 5\n"
+ "#####\n"
+ "# #\n"
+ "# @ #\n"
+ "# #\n"
+ "#####\n";
private static String RABBIT_MAP = "5 5\n"
+ "#####\n"
+ "#RRR#\n"
+ "#R@R#\n"
+ "#RRR#\n"
+ "#####\n";
private static String CARROT_MAP = "5 5\n"
+ "#####\n"
+ "#CCC#\n"
+ "#C@C#\n"
+ "#CCC#\n"
+ "#####\n";
@Test
public void testOutOfBounds() {
Game game = new Game(NO_WALLS_MAP);
String NO_WALLS_MAP = "1 1\n"
+ "@\n";
Game game = new Game(NO_WALLS_MAP);
IPlayer player = (IPlayer) game.setCurrent(0, 0);
ILocation loc = game.getLocation();
player.keyPressed(game, KeyCode.LEFT);
@ -47,6 +25,12 @@ public class PlayerTest {
@Test
public void testActor() {
String RABBIT_MAP = "5 5\n"
+ "#####\n"
+ "#RRR#\n"
+ "#R@R#\n"
+ "#RRR#\n"
+ "#####\n";
Game game = new Game(RABBIT_MAP);
IPlayer player = (IPlayer) game.setCurrent(2, 2);
ILocation loc = game.getLocation();
@ -62,6 +46,12 @@ public class PlayerTest {
@Test
public void testItem() {
String CARROT_MAP = "5 5\n"
+ "#####\n"
+ "#CCC#\n"
+ "#C@C#\n"
+ "#CCC#\n"
+ "#####\n";
Game game = new Game(CARROT_MAP);
IPlayer player = (IPlayer) game.setCurrent(2, 2);
ILocation loc = game.getLocation();
@ -76,6 +66,12 @@ public class PlayerTest {
@Test
public void testWallsAndKeys() { //This probably seems a little overkill, but we need to check all keys.
String EMPTY_MAP = "5 5\n"
+ "#####\n"
+ "# #\n"
+ "# @ #\n"
+ "# #\n"
+ "#####\n";
Game game = new Game(EMPTY_MAP);
IPlayer player = (IPlayer) game.setCurrent(2, 2);
ILocation loc = game.getLocation();