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 "Actor.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
#include "BehaviourTree.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) {
|
Actor::Actor(Tilemap * map, vec2i pos) {
|
||||||
this->map = map;
|
this->map = map;
|
||||||
position = pos;
|
position = pos;
|
||||||
vision = new Tilemap(map->GetWidth(), map->GetHeight());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const vec2i Actor::getPosition() {
|
const vec2i Actor::getPosition() {
|
||||||
|
@ -32,7 +26,6 @@ void Actor::Update() {
|
||||||
|
|
||||||
if (bt) {
|
if (bt) {
|
||||||
bt->tick(this);
|
bt->tick(this);
|
||||||
CalcFOV();
|
|
||||||
}
|
}
|
||||||
if (health < maxhealth) {
|
if (health < maxhealth) {
|
||||||
if (healcounter <= 0) {
|
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() {
|
Actor::~Actor() {
|
||||||
if (bt != nullptr) {
|
if (bt != nullptr) {
|
||||||
delete bt;
|
delete bt;
|
||||||
|
|
|
@ -20,8 +20,6 @@ protected:
|
||||||
BehaviourTree* bt;
|
BehaviourTree* bt;
|
||||||
public:
|
public:
|
||||||
Tilemap* map;
|
Tilemap* map;
|
||||||
Tilemap* vision;
|
|
||||||
int visioncounter;
|
|
||||||
bool alive;
|
bool alive;
|
||||||
int health;
|
int health;
|
||||||
int maxhealth;
|
int maxhealth;
|
||||||
|
@ -35,9 +33,6 @@ public:
|
||||||
int GetHealth() { return health; }
|
int GetHealth() { return health; }
|
||||||
void Kill() { alive = false; health = 0; };
|
void Kill() { alive = false; health = 0; };
|
||||||
void Update();
|
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 bool isTypeOf(Actors actor){ return actor == ACT_BASE; };
|
||||||
virtual Actors Type() { return ACT_BASE; };
|
virtual Actors Type() { return ACT_BASE; };
|
||||||
~Actor();
|
~Actor();
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
#include "Pathfinder.h"
|
#include "Pathfinder.h"
|
||||||
|
#include "FieldOfView.h"
|
||||||
|
|
||||||
AttackEnemyNode::AttackEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent){}
|
AttackEnemyNode::AttackEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent){}
|
||||||
|
|
||||||
|
@ -19,7 +20,7 @@ BehaviourTreeStatus AttackEnemyNode::tick(BTTick * tick) {
|
||||||
|
|
||||||
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
||||||
vec2i pos = actor->getPosition();
|
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);
|
visibleEnemies.push_back(actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,16 @@
|
||||||
#include "BehaviourTree.h"
|
#include "BehaviourTree.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
ExploreNode::ExploreNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent){}
|
ExploreNode::ExploreNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent){}
|
||||||
|
|
||||||
ExploreNode::~ExploreNode() {}
|
ExploreNode::~ExploreNode() {}
|
||||||
|
|
||||||
BehaviourTreeStatus ExploreNode::tick(BTTick * tick) {
|
BehaviourTreeStatus ExploreNode::tick(BTTick * tick) {
|
||||||
|
SDL_LogWarn(SDL_LOG_CATEGORY_APPLICATION, "Tried to use disabled AutoExplore BehaviourTree node!");
|
||||||
|
return BT_FAILED;
|
||||||
|
/*
|
||||||
Pathfinder::DijkstraMap dijkstra;
|
Pathfinder::DijkstraMap dijkstra;
|
||||||
Tilemap * map = tick->target->map;
|
Tilemap * map = tick->target->map;
|
||||||
std::vector<vec2i> unexplored;
|
std::vector<vec2i> unexplored;
|
||||||
|
@ -55,4 +59,5 @@ BehaviourTreeStatus ExploreNode::tick(BTTick * tick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return BT_FAILED;
|
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 "BehaviourTree.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
|
#include "FieldOfView.h"
|
||||||
|
|
||||||
|
|
||||||
FleeNode::FleeNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent) {}
|
FleeNode::FleeNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent) {}
|
||||||
|
@ -20,7 +21,7 @@ BehaviourTreeStatus FleeNode::tick(BTTick * tick) {
|
||||||
for (Actor* actor : *actors) {
|
for (Actor* actor : *actors) {
|
||||||
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
||||||
vec2i pos = actor->getPosition();
|
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);
|
enemyPos.push_back(pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "BehaviourTree.h"
|
#include "BehaviourTree.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
|
#include "FieldOfView.h"
|
||||||
|
|
||||||
|
|
||||||
HealFriendNode::HealFriendNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent){}
|
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) {
|
if (actor->isTypeOf(ACT_HERO) == ishero && actor->health < actor->maxhealth-1) {
|
||||||
vec2i pos = actor->getPosition();
|
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);
|
friends.push_back(actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ Hero::Hero(Tilemap* map, vec2i pos) : Actor(map, pos) {
|
||||||
|
|
||||||
new AttackEnemyNode(root);
|
new AttackEnemyNode(root);
|
||||||
new RestNode(root);
|
new RestNode(root);
|
||||||
new ExploreNode(root);
|
//new ExploreNode(root);
|
||||||
new WanderNode(root);
|
new WanderNode(root);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "BehaviourTree.h"
|
#include "BehaviourTree.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
|
#include "FieldOfView.h"
|
||||||
|
|
||||||
|
|
||||||
IfNotSeeEnemyNode::IfNotSeeEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent) {}
|
IfNotSeeEnemyNode::IfNotSeeEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent) {}
|
||||||
|
@ -20,7 +21,7 @@ BehaviourTreeStatus IfNotSeeEnemyNode::tick(BTTick * tick) {
|
||||||
|
|
||||||
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
||||||
vec2i pos = actor->getPosition();
|
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;
|
return BT_FAILED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "BehaviourTree.h"
|
#include "BehaviourTree.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
|
#include "FieldOfView.h"
|
||||||
|
|
||||||
|
|
||||||
IfSeeEnemyNode::IfSeeEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent) {}
|
IfSeeEnemyNode::IfSeeEnemyNode(BehaviourTreeNode * parent) : BehaviourTreeNode(parent) {}
|
||||||
|
@ -20,7 +21,7 @@ BehaviourTreeStatus IfSeeEnemyNode::tick(BTTick * tick) {
|
||||||
|
|
||||||
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
||||||
vec2i pos = actor->getPosition();
|
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);
|
return children[0]->execute(tick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "BehaviourTree.h"
|
#include "BehaviourTree.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
|
#include "FieldOfView.h"
|
||||||
|
|
||||||
|
|
||||||
IfSeeFriendNode::IfSeeFriendNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent) {}
|
IfSeeFriendNode::IfSeeFriendNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent) {}
|
||||||
|
@ -21,7 +22,7 @@ BehaviourTreeStatus IfSeeFriendNode::tick(BTTick * tick) {
|
||||||
|
|
||||||
if (actor->isTypeOf(ACT_HERO) == ishero) {
|
if (actor->isTypeOf(ACT_HERO) == ishero) {
|
||||||
vec2i pos = actor->getPosition();
|
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);
|
return children[0]->execute(tick);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,9 @@ void Input::newframe() {
|
||||||
|
|
||||||
InputEvent Input::setkey(SDL_Keycode key, SDL_Keymod mod, bool pressed)
|
InputEvent Input::setkey(SDL_Keycode key, SDL_Keymod mod, bool pressed)
|
||||||
{
|
{
|
||||||
InputEvent event;
|
InputEvent event{};
|
||||||
event.type = INPUT_KEY_EVENT;
|
event.type = INPUT_KEY_EVENT;
|
||||||
|
event.action = ACTION_NONE;
|
||||||
event.key_press_event.key = key;
|
event.key_press_event.key = key;
|
||||||
event.key_press_event.mod = mod;
|
event.key_press_event.mod = mod;
|
||||||
event.pressed = pressed;
|
event.pressed = pressed;
|
||||||
|
@ -82,7 +83,8 @@ InputEvent Input::set_mouse_pos(int x, int y, int dx, int dy) {
|
||||||
mouse_x = x;
|
mouse_x = x;
|
||||||
mouse_y = y;
|
mouse_y = y;
|
||||||
|
|
||||||
InputEvent event;
|
InputEvent event{};
|
||||||
|
event.action = ACTION_NONE;
|
||||||
event.type = INPUT_MOUSE_MOVE_EVENT;
|
event.type = INPUT_MOUSE_MOVE_EVENT;
|
||||||
event.mouse_move_event.x = x;
|
event.mouse_move_event.x = x;
|
||||||
event.mouse_move_event.y = y;
|
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_x = x;
|
||||||
mouse_y = y;
|
mouse_y = y;
|
||||||
|
|
||||||
InputEvent event;
|
InputEvent event{};
|
||||||
|
event.action = ACTION_NONE;
|
||||||
event.type = INPUT_MOUSE_CLICK_EVENT;
|
event.type = INPUT_MOUSE_CLICK_EVENT;
|
||||||
event.action = ACTION_NONE;
|
event.action = ACTION_NONE;
|
||||||
event.pressed = pressed;
|
event.pressed = pressed;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
#include "Tileset.h"
|
#include "Tileset.h"
|
||||||
|
#include "FieldOfView.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "Hero.h"
|
#include "Hero.h"
|
||||||
#include "Goblin.h"
|
#include "Goblin.h"
|
||||||
|
@ -72,6 +73,68 @@ void PlayState::load() {
|
||||||
new_game();
|
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) {
|
Gamestate *PlayState::update(double delta) {
|
||||||
timer += delta;
|
timer += delta;
|
||||||
if (!paused) {
|
if (!paused) {
|
||||||
|
@ -91,6 +154,7 @@ Gamestate *PlayState::update(double delta) {
|
||||||
actors->erase(actors->begin() + i);
|
actors->erase(actors->begin() + i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fov->calc(hero->getPosition(), 6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -131,22 +195,12 @@ void PlayState::draw(double delta) {
|
||||||
offset.x -= heropos.x * 12;
|
offset.x -= heropos.x * 12;
|
||||||
offset.y -= heropos.y * 12;
|
offset.y -= heropos.y * 12;
|
||||||
|
|
||||||
for (int x = 0; x < 32; x++) {
|
tilemap->draw(app->renderer, ascii, offset.x, offset.y, fov);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto actors = tilemap->GetActorList();
|
auto actors = tilemap->GetActorList();
|
||||||
for (Actor* var : *actors) {
|
for (Actor* var : *actors) {
|
||||||
vec2i pos = var->getPosition();
|
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->SetColor(0, 0, 0, 255);
|
||||||
app->renderer->DrawSprite(ascii->GetSprite(219), offset.x + pos.x * 12, offset.y + pos.y * 12);
|
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) {
|
void PlayState::inputevent(InputEvent *event) {
|
||||||
if (event->pressed) {
|
if (event->type == INPUT_KEY_EVENT && event->pressed) {
|
||||||
switch (event->action) {
|
switch (event->action) {
|
||||||
case ACTION_TOGGLE_DEBUG: debug = !debug; break;
|
case ACTION_TOGGLE_DEBUG: debug = !debug; break;
|
||||||
case ACTION_ESCAPE_MENU: paused = !paused; 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 Tileset;
|
||||||
class Tilemap;
|
class Tilemap;
|
||||||
class Actor;
|
class Actor;
|
||||||
|
class FieldOfView;
|
||||||
|
|
||||||
class PlayState : public Gamestate {
|
class PlayState : public Gamestate {
|
||||||
Tileset* ascii;
|
Tileset* ascii;
|
||||||
Tilemap* tilemap;
|
Tilemap* tilemap;
|
||||||
Actor * hero;
|
Actor * hero;
|
||||||
|
FieldOfView *fov;
|
||||||
float delay = .5;
|
float delay = .5;
|
||||||
double timer;
|
double timer;
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "BehaviourTree.h"
|
#include "BehaviourTree.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
|
#include "FieldOfView.h"
|
||||||
|
|
||||||
|
|
||||||
RangedAttackNode::RangedAttackNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent) {}
|
RangedAttackNode::RangedAttackNode(BehaviourTreeNode* parent) : BehaviourTreeNode(parent) {}
|
||||||
|
@ -22,7 +23,7 @@ BehaviourTreeStatus RangedAttackNode::tick(BTTick * tick) {
|
||||||
|
|
||||||
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
if (actor->isTypeOf(ACT_HERO) != ishero) {
|
||||||
vec2i pos = actor->getPosition();
|
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);
|
enemies.push_back(actor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#include "Tilemap.h"
|
#include "Tilemap.h"
|
||||||
#include "vec2i.h"
|
#include "vec2i.h"
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
|
#include "Renderer.h"
|
||||||
|
#include "Tileset.h"
|
||||||
|
#include "FieldOfView.h"
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
int Tilemap::GetIndex(int x, int y)
|
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() {
|
std::vector<Actor*>* Tilemap::GetActorList() {
|
||||||
return &actors;
|
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
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Actor.h"
|
#include "Actor.h"
|
||||||
|
#include "Tileset.h"
|
||||||
|
|
||||||
struct vec2i;
|
struct vec2i;
|
||||||
|
class Renderer;
|
||||||
|
class FieldOfView;
|
||||||
|
|
||||||
class Tilemap {
|
class Tilemap {
|
||||||
unsigned int* tilemap;
|
unsigned int* tilemap;
|
||||||
|
@ -21,8 +24,13 @@ public:
|
||||||
int GetTile(int x, int y);
|
int GetTile(int x, int y);
|
||||||
bool IsBlocked(int x, int y); // Checks if there is an actor blocking the tile.
|
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 AddActor(Actor* actor);
|
||||||
void RemoveActor(Actor* actor);
|
void RemoveActor(Actor* actor);
|
||||||
|
|
||||||
|
void debug_print();
|
||||||
|
|
||||||
Actor* GetActor(int x, int y, Actors type);
|
Actor* GetActor(int x, int y, Actors type);
|
||||||
std::vector<Actor*> GetActors(int x, int y, int range, Actors type);
|
std::vector<Actor*> GetActors(int x, int y, int range, Actors type);
|
||||||
std::vector<Actor*>* GetActorList();
|
std::vector<Actor*>* GetActorList();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue