Initial Commit
Late as shit... as usual
This commit is contained in:
commit
439051e52c
26 changed files with 6352 additions and 0 deletions
65
.gitignore
vendored
Normal file
65
.gitignore
vendored
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/cmake,c++
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=cmake,c++
|
||||||
|
|
||||||
|
### C++ ###
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
|
*.o
|
||||||
|
*.obj
|
||||||
|
|
||||||
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Linker files
|
||||||
|
*.ilk
|
||||||
|
|
||||||
|
# Debugger Files
|
||||||
|
*.pdb
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
|
*.so
|
||||||
|
*.dylib
|
||||||
|
*.dll
|
||||||
|
|
||||||
|
# Fortran module files
|
||||||
|
*.mod
|
||||||
|
*.smod
|
||||||
|
|
||||||
|
# Compiled Static libraries
|
||||||
|
*.lai
|
||||||
|
*.la
|
||||||
|
*.a
|
||||||
|
*.lib
|
||||||
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
|
*.app
|
||||||
|
|
||||||
|
### CMake ###
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Testing
|
||||||
|
Makefile
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
_deps
|
||||||
|
CMakeUserPresets.json
|
||||||
|
|
||||||
|
### CMake Patch ###
|
||||||
|
# External projects
|
||||||
|
*-prefix/
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/cmake,c++
|
||||||
|
|
||||||
|
build/
|
||||||
|
|
17
CMakeLists.txt
Normal file
17
CMakeLists.txt
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
project(main)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")
|
||||||
|
|
||||||
|
include_directories(src)
|
||||||
|
add_definitions(-g)
|
||||||
|
add_definitions(-fsanitize=address)
|
||||||
|
|
||||||
|
file(GLOB SOURCES "src/*.cpp" "src/**/*.cpp")
|
||||||
|
|
||||||
|
add_executable(${CMAKE_PROJECT_NAME} ${SOURCES})
|
||||||
|
target_link_libraries(${CMAKE_PROJECT_NAME} X11 GL pthread png stdc++fs)
|
||||||
|
target_link_options(${CMAKE_PROJECT_NAME} PRIVATE -fsanitize=address)
|
93
src/app.cpp
Normal file
93
src/app.cpp
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
|
#include "map/map.h"
|
||||||
|
#include "tiles/dirt.h"
|
||||||
|
#include "tiles/grass.h"
|
||||||
|
#include "util/vector2.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
App::App() :
|
||||||
|
m_render(this) {
|
||||||
|
sAppName = "Automation";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool App::OnUserCreate()
|
||||||
|
{
|
||||||
|
std::cout << "Create" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool App::OnUserUpdate(float delta)
|
||||||
|
{
|
||||||
|
Vector2<int> screen = {ScreenWidth(), ScreenHeight()};
|
||||||
|
Vector2<int> mouse = {GetMouseX(), GetMouseY()};
|
||||||
|
|
||||||
|
// Save and load keys
|
||||||
|
if(GetKey(olc::Key::S).bReleased)
|
||||||
|
m_map.save();
|
||||||
|
if(GetKey(olc::Key::L).bReleased)
|
||||||
|
m_map.load();
|
||||||
|
|
||||||
|
// Basic block placing
|
||||||
|
if(GetMouse(0).bPressed) {
|
||||||
|
auto screen_pos = mouse - m_camera_pos;
|
||||||
|
auto tile_pos = screen_pos / (TILE_SIZE + 1);
|
||||||
|
if(screen_pos.x() < 0) tile_pos -= {1, 0};
|
||||||
|
if(screen_pos.y() < 0) tile_pos -= {0, 1};
|
||||||
|
m_map.set_tile(tile_pos, new Tile());
|
||||||
|
}
|
||||||
|
if(GetMouse(1).bPressed) {
|
||||||
|
auto screen_pos = mouse - m_camera_pos;
|
||||||
|
auto tile_pos = screen_pos / (TILE_SIZE + 1);
|
||||||
|
if(screen_pos.x() < 0) tile_pos -= {1, 0};
|
||||||
|
if(screen_pos.y() < 0) tile_pos -= {0, 1};
|
||||||
|
m_map.set_tile(tile_pos, new Dirt());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pan camera with middle mouse
|
||||||
|
if(GetMouse(2).bPressed) {
|
||||||
|
m_drag_start = {GetMouseX(), GetMouseY()};
|
||||||
|
}
|
||||||
|
if(GetMouse(2).bHeld) {
|
||||||
|
m_camera_pos += mouse - m_drag_start;
|
||||||
|
m_drag_start = mouse;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_render.set_camera_pos(m_camera_pos);
|
||||||
|
|
||||||
|
// Clear screen
|
||||||
|
Clear({24, 24, 24});
|
||||||
|
|
||||||
|
// Render only what we can see
|
||||||
|
auto min = -m_camera_pos / (TILE_SIZE + 1);
|
||||||
|
auto max = (screen - m_camera_pos) / (TILE_SIZE + 1);
|
||||||
|
|
||||||
|
for(int y = min.y() - 1; y < max.y() + 1; y++) {
|
||||||
|
for(int x = min.x() - 1; x < max.x() + 1; x++) {
|
||||||
|
auto node = m_map.at(Vector2<int>(x, y));
|
||||||
|
node.render(m_render);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw current coordinates in top left
|
||||||
|
char buf[128] = "";
|
||||||
|
sprintf(buf, "%d, %d", -m_camera_pos.x() / TILE_SIZE, -m_camera_pos.y() / TILE_SIZE);
|
||||||
|
DrawString(0, 0, buf, {255, 255, 255}, 1);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool App::OnUserDestroy() {
|
||||||
|
std::cout << "Destroy" << std::endl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
App app;
|
||||||
|
if (app.Construct(800, 600, 1, 1))
|
||||||
|
app.Start();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
25
src/app.h
Normal file
25
src/app.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#define OLC_PGE_APPLICATION
|
||||||
|
#include "olcPixelGameEngine.h"
|
||||||
|
|
||||||
|
#include "map/map.h"
|
||||||
|
#include "util/render.h"
|
||||||
|
|
||||||
|
class App : public olc::PixelGameEngine {
|
||||||
|
public:
|
||||||
|
App();
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool OnUserCreate() override;
|
||||||
|
bool OnUserUpdate(float delta) override;
|
||||||
|
bool OnUserDestroy() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Render m_render;
|
||||||
|
Map m_map;
|
||||||
|
|
||||||
|
Vector2<int> m_drag_start;
|
||||||
|
Vector2<int> m_camera_pos;
|
||||||
|
};
|
||||||
|
|
31
src/map/generator.cpp
Normal file
31
src/map/generator.cpp
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#include "map/generator.h"
|
||||||
|
#include "tiles/dirt.h"
|
||||||
|
#include "tiles/grass.h"
|
||||||
|
#include "tiles/stone.h"
|
||||||
|
|
||||||
|
Generator::Generator() {
|
||||||
|
// set_seed(420);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Generator::generate(Vector2<int> pos, Region ®ion) {
|
||||||
|
for(int y = 0; y < REGION_SIZE; y++) {
|
||||||
|
for(int x = 0; x < REGION_SIZE; x++) {
|
||||||
|
auto world_pos = pos * REGION_SIZE + Vector2<int>(x, y);
|
||||||
|
double noise = m_noise.accumulatedOctaveNoise2D_0_1(
|
||||||
|
world_pos.x() / 64.0,
|
||||||
|
world_pos.y() / 64.0,
|
||||||
|
5
|
||||||
|
);
|
||||||
|
|
||||||
|
Tile *tile;
|
||||||
|
if(noise > 0.85) {
|
||||||
|
tile = new Stone();
|
||||||
|
} else if(noise > 0.3) {
|
||||||
|
tile = new Grass();
|
||||||
|
} else {
|
||||||
|
tile = new Dirt();
|
||||||
|
}
|
||||||
|
region.at({x, y}).set_tile(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
src/map/generator.h
Normal file
19
src/map/generator.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "map/region.h"
|
||||||
|
#include "perlin.h"
|
||||||
|
#include "util/vector2.h"
|
||||||
|
|
||||||
|
class Generator {
|
||||||
|
public:
|
||||||
|
Generator();
|
||||||
|
|
||||||
|
// void set_seed(int seed) { m_noise.reseed(seed); }
|
||||||
|
int seed() { return m_seed; }
|
||||||
|
|
||||||
|
void generate(Vector2<int> pos, Region ®ion);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_seed;
|
||||||
|
siv::PerlinNoise m_noise;
|
||||||
|
};
|
62
src/map/map.cpp
Normal file
62
src/map/map.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include "map/map.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "tiles/grass.h"
|
||||||
|
|
||||||
|
#define MOD(a, b) (((b) + ((a) % (b))) % (b))
|
||||||
|
|
||||||
|
Node &Map::at(Vector2<int> pos) {
|
||||||
|
Vector2<int> region_offset = pos / (REGION_SIZE + 0);
|
||||||
|
// Floor division
|
||||||
|
if(pos.x() < 0 && pos.x() % REGION_SIZE) region_offset -= {1, 0};
|
||||||
|
if(pos.y() < 0 && pos.y() % REGION_SIZE) region_offset -= {0, 1};
|
||||||
|
|
||||||
|
auto it = m_reigons.find(region_offset);
|
||||||
|
|
||||||
|
if(it == m_reigons.end()) {
|
||||||
|
m_reigons.insert(
|
||||||
|
std::pair<Vector2<int>, Region>(
|
||||||
|
region_offset,
|
||||||
|
load_or_create_region(region_offset)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Region ®ion = m_reigons.at(region_offset);
|
||||||
|
|
||||||
|
Vector2<int> tile_offset = Vector2<int>(MOD(pos.x(), REGION_SIZE), MOD(pos.y(), REGION_SIZE));
|
||||||
|
return region.at(tile_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::set_tile(Vector2<int> pos, Tile *tile) {
|
||||||
|
at(pos).set_tile(tile);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::save() {
|
||||||
|
for(auto &elm : m_reigons) {
|
||||||
|
elm.second.save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Map::load() {
|
||||||
|
for(auto &elm : m_reigons) {
|
||||||
|
elm.second.load();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Region Map::load_or_create_region(Vector2<int> pos) {
|
||||||
|
Region region(pos);
|
||||||
|
if(!region.load()) {
|
||||||
|
std::cout << "Generating region @" << pos << std::endl;
|
||||||
|
// Call generator
|
||||||
|
m_grass.generate(pos, region);
|
||||||
|
|
||||||
|
// Save the newly generated region
|
||||||
|
region.save();
|
||||||
|
} else {
|
||||||
|
std::cout << "Loaded region @" << pos << std::endl;
|
||||||
|
}
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
24
src/map/map.h
Normal file
24
src/map/map.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "map/generator.h"
|
||||||
|
#include "map/region.h"
|
||||||
|
#include "util/vector2.h"
|
||||||
|
|
||||||
|
class Map {
|
||||||
|
public:
|
||||||
|
Map() = default;
|
||||||
|
|
||||||
|
Node &at(Vector2<int> pos);
|
||||||
|
void set_tile(Vector2<int> pos, Tile *tile);
|
||||||
|
|
||||||
|
void save();
|
||||||
|
void load();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Region load_or_create_region(Vector2<int> pos);
|
||||||
|
|
||||||
|
std::map<Vector2<int>, Region> m_reigons;
|
||||||
|
Generator m_grass;
|
||||||
|
};
|
68
src/map/node.cpp
Normal file
68
src/map/node.cpp
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#include "map/node.h"
|
||||||
|
|
||||||
|
#include "tiles/dirt.h"
|
||||||
|
#include "tiles/grass.h"
|
||||||
|
#include "tiles/stone.h"
|
||||||
|
|
||||||
|
Node::Node(const Node &other) {
|
||||||
|
if(other.m_tile) m_tile = other.m_tile->clone();
|
||||||
|
// if(other.m_entity) m_entity = other.m_entity->clone();
|
||||||
|
|
||||||
|
m_pos = other.m_pos;
|
||||||
|
m_size = other.m_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node::~Node() {
|
||||||
|
if(m_tile) delete m_tile;
|
||||||
|
// if(m_entity) delete(m_entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Node::render(Render r) {
|
||||||
|
if(m_tile)
|
||||||
|
m_tile->render(r, pos(), size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, const Node &node) {
|
||||||
|
os.write(reinterpret_cast<const char *>(&node.m_size), sizeof(node.m_size));
|
||||||
|
|
||||||
|
if(node.m_tile) {
|
||||||
|
os << '\x01';
|
||||||
|
os << *node.m_tile;
|
||||||
|
} else {
|
||||||
|
os << '\x00';
|
||||||
|
}
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream &operator>>(std::istream &is, Node &node) {
|
||||||
|
is.read(reinterpret_cast<char *>(&node.m_size), sizeof(node.m_size));
|
||||||
|
|
||||||
|
uint8_t has_tile = 0;
|
||||||
|
is.read(reinterpret_cast<char *>(&has_tile), sizeof(has_tile));
|
||||||
|
if(has_tile) {
|
||||||
|
int id = 0;
|
||||||
|
// TODO: Move / figure this shit out
|
||||||
|
is.read(reinterpret_cast<char *>(&id), sizeof(id));
|
||||||
|
Tile *tile;
|
||||||
|
switch(id) {
|
||||||
|
case -1:
|
||||||
|
tile = new Tile();
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
tile = new Dirt();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
tile = new Grass();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
tile = new Stone();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(tile) node.set_tile(tile);
|
||||||
|
is >> *node.m_tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
54
src/map/node.h
Normal file
54
src/map/node.h
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "tiles/tile.h"
|
||||||
|
#include "util/render.h"
|
||||||
|
#include "util/vector2.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Node {
|
||||||
|
public:
|
||||||
|
Node() : Node({0, 0}, {1, 1}) {}
|
||||||
|
Node(Vector2<int> pos, Vector2<int> size) :
|
||||||
|
m_pos(pos),
|
||||||
|
m_size(size) {}
|
||||||
|
|
||||||
|
Node(const Node &other);
|
||||||
|
Node &operator=(const Node &other) = default;
|
||||||
|
|
||||||
|
~Node();
|
||||||
|
|
||||||
|
// Get a reference to the tile associated with this node
|
||||||
|
Tile *tile() { return m_tile; }
|
||||||
|
void set_tile(Tile *tile) {
|
||||||
|
if(m_tile)
|
||||||
|
delete m_tile;
|
||||||
|
|
||||||
|
m_tile = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a reference to the tile entity associated with this node
|
||||||
|
// Entity &entity() { return *m_entity; }
|
||||||
|
|
||||||
|
// Get/Set the position in world coordinates
|
||||||
|
Vector2<int> pos() { return m_pos; }
|
||||||
|
void set_pos(Vector2<int> pos) { m_pos = pos; }
|
||||||
|
|
||||||
|
// Get/Set the size of this block in tiles
|
||||||
|
Vector2<int> size() { return m_size; }
|
||||||
|
void set_size(Vector2<int> size) { m_size = size; }
|
||||||
|
|
||||||
|
void render(Render r);
|
||||||
|
|
||||||
|
friend std::ostream &operator<<(std::ostream &os, const Node &node);
|
||||||
|
friend std::istream &operator>>(std::istream &is, Node &node);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Tile *m_tile = 0;
|
||||||
|
// Entity *m_entity;
|
||||||
|
|
||||||
|
Vector2<int> m_pos;
|
||||||
|
Vector2<int> m_size;
|
||||||
|
};
|
66
src/map/region.cpp
Normal file
66
src/map/region.cpp
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
#include "map/region.h"
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <fstream>
|
||||||
|
using std::ios;
|
||||||
|
using std::ofstream;
|
||||||
|
using std::ifstream;
|
||||||
|
|
||||||
|
Region::Region(Vector2<int> pos) :
|
||||||
|
m_pos(pos) {
|
||||||
|
// Initialize node positions
|
||||||
|
for(int y = 0; y < REGION_SIZE; y++)
|
||||||
|
for(int x = 0; x < REGION_SIZE; x++)
|
||||||
|
m_nodes[y][x] = Node(pos * REGION_SIZE + Vector2<int>(x, y), {1, 1});
|
||||||
|
}
|
||||||
|
|
||||||
|
Node &Region::at(Vector2<int> pos) {
|
||||||
|
if(pos.x() < 0 || pos.y() < 0 || pos.x() >= REGION_SIZE || pos.y() >= REGION_SIZE) {
|
||||||
|
printf("[ERR] Region::at(%i, %i): Invalid tile location!", pos.x(), pos.y());
|
||||||
|
return *(Node *)0; // TODO: Crash
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_nodes[pos.y()][pos.x()];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Region::save() {
|
||||||
|
char path[25];
|
||||||
|
sprintf(path, "region/%d_%d.dat", m_pos.x(), m_pos.y());
|
||||||
|
ofstream file;
|
||||||
|
file.open(path, ios::out | ios::binary);
|
||||||
|
|
||||||
|
if(!file.good()) return false;
|
||||||
|
|
||||||
|
file.write(reinterpret_cast<const char *>(&m_pos), sizeof(m_pos));
|
||||||
|
|
||||||
|
for(int y = 0; y < REGION_SIZE; y++)
|
||||||
|
for(int x = 0; x < REGION_SIZE; x++)
|
||||||
|
file << m_nodes[y][x];
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Region::load() {
|
||||||
|
char path[25];
|
||||||
|
sprintf(path, "region/%d_%d.dat", m_pos.x(), m_pos.y());
|
||||||
|
ifstream file;
|
||||||
|
file.open(path, ios::in | ios::binary);
|
||||||
|
|
||||||
|
if(!file.good()) return false;
|
||||||
|
|
||||||
|
file.read(reinterpret_cast<char *>(&m_pos), sizeof(m_pos));
|
||||||
|
|
||||||
|
for(int y = 0; y < REGION_SIZE; y++)
|
||||||
|
for(int x = 0; x < REGION_SIZE; x++) {
|
||||||
|
// Load node data
|
||||||
|
file >> m_nodes[y][x];
|
||||||
|
|
||||||
|
// Set node position
|
||||||
|
m_nodes[y][x].set_pos(m_pos * REGION_SIZE + Vector2<int>(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
24
src/map/region.h
Normal file
24
src/map/region.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "map/node.h"
|
||||||
|
|
||||||
|
#define REGION_SIZE 16
|
||||||
|
|
||||||
|
class Region {
|
||||||
|
public:
|
||||||
|
Region() : Region({0, 0}) {};
|
||||||
|
Region(Vector2<int> pos);
|
||||||
|
|
||||||
|
Vector2<int> pos() { return m_pos; };
|
||||||
|
|
||||||
|
Color m_color = Color::from_hsv(rand() % 254, 255, 255);
|
||||||
|
Node &at(Vector2<int> pos);
|
||||||
|
|
||||||
|
bool save();
|
||||||
|
bool load();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Vector2<int> m_pos;
|
||||||
|
|
||||||
|
Node m_nodes[REGION_SIZE][REGION_SIZE];
|
||||||
|
};
|
5105
src/olcPixelGameEngine.h
Normal file
5105
src/olcPixelGameEngine.h
Normal file
File diff suppressed because it is too large
Load diff
407
src/perlin.h
Normal file
407
src/perlin.h
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// siv::PerlinNoise
|
||||||
|
// Perlin noise library for modern C++
|
||||||
|
//
|
||||||
|
// Copyright (C) 2013-2020 Ryo Suzuki <reputeless@gmail.com>
|
||||||
|
//
|
||||||
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
// of this software and associated documentation files(the "Software"), to deal
|
||||||
|
// in the Software without restriction, including without limitation the rights
|
||||||
|
// to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
||||||
|
// copies of the Software, and to permit persons to whom the Software is
|
||||||
|
// furnished to do so, subject to the following conditions :
|
||||||
|
//
|
||||||
|
// The above copyright notice and this permission notice shall be included in
|
||||||
|
// all copies or substantial portions of the Software.
|
||||||
|
//
|
||||||
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||||
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
// THE SOFTWARE.
|
||||||
|
//
|
||||||
|
//----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# pragma once
|
||||||
|
# include <cstdint>
|
||||||
|
# include <algorithm>
|
||||||
|
# include <array>
|
||||||
|
# ifdef __cpp_concepts
|
||||||
|
# if __has_include(<concepts>)
|
||||||
|
# include <concepts>
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
# include <iterator>
|
||||||
|
# include <numeric>
|
||||||
|
# include <random>
|
||||||
|
# include <type_traits>
|
||||||
|
|
||||||
|
namespace siv
|
||||||
|
{
|
||||||
|
# ifdef __cpp_lib_concepts
|
||||||
|
template <std::floating_point Float>
|
||||||
|
# else
|
||||||
|
template <class Float>
|
||||||
|
# endif
|
||||||
|
class BasicPerlinNoise
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
using value_type = Float;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::uint8_t p[512];
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr value_type Fade(value_type t) noexcept
|
||||||
|
{
|
||||||
|
return t * t * t * (t * (t * 6 - 15) + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr value_type Lerp(value_type t, value_type a, value_type b) noexcept
|
||||||
|
{
|
||||||
|
return a + t * (b - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr value_type Grad(std::uint8_t hash, value_type x, value_type y, value_type z) noexcept
|
||||||
|
{
|
||||||
|
const std::uint8_t h = hash & 15;
|
||||||
|
const value_type u = h < 8 ? x : y;
|
||||||
|
const value_type v = h < 4 ? y : h == 12 || h == 14 ? x : z;
|
||||||
|
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
static constexpr value_type Weight(std::int32_t octaves) noexcept
|
||||||
|
{
|
||||||
|
value_type amp = 1;
|
||||||
|
value_type value = 0;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
value += amp;
|
||||||
|
amp /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
# if __has_cpp_attribute(nodiscard) >= 201907L
|
||||||
|
[[nodiscard]]
|
||||||
|
# endif
|
||||||
|
explicit BasicPerlinNoise(std::uint32_t seed = std::default_random_engine::default_seed)
|
||||||
|
{
|
||||||
|
reseed(seed);
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef __cpp_lib_concepts
|
||||||
|
template <std::uniform_random_bit_generator URNG>
|
||||||
|
# else
|
||||||
|
template <class URNG, std::enable_if_t<!std::is_arithmetic_v<URNG>>* = nullptr>
|
||||||
|
# endif
|
||||||
|
# if __has_cpp_attribute(nodiscard) >= 201907L
|
||||||
|
[[nodiscard]]
|
||||||
|
# endif
|
||||||
|
explicit BasicPerlinNoise(URNG&& urng)
|
||||||
|
{
|
||||||
|
reseed(std::forward<URNG>(urng));
|
||||||
|
}
|
||||||
|
|
||||||
|
void reseed(std::uint32_t seed)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
p[i] = static_cast<std::uint8_t>(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shuffle(std::begin(p), std::begin(p) + 256, std::default_random_engine(seed));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
p[256 + i] = p[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ifdef __cpp_lib_concepts
|
||||||
|
template <std::uniform_random_bit_generator URNG>
|
||||||
|
# else
|
||||||
|
template <class URNG, std::enable_if_t<!std::is_arithmetic_v<URNG>>* = nullptr>
|
||||||
|
# endif
|
||||||
|
void reseed(URNG&& urng)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
p[i] = static_cast<std::uint8_t>(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shuffle(std::begin(p), std::begin(p) + 256, std::forward<URNG>(urng));
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
p[256 + i] = p[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Noise [-1, 1]
|
||||||
|
//
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise1D(value_type x) const noexcept
|
||||||
|
{
|
||||||
|
return noise3D(x, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise2D(value_type x, value_type y) const noexcept
|
||||||
|
{
|
||||||
|
return noise3D(x, y, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise3D(value_type x, value_type y, value_type z) const noexcept
|
||||||
|
{
|
||||||
|
const std::int32_t X = static_cast<std::int32_t>(std::floor(x)) & 255;
|
||||||
|
const std::int32_t Y = static_cast<std::int32_t>(std::floor(y)) & 255;
|
||||||
|
const std::int32_t Z = static_cast<std::int32_t>(std::floor(z)) & 255;
|
||||||
|
|
||||||
|
x -= std::floor(x);
|
||||||
|
y -= std::floor(y);
|
||||||
|
z -= std::floor(z);
|
||||||
|
|
||||||
|
const value_type u = Fade(x);
|
||||||
|
const value_type v = Fade(y);
|
||||||
|
const value_type w = Fade(z);
|
||||||
|
|
||||||
|
const std::int32_t A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z;
|
||||||
|
const std::int32_t B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z;
|
||||||
|
|
||||||
|
return Lerp(w, Lerp(v, Lerp(u, Grad(p[AA], x, y, z),
|
||||||
|
Grad(p[BA], x - 1, y, z)),
|
||||||
|
Lerp(u, Grad(p[AB], x, y - 1, z),
|
||||||
|
Grad(p[BB], x - 1, y - 1, z))),
|
||||||
|
Lerp(v, Lerp(u, Grad(p[AA + 1], x, y, z - 1),
|
||||||
|
Grad(p[BA + 1], x - 1, y, z - 1)),
|
||||||
|
Lerp(u, Grad(p[AB + 1], x, y - 1, z - 1),
|
||||||
|
Grad(p[BB + 1], x - 1, y - 1, z - 1))));
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Noise [0, 1]
|
||||||
|
//
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise1D_0_1(value_type x) const noexcept
|
||||||
|
{
|
||||||
|
return noise1D(x)
|
||||||
|
* value_type(0.5) + value_type(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise2D_0_1(value_type x, value_type y) const noexcept
|
||||||
|
{
|
||||||
|
return noise2D(x, y)
|
||||||
|
* value_type(0.5) + value_type(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type noise3D_0_1(value_type x, value_type y, value_type z) const noexcept
|
||||||
|
{
|
||||||
|
return noise3D(x, y, z)
|
||||||
|
* value_type(0.5) + value_type(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Accumulated octave noise
|
||||||
|
// * Return value can be outside the range [-1, 1]
|
||||||
|
//
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type accumulatedOctaveNoise1D(value_type x, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
value_type result = 0;
|
||||||
|
value_type amp = 1;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += noise1D(x) * amp;
|
||||||
|
x *= 2;
|
||||||
|
amp /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result; // unnormalized
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type accumulatedOctaveNoise2D(value_type x, value_type y, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
value_type result = 0;
|
||||||
|
value_type amp = 1;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += noise2D(x, y) * amp;
|
||||||
|
x *= 2;
|
||||||
|
y *= 2;
|
||||||
|
amp /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result; // unnormalized
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type accumulatedOctaveNoise3D(value_type x, value_type y, value_type z, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
value_type result = 0;
|
||||||
|
value_type amp = 1;
|
||||||
|
|
||||||
|
for (std::int32_t i = 0; i < octaves; ++i)
|
||||||
|
{
|
||||||
|
result += noise3D(x, y, z) * amp;
|
||||||
|
x *= 2;
|
||||||
|
y *= 2;
|
||||||
|
z *= 2;
|
||||||
|
amp /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result; // unnormalized
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Normalized octave noise [-1, 1]
|
||||||
|
//
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctaveNoise1D(value_type x, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
return accumulatedOctaveNoise1D(x, octaves)
|
||||||
|
/ Weight(octaves);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctaveNoise2D(value_type x, value_type y, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
return accumulatedOctaveNoise2D(x, y, octaves)
|
||||||
|
/ Weight(octaves);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctaveNoise3D(value_type x, value_type y, value_type z, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
return accumulatedOctaveNoise3D(x, y, z, octaves)
|
||||||
|
/ Weight(octaves);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Accumulated octave noise clamped within the range [0, 1]
|
||||||
|
//
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type accumulatedOctaveNoise1D_0_1(value_type x, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
return std::clamp<value_type>(accumulatedOctaveNoise1D(x, octaves)
|
||||||
|
* value_type(0.5) + value_type(0.5), 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type accumulatedOctaveNoise2D_0_1(value_type x, value_type y, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
return std::clamp<value_type>(accumulatedOctaveNoise2D(x, y, octaves)
|
||||||
|
* value_type(0.5) + value_type(0.5), 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type accumulatedOctaveNoise3D_0_1(value_type x, value_type y, value_type z, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
return std::clamp<value_type>(accumulatedOctaveNoise3D(x, y, z, octaves)
|
||||||
|
* value_type(0.5) + value_type(0.5), 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Normalized octave noise [0, 1]
|
||||||
|
//
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctaveNoise1D_0_1(value_type x, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
return normalizedOctaveNoise1D(x, octaves)
|
||||||
|
* value_type(0.5) + value_type(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctaveNoise2D_0_1(value_type x, value_type y, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
return normalizedOctaveNoise2D(x, y, octaves)
|
||||||
|
* value_type(0.5) + value_type(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]]
|
||||||
|
value_type normalizedOctaveNoise3D_0_1(value_type x, value_type y, value_type z, std::int32_t octaves) const noexcept
|
||||||
|
{
|
||||||
|
return normalizedOctaveNoise3D(x, y, z, octaves)
|
||||||
|
* value_type(0.5) + value_type(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Serialization
|
||||||
|
//
|
||||||
|
void serialize(std::array<std::uint8_t, 256>& s) const noexcept
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
s[i] = p[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void deserialize(const std::array<std::uint8_t, 256>& s) noexcept
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < 256; ++i)
|
||||||
|
{
|
||||||
|
p[256 + i] = p[i] = s[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Legacy interface
|
||||||
|
//
|
||||||
|
[[deprecated("use noise1D() instead")]]
|
||||||
|
double noise(double x) const;
|
||||||
|
[[deprecated("use noise2D() instead")]]
|
||||||
|
double noise(double x, double y) const;
|
||||||
|
[[deprecated("use noise3D() instead")]]
|
||||||
|
double noise(double x, double y, double z) const;
|
||||||
|
|
||||||
|
[[deprecated("use noise1D_0_1() instead")]]
|
||||||
|
double noise0_1(double x) const;
|
||||||
|
[[deprecated("use noise2D_0_1() instead")]]
|
||||||
|
double noise0_1(double x, double y) const;
|
||||||
|
[[deprecated("use noise3D_0_1() instead")]]
|
||||||
|
double noise0_1(double x, double y, double z) const;
|
||||||
|
|
||||||
|
[[deprecated("use accumulatedOctaveNoise1D() instead")]]
|
||||||
|
double octaveNoise(double x, std::int32_t octaves) const;
|
||||||
|
[[deprecated("use accumulatedOctaveNoise2D() instead")]]
|
||||||
|
double octaveNoise(double x, double y, std::int32_t octaves) const;
|
||||||
|
[[deprecated("use accumulatedOctaveNoise3D() instead")]]
|
||||||
|
double octaveNoise(double x, double y, double z, std::int32_t octaves) const;
|
||||||
|
|
||||||
|
[[deprecated("use accumulatedOctaveNoise1D_0_1() instead")]]
|
||||||
|
double octaveNoise0_1(double x, std::int32_t octaves) const;
|
||||||
|
[[deprecated("use accumulatedOctaveNoise2D_0_1() instead")]]
|
||||||
|
double octaveNoise0_1(double x, double y, std::int32_t octaves) const;
|
||||||
|
[[deprecated("use accumulatedOctaveNoise3D_0_1() instead")]]
|
||||||
|
double octaveNoise0_1(double x, double y, double z, std::int32_t octaves) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
using PerlinNoise = BasicPerlinNoise<double>;
|
||||||
|
}
|
10
src/tiles/dirt.cpp
Normal file
10
src/tiles/dirt.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include "tiles/dirt.h"
|
||||||
|
|
||||||
|
void Dirt::render(Render r, Vector2<int>pos, Vector2<int>size) {
|
||||||
|
r.fill_rectangle_sz(
|
||||||
|
pos * (TILE_SIZE + 1),
|
||||||
|
size * TILE_SIZE,
|
||||||
|
{100, 50, 10}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
18
src/tiles/dirt.h
Normal file
18
src/tiles/dirt.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "tiles/tile.h"
|
||||||
|
|
||||||
|
class Dirt : public Tile {
|
||||||
|
public:
|
||||||
|
Dirt() : Tile(1) {}
|
||||||
|
|
||||||
|
Dirt(const Dirt &other) = default;
|
||||||
|
Dirt &operator=(const Dirt &other) = delete;
|
||||||
|
|
||||||
|
virtual ~Dirt() = default;
|
||||||
|
|
||||||
|
virtual Dirt *clone() { return new Dirt(*this); }
|
||||||
|
|
||||||
|
void render(Render r, Vector2<int>pos, Vector2<int>size) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
10
src/tiles/grass.cpp
Normal file
10
src/tiles/grass.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include "tiles/grass.h"
|
||||||
|
|
||||||
|
void Grass::render(Render r, Vector2<int>pos, Vector2<int>size) {
|
||||||
|
r.fill_rectangle_sz(
|
||||||
|
pos * (TILE_SIZE + 1),
|
||||||
|
size * TILE_SIZE,
|
||||||
|
{7, 176, 52}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
18
src/tiles/grass.h
Normal file
18
src/tiles/grass.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "tiles/tile.h"
|
||||||
|
|
||||||
|
class Grass : public Tile {
|
||||||
|
public:
|
||||||
|
Grass() : Tile(2) {}
|
||||||
|
|
||||||
|
Grass(const Grass &other) = default;
|
||||||
|
Grass &operator=(const Grass &other) = delete;
|
||||||
|
|
||||||
|
virtual ~Grass() = default;
|
||||||
|
|
||||||
|
virtual Grass *clone() { return new Grass(*this); }
|
||||||
|
|
||||||
|
void render(Render r, Vector2<int>pos, Vector2<int>size) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
10
src/tiles/stone.cpp
Normal file
10
src/tiles/stone.cpp
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#include "tiles/stone.h"
|
||||||
|
|
||||||
|
void Stone::render(Render r, Vector2<int>pos, Vector2<int>size) {
|
||||||
|
r.fill_rectangle_sz(
|
||||||
|
pos * (TILE_SIZE + 1),
|
||||||
|
size * TILE_SIZE,
|
||||||
|
{42, 42, 42}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
18
src/tiles/stone.h
Normal file
18
src/tiles/stone.h
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "tiles/tile.h"
|
||||||
|
|
||||||
|
class Stone : public Tile {
|
||||||
|
public:
|
||||||
|
Stone() : Tile(3) {}
|
||||||
|
|
||||||
|
Stone(const Stone &other) = default;
|
||||||
|
Stone &operator=(const Stone &other) = delete;
|
||||||
|
|
||||||
|
virtual ~Stone() = default;
|
||||||
|
|
||||||
|
virtual Stone *clone() { return new Stone(*this); }
|
||||||
|
|
||||||
|
void render(Render r, Vector2<int>pos, Vector2<int>size) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
23
src/tiles/tile.cpp
Normal file
23
src/tiles/tile.cpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
#include "tiles/tile.h"
|
||||||
|
|
||||||
|
void Tile::render(Render r, Vector2<int>pos, Vector2<int>size) {
|
||||||
|
r.rectangle_sz(
|
||||||
|
pos * (TILE_SIZE + 1),
|
||||||
|
size * TILE_SIZE,
|
||||||
|
m_color
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream &operator<<(std::ostream &os, const Tile &tile) {
|
||||||
|
os.write(reinterpret_cast<const char *>(&tile.m_id), sizeof(tile.m_id));
|
||||||
|
os.write(reinterpret_cast<const char *>(&tile.m_color), sizeof(tile.m_color));
|
||||||
|
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream &operator>>(std::istream &is, Tile &tile) {
|
||||||
|
is.read(reinterpret_cast<char *>(&tile.m_color), sizeof(tile.m_color));
|
||||||
|
|
||||||
|
return is;
|
||||||
|
}
|
||||||
|
|
34
src/tiles/tile.h
Normal file
34
src/tiles/tile.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "util/render.h"
|
||||||
|
#include "util/vector2.h"
|
||||||
|
|
||||||
|
#define TILE_SIZE 16
|
||||||
|
|
||||||
|
class Tile {
|
||||||
|
public:
|
||||||
|
Tile() : Tile(-1) {}
|
||||||
|
Tile(int id) : m_id(id) {}
|
||||||
|
|
||||||
|
Tile(const Tile &other) = default;
|
||||||
|
Tile &operator=(const Tile &other) = delete;
|
||||||
|
|
||||||
|
virtual ~Tile() = default;
|
||||||
|
|
||||||
|
virtual Tile *clone() { return new Tile(*this); }
|
||||||
|
|
||||||
|
// Get the tile's ID
|
||||||
|
int id() { return m_id; }
|
||||||
|
// void set_id(int id) { m_id = id; }
|
||||||
|
|
||||||
|
virtual void render(Render r, Vector2<int>pos, Vector2<int>size);
|
||||||
|
|
||||||
|
friend std::ostream &operator<<(std::ostream &os, const Tile &tile);
|
||||||
|
friend std::istream &operator>>(std::istream &is, Tile &tile);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_id;
|
||||||
|
Color m_color = Color::from_hsv(rand() % 255, 255, 255);
|
||||||
|
};
|
48
src/util/color.h
Normal file
48
src/util/color.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class Color {
|
||||||
|
public:
|
||||||
|
Color() = default;
|
||||||
|
Color(int r, int g, int b) : m_r(r), m_g(g), m_b(b) {}
|
||||||
|
|
||||||
|
int r() { return m_r; }
|
||||||
|
int g() { return m_g; }
|
||||||
|
int b() { return m_b; }
|
||||||
|
|
||||||
|
void set_r(int r) { m_r = r; }
|
||||||
|
void set_g(int g) { m_g = g; }
|
||||||
|
void set_b(int b) { m_b = b; }
|
||||||
|
|
||||||
|
static Color from_hsv(int h, int s, int v) {
|
||||||
|
if(s == 0) {
|
||||||
|
return {v, v, v};
|
||||||
|
}
|
||||||
|
|
||||||
|
int region = h / 43;
|
||||||
|
int remainder = (h - region * 43) * 6;
|
||||||
|
|
||||||
|
int p = (v * (255 - s)) >> 8;
|
||||||
|
int q = (v * (255 - ((s * remainder) >> 8))) >> 8;
|
||||||
|
int t = (v * (255 - ((s * (255 - remainder)) >> 8))) >> 8;
|
||||||
|
|
||||||
|
switch(region) {
|
||||||
|
case 0:
|
||||||
|
return {v, t, p};
|
||||||
|
case 1:
|
||||||
|
return {q, v, p};
|
||||||
|
case 2:
|
||||||
|
return {p, v, t};
|
||||||
|
case 3:
|
||||||
|
return {p, q, v};
|
||||||
|
case 4:
|
||||||
|
return {t, p, v};
|
||||||
|
default:
|
||||||
|
return {v, p ,q};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_r;
|
||||||
|
int m_g;
|
||||||
|
int m_b;
|
||||||
|
};
|
22
src/util/render.cpp
Normal file
22
src/util/render.cpp
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
#include "util/render.h"
|
||||||
|
|
||||||
|
void Render::rectangle(Vector2<int> start, Vector2<int> end, Color color) {
|
||||||
|
auto origin = start + m_camera_pos;
|
||||||
|
m_pge->DrawRect(origin.x(), origin.y(), end.x() - start.x(), end.y() - start.y(), olc::Pixel(color.r(), color.g(), color.b()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::rectangle_sz(Vector2<int> start, Vector2<int> size, Color color) {
|
||||||
|
auto origin = start + m_camera_pos;
|
||||||
|
m_pge->DrawRect(origin.x(), origin.y(), size.x(), size.y(), olc::Pixel(color.r(), color.g(), color.b()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::fill_rectangle(Vector2<int> start, Vector2<int> end, Color color) {
|
||||||
|
auto origin = start + m_camera_pos;
|
||||||
|
m_pge->FillRect(origin.x(), origin.y(), end.x() - start.x() + 1, end.y() - start.y() + 1, olc::Pixel(color.r(), color.g(), color.b()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Render::fill_rectangle_sz(Vector2<int> start, Vector2<int> size, Color color) {
|
||||||
|
auto origin = start + m_camera_pos;
|
||||||
|
m_pge->FillRect(origin.x(), origin.y(), size.x() + 1, size.y() + 1, olc::Pixel(color.r(), color.g(), color.b()));
|
||||||
|
}
|
||||||
|
|
24
src/util/render.h
Normal file
24
src/util/render.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "olcPixelGameEngine.h"
|
||||||
|
#include "util/color.h"
|
||||||
|
#include "util/vector2.h"
|
||||||
|
|
||||||
|
class Render {
|
||||||
|
public:
|
||||||
|
Render(olc::PixelGameEngine *pge) : m_pge(pge) {}
|
||||||
|
|
||||||
|
void rectangle(Vector2<int> start, Vector2<int> end, Color color = {0, 0, 0});
|
||||||
|
void rectangle_sz(Vector2<int> start, Vector2<int> size, Color color = {0, 0, 0});
|
||||||
|
|
||||||
|
void fill_rectangle(Vector2<int> start, Vector2<int> end, Color color = {0, 0, 0});
|
||||||
|
void fill_rectangle_sz(Vector2<int> start, Vector2<int> size, Color color = {0, 0, 0});
|
||||||
|
|
||||||
|
void set_camera_pos(Vector2<int> camera_pos) { m_camera_pos = camera_pos; }
|
||||||
|
Vector2<int> camera_pos() { return m_camera_pos; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
olc::PixelGameEngine *m_pge;
|
||||||
|
|
||||||
|
Vector2<int> m_camera_pos;
|
||||||
|
};
|
57
src/util/vector2.h
Normal file
57
src/util/vector2.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Vector2 {
|
||||||
|
public:
|
||||||
|
Vector2() = default;
|
||||||
|
Vector2(T x, T y) : m_x(x), m_y(y) {}
|
||||||
|
|
||||||
|
T x() { return m_x; }
|
||||||
|
T y() { return m_y; }
|
||||||
|
|
||||||
|
void set_x(T x) { m_x = x; }
|
||||||
|
void set_y(T y) { m_y = y; }
|
||||||
|
|
||||||
|
void set(T x, T y) { m_x = x; m_y = y; }
|
||||||
|
|
||||||
|
Vector2<T> operator-() const { return Vector2<T>(-m_x, -m_y); }
|
||||||
|
|
||||||
|
Vector2<T> &operator=(const Vector2<T> &other) { m_x = other.m_x; m_y = other.m_y; return *this; }
|
||||||
|
|
||||||
|
Vector2<T> operator+(const Vector2<T> &other) const { return Vector2(m_x + other.m_x, m_y + other.m_y); }
|
||||||
|
Vector2<T> &operator+=(const Vector2<T> &other) { m_x += other.m_x; m_y += other.m_y; return *this; }
|
||||||
|
|
||||||
|
Vector2<T> operator-(const Vector2<T> &other) const { return Vector2(m_x - other.m_x, m_y - other.m_y); }
|
||||||
|
Vector2<T> &operator-=(const Vector2<T> &other) { m_x -= other.m_x; m_y -= other.m_y; return *this; }
|
||||||
|
|
||||||
|
Vector2<T> operator*(const Vector2<T> &other) const { return Vector2(m_x * other.m_x, m_y * other.m_y); }
|
||||||
|
Vector2<T> &operator*=(const Vector2<T> &other) { m_x *= other.m_x; m_y *= other.m_y; return *this; }
|
||||||
|
Vector2<T> operator*(const T &s) const { return Vector2(m_x * s, m_y * s); }
|
||||||
|
Vector2<T> &operator*=(const T &s) { m_x *= s; m_y *= s; return *this; }
|
||||||
|
|
||||||
|
Vector2<T> operator/(const Vector2<T> &other) const { return Vector2(m_x / other.m_x, m_y / other.m_y); }
|
||||||
|
Vector2<T> &operator/=(const Vector2<T> &other) { m_x /= other.m_x; m_y /= other.m_y; return *this; }
|
||||||
|
Vector2<T> operator/(const T &s) const { return Vector2(m_x / s, m_y / s); }
|
||||||
|
Vector2<T> &operator/=(const T &s) { m_x /= s; m_y /= s; return *this; }
|
||||||
|
|
||||||
|
bool operator==(const Vector2<T> &other) const { return m_x == other.m_x && m_y == other.m_y; }
|
||||||
|
bool operator!=(const Vector2<T> &other) const { return m_x != other.m_x || m_y != other.m_y; }
|
||||||
|
|
||||||
|
bool operator<(const Vector2<T> &other) const { return m_x < other.m_x || (m_x == other.m_x && m_y < other.m_y); }
|
||||||
|
bool operator>(const Vector2<T> &other) const { return m_x > other.m_x || (m_x == other.m_x && m_y > other.m_y); }
|
||||||
|
|
||||||
|
bool operator<=(const Vector2<T> &other) const { return m_x <= other.m_x || (m_x == other.m_x && m_y <= other.m_y); }
|
||||||
|
bool operator>=(const Vector2<T> &other) const { return m_x >= other.m_x || (m_x == other.m_x && m_y >= other.m_y); }
|
||||||
|
|
||||||
|
friend std::ostream &operator<<(std::ostream &os, const Vector2<T> &vec) {
|
||||||
|
os << "Vector2(" << vec.m_x << ", " << vec.m_y << ")";
|
||||||
|
return os;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T m_x = 0;
|
||||||
|
T m_y = 0;
|
||||||
|
};
|
||||||
|
|
Loading…
Reference in a new issue