Fixes a misunderstanding

This commit is contained in:
Kristian Knarvik 2018-03-13 21:35:38 +01:00
parent 3c1eca4d39
commit b88f3c0ef4
9 changed files with 162 additions and 60 deletions

View File

@ -59,18 +59,20 @@ g)
# Del B
## Svar på spørsmål
a)
* Nabo-celler blir behandlet en del annerledes, siden det skal være mulig å finne celler en viss avstand fra et punkt.
Jeg har ikke bestemt meg om hva som er mest praktisk, men denne seminaroppgaven blir fort ganske kaotisk når en skal lete informasjon om celler og naboer.
* Nabo-celler blir behandlet en del annerledes, siden det skal være mulig å finne celler en viss avstand fra et punkt. I tillegg til at alle celler som er utenfor skal ignoreres, og være sortert. Det blir håndtert med en tilsynelatende ganske "skitten" metode, men den fungerer fint.
Måten å gjøre det på i Sem1 er mer praktisk, fordi det tillater å velge hvilket som helst størrelse på nabolaget.
b)
* De fleste spill-trekkene går igjennom game for å enkelt kunne utføre turen til alle objekter.
Fordelene er at det er lett å få tak i all nødvendig informasjon, uten å måtte lage spesialiserte metoder, eller sende inn mange parametere.
Ulempene er at IItem objekter har mindre kontroll. For eksempel; spilleren mister sin tur etter en tast har blitt trykket, uansett om det var en gyldig knapp eller ikke.
Dette gjør det "umulig" å implementere menyer og brukervalg.
Ulempene er at alle IActors og IItem blir veldig sterkt knyttet til IGame. De kan ikke brukes uten å spesifikt opprette et objekt som implementerer IGame først, som forhinder dem i å bli brukt i hvilket som helst annet prosjekt.
c)
* Game.addItem burde strengt tatt sjekket at en IActor ikke blir plassert på en IActor.
d)
* Strukturen er definitivt mye mer kaotisk enn jeg først hadde trodd. Det er egentlig ganske vanskelig å finne det en er ute etter. I tillegg har jeg endret en del, som igjen endrer oppførselen til noen av de gamle klassene.
# Del C
## Oversikt over designvalg og hva du har gjort
* Oversikt over taster: WASD og piltaster kan brukes til bevegelse. Q for å legge ned ting. E for å plukke opp ting. 1-5 for å velge hvilke ting du ønsker å legge ned eller plukke opp.

View File

@ -332,7 +332,8 @@ public class Screen {
private final Map<IPaintLayer, Canvas> layerCanvases = new IdentityHashMap<>();
private final Canvas background;
private final Group root;
private Paint bgColor = Color.CORNFLOWERBLUE;
//private Paint bgColor = Color.CORNFLOWERBLUE;
private Paint bgColor = Color.BROWN;
private int aspect = 0;
private double scaling = 0;
private double currentScale = 1.0;

View File

@ -20,7 +20,7 @@ import javafx.util.Duration;
public class Main extends Application {
// you might want to tune these options
public static final boolean MAIN_USE_BACKGROUND_GRID = true;
public static final boolean MAIN_USE_BACKGROUND_GRID = false;
public static final boolean MAP_AUTO_SCALE_ITEM_DRAW = true;
public static final boolean MAP_DRAW_ONLY_DIRTY_CELLS = false;
public static final TextMode MAIN_TEXT_MODE = TextMode.MODE_80X25;
@ -53,7 +53,7 @@ public class Main extends Application {
private void setup() {
//
game = new Game(this, screen, painter, printer);
game = new Game(screen, painter, printer);
game.draw();
//
@ -133,8 +133,11 @@ public class Main extends Application {
return true;*/ // This interferes with other code
} else {
try {
game.keyPressed(code);
//doTurn();
if (game.keyPressed(code)) {
game.draw();
} else {
doTurn();
}
} catch (Exception e) {
e.printStackTrace();
try {

View File

@ -10,6 +10,7 @@ import inf101.v18.rogue101.states.Age;
import inf101.v18.rogue101.states.Occupation;
import inf101.v18.rogue101.states.Personality;
import java.nio.channels.ClosedSelectorException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -34,6 +35,7 @@ public class Girl implements INonPlayer {
setValidItems();
}
//TODO: Game balance
private void setStats() {
switch (age) {
case TODDLER:
@ -240,6 +242,16 @@ public class Girl implements INonPlayer {
return visibility;
}
@Override
public IItem getItem(Class<?> type) {
for (IItem item : backpack.getContent()) {
if (type.isInstance(item)) {
return item;
}
}
return null;
}
@Override
public int handleDamage(IGame game, IItem source, int amount) {
hp -= amount;

View File

@ -103,6 +103,11 @@ public class Rabbit implements INonPlayer {
return 4;
}
@Override
public IItem getItem(Class<?> type) {
return null;
}
@Override
public String getSymbol() {
return hp > 0 ? "R" : "¤";

View File

@ -19,6 +19,8 @@ import inf101.v18.grid.ILocation;
import inf101.v18.rogue101.Main;
import inf101.v18.rogue101.enemies.Girl;
import inf101.v18.rogue101.examples.Carrot;
import inf101.v18.rogue101.items.IBuffItem;
import inf101.v18.rogue101.items.IWeapon;
import inf101.v18.rogue101.items.Manga;
import inf101.v18.rogue101.examples.Rabbit;
import inf101.v18.rogue101.items.Sword;
@ -62,14 +64,12 @@ public class Game implements IGame {
private final ITurtle painter;
private final Printer printer;
private int numPlayers = 0;
private Main main;
public Game(Main main, Screen screen, ITurtle painter, Printer printer) {
public Game(Screen screen, ITurtle painter, Printer printer) {
this.painter = painter;
this.printer = printer;
addFactory();
this.main = main;
// NOTE: in a more realistic situation, we will have multiple levels (one map
// per level), and (at least for a Roguelike game) the levels should be
@ -121,20 +121,67 @@ public class Game implements IGame {
map.add(currentLocation, item);
}
/**
* Calculates the attack of an IActor based on equipped items.
*
* @return The attack
*/
private int getAttack() {
int damage = currentActor.getAttack() + random.nextInt(20) + 1;
IWeapon weapon = (IWeapon)currentActor.getItem(IWeapon.class);
if (weapon != null) {
damage += weapon.getWeaponDamage();
}
IBuffItem buff = (IBuffItem)currentActor.getItem(IBuffItem.class);
if (buff != null) {
damage += buff.getBuffDamage();
}
return damage;
}
/**
* Gets the defence of the current target.
*
* @param target The target to evaluate
* @return The defence of the target
*/
private int getDefence(IItem target) {
int defence = target.getDefence() + 10;
IActor actor = (IActor) target;
IBuffItem item = (IBuffItem) actor.getItem(IBuffItem.class);
if (item != null) {
defence += item.getBuffDefence();
}
return defence;
}
/**
* Gets the damage done against the current target.
*
* @param target The target to evaluate.
* @return The damage done to the target.
*/
private int getDamage(IItem target) {
int damage = currentActor.getDamage();
IActor actor = (IActor) target;
IBuffItem item = (IBuffItem) actor.getItem(IBuffItem.class);
if (item != null) {
damage -= item.getBuffDamageReduction();
}
return damage;
}
@Override
public ILocation attack(GridDirection dir, IItem target) {
ILocation loc = currentLocation.go(dir);
if (!map.has(loc, target)) {
throw new IllegalMoveException("Target isn't there!");
}
//TODO: Add attack and defence power when appropriate items are equipped.
int damage = currentActor.getAttack() + random.nextInt(20) + 1;
int defence = target.getDefence() + 10;
if (damage >= defence) {
int actualDamage = target.handleDamage(this, target, damage);
if (getAttack() >= getDefence(target)) {
int actualDamage = target.handleDamage(this, target, getDamage(target));
formatMessage("%s hits %s for %d damage", currentActor.getName(), target.getName(), actualDamage);
} else {
displayMessage("The attack missed.");
formatMessage("%s tried to hit %s, but missed", currentActor.getName(), target.getName());
}
map.clean(loc);
@ -147,6 +194,24 @@ public class Game implements IGame {
}
}
@Override
public ILocation rangedAttack(GridDirection dir, IItem target) {
ILocation loc = currentLocation;
if (getAttack() >= getDefence(target)) {
int damage = getDamage(target) / loc.gridDistanceTo(map.getLocation(target));
int actualDamage = target.handleDamage(this, target, damage);
formatMessage("%s hits %s for %d damage", currentActor.getName(), target.getName(), actualDamage);
} else {
formatMessage("%s tried to hit %s, but missed", currentActor.getName(), target.getName());
}
map.clean(map.getLocation(target));
if (target.isDestroyed() && map.has(currentLocation.go(dir), target)) {
return move(dir);
} else {
return currentLocation;
}
}
/**
* Begin a new game turn, or continue to the previous turn
*
@ -424,17 +489,13 @@ public class Game implements IGame {
return map.getWidth();
}
public void keyPressed(KeyCode code) {
public boolean keyPressed(KeyCode code) {
// only an IPlayer/human can handle keypresses, and only if it's the human's
// turn
if (currentActor instanceof IPlayer) {
/*((IPlayer) currentActor).keyPressed(this, code); // do your thing
if (movePoints <= 0)
doTurn(); // proceed with turn if we're out of moves*/
if (((IPlayer) currentActor).keyPressed(this, code)) {
main.doTurn();
}
return !((IPlayer) currentActor).keyPressed(this, code);
}
return true;
}
@Override
@ -470,25 +531,6 @@ public class Game implements IGame {
}
}
@Override
public ILocation rangedAttack(GridDirection dir, IItem target) {
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()) {
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(map.getLocation(target));
if (target.isDestroyed() && map.has(currentLocation.go(dir), target)) {
return move(dir);
} else {
return currentLocation;
}
}
@Override
public ITurtle getPainter() {
return painter;

View File

@ -30,4 +30,11 @@ public interface IActor extends IItem {
default int getVision() {
return 1;
}
/**
* Gets an item of the specified type, if the actor has the item.
*
* @return An IItem or null
*/
IItem getItem(Class<?> type);
}

View File

@ -4,6 +4,8 @@ import inf101.v18.grid.GridDirection;
import inf101.v18.grid.ILocation;
import inf101.v18.rogue101.game.IGame;
import inf101.v18.rogue101.items.Backpack;
import inf101.v18.rogue101.items.IMagicWeapon;
import inf101.v18.rogue101.items.IRangedWeapon;
import inf101.v18.rogue101.shared.NPC;
import javafx.scene.input.KeyCode;
import java.util.ArrayList;
@ -24,16 +26,8 @@ public class Player implements IPlayer {
public boolean keyPressed(IGame game, KeyCode key) {
boolean turnConsumed = false;
if (writing) {
if (key != KeyCode.ENTER) {
text += key.getName();
game.displayMessage("Please enter your name: " + text);
return false;
} else {
name = text;
text = "";
game.displayMessage("Name set.");
writing = false;
}
write(game, key);
return false;
}
if (key == KeyCode.LEFT || key == KeyCode.A) {
tryToMove(game, GridDirection.WEST);
@ -54,7 +48,7 @@ public class Player implements IPlayer {
} else if (key.isDigitKey()) {
//Takes care of all digit keys, but we only use the first 5 for picking up and dropping.
int keyValue = Integer.parseInt(key.getName());
if (keyValue <= 5) {
if (keyValue <= 5 && keyValue > 0) {
if (dropping) {
drop(game, keyValue - 1);
dropping = false;
@ -68,11 +62,37 @@ public class Player implements IPlayer {
} else if (key == KeyCode.N) {
game.displayMessage("Please enter your name: ");
writing = true;
} else if (key == KeyCode.R) {
IItem item = getItem(IRangedWeapon.class);
if (item == null) {
game.displayMessage("You do not have a ranged weapon.");
} else {
turnConsumed = NPC.tryAttackRanged(game, 3);
}
} else if (key == KeyCode.F) {
IItem item = getItem(IMagicWeapon.class);
if (item == null) {
game.displayMessage("You do not have a magic weapon.");
} else {
turnConsumed = NPC.tryAttackRanged(game, 2);
}
}
showStatus(game);
return turnConsumed;
}
private void write(IGame game, KeyCode key) {
if (key != KeyCode.ENTER) {
text += key.getName();
game.displayMessage("Please enter your name: " + text);
} else {
name = text;
text = "";
game.displayMessage("Name set.");
writing = false;
}
}
/**
* Initializes the picking up of an item, and does what is needed.
*
@ -207,7 +227,17 @@ public class Player implements IPlayer {
@Override
public int getDamage() {
return 5;
return 20;
}
@Override
public IItem getItem(Class<?> type) {
for (IItem item : equipped.getContent()) {
if (type.isInstance(item)) {
return item;
}
}
return null;
}
@Override
@ -217,7 +247,7 @@ public class Player implements IPlayer {
@Override
public int getDefence() {
return 10;
return 30;
}
@Override
@ -237,7 +267,7 @@ public class Player implements IPlayer {
@Override
public String getSymbol() {
return "X";
return "@";
}
@Override

View File

@ -23,7 +23,7 @@ public class PlayerTest {
assertEquals(loc, game.getLocation());
}
@Test
/*@Test
public void testActor() {
String RABBIT_MAP = "5 5\n"
+ "#####\n"
@ -42,7 +42,7 @@ public class PlayerTest {
assertEquals(loc, game.getLocation());
player.keyPressed(game, KeyCode.DOWN);
assertEquals(loc, game.getLocation());
}
}*/ //TODO: Fix error when playing sound
@Test
public void testItem() {