Skip to content

Commit

Permalink
add template to basic_engine, add camera move script
Browse files Browse the repository at this point in the history
  • Loading branch information
dedztbh committed Apr 21, 2024
1 parent a66a111 commit 93df0e9
Show file tree
Hide file tree
Showing 9 changed files with 170 additions and 96 deletions.
2 changes: 2 additions & 0 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ env.Alias("compiledb", compilation_db)

env = SConscript("godot-cpp/SConstruct", {"env": env, "customs": customs})

env.Append(CXXFLAGS=["-std=c++20"])

env.Append(CPPPATH=["src/"])
sources = Glob("src/*.cpp")

Expand Down
40 changes: 40 additions & 0 deletions game/Camera2D.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
extends Camera2D

# Speed of camera movement
@export var speed = 200
# Zoom speed
@export var zoom_speed = 0.1
# Minimum and maximum zoom levels
@export var min_zoom = 0.5
@export var max_zoom = 2.0

func _process(delta):
var motion = Vector2.ZERO

# Check for movement keys
if Input.is_action_pressed("ui_up"):
motion.y -= 1
if Input.is_action_pressed("ui_down"):
motion.y += 1
if Input.is_action_pressed("ui_left"):
motion.x -= 1
if Input.is_action_pressed("ui_right"):
motion.x += 1

# Normalize to prevent faster diagonal movement
motion = motion.normalized() * speed

# Apply the motion to the camera's position
position += motion * delta

# Zoom in
if Input.is_action_pressed("ui_zoom_in"):
zoom = Vector2(zoom.x - zoom_speed * delta, zoom.y - zoom_speed * delta)
zoom.x = max(min_zoom, zoom.x)
zoom.y = max(min_zoom, zoom.y)

# Zoom out
if Input.is_action_pressed("ui_zoom_out"):
zoom = Vector2(zoom.x + zoom_speed * delta, zoom.y + zoom_speed * delta)
zoom.x = min(max_zoom, zoom.x)
zoom.y = min(max_zoom, zoom.y)
13 changes: 9 additions & 4 deletions game/main.tscn
Original file line number Diff line number Diff line change
@@ -1,19 +1,24 @@
[gd_scene load_steps=3 format=3 uid="uid://dss4vqph6ixgk"]
[gd_scene load_steps=4 format=3 uid="uid://dss4vqph6ixgk"]

[ext_resource type="PackedScene" uid="uid://djahqxlcbinjp" path="res://board.tscn" id="1_i8xh8"]
[ext_resource type="Script" path="res://FPSCounter.gd" id="2_avnxl"]
[ext_resource type="Script" path="res://Camera2D.gd" id="2_wwmnb"]

[node name="Main" type="Node"]

[node name="Board" parent="." instance=ExtResource("1_i8xh8")]
columns = 100

[node name="Camera2D" type="Camera2D" parent="."]
offset = Vector2(500, 300)
script = ExtResource("2_wwmnb")
speed = 500
zoom_speed = 0.5
min_zoom = 1.0

[node name="FPSCounter" type="Label" parent="Camera2D"]
offset_left = -41.0
offset_top = -24.0
offset_right = -1.0
offset_bottom = -1.0
script = ExtResource("2_avnxl")

[node name="Board" parent="." instance=ExtResource("1_i8xh8")]
columns = 100
14 changes: 13 additions & 1 deletion game/project.godot
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,19 @@ config/name="GameOfLifePVP"
config/features=PackedStringArray("4.2", "GL Compatibility")
config/icon="res://icon.svg"

[input]

ui_zoom_in={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194323,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}
ui_zoom_out={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194324,"key_label":0,"unicode":0,"echo":false,"script":null)
]
}

[rendering]

renderer/rendering_method.mobile="gl_compatibility"
environment/defaults/default_clear_color=Color(0.301961, 0.301961, 0.301961, 1)
52 changes: 0 additions & 52 deletions src/basic_engine.cpp

This file was deleted.

93 changes: 86 additions & 7 deletions src/basic_engine.h
Original file line number Diff line number Diff line change
@@ -1,32 +1,111 @@
#ifndef LIFEPVP_BASIC_ENGINE_H
#define LIFEPVP_BASIC_ENGINE_H

#include <concepts>
#include <vector>

#include "engine_base.h"

namespace lifepvp::engine {

template<class T>
concept BoardConstructibleBySize = requires (T&& board) {
T(board.size());
};

template<class T>
concept BoardResizable = std::is_default_constructible_v<T> &&
requires (T board, size_t x) {
board.resize(x);
};

template<class T>
concept BasicEngineContainer =
std::move_constructible<T> &&
(BoardResizable<T> || BoardConstructibleBySize<T>) &&
requires (T& board, const T& cboard, size_t i) {
{ board[i] } -> std::convertible_to<EngineBase::state_t&>;
{ cboard[i] } -> std::convertible_to<EngineBase::state_t const&>;
};

template<BasicEngineContainer T = std::vector<EngineBase::state_t>>
class BasicEngine : public EngineBase {
public:
using board_t = std::vector<state_t>;
using board_t = std::remove_reference_t<T>;

BasicEngine(board_t&& board,
const size_t w,
const size_t h,
const update_cb_t update_cb,
const done_cb_t done_cb)
: EngineBase(w, h, update_cb, done_cb),
m_board_pair{board, board_t(board.size())} {}
: EngineBase(w, h, update_cb, done_cb) {
if constexpr (BoardConstructibleBySize<board_t>) {
m_board_pair = {board, board_t(board.size())};
} else {
static_assert(BoardResizable<board_t>);
m_board_pair = {board, board_t()};
m_board_pair[1].resize(w * h);
}
}

virtual ~BasicEngine() = default;
void next_iteration() override;
state_t get_state(size_t i, size_t j) override;

void next_iteration() override {
const auto& curr_board = m_board_pair[m_board];
auto& next_board = m_board_pair[m_board ^ 1];

for (size_t i = 0; i < W; ++i) {
for (size_t j = 0; j < H; ++j) {
static const std::pair<int64_t, int64_t> neighbor_offsets[]
{
{-1, -1}, {-1, 0}, {-1, 1},
{ 0, -1}, { 0, 1},
{ 1, -1}, { 1, 0}, { 1, 1}
};
size_t count = 0;
for (const auto [x, y] : neighbor_offsets) {
if (at(curr_board, (x+W+i)%W, (y+H+j)%H)) {
++count;
}
}

const state_t curr_cell = at(curr_board, i, j);
state_t& next_cell = at(next_board, i, j);
if (count < 2 || count > 3) {
next_cell = 0; // die
} else if (count == 3) {
next_cell = 1; // survive or create
} else { // count == 2
next_cell = curr_cell; // survive
}

if (next_cell != curr_cell) {
m_update_cb(i, j, next_cell);
}
}
}

m_board ^= 1;
m_done_cb();
}

state_t get_state(size_t i, size_t j) override {
return at(m_board_pair[m_board], i, j);
};

protected:
size_t m_board = 0;
std::array<board_t, 2> m_board_pair;

state_t& at(board_t& v, size_t i, size_t j);
const state_t& at(const board_t& v, size_t i, size_t j) const;
state_t& at(board_t& v, size_t i, size_t j) {
return v[i * W + j];
};

const state_t& at(const board_t& v, size_t i, size_t j) const {
return v[i * W + j];
};
};

}

#endif
4 changes: 4 additions & 0 deletions src/engine_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
#include <functional>
#include <cstdint>

namespace lifepvp::engine {

class EngineBase {
public:
using state_t = uint8_t;
Expand All @@ -26,4 +28,6 @@ class EngineBase {
const done_cb_t m_done_cb;
};

}

#endif
46 changes: 15 additions & 31 deletions src/life_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,23 @@

using namespace godot;

void LifeDriver::setup(const size_t w, const size_t h, const Variant& init_board, const EngineType engine) {

const auto init_board_to_vec = [&]() {
const PackedByteArray& array = std::forward<PackedByteArray>(init_board);
static_assert(sizeof(*(array.ptr())) == sizeof(EngineBase::state_t));
std::vector<EngineBase::state_t> vec(w * h);
memcpy(vec.data(), array.ptr(), sizeof(EngineBase::state_t) * vec.size());
return vec;
};
using namespace lifepvp::engine;

const auto get_board_vec = [&]() {
switch (init_board.get_type()) {
case Variant::NIL:
return std::vector<EngineBase::state_t>(w * h);
void LifeDriver::setup(const size_t w, const size_t h, const Variant& init_board, const EngineType engine) {

case Variant::PACKED_BYTE_ARRAY:
return init_board_to_vec();
break;

default:
ERR_PRINT("Unknown init_board type");
return std::vector<EngineBase::state_t>{};
}
};
const auto update_cell_cb = [&](size_t i, size_t j, uint8_t state) { emit_signal("update_cell", i, j, state); };
const auto update_done_cb = [&]() { emit_signal("update_done"); };

switch (engine) {
case BASIC:
m_engine = std::make_unique<BasicEngine>(get_board_vec(), w, h,
[&](size_t i, size_t j, uint8_t state) {
emit_signal("update_cell", i, j, state);
},
[&]() {
emit_signal("update_done");
}
);
if (init_board.get_type() == Variant::NIL) {
std::vector<EngineBase::state_t> board(w * h);
m_engine = std::make_unique<BasicEngine<>>(std::move(board), w, h, update_cell_cb, update_done_cb);
} else if (init_board.get_type() == Variant::PACKED_BYTE_ARRAY) {
m_engine = std::make_unique<BasicEngine<PackedByteArray>>(init_board, w, h, update_cell_cb, update_done_cb);
} else {
ERR_PRINT("Unknown init_board type");
}
break;

default:
Expand All @@ -56,7 +38,9 @@ void LifeDriver::setup(const size_t w, const size_t h, const Variant& init_board
}

void LifeDriver::next_iteration() {
m_engine->next_iteration();
if (m_engine) {
m_engine->next_iteration();
}
}

void LifeDriver::_bind_methods() {
Expand Down
2 changes: 1 addition & 1 deletion src/life_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class LifeDriver : public Object {
static void _bind_methods();

private:
std::unique_ptr<EngineBase> m_engine;
std::unique_ptr<lifepvp::engine::EngineBase> m_engine;
};

}
Expand Down

0 comments on commit 93df0e9

Please sign in to comment.