Monsters
This commit is contained in:
parent
a6f7aacdfb
commit
7d6094a049
4
ADG5.cpp
4
ADG5.cpp
@ -15,8 +15,6 @@ int main(int argc, char **argv)
|
|||||||
auto console = tcod::Console(80, 50);
|
auto console = tcod::Console(80, 50);
|
||||||
auto params = TCOD_ContextParams{};
|
auto params = TCOD_ContextParams{};
|
||||||
|
|
||||||
int playerx = 40, playery = 25;
|
|
||||||
|
|
||||||
params.console = console.get();
|
params.console = console.get();
|
||||||
params.window_title = "Andrew's Dungeon Game 5";
|
params.window_title = "Andrew's Dungeon Game 5";
|
||||||
params.sdl_window_flags = SDL_WINDOW_RESIZABLE;
|
params.sdl_window_flags = SDL_WINDOW_RESIZABLE;
|
||||||
@ -25,7 +23,7 @@ int main(int argc, char **argv)
|
|||||||
params.argv = argv;
|
params.argv = argv;
|
||||||
|
|
||||||
auto context = tcod::Context(params);
|
auto context = tcod::Context(params);
|
||||||
engine = new Engine(&context, &console);
|
engine = new Engine(80, 50, &context, &console);
|
||||||
engine->init();
|
engine->init();
|
||||||
|
|
||||||
while (engine->update()) {
|
while (engine->update()) {
|
||||||
|
17
Actor.cpp
17
Actor.cpp
@ -1,10 +1,23 @@
|
|||||||
|
#include <cstdio>
|
||||||
#include "libtcod.hpp"
|
#include "libtcod.hpp"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
|
#include "Map.h"
|
||||||
|
#include "Engine.h"
|
||||||
|
#include "Ai.h"
|
||||||
|
#include "Destructible.h"
|
||||||
|
#include "Attacker.h"
|
||||||
|
|
||||||
Actor::Actor(int x, int y, std::string_view ch, const TCOD_ColorRGB& col) :
|
Actor::Actor(int x, int y, std::string_view ch, std::string name, const TCOD_ColorRGB& col) :
|
||||||
x(x), y(y), ch(ch), col(col) {
|
x(x), y(y), ch(ch), col(col), name(name),
|
||||||
|
blocks(true),attacker(nullptr), destructible(nullptr), ai(nullptr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Actor::render(TCOD_Console& cons) const {
|
void Actor::render(TCOD_Console& cons) const {
|
||||||
tcod::print(cons, { x, y }, ch, col, std::nullopt);
|
tcod::print(cons, { x, y }, ch, col, std::nullopt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Actor::update() {
|
||||||
|
if (ai) {
|
||||||
|
ai->update(this);
|
||||||
|
}
|
||||||
|
}
|
12
Actor.h
12
Actor.h
@ -2,12 +2,22 @@
|
|||||||
|
|
||||||
#include "libtcod.hpp"
|
#include "libtcod.hpp"
|
||||||
|
|
||||||
|
class Attacker;
|
||||||
|
class Destructible;
|
||||||
|
class Ai;
|
||||||
|
|
||||||
class Actor {
|
class Actor {
|
||||||
public:
|
public:
|
||||||
int x, y; // position on map
|
int x, y; // position on map
|
||||||
std::string_view ch; // ascii code
|
std::string_view ch; // ascii code
|
||||||
TCOD_ColorRGB col; // color
|
TCOD_ColorRGB col; // color
|
||||||
|
std::string name;
|
||||||
|
bool blocks;
|
||||||
|
Attacker* attacker;
|
||||||
|
Destructible* destructible;
|
||||||
|
Ai* ai;
|
||||||
|
|
||||||
Actor(int x, int y, std::string_view ch, const TCOD_ColorRGB& col);
|
Actor(int x, int y, std::string_view ch, std::string name, const TCOD_ColorRGB& col);
|
||||||
void render(TCOD_Console& cons) const;
|
void render(TCOD_Console& cons) const;
|
||||||
|
void update();
|
||||||
};
|
};
|
129
Ai.cpp
Normal file
129
Ai.cpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#include <SDL3/SDL.h>
|
||||||
|
#include "Ai.h"
|
||||||
|
#include "Actor.h"
|
||||||
|
#include "Engine.h"
|
||||||
|
#include "Map.h"
|
||||||
|
#include "Destructible.h"
|
||||||
|
#include "Attacker.h"
|
||||||
|
|
||||||
|
void PlayerAi::update(Actor* owner) {
|
||||||
|
SDL_Event event;
|
||||||
|
int dx = 0, dy = 0;
|
||||||
|
|
||||||
|
if (owner->destructible && owner->destructible->isDead()) {
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_EVENT_QUIT:
|
||||||
|
engine->gameStatus = Engine::QUIT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
engine->context->convert_event_coordinates(event);
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_EVENT_KEY_DOWN:
|
||||||
|
switch (event.key.key) {
|
||||||
|
case SDLK_UP:
|
||||||
|
dy = -1;
|
||||||
|
break;
|
||||||
|
case SDLK_DOWN:
|
||||||
|
dy = 1;
|
||||||
|
break;
|
||||||
|
case SDLK_LEFT:
|
||||||
|
dx = -1;
|
||||||
|
break;
|
||||||
|
case SDLK_RIGHT:
|
||||||
|
dx = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SDL_EVENT_QUIT:
|
||||||
|
engine->gameStatus = Engine::QUIT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dx != 0 || dy != 0) {
|
||||||
|
engine->gameStatus = Engine::NEW_TURN;
|
||||||
|
if (moveOrAttack(owner, owner->x + dx, owner->y + dy)) {
|
||||||
|
engine->map->computeFov();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayerAi::moveOrAttack(Actor* owner, int targetx, int targety) {
|
||||||
|
if (engine->map->isWall(targetx, targety)) return false;
|
||||||
|
// look for living actors to attack
|
||||||
|
for (Actor** iterator = engine->actors.begin();
|
||||||
|
iterator != engine->actors.end(); iterator++) {
|
||||||
|
Actor* actor = *iterator;
|
||||||
|
if (actor->destructible && !actor->destructible->isDead()
|
||||||
|
&& actor->x == targetx && actor->y == targety) {
|
||||||
|
owner->attacker->attack(owner, actor);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Actor** iterator = engine->actors.begin();
|
||||||
|
iterator != engine->actors.end(); iterator++) {
|
||||||
|
Actor* actor = *iterator;
|
||||||
|
if (actor->destructible && actor->destructible->isDead()
|
||||||
|
&& actor->x == targetx && actor->y == targety) {
|
||||||
|
printf("There's a %s here\n", actor->name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
owner->x = targetx;
|
||||||
|
owner->y = targety;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int TRACKING_TURNS = 3;
|
||||||
|
|
||||||
|
void MonsterAi::update(Actor* owner) {
|
||||||
|
if (owner->destructible && owner->destructible->isDead()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (engine->map->isInFov(owner->x, owner->y)) {
|
||||||
|
// we can see the player. move towards him
|
||||||
|
moveCount = TRACKING_TURNS;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
moveCount--;
|
||||||
|
}
|
||||||
|
if (moveCount > 0) {
|
||||||
|
// we can see the player. move towards him
|
||||||
|
moveOrAttack(owner, engine->player->x, engine->player->y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MonsterAi::moveOrAttack(Actor* owner, int targetx, int targety) {
|
||||||
|
int dx = targetx - owner->x;
|
||||||
|
int dy = targety - owner->y;
|
||||||
|
int stepdx = (dx > 0 ? 1 : -1);
|
||||||
|
int stepdy = (dy > 0 ? 1 : -1);
|
||||||
|
float distance = sqrtf((float)dx * (float)dx + (float)dy * (float)dy);
|
||||||
|
if (distance >= 2) {
|
||||||
|
dx = (int)(round(dx / distance));
|
||||||
|
dy = (int)(round(dy / distance));
|
||||||
|
if (engine->map->canWalk(owner->x + dx, owner->y + dy)) {
|
||||||
|
owner->x += dx;
|
||||||
|
owner->y += dy;
|
||||||
|
}
|
||||||
|
else if (engine->map->canWalk(owner->x + stepdx, owner->y)) {
|
||||||
|
owner->x += stepdx;
|
||||||
|
}
|
||||||
|
else if (engine->map->canWalk(owner->x, owner->y + stepdy)) {
|
||||||
|
owner->y += stepdy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (owner->attacker) {
|
||||||
|
owner->attacker->attack(owner, engine->player);
|
||||||
|
}
|
||||||
|
}
|
25
Ai.h
Normal file
25
Ai.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Actor;
|
||||||
|
|
||||||
|
class Ai {
|
||||||
|
public:
|
||||||
|
virtual void update(Actor* owner) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PlayerAi : public Ai {
|
||||||
|
public:
|
||||||
|
void update(Actor* owner);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool moveOrAttack(Actor* owner, int targetx, int targety);
|
||||||
|
};
|
||||||
|
|
||||||
|
class MonsterAi : public Ai {
|
||||||
|
public:
|
||||||
|
void update(Actor* owner);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int moveCount;
|
||||||
|
void moveOrAttack(Actor* owner, int targetx, int targety);
|
||||||
|
};
|
22
Attacker.cpp
Normal file
22
Attacker.cpp
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "Attacker.h"
|
||||||
|
#include "Actor.h"
|
||||||
|
#include "Destructible.h"
|
||||||
|
|
||||||
|
Attacker::Attacker(float power) : power(power) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Attacker::attack(Actor* owner, Actor* target) {
|
||||||
|
if (target->destructible && !target->destructible->isDead()) {
|
||||||
|
if (power - target->destructible->defense > 0) {
|
||||||
|
printf("%s attacks %s for %g hit points.\n", owner->name.c_str(), target->name.c_str(),
|
||||||
|
power - target->destructible->defense);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("%s attacks %s but it has no effect!\n", owner->name.c_str(), target->name.c_str());
|
||||||
|
}
|
||||||
|
target->destructible->takeDamage(target, power);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("%s attacks %s in vain.\n", owner->name.c_str(), target->name.c_str());
|
||||||
|
}
|
||||||
|
}
|
11
Attacker.h
Normal file
11
Attacker.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Actor;
|
||||||
|
|
||||||
|
class Attacker {
|
||||||
|
public:
|
||||||
|
float power; // hit points given
|
||||||
|
|
||||||
|
Attacker(float power);
|
||||||
|
void attack(Actor* owner, Actor* target);
|
||||||
|
};
|
@ -14,7 +14,7 @@ project ("ADG5")
|
|||||||
find_package(libtcod CONFIG REQUIRED)
|
find_package(libtcod CONFIG REQUIRED)
|
||||||
|
|
||||||
# Add source to this project's executable.
|
# Add source to this project's executable.
|
||||||
add_executable (ADG5 "ADG5.cpp" "ADG5.h" "Actor.cpp" "Actor.h" "Map.h" "Map.cpp" "Engine.h" "Engine.cpp" )
|
add_executable (ADG5 "ADG5.cpp" "ADG5.h" "Actor.cpp" "Actor.h" "Map.h" "Map.cpp" "Engine.h" "Engine.cpp" "Destructible.h" "Destructible.cpp" "Attacker.h" "Attacker.cpp" "Ai.h" "Ai.cpp")
|
||||||
|
|
||||||
target_link_libraries(ADG5
|
target_link_libraries(ADG5
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
52
Destructible.cpp
Normal file
52
Destructible.cpp
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "Destructible.h"
|
||||||
|
#include "Actor.h"
|
||||||
|
#include "Engine.h"
|
||||||
|
|
||||||
|
Destructible::Destructible(float maxHp, float defense, std::string corpseName) :
|
||||||
|
maxHp(maxHp), hp(maxHp), defense(defense), corpseName(corpseName) {
|
||||||
|
}
|
||||||
|
|
||||||
|
float Destructible::takeDamage(Actor* owner, float damage) {
|
||||||
|
damage -= defense;
|
||||||
|
if (damage > 0) {
|
||||||
|
hp -= damage;
|
||||||
|
if (hp <= 0) {
|
||||||
|
die(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
damage = 0;
|
||||||
|
}
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Destructible::die(Actor* owner) {
|
||||||
|
// transform the actor into a corpse!
|
||||||
|
owner->ch = "%";
|
||||||
|
owner->col = TCOD_ColorRGB(100, 0, 0);
|
||||||
|
owner->name = corpseName;
|
||||||
|
owner->blocks = false;
|
||||||
|
// make sure corpses are drawn before living actors
|
||||||
|
engine->sendToBack(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
MonsterDestructible::MonsterDestructible(float maxHp, float defense, std::string corpseName) :
|
||||||
|
Destructible(maxHp, defense, corpseName) {
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerDestructible::PlayerDestructible(float maxHp, float defense, std::string corpseName) :
|
||||||
|
Destructible(maxHp, defense, corpseName) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void MonsterDestructible::die(Actor* owner) {
|
||||||
|
// transform it into a nasty corpse! it doesn't block, can't be
|
||||||
|
// attacked and doesn't move
|
||||||
|
printf("%s is dead\n", owner->name.c_str());
|
||||||
|
Destructible::die(owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerDestructible::die(Actor* owner) {
|
||||||
|
printf("You died!\n");
|
||||||
|
Destructible::die(owner);
|
||||||
|
engine->gameStatus = Engine::DEFEAT;
|
||||||
|
}
|
31
Destructible.h
Normal file
31
Destructible.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
class Actor;
|
||||||
|
|
||||||
|
class Destructible {
|
||||||
|
public:
|
||||||
|
float maxHp; // maximum health points
|
||||||
|
float hp; // current health points
|
||||||
|
float defense; // hit points deflected
|
||||||
|
std::string corpseName; // the actor's name once dead/destroyed
|
||||||
|
|
||||||
|
Destructible(float maxHp, float defense, std::string corpseName);
|
||||||
|
inline bool isDead() { return hp <= 0; }
|
||||||
|
float takeDamage(Actor* owner, float damage);
|
||||||
|
virtual void die(Actor* owner);
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class MonsterDestructible : public Destructible {
|
||||||
|
public:
|
||||||
|
MonsterDestructible(float maxHp, float defense, std::string corpseName);
|
||||||
|
void die(Actor* owner);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PlayerDestructible : public Destructible {
|
||||||
|
public:
|
||||||
|
PlayerDestructible(float maxHp, float defense, std::string corpseName);
|
||||||
|
void die(Actor* owner);
|
||||||
|
};
|
86
Engine.cpp
86
Engine.cpp
@ -3,20 +3,29 @@
|
|||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
#include "Engine.h"
|
#include "Engine.h"
|
||||||
|
#include "Destructible.h"
|
||||||
|
#include "Attacker.h"
|
||||||
|
#include "Ai.h"
|
||||||
|
|
||||||
|
Engine::Engine(int screenWidth, int screenHeight, tcod::Context *context, tcod::Console *console) {
|
||||||
|
|
||||||
Engine::Engine(tcod::Context *context, tcod::Console *console) {
|
|
||||||
this->context = context;
|
this->context = context;
|
||||||
this->console = console;
|
this->console = console;
|
||||||
|
this->screenWidth = screenWidth;
|
||||||
|
this->screenHeight = screenHeight;
|
||||||
|
|
||||||
map = nullptr;
|
map = nullptr;
|
||||||
player = nullptr;
|
player = nullptr;
|
||||||
fovRadius = 10;
|
fovRadius = 10;
|
||||||
computeFov = true;
|
computeFov = true;
|
||||||
|
gameStatus = STARTUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::init() {
|
void Engine::init() {
|
||||||
player = new Actor(40, 25, "@", TCOD_ColorRGB(255, 255, 255));
|
|
||||||
|
player = new Actor(40, 25, "@", "player", TCOD_ColorRGB(255, 255, 255));
|
||||||
|
player->destructible = new PlayerDestructible(30, 2, "player corpse");
|
||||||
|
player->attacker = new Attacker(5);
|
||||||
|
player->ai = new PlayerAi();
|
||||||
actors.push(player);
|
actors.push(player);
|
||||||
map = new Map(80, 45);
|
map = new Map(80, 45);
|
||||||
}
|
}
|
||||||
@ -27,50 +36,21 @@ Engine::~Engine() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Engine::update() {
|
bool Engine::update() {
|
||||||
SDL_Event event;
|
if (gameStatus == STARTUP) map->computeFov();
|
||||||
while (SDL_PollEvent(&event)) {
|
gameStatus = IDLE;
|
||||||
context->convert_event_coordinates(event);
|
|
||||||
switch (event.type) {
|
|
||||||
case SDL_EVENT_KEY_DOWN:
|
|
||||||
switch (event.key.key) {
|
|
||||||
case SDLK_UP:
|
|
||||||
if (!map->isWall(player->x, player->y - 1)) {
|
|
||||||
player->y--;
|
|
||||||
computeFov = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SDLK_DOWN:
|
|
||||||
if (!map->isWall(player->x, player->y + 1)) {
|
|
||||||
player->y++;
|
|
||||||
computeFov = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SDLK_LEFT:
|
|
||||||
if (!map->isWall(player->x - 1, player->y)) {
|
|
||||||
player->x--;
|
|
||||||
computeFov = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SDLK_RIGHT:
|
|
||||||
if (!map->isWall(player->x + 1, player->y)) {
|
|
||||||
player->x++;
|
|
||||||
computeFov = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case SDL_EVENT_QUIT:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (computeFov) {
|
|
||||||
map->computeFov();
|
|
||||||
computeFov = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
player->update();
|
||||||
|
if (gameStatus == NEW_TURN) {
|
||||||
|
for (Actor** iterator = actors.begin(); iterator != actors.end();
|
||||||
|
iterator++) {
|
||||||
|
Actor* actor = *iterator;
|
||||||
|
if (actor != player) {
|
||||||
|
actor->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gameStatus == QUIT) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -84,9 +64,19 @@ void Engine::render() {
|
|||||||
for (Actor** iterator = actors.begin();
|
for (Actor** iterator = actors.begin();
|
||||||
iterator != actors.end(); iterator++) {
|
iterator != actors.end(); iterator++) {
|
||||||
Actor* actor = *iterator;
|
Actor* actor = *iterator;
|
||||||
if (map->isInFov(actor->x, actor->y)) {
|
if (actor != player && map->isInFov(actor->x, actor->y)) {
|
||||||
actor->render(*console);
|
actor->render(*console);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
player->render(*console);
|
||||||
|
|
||||||
|
std::string hp = "HP : " + std::to_string(player->destructible->hp) + "/" + std::to_string(player->destructible->maxHp);
|
||||||
|
|
||||||
|
tcod::print(*console, { 1, 1 }, hp, TCOD_ColorRGB(255, 255, 255), std::nullopt);
|
||||||
context->present(*console);
|
context->present(*console);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::sendToBack(Actor* actor) {
|
||||||
|
actors.remove(actor);
|
||||||
|
actors.insertBefore(actor, 0);
|
||||||
|
}
|
15
Engine.h
15
Engine.h
@ -6,17 +6,30 @@ class Map;
|
|||||||
|
|
||||||
class Engine {
|
class Engine {
|
||||||
public:
|
public:
|
||||||
|
enum GameStatus {
|
||||||
|
STARTUP,
|
||||||
|
IDLE,
|
||||||
|
NEW_TURN,
|
||||||
|
VICTORY,
|
||||||
|
DEFEAT,
|
||||||
|
QUIT
|
||||||
|
} gameStatus;
|
||||||
|
|
||||||
|
int screenWidth;
|
||||||
|
int screenHeight;
|
||||||
|
|
||||||
TCODList<Actor*> actors;
|
TCODList<Actor*> actors;
|
||||||
Actor* player;
|
Actor* player;
|
||||||
Map* map;
|
Map* map;
|
||||||
int fovRadius;
|
int fovRadius;
|
||||||
tcod::Context *context;
|
tcod::Context *context;
|
||||||
tcod::Console* console;
|
tcod::Console* console;
|
||||||
Engine(tcod::Context *context, tcod::Console *console);
|
Engine(int screenWidth, int screenHeight, tcod::Context *context, tcod::Console *console);
|
||||||
void init();
|
void init();
|
||||||
~Engine();
|
~Engine();
|
||||||
bool update();
|
bool update();
|
||||||
void render();
|
void render();
|
||||||
|
void sendToBack(Actor* actor);
|
||||||
private:
|
private:
|
||||||
bool computeFov;
|
bool computeFov;
|
||||||
};
|
};
|
||||||
|
53
Map.cpp
53
Map.cpp
@ -2,9 +2,14 @@
|
|||||||
#include "Map.h"
|
#include "Map.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Engine.h"
|
#include "Engine.h"
|
||||||
|
#include "Destructible.h"
|
||||||
|
#include "Attacker.h"
|
||||||
|
#include "Ai.h"
|
||||||
|
|
||||||
|
|
||||||
static const int ROOM_MAX_SIZE = 12;
|
static const int ROOM_MAX_SIZE = 12;
|
||||||
static const int ROOM_MIN_SIZE = 6;
|
static const int ROOM_MIN_SIZE = 6;
|
||||||
|
static const int MAX_ROOM_MONSTERS = 3;
|
||||||
|
|
||||||
class BspListener : public ITCODBspCallback {
|
class BspListener : public ITCODBspCallback {
|
||||||
private:
|
private:
|
||||||
@ -50,6 +55,21 @@ Map::~Map() {
|
|||||||
delete[] tiles;
|
delete[] tiles;
|
||||||
delete map;
|
delete map;
|
||||||
}
|
}
|
||||||
|
bool Map::canWalk(int x, int y) const {
|
||||||
|
if (isWall(x, y)) {
|
||||||
|
// this is a wall
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (Actor** iterator = engine->actors.begin();
|
||||||
|
iterator != engine->actors.end();iterator++) {
|
||||||
|
Actor* actor = *iterator;
|
||||||
|
if (actor->blocks && actor->x == x && actor->y == y) {
|
||||||
|
// there is an actor there. cannot walk
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Map::isInFov(int x, int y) const {
|
bool Map::isInFov(int x, int y) const {
|
||||||
if (map->isInFov(x, y)) {
|
if (map->isInFov(x, y)) {
|
||||||
@ -122,9 +142,36 @@ void Map::createRoom(bool first, int x1, int y1, int x2, int y2) {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TCODRandom* rng = TCODRandom::getInstance();
|
TCODRandom* rng = TCODRandom::getInstance();
|
||||||
if (rng->getInt(0, 3) == 0) {
|
int nbMonsters = rng->getInt(0, MAX_ROOM_MONSTERS);
|
||||||
engine->actors.push(new Actor((x1 + x2) / 2, (y1 + y2) / 2, "@",
|
while (nbMonsters > 0) {
|
||||||
TCOD_ColorRGB(255, 255, 0)));
|
int x = rng->getInt(x1, x2);
|
||||||
|
int y = rng->getInt(y1, y2);
|
||||||
|
if (canWalk(x, y)) {
|
||||||
|
addMonster(x, y);
|
||||||
|
}
|
||||||
|
nbMonsters--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Map::addMonster(int x, int y) {
|
||||||
|
TCODRandom* rng = TCODRandom::getInstance();
|
||||||
|
if (rng->getInt(0, 100) < 80) {
|
||||||
|
// create an orc
|
||||||
|
Actor* orc = new Actor(x, y, "o", "orc",
|
||||||
|
TCOD_ColorRGB(0, 100, 0));
|
||||||
|
orc->destructible = new MonsterDestructible(10, 0, "dead orc");
|
||||||
|
orc->attacker = new Attacker(3);
|
||||||
|
orc->ai = new MonsterAi();
|
||||||
|
engine->actors.push(orc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// create a troll
|
||||||
|
Actor* troll = new Actor(x, y, "T", "troll",
|
||||||
|
TCOD_ColorRGB(0, 255, 0));
|
||||||
|
troll->destructible = new MonsterDestructible(16, 1, "troll carcass");
|
||||||
|
troll->attacker = new Attacker(4);
|
||||||
|
troll->ai = new MonsterAi();
|
||||||
|
engine->actors.push(troll);
|
||||||
|
}
|
||||||
|
}
|
3
Map.h
3
Map.h
@ -11,6 +11,7 @@ public:
|
|||||||
|
|
||||||
Map(int width, int height);
|
Map(int width, int height);
|
||||||
~Map();
|
~Map();
|
||||||
|
bool canWalk(int x, int y) const;
|
||||||
bool isWall(int x, int y) const;
|
bool isWall(int x, int y) const;
|
||||||
bool isInFov(int x, int y) const;
|
bool isInFov(int x, int y) const;
|
||||||
bool isExplored(int x, int y) const;
|
bool isExplored(int x, int y) const;
|
||||||
@ -22,6 +23,6 @@ protected:
|
|||||||
TCODMap* map;
|
TCODMap* map;
|
||||||
void dig(int x1, int y1, int x2, int y2);
|
void dig(int x1, int y1, int x2, int y2);
|
||||||
void createRoom(bool first, int x1, int y1, int x2, int y2);
|
void createRoom(bool first, int x1, int y1, int x2, int y2);
|
||||||
|
void addMonster(int x, int y);
|
||||||
void setWall(int x, int y);
|
void setWall(int x, int y);
|
||||||
};
|
};
|
Loading…
x
Reference in New Issue
Block a user