summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaweł Redman <pawel.redman@gmail.com>2017-10-07 08:03:44 +0200
committerPaweł Redman <pawel.redman@gmail.com>2017-10-07 08:03:44 +0200
commit9e7d64d052eabcf40d85c3e903aaba44903a380a (patch)
tree0a3a2c7f53884bd035b54812a77d493be058f43c
Initial commit.
-rw-r--r--Makefile41
-rw-r--r--src/common.hpp70
-rw-r--r--src/game.cpp7
-rw-r--r--src/interface.cpp92
-rw-r--r--src/main.cpp23
-rw-r--r--src/render.cpp67
-rw-r--r--src/world.cpp86
7 files changed, 386 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8ceb27a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,41 @@
+CC ?= gcc
+CFLAGS += -g3 -O3 -Wall
+CPPFLAGS += -MMD
+LDFLAGS += -lstdc++ -lm -lsfml-system -lsfml-window -lsfml-graphics
+
+PP_BOLD := $(shell tput bold)
+PP_RESET := $(shell tput sgr0)
+PP_CC := $(PP_BOLD)$(shell tput setf 6)CC$(PP_RESET)
+PP_LD := $(PP_BOLD)$(shell tput setf 2)LD$(PP_RESET)
+PP_RM := $(PP_BOLD)$(shell tput setf 4)RM$(PP_RESET)
+
+SRC := src/game.cpp \
+ src/interface.cpp \
+ src/main.cpp \
+ src/render.cpp \
+ src/world.cpp
+
+OBJ := $(SRC:src/%.cpp=obj/%.o)
+OUT := minitrem
+
+all: $(OUT)
+
+-include $(OBJ:.o=.d)
+
+obj/%.o : src/%.cpp
+ @echo "$(PP_CC) src/$*.cpp"
+ @mkdir -p $(@D)
+ @$(CC) $(CFLAGS) $(CPPFLAGS) -c src/$*.cpp -o obj/$*.o
+
+$(OUT): $(OBJ)
+ @echo "$(PP_LD) $(OUT)"
+ @$(CC) $(OBJ) -o $(OUT) $(LDFLAGS)
+
+clean:
+ @echo "${PP_RM} obj"
+ @rm -rf obj
+ @echo "${PP_RM} ${OUT}"
+ @rm -rf ${OUT}
+
+.PHONY: clean
+
diff --git a/src/common.hpp b/src/common.hpp
new file mode 100644
index 0000000..aaf1cad
--- /dev/null
+++ b/src/common.hpp
@@ -0,0 +1,70 @@
+#include <iostream>
+#include <cstdint>
+#include <cmath>
+#include <map>
+#include <SFML/Graphics.hpp>
+
+namespace game {
+ class entity_t {
+ virtual void render(sf::RenderWindow *window) = 0;
+ };
+}
+
+namespace world {
+ #define SECTOR_SIZE 16
+
+ class tile_t {
+ public:
+ char type;
+ };
+
+ class sector_index_t {
+ public:
+ int64_t x, y;
+
+ sector_index_t ();
+ sector_index_t (int64_t x_, int64_t y_);
+ bool operator<(sector_index_t B) const;
+ };
+
+ class sector_t {
+ std::vector<game::entity_t*> entities;
+ public:
+ bool empty = true;
+ tile_t tiles[SECTOR_SIZE * SECTOR_SIZE];
+
+ void generate(sector_index_t index);
+ };
+
+ class world_t {
+ std::map<sector_index_t, sector_t> sectors;
+
+ public:
+ sector_t *get_sector(sector_index_t index);
+ tile_t *get_tile(ssize_t x, ssize_t y);
+
+ void link(game::entity_t *entity);
+ void unlink(game::entity_t *entity);
+ void render(sf::RenderWindow *window);
+ };
+}
+
+namespace interface {
+ class state_t {
+ struct {
+ sf::Vector2f center;
+ int target_zoom = 3;
+ float zoom = 3.0f;
+ bool dragging = false;
+ sf::Vector2f drag_ref;
+ } camera;
+
+ public:
+ sf::RenderWindow *window;
+ world::world_t *world;
+
+ state_t(sf::RenderWindow *window_, world::world_t *world_);
+ void tick(void);
+ void render(void);
+ };
+}
diff --git a/src/game.cpp b/src/game.cpp
new file mode 100644
index 0000000..9ce0a82
--- /dev/null
+++ b/src/game.cpp
@@ -0,0 +1,7 @@
+#include "common.hpp"
+
+namespace game {
+
+
+
+} //namespace game
diff --git a/src/interface.cpp b/src/interface.cpp
new file mode 100644
index 0000000..aacc4b0
--- /dev/null
+++ b/src/interface.cpp
@@ -0,0 +1,92 @@
+#include "common.hpp"
+
+namespace interface {
+
+state_t::state_t(sf::RenderWindow *window_, world::world_t *world_)
+{
+ window = window_;
+ world = world_;
+}
+
+static sf::Vector2f compute_drag(sf::RenderWindow *window, sf::Vector2f drag_ref)
+{
+ sf::Vector2i mouse = sf::Mouse::getPosition(*window);
+ sf::Vector2f vmouse = window->mapPixelToCoords(mouse);
+ return -(vmouse - drag_ref);
+}
+
+void state_t::tick(void)
+{
+ sf::Vector2u size;
+ sf::Event event;
+ sf::Vector2f view_size;
+
+ size = window->getSize();
+
+ camera.zoom = (camera.zoom + camera.target_zoom) / 2;
+
+ {
+ float view_scale;
+
+ view_scale = 3 * exp(camera.zoom * 0.3);
+ if (size.x > size.y) {
+ view_size.y = view_scale;
+ view_size.x = view_scale * size.x / size.y;
+ } else {
+ view_size.x = view_scale;
+ view_size.y = view_scale * size.y / size.x;
+ }
+
+ window->setView(sf::View(camera.center, view_size));
+ }
+
+
+ while (window->pollEvent(event)) {
+ switch (event.type) {
+ case sf::Event::Closed:
+ window->close();
+ return;
+
+ case sf::Event::MouseButtonPressed:
+ if (event.mouseButton.button == 0) {
+ sf::Vector2f vmouse = window->mapPixelToCoords(
+ sf::Vector2i(event.mouseButton.x,
+ event.mouseButton.y));
+ world->get_tile(vmouse.x, vmouse.y)->type = 0;
+ }
+ if (event.mouseButton.button == 1) {
+ camera.dragging = true;
+ camera.drag_ref = window->mapPixelToCoords(
+ sf::Vector2i(event.mouseButton.x,
+ event.mouseButton.y));
+ }
+ break;
+
+ case sf::Event::MouseButtonReleased:
+ if (event.mouseButton.button == 1) {
+ if (camera.dragging)
+ camera.center += compute_drag(window, camera.drag_ref);
+ camera.dragging = false;
+ }
+ break;
+
+ case sf::Event::MouseWheelScrolled:
+ camera.target_zoom -= event.mouseWheelScroll.delta;
+ if (camera.target_zoom < 0)
+ camera.target_zoom = 0;
+ if (camera.target_zoom > 10)
+ camera.target_zoom = 10;
+ break;
+
+ default:;
+ }
+ }
+
+ if (camera.dragging) {
+ sf::Vector2f delta = compute_drag(window, camera.drag_ref);
+ window->setView(sf::View(camera.center + delta, view_size));
+ } else
+ window->setView(sf::View(camera.center, view_size));
+}
+
+} // namespace interface
diff --git a/src/main.cpp b/src/main.cpp
new file mode 100644
index 0000000..1f69582
--- /dev/null
+++ b/src/main.cpp
@@ -0,0 +1,23 @@
+#include "common.hpp"
+
+int main()
+{
+ sf::RenderWindow window(sf::VideoMode(800, 600), "SFML");
+ world::world_t world;
+ interface::state_t interface(&window, &world);
+
+ window.setVerticalSyncEnabled(true);
+
+ while (1) {
+ interface.tick();
+ if (!window.isOpen())
+ break;
+
+ window.clear();
+ world.render(&window);
+ interface.render();
+ window.display();
+ }
+
+ return 0;
+}
diff --git a/src/render.cpp b/src/render.cpp
new file mode 100644
index 0000000..218dff0
--- /dev/null
+++ b/src/render.cpp
@@ -0,0 +1,67 @@
+#include "common.hpp"
+
+static sf::RectangleShape wot_rect;
+
+static void draw_tile(sf::RenderWindow *window, float x, float y,
+ world::tile_t *tile)
+{
+ wot_rect.setSize(sf::Vector2f(1.0f, 1.0f));
+ wot_rect.setPosition(sf::Vector2f(x, y));
+ wot_rect.setFillColor(sf::Color(tile->type, 255 - tile->type, tile->type + 128));
+ wot_rect.setOutlineColor(sf::Color::Transparent);
+ window->draw(wot_rect);
+}
+
+static void draw_sector(sf::RenderWindow *window, world::world_t *world,
+ world::sector_index_t index)
+{
+ world::sector_t *sector;
+
+ sector = world->get_sector(index);
+
+ for (ssize_t y = 0; y < SECTOR_SIZE; y++)
+ for (ssize_t x = 0; x < SECTOR_SIZE; x++) {
+ draw_tile(window,
+ index.x * SECTOR_SIZE + x,
+ index.y * SECTOR_SIZE + y,
+ sector->tiles + y * SECTOR_SIZE + x);
+ }
+
+ wot_rect.setSize(sf::Vector2f(SECTOR_SIZE, SECTOR_SIZE));
+ wot_rect.setPosition(sf::Vector2f(index.x * 16, index.y * 16));
+ wot_rect.setOutlineColor(sf::Color::Yellow);
+ wot_rect.setOutlineThickness(0.06f);
+ wot_rect.setFillColor(sf::Color::Transparent);
+ window->draw(wot_rect);
+}
+
+void world::world_t::render(sf::RenderWindow *window)
+{
+ sf::Vector2u size = window->getSize();
+ sf::Vector2f A, B, C, D;
+ sf::Rect<float> bbox;
+ sf::Rect<ssize_t> index_box;
+
+ A = window->mapPixelToCoords(sf::Vector2i(0, 0));
+ B = window->mapPixelToCoords(sf::Vector2i(size.x, 0));
+ C = window->mapPixelToCoords(sf::Vector2i(0, size.y));
+ D = window->mapPixelToCoords(sf::Vector2i(size.x, size.y));
+
+ bbox.left = std::min({A.x, B.x, C.x, D.x});
+ bbox.top = std::min({A.y, B.y, C.y, D.y});
+ bbox.width = std::max({A.x, B.x, C.x, D.x});
+ bbox.height = std::max({A.y, B.y, C.y, D.y});
+
+ index_box.left = floor(bbox.left / SECTOR_SIZE);
+ index_box.top = floor(bbox.top / SECTOR_SIZE);
+ index_box.width = ceil(bbox.width / SECTOR_SIZE);
+ index_box.height = ceil(bbox.height / SECTOR_SIZE);
+
+ for (ssize_t y = index_box.top; y < index_box.height; y++)
+ for (ssize_t x = index_box.left; x < index_box.width; x++)
+ draw_sector(window, this, world::sector_index_t(x, y));
+}
+
+void interface::state_t::render()
+{
+}
diff --git a/src/world.cpp b/src/world.cpp
new file mode 100644
index 0000000..b5aeea2
--- /dev/null
+++ b/src/world.cpp
@@ -0,0 +1,86 @@
+#include "common.hpp"
+
+namespace world {
+
+sector_index_t::sector_index_t ()
+{
+}
+
+sector_index_t::sector_index_t (int64_t x_, int64_t y_)
+{
+ x = x_;
+ y = y_;
+}
+
+bool sector_index_t::operator<(sector_index_t B) const
+{
+ if (x < B.x)
+ return true;
+ if (x > B.x)
+ return false;
+ if (y < B.y)
+ return true;
+ return false;
+}
+
+void sector_t::generate(sector_index_t index)
+{
+ std::cout << "generating (" << index.x << ", " << index.y << ")\n";
+
+ for (ssize_t ly = 0; ly < SECTOR_SIZE; ly++)
+ for (ssize_t lx = 0; lx < SECTOR_SIZE; lx++) {
+ ssize_t x, y;
+
+ x = index.x * SECTOR_SIZE + lx;
+ y = index.y * SECTOR_SIZE + ly;
+
+ tiles[ly * SECTOR_SIZE + lx].type = (x ^ y) * 151;
+ }
+
+ empty = false;
+}
+
+sector_t *world_t::get_sector(sector_index_t index)
+{
+ sector_t *sector;
+
+ sector = &sectors[index];
+
+ if (sector->empty)
+ sector->generate(index);
+
+ return sector;
+}
+
+// divide and round to minus infinity
+static ssize_t divide_rmi(ssize_t x, ssize_t y, size_t *rem)
+{
+ ssize_t rv;
+
+ if (x >= 0) {
+ *rem = x % y;
+ return x / y;
+ }
+
+ rv = (x + 1) / y - 1;
+ *rem = x - rv * y;
+ return rv;
+}
+
+tile_t *world_t::get_tile(ssize_t x, ssize_t y)
+{
+ sector_index_t index;
+ sector_t *sector;
+ size_t tx, ty;
+
+ index.x = divide_rmi(x, SECTOR_SIZE, &tx);
+ index.y = divide_rmi(y, SECTOR_SIZE, &ty);
+ printf("get_tile(%zd, %zd)\n", x, y);
+ printf("\tsector is (%zd, %zd)\n", index.x, index.y);
+ sector = get_sector(index);
+
+ printf("\ttile is (%zd, %zd)\n", tx, ty);
+ return sector->tiles + ty * SECTOR_SIZE + tx;
+}
+
+}