Moved fov to its own class, removed it from Actor

This commit is contained in:
Adrian Hedqvist 2017-09-21 22:17:06 +02:00
parent 35a5a74c97
commit 6122f1d31d
20 changed files with 295 additions and 174 deletions

View file

@ -1,16 +1,10 @@
#include "Actor.h"
#include "Tilemap.h"
#include "BehaviourTree.h"
#include "FieldOfVision.h"
void Actor::CalcFOV() {
FOV::DoFOV(map, vision, ++visioncounter, position.x, position.y, 6);
}
Actor::Actor(Tilemap * map, vec2i pos) {
this->map = map;
position = pos;
vision = new Tilemap(map->GetWidth(), map->GetHeight());
}
const vec2i Actor::getPosition() {
@ -32,7 +26,6 @@ void Actor::Update() {
if (bt) {
bt->tick(this);
CalcFOV();
}
if (health < maxhealth) {
if (healcounter <= 0) {
@ -47,14 +40,6 @@ void Actor::Update() {
}
}
bool Actor::HasSeen(int x, int y) {
return vision->GetTile(x,y) != 0;
}
bool Actor::CanSee(int x, int y) {
return vision->GetTile(x,y) == visioncounter;
}
Actor::~Actor() {
if (bt != nullptr) {
delete bt;

View file

@ -20,8 +20,6 @@ protected:
BehaviourTree* bt;
public:
Tilemap* map;
Tilemap* vision;
int visioncounter;
bool alive;
int health;
int maxhealth;
@ -35,9 +33,6 @@ public:
int GetHealth() { return health; }
void Kill() { alive = false; health = 0; };
void Update();
void CalcFOV();
bool HasSeen(int x, int y);
bool CanSee(int x, int y);
virtual bool isTypeOf(Actors actor){ return actor == ACT_BASE; };
virtual Actors Type() { return ACT_BASE; };
~Actor();

View file

@ -3,6 +3,7 @@
#include "Actor.h"
#include "Tilemap.h"
#include "Pathfinder.h"
#include "FieldOfView.h"
AttackEnemyNode::AttackEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent){}
@ -19,7 +20,7 @@ BehaviourTreeStatus AttackEnemyNode::tick(BTTick * tick) {
if (actor->isTypeOf(ACT_HERO) != ishero) {
vec2i pos = actor->getPosition();
if (tick->target->CanSee(pos.x, pos.y)) {
if (line_of_sight(tick->target->map, tick->target->getPosition(), pos)) {
visibleEnemies.push_back(actor);
}
}

View file

@ -4,12 +4,16 @@
#include "BehaviourTree.h"
#include "Actor.h"
#include "Tilemap.h"
#include <SDL.h>
ExploreNode::ExploreNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent){}
ExploreNode::~ExploreNode() {}
BehaviourTreeStatus ExploreNode::tick(BTTick * tick) {
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Tried to use disabled AutoExplore BehaviourTree node!");
return BT_FAILED;
/*
Pathfinder::DijkstraMap dijkstra;
Tilemap * map = tick->target->map;
std::vector<vec2i> unexplored;
@ -55,4 +59,5 @@ BehaviourTreeStatus ExploreNode::tick(BTTick * tick) {
}
}
return BT_FAILED;
*/
}

135
src/FieldOfView.cpp Normal file
View file

@ -0,0 +1,135 @@
//
// Created by Adrian on 2017-09-21.
//
#include <cmath>
#include "FieldOfView.h"
#include "Tilemap.h"
FieldOfView::FieldOfView(Tilemap *map) {
this->map = map;
seen = new Tilemap(map->GetWidth(), map->GetHeight());
counter = 0;
}
FieldOfView::~FieldOfView() {
delete seen;
}
void FieldOfView::calc(vec2i pos, float range) {
counter++;
seen->SetTile(pos.x, pos.y, counter);
// Once for each octant
cast_light(1, 1.0f, 0.0f, 0, -1, -1, 0, pos.x, pos.y, range);
cast_light(1, 1.0f, 0.0f, -1, 0, 0, -1, pos.x, pos.y, range);
cast_light(1, 1.0f, 0.0f, 0, 1, -1, 0, pos.x, pos.y, range);
cast_light(1, 1.0f, 0.0f, 1, 0, 0, -1, pos.x, pos.y, range);
cast_light(1, 1.0f, 0.0f, 0, -1, 1, 0, pos.x, pos.y, range);
cast_light(1, 1.0f, 0.0f, -1, 0, 0, 1, pos.x, pos.y, range);
cast_light(1, 1.0f, 0.0f, 0, 1, 1, 0, pos.x, pos.y, range);
cast_light(1, 1.0f, 0.0f, 1, 0, 0, 1, pos.x, pos.y, range);
}
bool FieldOfView::can_see(vec2i pos) {
return seen->GetTile(pos.x, pos.y) >= counter;
}
bool FieldOfView::has_seen(vec2i pos) {
return seen->GetTile(pos.x, pos.y) > 0;
}
void FieldOfView::cast_light(int row, float start, float end, int xx, int xy, int yx, int yy, int startX, int startY,
float radius) {
float newStart = 0.0f;
if (start < end) {
return;
}
bool blocked = false;
for (int distance = row; distance <= radius && !blocked; distance++) {
int deltaY = -distance;
for (int deltaX = -distance; deltaX <= 0; deltaX++) {
int currentX = startX + deltaX * xx + deltaY * xy;
int currentY = startY + deltaX * yx + deltaY * yy;
float leftSlope = (deltaX - 0.5f) / (deltaY + 0.5f);
float rightSlope = (deltaX + 0.5f) / (deltaY - 0.5f);
if (!(currentX >= 0 && currentY >= 0 && currentX < map->GetWidth() && currentY < map->GetHeight()) || start < rightSlope) {
continue;
}
else if (end > leftSlope) {
break;
}
if (sqrt(deltaX*deltaX + deltaY*deltaY) <= radius) {
seen->SetTile(currentX, currentY, counter);
}
if (blocked) {
if (map->GetTile(currentX, currentY) == '#') { // TODO: Stop hardcoding tiles
newStart = rightSlope;
continue;
}
else {
blocked = false;
start = newStart;
}
}
else {
if (map->GetTile(currentX, currentY) == '#' && distance < radius) { // TODO: Get rid of hardcoded tiles
blocked = true;
cast_light(distance + 1, start, leftSlope, xx, xy, yx, yy, startX, startY, radius);
newStart = rightSlope;
}
}
}
}
}
bool line_of_sight(Tilemap *map, vec2i start, vec2i end) {
if (start == end) return true;
vec2i delta = end - start;
const char ix = (delta.x > 0) - (delta.x < 0);
const char iy = (delta.y > 0) - (delta.y < 0);
delta.x = std::abs(delta.x) << 1;
delta.y = std::abs(delta.y) << 1;
if (delta.x >= delta.y)
{
// error may go below zero
int error(delta.y - (delta.x >> 1));
while (start.x != end.x && map->GetTile(start.x, start.y) != '#') // TODO: Hardcoded tiles
{
// reduce error, while taking into account the corner case of error == 0
if ((error > 0) || (!error && (ix > 0)))
{
error -= delta.x;
start.y += iy;
}
// else do nothing
error += delta.y;
start.x += ix;
}
}
else
{
// error may go below zero
int error(delta.x - (delta.y >> 1));
while (start.y != end.y && map->GetTile(start.x, start.y) != '#') // TODO: Stop hardcoding tiles
{
// reduce error, while taking into account the corner case of error == 0
if ((error > 0) || (!error && (iy > 0)))
{
error -= delta.y;
start.x += ix;
}
// else do nothing
error += delta.x;
start.y += iy;
}
}
return start == end;
}

27
src/FieldOfView.h Normal file
View file

@ -0,0 +1,27 @@
//
// Created by Adrian on 2017-09-21.
//
#ifndef DUNGEON_FIELDOFVIEW_H
#define DUNGEON_FIELDOFVIEW_H
#include "vec2i.h"
class Tilemap;
class FieldOfView {
Tilemap* map;
unsigned int counter;
void cast_light(int row, float start, float end, int xx, int xy, int yx, int yy, int startX, int startY, float radius);
public:
Tilemap* seen;
explicit FieldOfView(Tilemap* map);
~FieldOfView();
void calc(vec2i pos, float range);
bool can_see(vec2i pos);
bool has_seen(vec2i pos);
};
bool line_of_sight(Tilemap* map, vec2i start, vec2i end);
#endif //DUNGEON_FIELDOFVIEW_H

View file

@ -1,65 +0,0 @@
#include <cmath>
#include "FieldOfVision.h"
#include "Tilemap.h"
namespace FOV {
void DoFOV(Tilemap* map, Tilemap* vision, int visionvalue, int x, int y, float radius) {
vision->SetTile(x, y, visionvalue);
// Once for each octant
CastLight(map, vision, visionvalue, 1, 1.0f, 0.0f, 0, -1, -1, 0, x, y, radius);
CastLight(map, vision, visionvalue, 1, 1.0f, 0.0f, -1, 0, 0, -1, x, y, radius);
CastLight(map, vision, visionvalue, 1, 1.0f, 0.0f, 0, 1, -1, 0, x, y, radius);
CastLight(map, vision, visionvalue, 1, 1.0f, 0.0f, 1, 0, 0, -1, x, y, radius);
CastLight(map, vision, visionvalue, 1, 1.0f, 0.0f, 0, -1, 1, 0, x, y, radius);
CastLight(map, vision, visionvalue, 1, 1.0f, 0.0f, -1, 0, 0, 1, x, y, radius);
CastLight(map, vision, visionvalue, 1, 1.0f, 0.0f, 0, 1, 1, 0, x, y, radius);
CastLight(map, vision, visionvalue, 1, 1.0f, 0.0f, 1, 0, 0, 1, x, y, radius);
}
void CastLight(Tilemap* map, Tilemap* vision, int visioncounter, int row, float start, float end, int xx, int xy, int yx, int yy, int startX, int startY, float radius) {
float newStart = 0.0f;
if (start < end) {
return;
}
bool blocked = false;
for (int distance = row; distance <= radius && !blocked; distance++) {
int deltaY = -distance;
for (int deltaX = -distance; deltaX <= 0; deltaX++) {
int currentX = startX + deltaX * xx + deltaY * xy;
int currentY = startY + deltaX * yx + deltaY * yy;
float leftSlope = (deltaX - 0.5f) / (deltaY + 0.5f);
float rightSlope = (deltaX + 0.5f) / (deltaY - 0.5f);
if (!(currentX >= 0 && currentY >= 0 && currentX < map->GetWidth() && currentY < map->GetHeight()) || start < rightSlope) {
continue;
}
else if (end > leftSlope) {
break;
}
if (sqrt(deltaX*deltaX + deltaY*deltaY) <= radius) {
vision->SetTile(currentX, currentY, visioncounter);
}
if (blocked) {
if (map->GetTile(currentX, currentY) == '#') { // TODO: Stop hardcoding tiles
newStart = rightSlope;
continue;
}
else {
blocked = false;
start = newStart;
}
}
else {
if (map->GetTile(currentX, currentY) == '#' && distance < radius) { // TODO: Get rid of hardcoded tiles
blocked = true;
CastLight(map, vision, visioncounter, distance + 1, start, leftSlope, xx, xy, yx, yy, startX, startY, radius);
newStart = rightSlope;
}
}
}
}
}
}

View file

@ -1,8 +0,0 @@
#pragma once
class Tilemap;
namespace FOV {
void DoFOV(Tilemap* map, Tilemap* vision, int visionvalue, int x, int y, float radius);
void CastLight(Tilemap* map, Tilemap* vision, int visioncounter, int row, float start, float end, int xx, int xy, int yx, int yy, int startX, int startY, float radius);
}

View file

@ -4,6 +4,7 @@
#include "BehaviourTree.h"
#include "Actor.h"
#include "Tilemap.h"
#include "FieldOfView.h"
FleeNode::FleeNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent) {}
@ -20,7 +21,7 @@ BehaviourTreeStatus FleeNode::tick(BTTick * tick) {
for (Actor* actor : *actors) {
if (actor->isTypeOf(ACT_HERO) != ishero) {
vec2i pos = actor->getPosition();
if (tick->target->CanSee(pos.x, pos.y)) {
if (line_of_sight(tick->target->map, tick->target->getPosition(), pos)) {
enemyPos.push_back(pos);
}
}

View file

@ -2,6 +2,7 @@
#include "BehaviourTree.h"
#include "Actor.h"
#include "Tilemap.h"
#include "FieldOfView.h"
HealFriendNode::HealFriendNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent){}
@ -18,7 +19,7 @@ BehaviourTreeStatus HealFriendNode::tick(BTTick * tick) {
if (actor->isTypeOf(ACT_HERO) == ishero && actor->health < actor->maxhealth-1) {
vec2i pos = actor->getPosition();
if (tick->target->CanSee(pos.x, pos.y)) {
if (line_of_sight(tick->target->map, tick->target->getPosition(), pos)) {
friends.push_back(actor);
}
}

View file

@ -22,7 +22,7 @@ Hero::Hero(Tilemap* map, vec2i pos) : Actor(map, pos) {
new AttackEnemyNode(root);
new RestNode(root);
new ExploreNode(root);
//new ExploreNode(root);
new WanderNode(root);
}
}

View file

@ -2,6 +2,7 @@
#include "BehaviourTree.h"
#include "Actor.h"
#include "Tilemap.h"
#include "FieldOfView.h"
IfNotSeeEnemyNode::IfNotSeeEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent) {}
@ -20,7 +21,7 @@ BehaviourTreeStatus IfNotSeeEnemyNode::tick(BTTick * tick) {
if (actor->isTypeOf(ACT_HERO) != ishero) {
vec2i pos = actor->getPosition();
if (tick->target->CanSee(pos.x, pos.y)) {
if (line_of_sight(tick->target->map, tick->target->getPosition(), pos)) {
return BT_FAILED;
}
}

View file

@ -2,6 +2,7 @@
#include "BehaviourTree.h"
#include "Actor.h"
#include "Tilemap.h"
#include "FieldOfView.h"
IfSeeEnemyNode::IfSeeEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent) {}
@ -20,7 +21,7 @@ BehaviourTreeStatus IfSeeEnemyNode::tick(BTTick * tick) {
if (actor->isTypeOf(ACT_HERO) != ishero) {
vec2i pos = actor->getPosition();
if (tick->target->CanSee(pos.x, pos.y)) {
if (line_of_sight(tick->target->map, tick->target->getPosition(), pos)) {
return children[0]->execute(tick);
}
}

View file

@ -2,6 +2,7 @@
#include "BehaviourTree.h"
#include "Actor.h"
#include "Tilemap.h"
#include "FieldOfView.h"
IfSeeFriendNode::IfSeeFriendNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent) {}
@ -21,7 +22,7 @@ BehaviourTreeStatus IfSeeFriendNode::tick(BTTick * tick) {
if (actor->isTypeOf(ACT_HERO) == ishero) {
vec2i pos = actor->getPosition();
if (tick->target->CanSee(pos.x, pos.y)) {
if (line_of_sight(tick->target->map, tick->target->getPosition(), pos)) {
return children[0]->execute(tick);
}
}

View file

@ -25,8 +25,9 @@ void Input::newframe() {
InputEvent Input::setkey(SDL_Keycode key, SDL_Keymod mod, bool pressed)
{
InputEvent event;
InputEvent event{};
event.type = INPUT_KEY_EVENT;
event.action = ACTION_NONE;
event.key_press_event.key = key;
event.key_press_event.mod = mod;
event.pressed = pressed;
@ -82,7 +83,8 @@ InputEvent Input::set_mouse_pos(int x, int y, int dx, int dy) {
mouse_x = x;
mouse_y = y;
InputEvent event;
InputEvent event{};
event.action = ACTION_NONE;
event.type = INPUT_MOUSE_MOVE_EVENT;
event.mouse_move_event.x = x;
event.mouse_move_event.y = y;
@ -95,7 +97,8 @@ InputEvent Input::set_mouse_button(int button, int x, int y, bool pressed) {
mouse_x = x;
mouse_y = y;
InputEvent event;
InputEvent event{};
event.action = ACTION_NONE;
event.type = INPUT_MOUSE_CLICK_EVENT;
event.action = ACTION_NONE;
event.pressed = pressed;

View file

@ -9,6 +9,7 @@
#include "App.h"
#include "Tilemap.h"
#include "Tileset.h"
#include "FieldOfView.h"
#include "imgui.h"
#include "Hero.h"
#include "Goblin.h"
@ -72,6 +73,68 @@ void PlayState::load() {
new_game();
}
void PlayState::new_game() {
paused = true;
if (tilemap != nullptr) {
delete tilemap;
tilemap = nullptr;
hero = nullptr;
}
if (hero != nullptr) {
delete hero;
hero = nullptr;
}
if (fov != nullptr) {
delete fov;
fov = nullptr;
}
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Creating tilemap...\n");
tilemap = new Tilemap(32, 32);
int y = 0;
int x = 0;
for (int i = 0; i < map.length(); i++) {
if (y >= 32) {
break;
}
if (x >= mapwidth) {
y++;
x = 0;
}
if (map[i] == ' ' || map[i] == '\t' || map[i] == '\n') {
continue;
}
if (map[i] == '@') {
hero = new Hero(tilemap, vec2i(x, y));
tilemap->AddActor(hero);
tilemap->SetTile(x, y, '.');
}
else if (map[i] == 'g') {
tilemap->AddActor(new Goblin(tilemap, vec2i(x, y)));
tilemap->SetTile(x, y, '.');
}
else if (map[i] == 's') {
tilemap->AddActor(new Shaman(tilemap, vec2i(x, y)));
tilemap->SetTile(x, y, '.');
}
else {
tilemap->SetTile(x, y, map[i]);
}
x++;
}
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Done.\n");
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Calculating initial FOV...\n");
fov = new FieldOfView(tilemap);
fov->calc(hero->getPosition(), 6);
fov->seen->debug_print();
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Done.\n");
}
Gamestate *PlayState::update(double delta) {
timer += delta;
if (!paused) {
@ -91,6 +154,7 @@ Gamestate *PlayState::update(double delta) {
actors->erase(actors->begin() + i);
}
}
fov->calc(hero->getPosition(), 6);
}
}
return nullptr;
@ -131,22 +195,12 @@ void PlayState::draw(double delta) {
offset.x -= heropos.x * 12;
offset.y -= heropos.y * 12;
for (int x = 0; x < 32; x++) {
for (int y = 0; y < 32; y++) {
if (hero == nullptr || hero->HasSeen(x, y)) {
app->renderer->SetColor(1, 1, 1, 1);
app->renderer->DrawSprite(ascii->GetSprite(tilemap->GetTile(x, y)), offset.x + x * 12, offset.y + y * 12);
if (hero != nullptr && !hero->CanSee(x, y)) {
app->renderer->SetColor(0, 0, 0, .5f);
app->renderer->DrawSprite(ascii->GetSprite(219), offset.x + x * 12, offset.y + y * 12);
}
}
}
}
tilemap->draw(app->renderer, ascii, offset.x, offset.y, fov);
auto actors = tilemap->GetActorList();
for (Actor* var : *actors) {
vec2i pos = var->getPosition();
if (hero == nullptr || hero->CanSee(pos.x, pos.y)) {
if (fov == nullptr || fov->can_see(pos)) {
app->renderer->SetColor(0, 0, 0, 255);
app->renderer->DrawSprite(ascii->GetSprite(219), offset.x + pos.x * 12, offset.y + pos.y * 12);
@ -208,7 +262,7 @@ void PlayState::quit() {
}
void PlayState::inputevent(InputEvent *event) {
if (event->pressed) {
if (event->type == INPUT_KEY_EVENT && event->pressed) {
switch (event->action) {
case ACTION_TOGGLE_DEBUG: debug = !debug; break;
case ACTION_ESCAPE_MENU: paused = !paused; break;
@ -217,58 +271,3 @@ void PlayState::inputevent(InputEvent *event) {
}
}
}
void PlayState::new_game() {
paused = true;
if (tilemap != nullptr) {
delete tilemap;
tilemap = nullptr;
hero = nullptr;
}
if (hero != nullptr) {
delete hero;
hero = nullptr;
}
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Creating tilemap...\n");
tilemap = new Tilemap(32, 32);
int y = 0;
int x = 0;
for (int i = 0; i < map.length(); i++) {
if (y >= 32) {
break;
}
if (x >= mapwidth) {
y++;
x = 0;
}
if (map[i] == ' ' || map[i] == '\t' || map[i] == '\n') {
continue;
}
if (map[i] == '@') {
hero = new Hero(tilemap, vec2i(x, y));
tilemap->AddActor(hero);
tilemap->SetTile(x, y, '.');
}
else if (map[i] == 'g') {
tilemap->AddActor(new Goblin(tilemap, vec2i(x, y)));
tilemap->SetTile(x, y, '.');
}
else if (map[i] == 's') {
tilemap->AddActor(new Shaman(tilemap, vec2i(x, y)));
tilemap->SetTile(x, y, '.');
}
else {
tilemap->SetTile(x, y, map[i]);
}
x++;
}
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Done.\n");
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Calculating initial FOV...\n");
hero->CalcFOV();
SDL_LogVerbose(SDL_LOG_CATEGORY_SYSTEM, "Done.\n");
}

View file

@ -11,12 +11,13 @@
class Tileset;
class Tilemap;
class Actor;
class FieldOfView;
class PlayState : public Gamestate {
Tileset* ascii;
Tilemap* tilemap;
Actor * hero;
FieldOfView *fov;
float delay = .5;
double timer;

View file

@ -2,6 +2,7 @@
#include "BehaviourTree.h"
#include "Actor.h"
#include "Tilemap.h"
#include "FieldOfView.h"
RangedAttackNode::RangedAttackNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent) {}
@ -22,7 +23,7 @@ BehaviourTreeStatus RangedAttackNode::tick(BTTick * tick) {
if (actor->isTypeOf(ACT_HERO) != ishero) {
vec2i pos = actor->getPosition();
if (tick->target->CanSee(pos.x, pos.y)) {
if (line_of_sight(tick->target->map, tick->target->getPosition(), pos)) {
enemies.push_back(actor);
}
}

View file

@ -1,6 +1,10 @@
#include "Tilemap.h"
#include "vec2i.h"
#include "Actor.h"
#include "Renderer.h"
#include "Tileset.h"
#include "FieldOfView.h"
#include <SDL.h>
int Tilemap::GetIndex(int x, int y)
{
@ -144,3 +148,28 @@ std::vector<Actor*> Tilemap::GetActors(int x, int y, int range, Actors type) {
std::vector<Actor*>* Tilemap::GetActorList() {
return &actors;
}
void Tilemap::draw(Renderer *renderer, Tileset* tileset, int ox, int oy, FieldOfView* view) {
for (int x = 0; x < 32; x++) {
for (int y = 0; y < 32; y++) {
if (view == nullptr || view->has_seen({x, y})) {
renderer->SetColor(1, 1, 1, 1);
renderer->DrawSprite(tileset->GetSprite(GetTile(x, y)), ox + x * 12, oy + y * 12);
if (view != nullptr && !view->can_see({x, y})) {
renderer->SetColor(0, 0, 0, .5f);
renderer->DrawSprite(tileset->GetSprite(219), ox + x * 12, oy + y * 12);
}
}
}
}
}
void Tilemap::debug_print() {
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
printf("\t%d", GetTile(x, y));
}
printf("\n");
}
}

View file

@ -1,8 +1,11 @@
#pragma once
#include <vector>
#include "Actor.h"
#include "Tileset.h"
struct vec2i;
class Renderer;
class FieldOfView;
class Tilemap {
unsigned int* tilemap;
@ -21,8 +24,13 @@ public:
int GetTile(int x, int y);
bool IsBlocked(int x, int y); // Checks if there is an actor blocking the tile.
void draw(Renderer *renderer, Tileset *tileset, int x, int y, FieldOfView* view);
void AddActor(Actor* actor);
void RemoveActor(Actor* actor);
void debug_print();
Actor* GetActor(int x, int y, Actors type);
std::vector<Actor*> GetActors(int x, int y, int range, Actors type);
std::vector<Actor*>* GetActorList();