From 99fa92f8ba8da320af1a33c6dcbdc9d2a8a83970 Mon Sep 17 00:00:00 2001 From: John McCardle Date: Fri, 10 Mar 2023 19:39:44 -0500 Subject: [PATCH] Field of view, discovered tiles, opaque fog of war rendering --- src/Grid.cpp | 71 ++++++++++++++++++++++++++++++++++++++++++---- src/Grid.h | 9 +++++- src/McRFPy_API.cpp | 15 ++++++++++ src/McRFPy_API.h | 1 + 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/Grid.cpp b/src/Grid.cpp index 9ed50dc..6f4a378 100644 --- a/src/Grid.cpp +++ b/src/Grid.cpp @@ -3,7 +3,7 @@ #include "Entity.h" GridPoint::GridPoint(): - color(0, 0, 0, 0), walkable(true), tilesprite(-1), transparent(true), visible(false), discovered(false), color_overlay(0,0,0,255), tile_overlay(-1), uisprite(-1) + color(0, 0, 0, 0), walkable(false), tilesprite(-1), transparent(false), visible(false), discovered(false), color_overlay(0,0,0,255), tile_overlay(-1), uisprite(-1) {}; void Grid::setSprite(int ti) @@ -22,6 +22,7 @@ Grid::Grid(int gx, int gy, int gs, int _x, int _y, int _w, int _h): //zoom = 1.0f; //grid_x = gx; //grid_y = gy; + tcodmap = new TCODMap(gx, gy); points.resize(gx*gy); box.setSize(sf::Vector2f(_w, _h)); box.setPosition(sf::Vector2f(_x, _y)); @@ -45,6 +46,33 @@ Grid::Grid(int gx, int gy, int gs, int _x, int _y, int _w, int _h): sprite.setTexture(texture); } +void Grid::refreshTCODmap() { + int total = 0, walkable = 0, transparent = 0; + for (int x = 0; x < grid_x; x++) { + for (int y = 0; y < grid_y; y++) { + auto p = at(x, y); + total++; if (p.walkable) walkable++; if (p.transparent) transparent++; + tcodmap->setProperties(x, y, p.transparent, p.walkable); + } + } + std::cout << "Map refreshed: " << total << " squares, " << walkable << "walkable, " << transparent << " transparent" << std::endl; +} +void Grid::refreshTCODsight(int x, int y) { + tcodmap->computeFov(x,y); + for (int x = 0; x < grid_x; x++) { + for (int y = 0; y < grid_y; y++) { + auto& p = at(x, y); + if (p.visible && !tcodmap->isInFov(x, y)) { + p.discovered = true; + p.visible = false; + } else if (!p.visible && tcodmap->isInFov(x,y)) { + p.discovered = true; + p.visible = true; + } + } + } +} + bool Grid::inBounds(int x, int y) { return (x >= 0 && y >= 0 && x < grid_x && y < grid_y); } @@ -230,10 +258,8 @@ void Grid::render(sf::RenderWindow & window) setSprite(gridpoint.tilesprite); renderTexture.draw(sprite); } - - // overlay - - // uisprite + + } } @@ -247,7 +273,42 @@ void Grid::render(sf::RenderWindow & window) drawent.setPosition(pixel_pos); renderTexture.draw(drawent); } + + // loop again and draw on top of entities + for (int x = (left_edge - 1 >= 0 ? left_edge - 1 : 0); + x < x_limit; //x < view_width; + x+=1) + { + //for (float y = (top_edge >= 0 ? top_edge : 0); + for (int y = (top_edge - 1 >= 0 ? top_edge - 1 : 0); + y < y_limit; //y < view_height; + y+=1) + { + + auto pixel_pos = sf::Vector2f( + (x*grid_size - left_spritepixels) * zoom, + (y*grid_size - top_spritepixels) * zoom ); + auto gridpoint = at(std::floor(x), std::floor(y)); + + sprite.setPosition(pixel_pos); + + r.setPosition(pixel_pos); + + // visible & discovered layers for testing purposes + if (!gridpoint.discovered) { + r.setFillColor(sf::Color(16, 16, 20, 255)); + renderTexture.draw(r); + } else if (!gridpoint.visible) { + r.setFillColor(sf::Color(32, 32, 40, 128)); + renderTexture.draw(r); + } + + // overlay + + // uisprite + } + } // grid lines for testing & validation /* sf::Vertex line[] = diff --git a/src/Grid.h b/src/Grid.h index e23e257..95755de 100644 --- a/src/Grid.h +++ b/src/Grid.h @@ -1,5 +1,7 @@ #pragma once #include "Common.h" +#include "libtcod.h" + //#include "Entity.h" class Entity; // forward declare @@ -26,6 +28,7 @@ public: sf::Texture texture; sf::Sprite sprite, output; sf::RenderTexture renderTexture; + TCODMap* tcodmap; void setSprite(int); const int texture_width, texture_height; auto contains(sf::Vector2i p) { return box.getGlobalBounds().contains(p.x, p.y); } @@ -45,5 +48,9 @@ public: void renderPxToGrid(int, int, int&, int&); void gridToRenderPx(int, int, int&, int&); - void integerGrid(float, float, int&, int&); + void integerGrid(float, float, int&, int&); + + void refreshTCODmap(); + void refreshTCODsight(int, int); + TCODDijkstra *dijkstra; //= new TCODDijkstra(myMap); }; diff --git a/src/McRFPy_API.cpp b/src/McRFPy_API.cpp index 36a3da9..7bfeda0 100644 --- a/src/McRFPy_API.cpp +++ b/src/McRFPy_API.cpp @@ -91,6 +91,7 @@ static PyMethodDef mcrfpyMethods[] = { {"turnNumber", McRFPy_API::_turnNumber, METH_VARARGS, ""}, {"createEntity", McRFPy_API::_createEntity, METH_VARARGS, ""}, //{"listEntities", McRFPy_API::_listEntities, METH_VARARGS, ""}, + {"refreshFov", McRFPy_API::_refreshFov, METH_VARARGS, ""}, {NULL, NULL, 0, NULL} }; @@ -681,6 +682,12 @@ PyObject* McRFPy_API::_modGrid(PyObject* self, PyObject* args) { grid->points[i].tile_overlay = PyLong_AsLong(PyObject_GetAttrString(gpointobj, "tile_overlay")); grid->points[i].uisprite = PyLong_AsLong(PyObject_GetAttrString(gpointobj, "uisprite")); } + + // update grid pathfinding & visibility + grid->refreshTCODmap(); + for (auto e : McRFPy_API::entities.getEntities("player")) { + grid->refreshTCODsight(e->cGrid->x, e->cGrid->y); + } } PyObject* entlist = PyObject_GetAttrString(o, "entities"); //std::cout << PyUnicode_AsUTF8(PyObject_Repr(entlist)) << std::endl; @@ -697,6 +704,14 @@ PyObject* McRFPy_API::_modGrid(PyObject* self, PyObject* args) { return Py_None; } +PyObject* McRFPy_API::_refreshFov(PyObject* self, PyObject* args) { + for (auto e : McRFPy_API::entities.getEntities("player")) { + e->cGrid->grid->refreshTCODsight(e->cGrid->x, e->cGrid->y); + } + Py_INCREF(Py_None); + return Py_None; +} + PyObject* _test_createAnimation(PyObject *self, PyObject *args) { //LerpAnimation::LerpAnimation(float _d, T _ev, T* _t, std::function _cb, std::function _w, bool _l) std::string menu_key = "demobox1"; diff --git a/src/McRFPy_API.h b/src/McRFPy_API.h index 22befbd..c416ae3 100644 --- a/src/McRFPy_API.h +++ b/src/McRFPy_API.h @@ -106,6 +106,7 @@ public: // turn cycle static int turn_number; static PyObject* _turnNumber(PyObject*, PyObject*); + static PyObject* _refreshFov(PyObject*, PyObject*); // accept keyboard input from scene static sf::Vector2i cursor_position;