From a74985844033dd9edff32b3cf4b7c49e96056410 Mon Sep 17 00:00:00 2001 From: Starla Insigna Date: Sun, 3 Jun 2012 19:50:36 -0400 Subject: Added Rat mob Rat is classified as "hostile," so it moves toward the player when it can see the player, otherwise it moves randomly. Rat still cannot yet attack the player. --- .../fourisland/frigidearth/MapViewGameState.java | 217 ++++++++++++++++++++- src/com/fourisland/frigidearth/Mob.java | 1 + src/com/fourisland/frigidearth/mobs/Mouse.java | 1 + src/com/fourisland/frigidearth/mobs/Rat.java | 40 ++++ 4 files changed, 249 insertions(+), 10 deletions(-) create mode 100644 src/com/fourisland/frigidearth/mobs/Rat.java (limited to 'src/com/fourisland') diff --git a/src/com/fourisland/frigidearth/MapViewGameState.java b/src/com/fourisland/frigidearth/MapViewGameState.java index 08bb151..67da9ae 100644 --- a/src/com/fourisland/frigidearth/MapViewGameState.java +++ b/src/com/fourisland/frigidearth/MapViewGameState.java @@ -5,11 +5,15 @@ package com.fourisland.frigidearth; import com.fourisland.frigidearth.mobs.Mouse; +import com.fourisland.frigidearth.mobs.Rat; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.KeyEvent; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Deque; import java.util.List; /** @@ -275,10 +279,15 @@ public class MapViewGameState implements GameState rooms.add(room); // Place mice in random rooms because yolo - if (Functions.random(0, 100) < 25) + int random = Functions.random(0,100); + if (random < 25) { Mob mob = new Mouse(Functions.random(room.getX()+1, room.getX()+room.getWidth()-2), Functions.random(room.getY()+1, room.getY()+room.getHeight()-2)); mobs.add(mob); + } else if (random < 50) + { + Mob mob = new Rat(Functions.random(room.getX()+1, room.getX()+room.getWidth()-2), Functions.random(room.getY()+1, room.getY()+room.getHeight()-2)); + mobs.add(mob); } return true; @@ -594,19 +603,37 @@ public class MapViewGameState implements GameState return; } - // Move mobs randomly + // Move mobs for (Mob mob : mobs) { - Direction toDir = null; - - for (int i=0; i<10; i++) + // If the mob is hostile, it should move toward the player IF IT CAN SEE the player + // Also, if it is adjacent to the player, it should attack + if ((mob.hostile) && (canSeePlayer(mob.x, mob.y))) { - toDir = Direction.getRandomDirection(); - Point to = toDir.to(mob.getPosition()); - if ((isValidPosition(to.x,to.y)) && (!grid[to.x][to.y].isBlocked()) && (!to.equals(new Point(playerx, playery)))) + if (arePointsAdjacent(playerx, playery, mob.x, mob.y)) { - mob.moveInDirection(toDir); - break; + // Attack! + } else { + List path = findPath(mob.getPosition(), new Point(playerx, playery)); + + if (path != null) + { + mob.moveInDirection(path.get(0)); + } + } + } else { + // If the mob isn't hostile, it should just move around randomly + Direction toDir = null; + + for (int i=0; i<10; i++) + { + toDir = Direction.getRandomDirection(); + Point to = toDir.to(mob.getPosition()); + if ((isValidPosition(to.x,to.y)) && (!grid[to.x][to.y].isBlocked()) && (!to.equals(new Point(playerx, playery)))) + { + mob.moveInDirection(toDir); + break; + } } } } @@ -693,4 +720,174 @@ public class MapViewGameState implements GameState messages[MESSAGE_HEIGHT-1] = message; } + + private boolean canSeePlayer(int mx, int my) + { + int dx = playerx - mx; + int dy = playery - my; + int ax = Math.abs(dx) << 1; + int ay = Math.abs(dy) << 1; + int sx = (int) Math.signum(dx); + int sy = (int) Math.signum(dy); + int x = mx; + int y = my; + + if (ax > ay) + { + int t = ay - (ax >> 1); + + do + { + if (t >= 0) + { + y += sy; + t -= ax; + } + + x += sx; + t += ay; + + if ((x == playerx) && (y == playery)) + { + return true; + } + } while (!grid[x][y].isBlocked()); + + return false; + } else { + int t = ax - (ay >> 1); + + do + { + if (t >= 0) + { + x += sx; + t -= ay; + } + + y += sy; + t += ax; + + if ((x == playerx) && (y == playery)) + { + return true; + } + } while (!grid[x][y].isBlocked()); + + return false; + } + } + + private boolean arePointsAdjacent(int px, int py, int mx, int my) + { + if (mx == (px-1)) + { + if (my == (py-1)) return true; + if (my == py) return true; + if (my == (py+1)) return true; + } else if (mx == px) + { + if (my == (py-1)) return true; + if (my == (py+1)) return true; + } else if (mx == (px+1)) + { + if (my == (py-1)) return true; + if (my == py) return true; + if (my == (py+1)) return true; + } + + return false; + } + + private List findPath(Point from, Point to) + { + return findPath(from, to, new ArrayList()); + } + + private List findPath(Point from, Point to, List attempts) + { + /* Iterate over all of the directions and check if moving in that + * direction would result in the destination position. If so, the + * correct path has been acquired and thus we can return. */ + for (Direction d : Direction.values()) + { + Point loc = d.to(from); + if (to.equals(loc)) + { + List moves = new ArrayList(); + moves.add(d); + + return moves; + } + } + + /* Calculate the directions to attempt and the order in which to do so + * based on proximity to the destination */ + List ds = new ArrayList(); + for (Direction d : Direction.values()) + { + Point loc = d.to(from); + if ((isValidPosition(loc.x, loc.y)) && (!grid[loc.x][loc.y].isBlocked())) + { + ds.add(d); + } + } + + List tempd = new ArrayList(); + + if (to.x < from.x) + { + tempd.add(Direction.West); + } else if (to.x > from.x) + { + tempd.add(Direction.East); + } else { + if (!ds.contains(Direction.North) || !ds.contains(Direction.South)) + { + tempd.add(Direction.West); + tempd.add(Direction.East); + } + } + + if (to.y < from.y) + { + tempd.add(Direction.North); + } else if (to.y > from.y) + { + tempd.add(Direction.South); + } else { + if (!ds.contains(Direction.West) || !ds.contains(Direction.East)) + { + tempd.add(Direction.North); + tempd.add(Direction.South); + } + } + + // Remove calculated directions that aren't legal movements + tempd.retainAll(ds); + + // Randomize directions so movement is more fluid + Collections.shuffle(tempd); + + // Iterate over the suggested directions + for (Direction d : tempd) + { + /* If the position in the suggested direction has not already been + * covered, recursively search from the new position */ + Point loc = d.to(from); + if (!attempts.contains(loc)) + { + attempts.add(loc); + + List moves = findPath(loc, to, attempts); + if (moves != null) + { + moves.add(0, d); + return moves; + } + } + } + + return null; + } } diff --git a/src/com/fourisland/frigidearth/Mob.java b/src/com/fourisland/frigidearth/Mob.java index b89831c..412c11e 100644 --- a/src/com/fourisland/frigidearth/Mob.java +++ b/src/com/fourisland/frigidearth/Mob.java @@ -16,6 +16,7 @@ public abstract class Mob public int x; public int y; public int health; + public boolean hostile; public Mob(int x, int y) { diff --git a/src/com/fourisland/frigidearth/mobs/Mouse.java b/src/com/fourisland/frigidearth/mobs/Mouse.java index af9fe44..3430a00 100644 --- a/src/com/fourisland/frigidearth/mobs/Mouse.java +++ b/src/com/fourisland/frigidearth/mobs/Mouse.java @@ -18,6 +18,7 @@ public class Mouse extends Mob super(x, y); health = 1; + hostile = false; } public char getDisplayCharacter() diff --git a/src/com/fourisland/frigidearth/mobs/Rat.java b/src/com/fourisland/frigidearth/mobs/Rat.java new file mode 100644 index 0000000..c2aecd4 --- /dev/null +++ b/src/com/fourisland/frigidearth/mobs/Rat.java @@ -0,0 +1,40 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.fourisland.frigidearth.mobs; + +import com.fourisland.frigidearth.Functions; +import com.fourisland.frigidearth.Mob; +import java.awt.Color; + +/** + * + * @author hatkirby + */ +public class Rat extends Mob +{ + public Rat(int x, int y) + { + super(x, y); + + health = Functions.rollDice(1, 4); + hostile = true; + } + + public char getDisplayCharacter() + { + return 'r'; + } + + public Color getDisplayColor() + { + return Color.GRAY; + } + + public String getName() + { + return "Rat"; + } + +} -- cgit 1.4.1