Various Refactoring

This commit is contained in:
2025-01-10 14:58:37 -05:00
parent 860f544467
commit d8c27dafb8
16 changed files with 265 additions and 213 deletions

View File

@@ -177,7 +177,7 @@ namespace CaveGame::Client {
}
// Debug Grid
//DrawChunkGrid();
DrawChunkGrid();
Vector2 transformed = camera.ScreenToWorld(mouse_pos);
@@ -291,19 +291,17 @@ namespace CaveGame::Client {
//void LocalWorld::LookForChunksNeedLoading()
void LocalWorld::LookForChunksNeedLoading()
{
// TODO: Make sure an extra layer of chunks beyond the viewport is generated.
// This will limit the amount of "pop-in" the player will notice.
Vector2 viewport_topleft = camera.ScaledViewport().minPoint;
Vector2 viewport_bottomright = camera.ScaledViewport().maxPoint;
int lower_bound_h = Math::Floor(viewport_topleft.x / Core::Chunk::ChunkSize);
int upper_bound_h = Math::Floor(viewport_bottomright.x / Core::Chunk::ChunkSize);
int lower_bound_h = Math::Floor(viewport_topleft.x / Core::Chunk::ChunkSize)-2;
int upper_bound_h = Math::Floor(viewport_bottomright.x / Core::Chunk::ChunkSize)+2;
int lower_bound_v = Math::Floor(viewport_topleft.y / Core::Chunk::ChunkSize);
int upper_bound_v = Math::Floor(viewport_bottomright.y / Core::Chunk::ChunkSize);
int lower_bound_v = Math::Floor(viewport_topleft.y / Core::Chunk::ChunkSize)-2;
int upper_bound_v = Math::Floor(viewport_bottomright.y / Core::Chunk::ChunkSize)+2;
for (int x = lower_bound_h; x <= upper_bound_h; x++)
{

View File

@@ -25,28 +25,21 @@ namespace CaveGame::ClientApp
class CaveGameWindow : public ReWindow::RWindow, public SceneManager
{
public:
[[nodiscard]] bool InGameSession() const;
[[nodiscard]] bool InMainMenu() const;
Client::AssetService assets;
CaveGame::Client::Splash* splash_ctx;
CaveGame::Client::MainMenu* menu_ctx;
CaveGame::Client::GameSession* game_ctx;
JUI::Scene* wm;
JUI::Window* settings_window;
JUI::Window* credits_window;
JUI::Window* console_window;
JUI::Window* stats_window;
//Scene* current_scene = nullptr;
bool render_grid = true;
bool generate_grid = true;
bool mbd = false;
float our_avg = 0.f;
/// Constructs and returns an instance of the game program.
@@ -86,7 +79,6 @@ namespace CaveGame::ClientApp
public:
void OnRefresh(float elapsed) override;
void OnMouseButtonDown(const ReWindow::MouseButtonDownEvent &ev) override;
void OnMouseButtonUp(const ReWindow::MouseButtonUpEvent &ev) override;
void OnKeyUp(const ReWindow::KeyUpEvent &ev) override;
void OnKeyDown(const ReWindow::KeyDownEvent& ev) override;

View File

@@ -1,5 +1,6 @@
#pragma once
#include <Event.h>
#include <J3ML/LinearAlgebra.hpp>
#include <vector>
#include "Color4.hpp"
@@ -11,9 +12,23 @@ namespace CaveGame::Core {
class StatusEffect {
};
class Lifeform {
public:
virtual int Health() const;
virtual void SetHealth(int hp);
};
class DamageSource {
};
class Entity {
public:
Event<> Died;
explicit Entity(const Vector2& spawnPoint);
int Health() const;
@@ -42,149 +57,6 @@ namespace CaveGame::Core {
};
class PhysicsEntity : public Entity {
public:
explicit PhysicsEntity(const Vector2& spawnPoint);
[[nodiscard]] Vector2 Velocity() const;
[[nodiscard]] Vector2 EstimatedNextPosition() const;
void Accelerate(const Vector2& vector);
virtual void PhysicsUpdate(float elapsed);
void CollisionTest(ITileMap* map, float elapsed) override
{
for (int x = -1; x <= bounding_box.x; x++) {
for (int y = -1; y <= bounding_box.y; y++) {
Vector2 tileBoxPos = Vector2(Math::Floor(position.x), Math::Floor(position.y)) + Vector2(x,y);
TileID id = map->GetTile(tileBoxPos.x, tileBoxPos.y);
if (id == TileID::VOID || id == TileID::AIR)
continue;
Vector2 entity_centroid = position + (bounding_box / 2.f);
Vector2 entity_halfbox = bounding_box / 2.f;
Vector2 tile_centroid = tileBoxPos + Vector2{0.5f, 0.5f};
Vector2 tile_halfbox = Vector2{0.5f, 0.5f};
if (Solver::AABB2Dvs(entity_centroid, entity_halfbox, tile_centroid, tile_halfbox)) {
Vector2 separation = Solver::SolveAABB(entity_centroid, entity_halfbox, tile_centroid, tile_halfbox);
Vector2 normal = Solver::GetNormalForAABB(separation, velocity);
next_position += separation;
// Touched top.
if (normal.y == -1)
velocity.y = 0;
if (normal.y == 1)
velocity.y = -velocity.y;
//if (normal.x != 0)
// velocity = {-velocity.x, velocity.y};
// TODO: Refine condition for "step-up"s
if (normal.x != 0 && velocity.y == 0)
next_position.y -= 1;
next_position += separation;
return;
}
}
}
}
void Update(float elapsed) override {
// TODO: Sophisticated mechanism to maintain locked-timestep, multiple-iteration physics steps.
PhysicsUpdate(elapsed);
}
protected:
Vector2 velocity;
Vector2 next_position;
float mass;
private:
};
class Humanoid : public PhysicsEntity {
public:
explicit Humanoid(const Vector2& spawnPoint) : PhysicsEntity(spawnPoint) { }
virtual int BaseDefense() const { return 0; }
virtual int ArmorDefense() const
{
return 0;
}
virtual int DefenseModifier() const { return 0;}
int Defense() const
{
return 0;
}
void Update(float elapsed) override {
PhysicsEntity::Update(elapsed);
}
void PhysicsUpdate(float elapsed) override {
PhysicsEntity::PhysicsUpdate(elapsed);
}
protected:
};
class Projectile : public PhysicsEntity
{
};
class Arrow : public Projectile {};
class Fireball : public Projectile {};
class Icecicle : public Projectile {};
class Player : public Humanoid {
public:
explicit Player(const Vector2& spawnPoint);
void Draw() override;
void Update(float elapsed) override;
void PhysicsUpdate(float elapsed) override;
void Jump() {
Accelerate({0, 1});
}
void Climb();
void Descend();
void Crouch();
void WalkLeft() {
Accelerate({-1, 0});
}
void WalkRight() {
Accelerate({1, 0});
}
protected:
};
class Zombie : public Humanoid {
public:
protected:
};
class ItemStack : PhysicsEntity {};
class PhysicalParticle {};

View File

@@ -0,0 +1,26 @@
#pragma once
#include <Core/PhysicsEntity.hpp>
namespace CaveGame::Core
{
class Humanoid : public PhysicsEntity {
public:
explicit Humanoid(const Vector2& spawnPoint);
virtual int BaseDefense() const { return 0; }
virtual int ArmorDefense() const { return 0; }
virtual int DefenseModifier() const { return 0;}
int Defense() const { return 0; }
void Update(float elapsed) override;
void PhysicsUpdate(float elapsed) override;
protected:
};
class Zombie : public Humanoid {
public:
protected:
};
}

View File

@@ -0,0 +1,7 @@
#pragma once
namespace CaveGame::Core
{
class ItemStack : PhysicsEntity {};
}

View File

@@ -0,0 +1,80 @@
#pragma once
#include "Entity.hpp"
namespace CaveGame::Core
{
class PhysicsEntity : public Entity {
public:
explicit PhysicsEntity(const Vector2& spawnPoint);
[[nodiscard]] Vector2 Velocity() const;
[[nodiscard]] Vector2 EstimatedNextPosition() const;
void Accelerate(const Vector2& vector);
virtual void PhysicsUpdate(float elapsed);
void CollisionTest(ITileMap* map, float elapsed) override
{
for (int x = -1; x <= bounding_box.x; x++) {
for (int y = -1; y <= bounding_box.y; y++) {
Vector2 tileBoxPos = Vector2(Math::Floor(position.x), Math::Floor(position.y)) + Vector2(x,y);
TileID id = map->GetTile(tileBoxPos.x, tileBoxPos.y);
if (id == TileID::VOID || id == TileID::AIR)
continue;
Vector2 entity_centroid = position + (bounding_box / 2.f);
Vector2 entity_halfbox = bounding_box / 2.f;
Vector2 tile_centroid = tileBoxPos + Vector2{0.5f, 0.5f};
Vector2 tile_halfbox = Vector2{0.5f, 0.5f};
if (Solver::AABB2Dvs(entity_centroid, entity_halfbox, tile_centroid, tile_halfbox)) {
Vector2 separation = Solver::SolveAABB(entity_centroid, entity_halfbox, tile_centroid, tile_halfbox);
Vector2 normal = Solver::GetNormalForAABB(separation, velocity);
next_position += separation;
// Touched top.
if (normal.y == -1)
velocity.y = 0;
if (normal.y == 1)
velocity.y = -velocity.y;
//if (normal.x != 0)
// velocity = {-velocity.x, velocity.y};
// TODO: Refine condition for "step-up"s
if (normal.x != 0 && velocity.y == 0)
next_position.y -= 1;
next_position += separation;
return;
}
}
}
}
void Update(float elapsed) override {
// TODO: Sophisticated mechanism to maintain locked-timestep, multiple-iteration physics steps.
PhysicsUpdate(elapsed);
}
protected:
Vector2 velocity;
Vector2 next_position;
float mass;
private:
};
}

View File

@@ -0,0 +1,29 @@
namespace CaveGame::Core
{
class Player : public Humanoid {
public:
explicit Player(const Vector2& spawnPoint);
void Draw() override;
void Update(float elapsed) override;
void PhysicsUpdate(float elapsed) override;
void Jump() {
Accelerate({0, 1});
}
void Climb();
void Descend();
void Crouch();
void WalkLeft() {
Accelerate({-1, 0});
}
void WalkRight() {
Accelerate({1, 0});
}
protected:
};
}

View File

@@ -0,0 +1,14 @@
#pragma once
namespace CaveGame::Core
{
class Projectile : public PhysicsEntity
{
};
class Arrow : public Projectile {};
class Fireball : public Projectile {};
class Icecicle : public Projectile {};
}

View File

@@ -35,6 +35,7 @@ namespace CaveGame::Core
/// The world class manages and coordinates terrain generation, chunk file IO, thread synchronization, and entity logic.
class World : public ITileMap {
public:
constexpr static float TileTiccRate = 48.f; // Ticcs per second.
constexpr static uint RandomTileTickCoefficient = 100;
constexpr static float PeriodicAutosaveIntervalSeconds = 30.f;
World() = default;
@@ -135,6 +136,8 @@ namespace CaveGame::Core
std::vector<Vector2> chunks_in_waiting;
ConcurrentQueue<Core::Chunk> ServedChunks;
float tile_ticc_counter;
private:

View File

@@ -4,10 +4,6 @@ CaveGame::Core::Entity::Entity(const Vector2 &spawnPoint) {
position = spawnPoint;
}
CaveGame::Core::Player::Player(const Vector2 &spawnPoint): Humanoid(spawnPoint) {
bounding_box = {16, 24};
}
int CaveGame::Core::Entity::Health() const { return health; }
int CaveGame::Core::Entity::MaxHealth() const { return max_health; }
@@ -15,38 +11,3 @@ int CaveGame::Core::Entity::MaxHealth() const { return max_health; }
Vector2 CaveGame::Core::Entity::Position() const { return position;}
Vector2 CaveGame::Core::Entity::Size() const { return bounding_box;}
CaveGame::Core::PhysicsEntity::PhysicsEntity(const Vector2 &spawnPoint): Entity(spawnPoint) {
next_position = spawnPoint;
}
Vector2 CaveGame::Core::PhysicsEntity::Velocity() const { return velocity; }
Vector2 CaveGame::Core::PhysicsEntity::EstimatedNextPosition() const { return next_position; }
void CaveGame::Core::PhysicsEntity::Accelerate(const Vector2 &vector) {
velocity += vector;
}
void CaveGame::Core::PhysicsEntity::PhysicsUpdate(float elapsed) {
next_position += velocity * elapsed;
float friction = 3.45f;
float gravity = 9.81f;
float mass = 32.f;
velocity *= (1 - (elapsed*friction));
velocity.y += (elapsed*gravity*mass);
position = next_position;
}
void CaveGame::Core::Player::Update(float elapsed) {
Humanoid::Update(elapsed);
}
void CaveGame::Core::Player::PhysicsUpdate(float elapsed) {
Humanoid::PhysicsUpdate(elapsed);
}

View File

@@ -0,0 +1,15 @@
#include <Core/Humanoid.hpp>
#include <J3ML/LinearAlgebra/Vector2.hpp>
namespace CaveGame::Core
{
Humanoid::Humanoid(const Vector2 &spawnPoint): PhysicsEntity(spawnPoint) { }
void Humanoid::Update(float elapsed) {
PhysicsEntity::Update(elapsed);
}
void Humanoid::PhysicsUpdate(float elapsed) {
PhysicsEntity::PhysicsUpdate(elapsed);
}
}

View File

@@ -0,0 +1,3 @@
//
// Created by dawsh on 1/10/25.
//

View File

@@ -0,0 +1,31 @@
#include <Core/PhysicsEntity.hpp>
#include <J3ML/LinearAlgebra/Vector2.hpp>
namespace CaveGame::Core
{
PhysicsEntity::PhysicsEntity(const Vector2 &spawnPoint): Entity(spawnPoint) {
next_position = spawnPoint;
}
Vector2 PhysicsEntity::Velocity() const { return velocity; }
Vector2 PhysicsEntity::EstimatedNextPosition() const { return next_position; }
void PhysicsEntity::Accelerate(const Vector2 &vector) {
velocity += vector;
}
void PhysicsEntity::PhysicsUpdate(float elapsed) {
next_position += velocity * elapsed;
float friction = 3.45f;
float gravity = 9.81f;
float mass = 32.f;
velocity *= (1 - (elapsed*friction));
velocity.y += (elapsed*gravity*mass);
position = next_position;
}
}

17
Core/src/Core/Player.cpp Normal file
View File

@@ -0,0 +1,17 @@
#include <Core/Entity.hpp>
#include <Core/Player.hpp>
namespace CaveGame::Core {
Player::Player(const Vector2 &spawnPoint): Humanoid(spawnPoint) {
bounding_box = {16, 24};
}
void Player::Update(float elapsed) {
Humanoid::Update(elapsed);
}
void Player::PhysicsUpdate(float elapsed) {
Humanoid::PhysicsUpdate(elapsed);
}
}

View File

@@ -0,0 +1,3 @@
//
// Created by dawsh on 1/10/25.
//

View File

@@ -25,8 +25,13 @@ namespace CaveGame::Core
}
if (simulate_tiles) {
DoRandomTileTicks();
DoForcedTileTicks();
tile_ticc_counter+=elapsed;
if (tile_ticc_counter > 1.f / TileTiccRate) {
tile_ticc_counter -= 1.f / TileTiccRate;
DoRandomTileTicks();
DoForcedTileTicks();
}
}
for (auto* entity : entities) {
@@ -34,14 +39,11 @@ namespace CaveGame::Core
entity->CollisionTest(this, elapsed);
}
}
TileID World::GetTile(int x, int y) const {
float chunkX = Math::Floor((float)x / Chunk::ChunkSize);
float chunkY = Math::Floor((float)y / Chunk::ChunkSize);
float tileX = Math::Mod(x, Chunk::ChunkSize);
float tileY = Math::Mod(y, Chunk::ChunkSize);
@@ -52,7 +54,6 @@ namespace CaveGame::Core
Vector2 coords = Vector2(chunkX, chunkY);
if (HasChunkAtCell(coords))
return loaded_chunks.at(coords).GetTile(tileX, tileY);
@@ -62,7 +63,6 @@ namespace CaveGame::Core
void World::SetTile(int x, int y, TileID t) {
float chunkX = Math::Floor((float)x / Chunk::ChunkSize);
float chunkY = Math::Floor((float)y / Chunk::ChunkSize);
float tileX = Math::Mod(x, Chunk::ChunkSize);
float tileY = Math::Mod(y, Chunk::ChunkSize);
@@ -71,12 +71,10 @@ namespace CaveGame::Core
if (tileY < 0)
tileY = Chunk::ChunkSize + tileY;
const Vector2 coords = Vector2(chunkX, chunkY);
if (HasChunkAtCell(coords))
{
loaded_chunks.at(coords).SetTile(tileX, tileY, t);
SetTileUpdateFlag(x, y-1, true);
@@ -248,12 +246,17 @@ namespace CaveGame::Core
RequestedChunks.front_pop(cell);
if (HasChunkOnFile(cell)) {
ServedChunks.emplace(Core::Chunk(cell, GetChunkFullPath(cell)));
//std::thread([&]() {
ServedChunks.emplace(Core::Chunk(cell, GetChunkFullPath(cell)));
//}).detach();
} else {
Core::Chunk chunk(cell);
generator.FirstPass(chunk);
//SaveChunkToFile(cell, chunk);
ServedChunks.emplace(chunk);
//std::thread( [&]() {
Core::Chunk chunk(cell);
generator.FirstPass(chunk);
//SaveChunkToFile(cell, chunk);
ServedChunks.emplace(chunk);
//}).detach();
}
@@ -358,11 +361,9 @@ namespace CaveGame::Core
chunk.SetTileUpdateFlag(x, y, false);
}
}
}
}
}
}
void World::DoRandomTileTicks() {