From 6122f1d31d8f330894d59b5461b0310eaf3bba22 Mon Sep 17 00:00:00 2001 From: Adrian Hedqvist Date: Thu, 21 Sep 2017 22:17:06 +0200 Subject: [PATCH] Moved fov to its own class, removed it from Actor --- src/Actor.cpp | 15 ----- src/Actor.h | 5 -- src/AttackEnemyNode.cpp | 3 +- src/ExploreNode.cpp | 5 ++ src/FieldOfView.cpp | 135 +++++++++++++++++++++++++++++++++++++ src/FieldOfView.h | 27 ++++++++ src/FieldOfVision.cpp | 65 ------------------ src/FieldOfVision.h | 8 --- src/FleeNode.cpp | 3 +- src/HealFriendNode.cpp | 3 +- src/Hero.cpp | 2 +- src/IfNotSeeEnemyNode.cpp | 3 +- src/IfSeeEnemyNode.cpp | 3 +- src/IfSeeFriendNode.cpp | 3 +- src/Input.cpp | 9 ++- src/PlayState.cpp | 137 +++++++++++++++++++------------------- src/PlayState.h | 3 +- src/RangedAttackNode.cpp | 3 +- src/Tilemap.cpp | 29 ++++++++ src/Tilemap.h | 8 +++ 20 files changed, 295 insertions(+), 174 deletions(-) create mode 100644 src/FieldOfView.cpp create mode 100644 src/FieldOfView.h delete mode 100644 src/FieldOfVision.cpp delete mode 100644 src/FieldOfVision.h diff --git a/src/Actor.cpp b/src/Actor.cpp index 882f81a..6e4f688 100644 --- a/src/Actor.cpp +++ b/src/Actor.cpp @@ -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; diff --git a/src/Actor.h b/src/Actor.h index 3c36cbe..5519738 100644 --- a/src/Actor.h +++ b/src/Actor.h @@ -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(); diff --git a/src/AttackEnemyNode.cpp b/src/AttackEnemyNode.cpp index 622a8e8..d0f9627 100644 --- a/src/AttackEnemyNode.cpp +++ b/src/AttackEnemyNode.cpp @@ -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); } } diff --git a/src/ExploreNode.cpp b/src/ExploreNode.cpp index a4e56a7..c2408ba 100644 --- a/src/ExploreNode.cpp +++ b/src/ExploreNode.cpp @@ -4,12 +4,16 @@ #include "BehaviourTree.h" #include "Actor.h" #include "Tilemap.h" +#include 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 unexplored; @@ -55,4 +59,5 @@ BehaviourTreeStatus ExploreNode::tick(BTTick * tick) { } } return BT_FAILED; + */ } diff --git a/src/FieldOfView.cpp b/src/FieldOfView.cpp new file mode 100644 index 0000000..e9933df --- /dev/null +++ b/src/FieldOfView.cpp @@ -0,0 +1,135 @@ +// +// Created by Adrian on 2017-09-21. +// + +#include +#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; +} diff --git a/src/FieldOfView.h b/src/FieldOfView.h new file mode 100644 index 0000000..ea2175d --- /dev/null +++ b/src/FieldOfView.h @@ -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 diff --git a/src/FieldOfVision.cpp b/src/FieldOfVision.cpp deleted file mode 100644 index bf86916..0000000 --- a/src/FieldOfVision.cpp +++ /dev/null @@ -1,65 +0,0 @@ -#include -#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; - } - } - } - } - } -} diff --git a/src/FieldOfVision.h b/src/FieldOfVision.h deleted file mode 100644 index e09d5e5..0000000 --- a/src/FieldOfVision.h +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/src/FleeNode.cpp b/src/FleeNode.cpp index fc347eb..4ec4661 100644 --- a/src/FleeNode.cpp +++ b/src/FleeNode.cpp @@ -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); } } diff --git a/src/HealFriendNode.cpp b/src/HealFriendNode.cpp index 7b55791..032c974 100644 --- a/src/HealFriendNode.cpp +++ b/src/HealFriendNode.cpp @@ -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); } } diff --git a/src/Hero.cpp b/src/Hero.cpp index a048976..28c08df 100644 --- a/src/Hero.cpp +++ b/src/Hero.cpp @@ -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); } } diff --git a/src/IfNotSeeEnemyNode.cpp b/src/IfNotSeeEnemyNode.cpp index 9665d9f..d3ccf8b 100644 --- a/src/IfNotSeeEnemyNode.cpp +++ b/src/IfNotSeeEnemyNode.cpp @@ -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; } } diff --git a/src/IfSeeEnemyNode.cpp b/src/IfSeeEnemyNode.cpp index 1f23971..5b73288 100644 --- a/src/IfSeeEnemyNode.cpp +++ b/src/IfSeeEnemyNode.cpp @@ -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); } } diff --git a/src/IfSeeFriendNode.cpp b/src/IfSeeFriendNode.cpp index 7cdb7f0..774d293 100644 --- a/src/IfSeeFriendNode.cpp +++ b/src/IfSeeFriendNode.cpp @@ -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); } } diff --git a/src/Input.cpp b/src/Input.cpp index 4e27a9e..938bc45 100644 --- a/src/Input.cpp +++ b/src/Input.cpp @@ -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; diff --git a/src/PlayState.cpp b/src/PlayState.cpp index 10757f4..4ea5458 100644 --- a/src/PlayState.cpp +++ b/src/PlayState.cpp @@ -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"); -} diff --git a/src/PlayState.h b/src/PlayState.h index 89010a5..50f87b6 100644 --- a/src/PlayState.h +++ b/src/PlayState.h @@ -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; diff --git a/src/RangedAttackNode.cpp b/src/RangedAttackNode.cpp index bfe0b95..b66fbe2 100644 --- a/src/RangedAttackNode.cpp +++ b/src/RangedAttackNode.cpp @@ -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); } } diff --git a/src/Tilemap.cpp b/src/Tilemap.cpp index 31e17c0..0c8ff5d 100644 --- a/src/Tilemap.cpp +++ b/src/Tilemap.cpp @@ -1,6 +1,10 @@ #include "Tilemap.h" #include "vec2i.h" #include "Actor.h" +#include "Renderer.h" +#include "Tileset.h" +#include "FieldOfView.h" +#include int Tilemap::GetIndex(int x, int y) { @@ -144,3 +148,28 @@ std::vector Tilemap::GetActors(int x, int y, int range, Actors type) { std::vector* 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"); + } +} diff --git a/src/Tilemap.h b/src/Tilemap.h index 8ad18e8..9a2267c 100644 --- a/src/Tilemap.h +++ b/src/Tilemap.h @@ -1,8 +1,11 @@ #pragma once #include #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 GetActors(int x, int y, int range, Actors type); std::vector* GetActorList();