Moved fov to its own class, removed it from Actor
This commit is contained in:
parent
35a5a74c97
commit
6122f1d31d
20 changed files with 295 additions and 174 deletions
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
135
src/FieldOfView.cpp
Normal 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
27
src/FieldOfView.h
Normal 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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue