aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLoek Le Blansch <loek@pipeframe.xyz>2024-10-23 19:16:19 +0200
committerLoek Le Blansch <loek@pipeframe.xyz>2024-10-23 19:16:19 +0200
commit1e0a52b03fe655d7073ef20703dbb2e7646f74d3 (patch)
treef1709c2e9565d78c791653e71e6a4b26b3138423
parent277157b3e06b2deeacbdbc8bf6190de19f88169d (diff)
add XY struct for 2d points and offsets
-rw-r--r--CMakeLists.txt1
-rw-r--r--Canvas.cpp56
-rw-r--r--Canvas.h7
-rw-r--r--Exception.cpp14
-rw-r--r--Exception.h6
-rw-r--r--PathfindingContext.cpp27
-rw-r--r--PathfindingContext.h16
-rw-r--r--SetNeighborTileBehavior.cpp16
-rw-r--r--SetNeighborTileBehavior.h4
-rw-r--r--StepTileCommand.cpp10
-rw-r--r--StepTileCommand.h8
-rw-r--r--Tile.cpp19
-rw-r--r--Tile.h3
-rw-r--r--ViewController.cpp16
-rw-r--r--ViewController.h5
-rw-r--r--XY.cpp35
-rw-r--r--XY.h13
17 files changed, 157 insertions, 99 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 034f9ee..51a2557 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,6 +55,7 @@ add_executable(main
NaiveCollisionChecker.cpp
CycleCollisionMethodCommand.cpp
PathfindingContext.cpp
+ XY.cpp
)
target_link_libraries(main
diff --git a/Canvas.cpp b/Canvas.cpp
index ce51e5c..b7cc8a5 100644
--- a/Canvas.cpp
+++ b/Canvas.cpp
@@ -1,7 +1,9 @@
+#include <cassert>
#include <cstdio>
#include <string>
#include "Canvas.h"
+#include "Exception.h"
#include "util.h"
#include "Museum.h"
@@ -9,20 +11,32 @@ using namespace std;
Canvas::Canvas(Museum & museum) : museum(museum), tile_behavior(museum), tile_color() { }
-Tile & Canvas::get_tile(unsigned x, unsigned y) {
- return *this->tiles[this->pos_to_index(x, y)];
+Tile * & Canvas::get_tile_unsafe(const XY & pos) {
+ size_t index = pos.y * this->data.columns + pos.x;
+ return this->tiles[index];
}
-void Canvas::set_tile(TileData data) {
- size_t index = this->pos_to_index(data.x, data.y);
- if (this->tiles[index] != nullptr)
- delete this->tiles[index];
- this->tiles[index] = new Tile(this->museum, data);
+Tile & Canvas::get_tile(const XY & pos) {
+ Exception outside_range("get_tile: position (%d, %d) outside canvas", pos.x, pos.y);
+ if (pos.x < 0) throw outside_range;
+ if (pos.y < 0) throw outside_range;
+ if (pos.x >= this->data.columns) throw outside_range;
+ if (pos.y >= this->data.rows) throw outside_range;
+
+ Tile * tile = get_tile_unsafe(pos);
+ assert(tile != nullptr);
+
+ return *tile;
}
-size_t Canvas::pos_to_index(unsigned x, unsigned y) {
- size_t index = y * this->data.columns + x;
- return index;
+void Canvas::set_tile(TileData data) {
+ Tile * & tile = this->get_tile_unsafe({
+ static_cast<int>(data.x),
+ static_cast<int>(data.y)
+ });
+ if (tile != nullptr)
+ delete tile;
+ tile = new Tile(this->museum, data);
}
void Canvas::update() {
@@ -33,9 +47,9 @@ void Canvas::update() {
void Canvas::set_data(CanvasData data) {
this->data = data;
this->tiles.resize(this->data.rows * this->data.columns);
- for (size_t y = 0; y < this->data.rows; y++) {
- for (size_t x = 0; x < this->data.columns; x++) {
- if (this->tiles[this->pos_to_index(x, y)] != nullptr)
+ for (int y = 0; y < this->data.rows; y++) {
+ for (int x = 0; x < this->data.columns; x++) {
+ if (this->get_tile_unsafe({ x, y }) != nullptr)
continue;
this->set_tile({
.x = static_cast<unsigned int>(x),
@@ -56,15 +70,15 @@ Canvas::~Canvas() {
string Canvas::to_string(bool truecolor) {
string out = "";
- for (size_t y = 0; y < this->data.rows; y++) {
- for (size_t x = 0; x < this->data.columns; x++) {
- Tile & tile = this->get_tile(x, y);
- string type_str = tile.data.type;
+ for (int y = 0; y < this->data.rows; y++) {
+ for (int x = 0; x < this->data.columns; x++) {
+ Tile * tile = this->get_tile_unsafe({ x, y });
+ string type_str = tile->data.type;
if (type_str.length() == 0) type_str = ".";
if (truecolor)
out += stringf("\e[38;2;0;0;0;48;2;%d;%d;%dm",
- tile.color.red, tile.color.green, tile.color.blue);
+ tile->color.red, tile->color.green, tile->color.blue);
out += stringf("%-2s ", type_str.c_str());
}
@@ -80,7 +94,11 @@ void Canvas::update_steps() {
if (artist->step == false) continue;
artist->step = false;
- this->get_tile(artist->data.x, artist->data.y).behavior->step(artist);
+ Tile * tile = this->get_tile_unsafe({
+ static_cast<int>(artist->data.x),
+ static_cast<int>(artist->data.y)
+ });
+ tile->behavior->step(artist);
}
}
diff --git a/Canvas.h b/Canvas.h
index 6f59c15..e25c4b9 100644
--- a/Canvas.h
+++ b/Canvas.h
@@ -5,6 +5,7 @@
#include "CanvasData.h"
#include "Tile.h"
+#include "XY.h"
#include "TileBehaviorFactory.h"
#include "TileColorFactory.h"
@@ -18,7 +19,7 @@ public:
std::string to_string(bool truecolor = false);
public:
- virtual Tile & get_tile(unsigned x, unsigned y);
+ virtual Tile & get_tile(const XY &);
virtual void set_tile(TileData data);
public:
@@ -36,9 +37,9 @@ private:
private:
std::vector<Tile *> tiles;
- Museum & museum;
+ virtual Tile * & get_tile_unsafe(const XY &);
private:
- size_t pos_to_index(unsigned x, unsigned y);
+ Museum & museum;
};
diff --git a/Exception.cpp b/Exception.cpp
index d9765da..423f4e9 100644
--- a/Exception.cpp
+++ b/Exception.cpp
@@ -4,25 +4,21 @@
#include "Exception.h"
-Exception::~Exception() {
- if (error != NULL)
- free(error);
-}
+using namespace std;
const char * Exception::what() {
- return error;
+ return error.get();
}
void Exception::va_format(va_list args, const char * fmt) {
va_list args_copy;
va_copy(args_copy, args);
-
size_t sz = vsnprintf(NULL, 0, fmt, args_copy) + 1;
- if (error != NULL) free(error);
- error = (char *) malloc(sz);
va_end(args_copy);
- vsnprintf(error, sz, fmt, args);
+ this->error = unique_ptr<char>(static_cast<char *>(malloc(sz)));
+
+ vsnprintf(this->error.get(), sz, fmt, args);
}
Exception::Exception(const char * fmt, ...) {
diff --git a/Exception.h b/Exception.h
index 31c517b..633cb4f 100644
--- a/Exception.h
+++ b/Exception.h
@@ -2,16 +2,16 @@
#include <cstdarg>
#include <exception>
+#include <memory>
class Exception : public std::exception {
public:
Exception(const char * fmt, ...);
- virtual ~Exception();
- virtual const char * what();
+ const char * what();
protected:
Exception() = default;
void va_format(va_list args, const char * fmt);
- char * error = NULL;
+ std::unique_ptr<char> error = NULL;
};
diff --git a/PathfindingContext.cpp b/PathfindingContext.cpp
index a1d31f6..cfebb44 100644
--- a/PathfindingContext.cpp
+++ b/PathfindingContext.cpp
@@ -1,4 +1,5 @@
#include "PathfindingContext.h"
+#include "XY.h"
#include "Museum.h"
#include "NullTileBehavior.h"
@@ -6,28 +7,26 @@ using namespace std;
PathfindingContext::PathfindingContext(Museum & m) : museum(m) {}
-void PathfindingContext::set_start(const pair<int, int> & point) {
+void PathfindingContext::set_start(const XY & point) {
if (!this->valid_point(point)) return;
this->start_point = point;
}
-void PathfindingContext::set_end(const pair<int, int> & point) {
+void PathfindingContext::set_end(const XY & point) {
if (!this->valid_point(point)) return;
this->end_point = point;
}
-bool PathfindingContext::valid_point(const std::pair<int, int> & point) {
- // check if out of bounds
- Canvas & canvas = this->museum.canvas;
- if (point.first < 0) return false;
- if (point.second < 0) return false;
- if (point.first >= canvas.data.columns) return false;
- if (point.second >= canvas.data.rows) return false;
-
- // check if square is empty (has null behavior)
- Tile & tile = canvas.get_tile(point.first, point.second);
- TileBehavior * behavior = tile.behavior.get();
- if (dynamic_cast<NullTileBehavior *>(behavior) != nullptr) return false;
+bool PathfindingContext::valid_point(const XY & point) {
+ try {
+ // check if square is empty (has null behavior)
+ Tile & tile = this->museum.canvas.get_tile(point);
+ TileBehavior * behavior = tile.behavior.get();
+ if (dynamic_cast<NullTileBehavior *>(behavior) != nullptr) return false;
+ } catch (...) {
+ // get_tile throws an exception if the point is outside the canvas bounds
+ return false;
+ }
return true;
}
diff --git a/PathfindingContext.h b/PathfindingContext.h
index ce46a55..19fd93d 100644
--- a/PathfindingContext.h
+++ b/PathfindingContext.h
@@ -1,6 +1,6 @@
#pragma once
-#include <utility>
+#include "XY.h"
class Museum;
@@ -9,15 +9,15 @@ public:
PathfindingContext(Museum &);
public:
- void set_start(const std::pair<int, int> & point);
- const std::pair<int, int> & get_start() { return this->start_point; }
- void set_end(const std::pair<int, int> & point);
- const std::pair<int, int> & get_end() { return this->end_point; }
- bool valid_point(const std::pair<int, int> & point);
+ void set_start(const XY & point);
+ const XY & get_start() { return this->start_point; }
+ void set_end(const XY & point);
+ const XY & get_end() { return this->end_point; }
+ bool valid_point(const XY & point);
private:
- std::pair<int, int> start_point = { -1, -1 };
- std::pair<int, int> end_point = { -1, -1 };
+ XY start_point = { -1, -1 };
+ XY end_point = { -1, -1 };
private:
Museum & museum;
diff --git a/SetNeighborTileBehavior.cpp b/SetNeighborTileBehavior.cpp
index 7b7ede7..0314e42 100644
--- a/SetNeighborTileBehavior.cpp
+++ b/SetNeighborTileBehavior.cpp
@@ -8,16 +8,16 @@ using namespace std;
void SetNeighborTileBehavior::step(Artist * artist) {
this->interactions++;
- if (dx != 0 || dy != 0) return;
+ if (this->offset.x != 0 || this->offset.y != 0) return;
if (artist == nullptr) return;
- if (artist->data.vx == 0) dx = 1;
- if (artist->data.vy == 0) dy = 1;
+ if (artist->data.vx == 0) this->offset.x = 1;
+ if (artist->data.vy == 0) this->offset.y = 1;
}
-static void update_neighbor(Tile & here, int dx, int dy) {
- if (dx == 0 && dy == 0) return;
- Tile * neighbor = here.get_neighbor(dx, dy);
+static void update_neighbor(Tile & here, const XY & offset) {
+ if (offset.x == 0 && offset.y == 0) return;
+ Tile * neighbor = here.get_neighbor(offset);
if (neighbor == &here) return;
if (neighbor == nullptr) return;
@@ -28,8 +28,8 @@ static void update_neighbor(Tile & here, int dx, int dy) {
void SetNeighborTileBehavior::update(Tile & tile) {
if (this->interactions < 1) return;
- update_neighbor(tile, this->dx, this->dy);
- update_neighbor(tile, -this->dx, -this->dy);
+ update_neighbor(tile, this->offset);
+ update_neighbor(tile, -this->offset);
tile.set_type(CreateArtistTileBehavior::type);
}
diff --git a/SetNeighborTileBehavior.h b/SetNeighborTileBehavior.h
index 53bfbc0..c52edf3 100644
--- a/SetNeighborTileBehavior.h
+++ b/SetNeighborTileBehavior.h
@@ -1,6 +1,7 @@
#pragma once
#include "TileBehavior.h"
+#include "XY.h"
class SetNeighborTileBehavior : public TileBehavior {
friend class TileBehaviorFactory;
@@ -13,7 +14,6 @@ public:
static constexpr const char * type = "B";
private:
- int dx = 0;
- int dy = 0;
+ XY offset = { 0, 0 };
};
diff --git a/StepTileCommand.cpp b/StepTileCommand.cpp
index bac9f5d..beefd34 100644
--- a/StepTileCommand.cpp
+++ b/StepTileCommand.cpp
@@ -3,16 +3,10 @@
using namespace std;
-StepTileCommand::StepTileCommand(Canvas & c, pair<unsigned int, unsigned int> tile) : canvas(c) {
- this->x = tile.first;
- this->y = tile.second;
-}
+StepTileCommand::StepTileCommand(Canvas & c, const XY & tile) : canvas(c), tile_pos(tile) { }
void StepTileCommand::execute() {
- Canvas & canvas = this->canvas;
- if (this->x >= canvas.data.columns) return;
- if (this->y >= canvas.data.rows) return;
- Tile & tile = canvas.get_tile(this->x, this->y);
+ Tile & tile = this->canvas.get_tile(this->tile_pos);
tile.behavior->step(nullptr);
tile.update();
}
diff --git a/StepTileCommand.h b/StepTileCommand.h
index 24d0b36..c9a2d8b 100644
--- a/StepTileCommand.h
+++ b/StepTileCommand.h
@@ -1,21 +1,19 @@
#pragma once
-#include <utility>
-
#include "Command.h"
+#include "XY.h"
class Canvas;
class StepTileCommand : public Command {
public:
- StepTileCommand(Canvas & c, std::pair<unsigned int, unsigned int> tile);
+ StepTileCommand(Canvas & c, const XY & tile);
public:
virtual void execute();
private:
Canvas & canvas;
- unsigned int x;
- unsigned int y;
+ XY tile_pos;
};
diff --git a/Tile.cpp b/Tile.cpp
index cd1e820..92da9e7 100644
--- a/Tile.cpp
+++ b/Tile.cpp
@@ -28,14 +28,15 @@ void Tile::update() {
this->behavior->update(*this);
}
-Tile * Tile::get_neighbor(int dx, int dy) {
- Canvas & canvas = this->museum.canvas;
- int x = this->data.x + dx;
- int y = this->data.y + dy;
- if (x < 0) return nullptr;
- if (x >= canvas.data.columns) return nullptr;
- if (y < 0) return nullptr;
- if (y >= canvas.data.columns) return nullptr;
- return &canvas.get_tile(x, y);
+Tile * Tile::get_neighbor(const XY & offset) {
+ XY here {
+ .x = static_cast<int>(this->data.x),
+ .y = static_cast<int>(this->data.y),
+ };
+ try {
+ return &this->museum.canvas.get_tile(here + offset);
+ } catch (...) {
+ return nullptr;
+ }
}
diff --git a/Tile.h b/Tile.h
index ccf8d3b..7e44b09 100644
--- a/Tile.h
+++ b/Tile.h
@@ -5,6 +5,7 @@
#include "TileData.h"
#include "Color.h"
#include "TileBehavior.h"
+#include "XY.h"
class Museum;
@@ -21,7 +22,7 @@ public:
void set_data(TileData & data);
void set_type(const std::string & type);
void update();
- Tile * get_neighbor(int dx, int dy);
+ Tile * get_neighbor(const XY & offset);
private:
Museum & museum;
diff --git a/ViewController.cpp b/ViewController.cpp
index 67fd77c..40e624a 100644
--- a/ViewController.cpp
+++ b/ViewController.cpp
@@ -39,9 +39,9 @@ void ViewController::update_size() {
}
void ViewController::update_tiles() {
- for (unsigned y = 0; y < this->museum.canvas.data.rows; y++) {
- for (unsigned x = 0; x < this->museum.canvas.data.columns; x++) {
- Tile & tile = this->museum.canvas.get_tile(x, y);
+ for (int y = 0; y < this->museum.canvas.data.rows; y++) {
+ for (int x = 0; x < this->museum.canvas.data.columns; x++) {
+ Tile & tile = this->museum.canvas.get_tile({ x, y });
Rectangle rect = {
.x = static_cast<float>(x * scale),
.y = static_cast<float>(y * scale),
@@ -66,10 +66,10 @@ void ViewController::update_artists() {
}
}
-void ViewController::draw_pathfinding_dot(pair<unsigned int, unsigned int> point, const Color & color) {
+void ViewController::draw_pathfinding_dot(const XY & point, const Color & color) {
this->view.fill_rect(center({
- .x = static_cast<float>(point.first * scale),
- .y = static_cast<float>(point.second * scale),
+ .x = static_cast<float>(point.x * scale),
+ .y = static_cast<float>(point.y * scale),
.width = static_cast<float>(pathfinding_size),
.height = static_cast<float>(pathfinding_size),
}), color);
@@ -177,8 +177,8 @@ void ViewController::ev_mousedown(MouseCode button) {
void ViewController::ev_mousemove(unsigned x, unsigned y) {
this->mouse_pos = {
- static_cast<float>(x) / static_cast<float>(this->scale),
- static_cast<float>(y) / static_cast<float>(this->scale),
+ .x = static_cast<int>(x / this->scale),
+ .y = static_cast<int>(y / this->scale),
};
}
diff --git a/ViewController.h b/ViewController.h
index f05d62b..d50dfb1 100644
--- a/ViewController.h
+++ b/ViewController.h
@@ -7,6 +7,7 @@
#include "KeyboardCode.h"
#include "MouseCode.h"
#include "Rectangle.h"
+#include "XY.h"
class View;
class Museum;
@@ -32,7 +33,7 @@ private:
void update_quadtree_recursive(QuadTreeCollisionChecker * tree);
private:
- void draw_pathfinding_dot(std::pair<unsigned int, unsigned int>, const Color &);
+ void draw_pathfinding_dot(const XY &, const Color &);
Rectangle center(Rectangle);
private:
@@ -52,6 +53,6 @@ private:
unsigned int pathfinding_size = scale - 4;
private:
- std::pair<float, float> mouse_pos = { 0, 0 };
+ XY mouse_pos;
};
diff --git a/XY.cpp b/XY.cpp
new file mode 100644
index 0000000..ad1262b
--- /dev/null
+++ b/XY.cpp
@@ -0,0 +1,35 @@
+#include "XY.h"
+
+XY XY::operator - () const {
+ return XY {
+ .x = -x,
+ .y = -y,
+ };
+}
+
+XY XY::operator + (const XY & rhs) const {
+ return XY {
+ .x = x + rhs.x,
+ .y = y + rhs.y,
+ };
+}
+
+XY XY::operator - (const XY & rhs) const {
+ return XY {
+ .x = x - rhs.x,
+ .y = y - rhs.y,
+ };
+}
+
+XY& XY::operator += (const XY & rhs) {
+ this->x += rhs.x;
+ this->y += rhs.y;
+ return *this;
+}
+
+XY& XY::operator -= (const XY & rhs) {
+ this->x -= rhs.x;
+ this->y -= rhs.y;
+ return *this;
+}
+
diff --git a/XY.h b/XY.h
new file mode 100644
index 0000000..2aac824
--- /dev/null
+++ b/XY.h
@@ -0,0 +1,13 @@
+#pragma once
+
+struct XY {
+ int x = 0;
+ int y = 0;
+
+ XY operator + (const XY &) const;
+ XY operator - () const;
+ XY operator - (const XY &) const;
+ XY& operator += (const XY &);
+ XY& operator -= (const XY &);
+};
+