/** * Move the player or open closed doors, remove any monsters the player bumped, then update the * DijkstraMap and have the monsters that can see the player try to approach. In a fully-fledged * game, this would not be organized like this, but this is a one-file demo. * * @param xmod * @param ymod */ private void move(int xmod, int ymod) { clearHelp(); if (health <= 0) return; int newX = player.gridX + xmod, newY = player.gridY + ymod; if (newX >= 0 && newY >= 0 && newX < width && newY < height && bareDungeon[newX][newY] != '#') { // '+' is a door. if (decoDungeon[newX][newY] == '+') { decoDungeon[newX][newY] = '/'; lineDungeon[newX * 2][newY] = '/'; // changes to the map mean the resistances for FOV need to be regenerated. res = DungeonUtility.generateResistances(decoDungeon); // recalculate FOV, store it in fovmap for the render to use. fovmap = fov.calculateFOV(res, player.gridX, player.gridY, 8, Radius.SQUARE); } else { // recalculate FOV, store it in fovmap for the render to use. fovmap = fov.calculateFOV(res, newX, newY, 8, Radius.SQUARE); display.slide(player, newX, newY); monsters.remove(Coord.get(newX, newY)); } if (newX == dungeonGen.stairsDown.x && newY == dungeonGen.stairsDown.y) { messages.appendMessage("WINNER WINNER CHICKEN DINNER!"); } phase = Phase.PLAYER_ANIM; } }
private void postMove() { phase = Phase.MONSTER_ANIM; // The next two lines are important to avoid monsters treating cells the player WAS in as goals. getToPlayer.clearGoals(); getToPlayer.resetMap(); // now that goals are cleared, we can mark the current player position as a goal. getToPlayer.setGoal(player.gridX, player.gridY); // this is an important piece of DijkstraMap usage; the argument is a Set of Points for squares // that // temporarily cannot be moved through (not walls, which are automatically known because the map // char[][] // was passed to the DijkstraMap constructor, but things like moving creatures and objects). LinkedHashSet<Coord> monplaces = monsters.positions(); pathMap = getToPlayer.scan(monplaces); // recalculate FOV, store it in fovmap for the render to use. fovmap = fov.calculateFOV(res, player.gridX, player.gridY, 8, Radius.SQUARE); // handle monster turns ArrayList<Coord> nextMovePositions = new ArrayList<Coord>(25); for (Coord pos : monsters.positions()) { Monster mon = monsters.get(pos); // monster values are used to store their aggression, 1 for actively stalking the player, 0 // for not. if (mon.state > 0 || fovmap[pos.x][pos.y] > 0.1) { if (mon.state == 0) { messages.appendMessage( "The PHANTOM cackles at you, \"" + FakeLanguageGen.RUSSIAN_AUTHENTIC.sentence( rng, 1, 3, new String[] {",", ",", ",", " -"}, new String[] {"!"}, 0.25) + "\""); } // this block is used to ensure that the monster picks the best path, or a random choice if // there // is more than one equally good best option. Direction choice = null; double best = 9999.0; Direction[] ds = new Direction[8]; rng.shuffle(Direction.OUTWARDS, ds); for (Direction d : ds) { Coord tmp = pos.translate(d); if (pathMap[tmp.x][tmp.y] < best && !checkOverlap(mon, tmp.x, tmp.y, nextMovePositions)) { // pathMap is a 2D array of doubles where 0 is the goal (the player). // we use best to store which option is closest to the goal. best = pathMap[tmp.x][tmp.y]; choice = d; } } if (choice != null) { Coord tmp = pos.translate(choice); // if we would move into the player, instead damage the player and give newMons the // current // position of this monster. if (tmp.x == player.gridX && tmp.y == player.gridY) { display.tint(player.gridX * 2, player.gridY, SColor.PURE_CRIMSON, 0, 0.415f); display.tint(player.gridX * 2 + 1, player.gridY, SColor.PURE_CRIMSON, 0, 0.415f); health--; // player.setText("" + health); monsters.positionalModify(pos, mon.change(1)); } // otherwise store the new position in newMons. else { /*if (fovmap[mon.getKey().x][mon.getKey().y] > 0.0) { display.put(mon.getKey().x, mon.getKey().y, 'M', 11); }*/ nextMovePositions.add(tmp); monsters.positionalModify(pos, mon.change(1)); monsters.move(pos, tmp); display.slide(mon.entity, tmp.x, tmp.y); } } else { monsters.positionalModify(pos, mon.change(1)); } } } }