From 9e7d64d052eabcf40d85c3e903aaba44903a380a Mon Sep 17 00:00:00 2001 From: PaweÅ‚ Redman Date: Sat, 7 Oct 2017 08:03:44 +0200 Subject: Initial commit. --- Makefile | 41 +++++++++++++++++++++++++ src/common.hpp | 70 ++++++++++++++++++++++++++++++++++++++++++ src/game.cpp | 7 +++++ src/interface.cpp | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.cpp | 23 ++++++++++++++ src/render.cpp | 67 ++++++++++++++++++++++++++++++++++++++++ src/world.cpp | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 386 insertions(+) create mode 100644 Makefile create mode 100644 src/common.hpp create mode 100644 src/game.cpp create mode 100644 src/interface.cpp create mode 100644 src/main.cpp create mode 100644 src/render.cpp create mode 100644 src/world.cpp 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 +#include +#include +#include +#include + +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 entities; + public: + bool empty = true; + tile_t tiles[SECTOR_SIZE * SECTOR_SIZE]; + + void generate(sector_index_t index); + }; + + class world_t { + std::map 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 bbox; + sf::Rect 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 = §ors[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; +} + +} -- cgit