Various edits going live. #56
@@ -20,8 +20,8 @@ set(CMAKE_CXX_STANDARD 23)
|
||||
if (UNIX)
|
||||
# TODO: Enable ALL optimization flags for RELEASE builds.
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -floop-nest-optimize -funroll-loops")
|
||||
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -floop-nest-optimize -funroll-loops")
|
||||
endif()
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
@@ -39,7 +39,7 @@ CPMAddPackage(
|
||||
|
||||
CPMAddPackage(
|
||||
NAME jjx
|
||||
URL https://git.redacted.cc/josh/jjx/archive/Release-1.zip
|
||||
URL https://git.redacted.cc/josh/jjx/archive/Release-1.1.zip
|
||||
)
|
||||
|
||||
CPMAddPackage(
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
/// @file AssetService.hpp
|
||||
/// @desc Manages game asset data.
|
||||
/// @edit 1/28/2025
|
||||
/// @edit 3/31/2025
|
||||
/// @auth Josh O'Leary
|
||||
|
||||
/// The AssetService is a class / static library that manages on-file game assets.
|
||||
@@ -21,9 +21,10 @@
|
||||
#include <JGL/types/Texture.h>
|
||||
#include <JGL/types/Font.h>
|
||||
#include <queue>
|
||||
#include <Core/Singleton.hpp>
|
||||
#include <Core/Macros.hpp>
|
||||
|
||||
namespace CaveGame::Client
|
||||
{
|
||||
namespace CaveGame::Client {
|
||||
|
||||
using namespace JGL;
|
||||
|
||||
@@ -32,6 +33,7 @@ namespace CaveGame::Client
|
||||
|
||||
|
||||
struct AssetRequest {
|
||||
std::string name;
|
||||
std::filesystem::path path;
|
||||
AssetType type;
|
||||
};
|
||||
@@ -62,9 +64,9 @@ namespace CaveGame::Client
|
||||
//return fonts[fontName];
|
||||
}
|
||||
|
||||
void EnqueueTexture(const std::filesystem::path &path);
|
||||
void EnqueueFont(const std::filesystem::path& path);
|
||||
void EnqueueSound(const std::filesystem::path& path);
|
||||
void EnqueueTexture(const std::string& name, const std::filesystem::path &path);
|
||||
void EnqueueFont(const std::string& name, const std::filesystem::path& path);
|
||||
void EnqueueSound(const std::string& name, const std::filesystem::path& path);
|
||||
|
||||
void LoadAllFromQueue();
|
||||
|
||||
@@ -81,6 +83,9 @@ namespace CaveGame::Client
|
||||
unsigned int TotalQueued() const { return total_queued; }
|
||||
unsigned int TotalLoaded() const { return total_loaded; }
|
||||
|
||||
void ParseManifest();
|
||||
void PreloadCertainAssets();
|
||||
|
||||
protected:
|
||||
|
||||
/// @returns only the filename of the given path.
|
||||
|
@@ -25,24 +25,14 @@
|
||||
#include <Core/Item.hpp>
|
||||
#include "TileTool.hpp"
|
||||
#include "ContainerWindow.hpp"
|
||||
#include <Client/PauseMenu.hpp>
|
||||
|
||||
namespace CaveGame::Client {
|
||||
using namespace Core;
|
||||
|
||||
class LootTable {
|
||||
|
||||
};
|
||||
|
||||
class LootTable {};
|
||||
class CraftingStation {};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ContainerGUI {
|
||||
|
||||
};
|
||||
class ContainerGUI {};
|
||||
|
||||
using namespace JUI::UDimLiterals;
|
||||
using CaveGame::Core::Entity;
|
||||
@@ -50,7 +40,7 @@ namespace CaveGame::Client {
|
||||
public:
|
||||
|
||||
GameSession() = default;
|
||||
GameSession(bool createNewWorld);
|
||||
explicit GameSession(bool createNewWorld);
|
||||
void Update(float elapsed) override;
|
||||
void Draw() override;
|
||||
void Load() override;
|
||||
@@ -99,6 +89,7 @@ namespace CaveGame::Client {
|
||||
LocalWorld* world = nullptr;
|
||||
TileHotbar hotbar;
|
||||
JUI::Scene* hud = nullptr;
|
||||
PauseMenuWidget* pause_menu = nullptr;
|
||||
Vector2 mouse_pos = {0,0};
|
||||
RNG tool_rng;
|
||||
|
||||
|
@@ -46,7 +46,7 @@ namespace CaveGame::Client
|
||||
JUI::Rect* title = nullptr;
|
||||
JUI::Rect* button_group = nullptr;
|
||||
JUI::Rect* changelog = nullptr;
|
||||
JGL::Texture* bg = nullptr; // TODO: RAII on this
|
||||
std::shared_ptr<JGL::Texture> bg = nullptr; // TODO: RAII on this
|
||||
|
||||
Vector2 mpos {0,0};
|
||||
Vector2 goal {0,0};
|
||||
|
56
Client/include/Client/PauseMenu.hpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#include <JUI/Widgets/Rect.hpp>
|
||||
#include <JUI/Widgets/ListLayout.hpp>
|
||||
#include <JUI/Widgets/TextButton.hpp>
|
||||
|
||||
namespace CaveGame::Client
|
||||
{
|
||||
using namespace JUI::UDimLiterals;
|
||||
|
||||
class PauseMenuWidget : public JUI::Rect {
|
||||
public:
|
||||
Event<> OnSettingsButtonPressed;
|
||||
Event<> OnQuitButtonPressed;
|
||||
|
||||
PauseMenuWidget() {
|
||||
this->Size({100_percent, 100_percent}); // Full Screen.
|
||||
this->BGColor({128, 128, 128, 128}); // Transparent Gray.
|
||||
|
||||
button_box = new JUI::Rect(this);
|
||||
button_box->Size({150_px, 150_px});
|
||||
|
||||
button_list = new JUI::VerticalListLayout(button_box);
|
||||
|
||||
resume_btn = new JUI::TextButton(button_list);
|
||||
resume_btn->SetContent("Resume");
|
||||
|
||||
|
||||
settings_btn = new JUI::TextButton(button_list);
|
||||
settings_btn->SetContent("Settings");
|
||||
|
||||
quit_btn = new JUI::TextButton(button_list);
|
||||
quit_btn->SetContent("Save & Exit World");
|
||||
}
|
||||
|
||||
explicit PauseMenuWidget(Widget* parent) : PauseMenuWidget() {
|
||||
this->Parent(parent);
|
||||
}
|
||||
|
||||
void Toggle() {
|
||||
is_open = !is_open;
|
||||
this->Visible(is_open);
|
||||
}
|
||||
protected:
|
||||
JUI::Rect* button_box;
|
||||
JUI::VerticalListLayout* button_list;
|
||||
JUI::TextButton* resume_btn;
|
||||
JUI::TextButton* settings_btn;
|
||||
JUI::TextButton* quit_btn;
|
||||
|
||||
bool is_open;
|
||||
private:
|
||||
};
|
||||
|
||||
|
||||
}
|
@@ -12,11 +12,48 @@
|
||||
#pragma once
|
||||
|
||||
#include <JUI/Widgets/Window.hpp>
|
||||
#include <JUI/Widgets/Collapsible.hpp>
|
||||
#include <JUI/Widgets/ListLayout.hpp>
|
||||
#include <Core/Singleton.hpp>
|
||||
|
||||
namespace CaveGame::Client
|
||||
{
|
||||
class SettingsMenu : public JUI::Window
|
||||
|
||||
namespace CaveGame::Client {
|
||||
|
||||
// TODO: Analyze behavior of singleton on an object that requires specific initialization, like this.
|
||||
class SettingsMenu : public JUI::Window, public Singleton<SettingsMenu>
|
||||
{
|
||||
public:
|
||||
SettingsMenu()
|
||||
{
|
||||
SetTitle("Settings");
|
||||
|
||||
auto* root_layout = new JUI::VerticalListLayout(this);
|
||||
|
||||
general_section = new JUI::Collapsible(root_layout);
|
||||
general_section->Title("General");
|
||||
|
||||
auto* gen_layout = new JUI::VerticalListLayout(general_section);
|
||||
|
||||
|
||||
sound_section = new JUI::Collapsible(root_layout);
|
||||
sound_section->Title("Sound");
|
||||
|
||||
auto* snd_layout = new JUI::VerticalListLayout(sound_section);
|
||||
|
||||
graphics_section = new JUI::Collapsible(root_layout);
|
||||
graphics_section->Title("Graphics");
|
||||
|
||||
auto* gfx_layout = new JUI::VerticalListLayout(graphics_section);
|
||||
|
||||
input_section = new JUI::Collapsible(root_layout);
|
||||
input_section->Title("Input");
|
||||
|
||||
}
|
||||
protected:
|
||||
JUI::Collapsible* general_section;
|
||||
JUI::Collapsible* sound_section;
|
||||
JUI::Collapsible* graphics_section;
|
||||
JUI::Collapsible* input_section;
|
||||
private:
|
||||
};
|
||||
}
|
@@ -32,7 +32,7 @@ namespace CaveGame::Client
|
||||
protected:
|
||||
float splash_timer = 1.5f;
|
||||
float load_percent = 0.f;
|
||||
JGL::Texture* splash = nullptr;
|
||||
std::shared_ptr<JGL::Texture> splash = nullptr;
|
||||
|
||||
std::array<JGL::RenderTarget*, 16> column_textures{};
|
||||
int column_width = 0;
|
||||
|
@@ -63,8 +63,9 @@ namespace CaveGame::Client {
|
||||
TextRect* tool_size_label;
|
||||
TextButton* step_btn;
|
||||
TextButton* step2_btn;
|
||||
TextButton* step3_btn;
|
||||
bool enabled = false;
|
||||
bool tile_sim_disabled;
|
||||
bool tile_sim_disabled = false;
|
||||
private:
|
||||
};
|
||||
}
|
@@ -1,6 +1,8 @@
|
||||
#include <Client/AssetService.hpp>
|
||||
#include <thread>
|
||||
#include <JGL/types/Texture.h>
|
||||
#include <JJX/JSON.hpp>
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
static CaveGame::Client::AssetService* singleton;
|
||||
@@ -9,18 +11,20 @@ CaveGame::Client::AssetService * CaveGame::Client::AssetService::Get() { return
|
||||
|
||||
CaveGame::Client::AssetService::AssetService() {
|
||||
singleton = this;
|
||||
|
||||
ParseManifest();
|
||||
}
|
||||
|
||||
void CaveGame::Client::AssetService::TempLoadSimple() {
|
||||
player_sprite = new JGL::Texture("assets/textures/player.png", JGL::FilteringMode::NEAREST);
|
||||
explosion_sprite = new JGL::Texture("assets/textures/explosion.png", JGL::FilteringMode::NEAREST);
|
||||
title_img = new JGL::Texture("assets/textures/title_1.png");
|
||||
//player_sprite = new JGL::Texture("assets/textures/player.png", JGL::FilteringMode::NEAREST);
|
||||
//explosion_sprite = new JGL::Texture("assets/textures/explosion.png", JGL::FilteringMode::NEAREST);
|
||||
//title_img = new JGL::Texture("assets/textures/title_1.png");
|
||||
}
|
||||
|
||||
void CaveGame::Client::AssetService::EnqueueDefaultAssetsFolder() {
|
||||
//EnqueueContents("assets");
|
||||
|
||||
textures.emplace("player", new JGL::Texture("assets/textures/player.png"));
|
||||
//textures.emplace("player", new JGL::Texture("assets/textures/player.png"));
|
||||
|
||||
}
|
||||
|
||||
@@ -35,27 +39,31 @@ std::string CaveGame::Client::AssetService::FilenameFromPathWithoutExtension(con
|
||||
return base.substr(0, p);
|
||||
}
|
||||
|
||||
void CaveGame::Client::AssetService::EnqueueTexture(const std::filesystem::path &path) {
|
||||
queue.push({path, AssetType::TEXTURE});
|
||||
void CaveGame::Client::AssetService::EnqueueTexture(const std::string& name, const std::filesystem::path &path) {
|
||||
queue.push({name, path, AssetType::TEXTURE});
|
||||
total_queued++;
|
||||
}
|
||||
|
||||
void CaveGame::Client::AssetService::EnqueueFont(const std::filesystem::path &path) {
|
||||
queue.push({path, AssetType::FONT});
|
||||
void CaveGame::Client::AssetService::EnqueueFont(const std::string& name, const std::filesystem::path &path) {
|
||||
queue.push({name, path, AssetType::FONT});
|
||||
total_queued++;
|
||||
}
|
||||
|
||||
void CaveGame::Client::AssetService::EnqueueSound(const std::filesystem::path &path) {
|
||||
queue.push({path, AssetType::AUDIO});
|
||||
void CaveGame::Client::AssetService::EnqueueSound(const std::string& name, const std::filesystem::path &path) {
|
||||
queue.push({name, path, AssetType::AUDIO});
|
||||
total_queued++;
|
||||
}
|
||||
|
||||
bool CaveGame::Client::AssetService::LoadAsset(const CaveGame::Client::AssetRequest &request) {
|
||||
last_asset_processed = request.path;
|
||||
|
||||
switch(request.type) {
|
||||
case AssetType::TEXTURE: {
|
||||
auto texture =std::make_shared<Texture>(request.path);
|
||||
textures[request.path] = texture;
|
||||
if (textures.contains(request.name)) // TODO: Note repeat request.
|
||||
return true;
|
||||
|
||||
auto texture = std::make_shared<Texture>(request.path, FilteringMode::NEAREST);
|
||||
textures[request.name] = texture;
|
||||
}
|
||||
default: {
|
||||
// TODO: We don't support this asset type yet!!!
|
||||
@@ -109,3 +117,53 @@ void CaveGame::Client::AssetService::LoadAllFromQueue() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaveGame::Client::AssetService::ParseManifest() {
|
||||
std::string contents = read_file("assets/data/manifest.json");
|
||||
|
||||
using namespace JJX;
|
||||
|
||||
auto [obj, errcode] = json::parse(contents);
|
||||
|
||||
json::object catalog = obj.as_object();
|
||||
|
||||
// TODO: in this case, calling obj.at("textures") results in a bad_alloc?
|
||||
|
||||
if (catalog.contains("textures")) {
|
||||
json::array texlist = catalog.at("textures").as_array();
|
||||
for (auto& texture_entry : texlist) {
|
||||
std::string name = texture_entry[0].string.value();
|
||||
std::string path = texture_entry[1].string.value();
|
||||
EnqueueTexture(name, path);
|
||||
}
|
||||
}
|
||||
|
||||
if (catalog.contains("fonts")) {
|
||||
for (auto &font_entry: catalog["fonts"].as_array()) {
|
||||
std::string name = font_entry[0].string.value();
|
||||
std::string path = font_entry[1].string.value();
|
||||
EnqueueFont(name, path);
|
||||
}
|
||||
}
|
||||
|
||||
if (catalog.contains("sfx")) {
|
||||
for (auto &sfx_entry: catalog["sfx"].as_array()) {
|
||||
std::string name = sfx_entry[0].string.value();
|
||||
std::string path = sfx_entry[1].string.value();
|
||||
EnqueueSound(name, path);
|
||||
}
|
||||
}
|
||||
|
||||
if (catalog.contains("music")) {
|
||||
for (auto &sfx_entry: catalog["music"].as_array()) {
|
||||
std::string name = sfx_entry[0].string.value();
|
||||
std::string path = sfx_entry[1].string.value();
|
||||
EnqueueSound(name, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaveGame::Client::AssetService::PreloadCertainAssets() {
|
||||
LoadAsset({"redacted", "assets/textures/redacted.png", AssetType::TEXTURE});
|
||||
LoadAsset({"title", "assets/textures/title_1.png", AssetType::TEXTURE});
|
||||
}
|
||||
|
@@ -116,13 +116,14 @@ namespace CaveGame::Client
|
||||
|
||||
Vector2 Camera2D::Position() const { return position; }
|
||||
|
||||
void Camera2D::MoveLeft(float rate) {
|
||||
position -= Vector2(move_speed * rate, 0);
|
||||
void Camera2D::Move(const Vector2& dir)
|
||||
{
|
||||
position += dir * move_speed;
|
||||
last_free_move = 0;
|
||||
}
|
||||
|
||||
void Camera2D::Move(const Vector2& velocity)
|
||||
{
|
||||
position += velocity * move_speed;
|
||||
void Camera2D::MoveLeft(float rate) {
|
||||
position -= Vector2(move_speed * rate, 0);
|
||||
last_free_move = 0;
|
||||
}
|
||||
|
||||
|
@@ -24,6 +24,9 @@ void CaveGame::Client::GameSession::Load() {
|
||||
world->PostInit();
|
||||
Logs::Info("Building player HUD.");
|
||||
hud = new JUI::Scene();
|
||||
|
||||
pause_menu = new PauseMenuWidget(hud);
|
||||
|
||||
hotbar = TileHotbar();
|
||||
// TODO: Redundant, use the constructor.
|
||||
hotbar.Load(world);
|
||||
@@ -98,8 +101,6 @@ void CaveGame::Client::GameSession::WorldEditToolDrawTiles(TileID tile) {
|
||||
//Vector2i rounded_coords = {Math::FloorInt(world_coords.x), Math::FloorInt(world_coords.y)};
|
||||
|
||||
|
||||
|
||||
|
||||
int radius = Math::FloorInt(tile_tool->BrushRadius());
|
||||
int density = Math::FloorInt(tile_tool->BrushDensity());
|
||||
int x = Math::FloorInt(world_coords.x);
|
||||
@@ -183,7 +184,7 @@ void CaveGame::Client::GameSession::Update(float elapsed) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Move the tile cursor when controller thumbstick is moved.
|
||||
auto rstick = jstick::GetRightThumbstickAxisNormalized();
|
||||
|
||||
if (rstick.Magnitude() > 0.1f)
|
||||
@@ -191,40 +192,6 @@ void CaveGame::Client::GameSession::Update(float elapsed) {
|
||||
float joystick_cursor_speed = 250.f;
|
||||
mouse_pos += rstick*elapsed*joystick_cursor_speed;
|
||||
}
|
||||
|
||||
|
||||
// FIXME: Temporary hack, we poll the bumper button state each frame, cause the jstick event doesn't propagate for some reason.
|
||||
/* bool lprn = jstick::IsButtonDown(jstick::XBoxButton::BumperL);
|
||||
bool rprn = jstick::IsButtonDown(jstick::XBoxButton::BumperR);
|
||||
|
||||
if (lprn && !lp)
|
||||
hotbar.PrevSlot();
|
||||
|
||||
if (rprn && !rp)
|
||||
hotbar.NextSlot();
|
||||
|
||||
lp = lprn;
|
||||
rp = rprn;*/
|
||||
|
||||
|
||||
/*
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
float angle = tool_rng.Float01Incl() * Math::TwoPi;
|
||||
Vector2 unit = {Math::Cos(angle), Math::Sin(angle)};
|
||||
Vector2 velocity = unit * tool_rng.Float(1, 50);
|
||||
world->Emit({.position = transformed, .velocity = velocity, .color = Colors::Red, .size = 2, .life = 3});
|
||||
}
|
||||
*/
|
||||
|
||||
// TODO: Do this once JUI can consume input.
|
||||
//
|
||||
// WorldEditToolControlsUpdate(elapsed);
|
||||
|
||||
//for (auto& entity: entity_list)
|
||||
//{
|
||||
// entity->Update(elapsed);
|
||||
//}
|
||||
}
|
||||
|
||||
void CaveGame::Client::GameSession::WorldEditToolDrawOverlay()
|
||||
@@ -275,6 +242,9 @@ void CaveGame::Client::GameSession::PassWindowSize(const Vector2 &size) {
|
||||
void CaveGame::Client::GameSession::PassKeyInput(Key key, bool pressed) {
|
||||
// DO NOT chain input conditions with else; you will introduce biasing
|
||||
|
||||
if (key == Keys::Escape)
|
||||
pause_menu->Toggle();
|
||||
|
||||
hud->ObserveKeyInput(key, pressed);
|
||||
hotbar.OnKeyInput(key, pressed);
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ void CaveGame::Client::MainMenu::Draw() {
|
||||
|
||||
void CaveGame::Client::MainMenu::Load() {
|
||||
|
||||
bg = new JGL::Texture("assets/textures/bg.png");
|
||||
bg = AssetService::Get()->GetTexture("bg");
|
||||
|
||||
|
||||
Scene::Load();
|
||||
@@ -86,7 +86,8 @@ void CaveGame::Client::MainMenu::BuildWidgets() {
|
||||
title->BorderWidth(0);
|
||||
|
||||
auto* content = new JUI::Image(title);
|
||||
content->Content(Client::AssetService::Get()->title_img);
|
||||
// TODO: Unsafe!
|
||||
content->Content(AssetService::Get()->GetTexture("title").get());
|
||||
content->FitImageToParent(true);
|
||||
|
||||
button_group = new Rect(scene);
|
||||
|
@@ -39,8 +39,8 @@ void CaveGame::Core::Player::Draw() {
|
||||
|
||||
// TODO: Utilize land quad when falling enough to take fall damage, player can't move for a half second.
|
||||
|
||||
auto myAsset = Client::AssetService::Get()->player_sprite;
|
||||
JGL::J2D::DrawPartialSprite(myAsset, RenderTopLeft(), quad.minPoint, {16, 24}, 0, {0,0}, {1,1}, Colors::White, dir);
|
||||
auto myAsset = Client::AssetService::Get()->GetTexture("player");
|
||||
JGL::J2D::DrawPartialSprite(myAsset.get(), RenderTopLeft(), quad.minPoint, {16, 24}, 0, {0,0}, {1,1}, Colors::White, dir);
|
||||
JGL::J2D::OutlineRect(Colors::Red, RenderTopLeft(), texture_center * 2.f);
|
||||
JGL::J2D::OutlineRect(Colors::Blue, TopLeft(), bounding_box);
|
||||
J2D::DrawString(Colors::White, std::format("vel: {},{}", Math::Round(velocity.x, 2), Math::Round(velocity.y, 2)), position.x, position.y-8, 0.5f, 8);
|
||||
|
@@ -133,7 +133,7 @@ void CaveGame::Client::Splash::Update(float elapsed)
|
||||
|
||||
void CaveGame::Client::Splash::Load() {
|
||||
column_textures.fill(nullptr);
|
||||
splash = new JGL::Texture("assets/textures/redacted.png");
|
||||
splash = AssetService::Get()->GetTexture("redacted"); //new JGL::Texture("assets/textures/redacted.png");
|
||||
ComputeMatrixTextureCache();
|
||||
|
||||
Scene::Load();
|
||||
@@ -143,7 +143,8 @@ void CaveGame::Client::Splash::Load() {
|
||||
void CaveGame::Client::Splash::Unload() {
|
||||
for (auto& r : column_textures)
|
||||
delete r;
|
||||
delete splash;
|
||||
|
||||
splash = nullptr;
|
||||
|
||||
column_textures.fill(nullptr);
|
||||
Scene::Unload();
|
||||
|
@@ -44,7 +44,7 @@ CaveGame::Client::TileTool::TileTool(JUI::Widget *parent) : JUI::Window(parent)
|
||||
brush_size_slider->Maximum(1.f);
|
||||
brush_size_slider->Minimum(0.01f);
|
||||
brush_size_slider->Interval(0.001f);
|
||||
brush_size_slider->ValueChanged += [&, this] (float val)
|
||||
brush_size_slider->ValueChanged += [&, this] (float val) mutable
|
||||
{
|
||||
float newval = val * 50;
|
||||
tool_size_label->SetContent(std::format("Size: {}", Math::Round(newval, 1)));
|
||||
@@ -59,7 +59,7 @@ CaveGame::Client::TileTool::TileTool(JUI::Widget *parent) : JUI::Window(parent)
|
||||
brush_percent_slider->Maximum(1.f);
|
||||
brush_percent_slider->Minimum(0.f);
|
||||
brush_percent_slider->Interval(0.001f);
|
||||
brush_percent_slider->ValueChanged += [&, this, tool_percent_label] (float val)
|
||||
brush_percent_slider->ValueChanged += [&, this, tool_percent_label] (float val) mutable
|
||||
{
|
||||
float newval = val * 100.f;
|
||||
tool_percent_label->SetContent(std::format("Percent: {}%", Math::Floor(newval)));
|
||||
@@ -71,11 +71,14 @@ CaveGame::Client::TileTool::TileTool(JUI::Widget *parent) : JUI::Window(parent)
|
||||
|
||||
auto* tile_sim_checkbox = new Checkbox(right_row_layout);
|
||||
tile_sim_checkbox->Size({row_height, row_height, 0, 0});
|
||||
tile_sim_checkbox->OnReleaseEvent += [&, this] (Vector2 _, JUI::MouseButton _2, bool _3) {
|
||||
tile_sim_checkbox->OnClickEvent += [&, this] (Vector2 _, JUI::MouseButton _2) mutable {
|
||||
tile_sim_disabled = !tile_sim_disabled;
|
||||
TileSimulationDisabledChanged.Invoke(tile_sim_disabled);
|
||||
|
||||
// Set the visual state of the "step" buttonns
|
||||
step_btn->SetEnabled(tile_sim_disabled);
|
||||
step2_btn->SetEnabled(tile_sim_disabled);
|
||||
step3_btn->SetEnabled(tile_sim_disabled);
|
||||
};
|
||||
|
||||
|
||||
@@ -86,26 +89,35 @@ CaveGame::Client::TileTool::TileTool(JUI::Widget *parent) : JUI::Window(parent)
|
||||
step_btn->BGColor(Colors::LightGray);
|
||||
step_btn->BaseBGColor(Colors::LightGray);
|
||||
step_btn->Disable();
|
||||
step_btn->OnClickEvent += [&, this] (auto a, auto b) {
|
||||
step_btn->OnClickEvent += [&, this] (auto a, auto b) mutable {
|
||||
TileSimulationStep.Invoke(1);
|
||||
};
|
||||
|
||||
step2_btn = new TextButton(right_row_layout);
|
||||
step2_btn = new TextButton(left_row_layout);
|
||||
step2_btn->Size({100_percent, UDim(row_height, 0)});
|
||||
step2_btn->SetContent("Step 10");
|
||||
step2_btn->BGColor(Colors::LightGray);
|
||||
step2_btn->BaseBGColor(Colors::LightGray);
|
||||
step2_btn->Disable();
|
||||
step2_btn->OnClickEvent += [&, this] (auto a, auto b) {
|
||||
step2_btn->OnClickEvent += [&, this] (auto a, auto b) mutable {
|
||||
TileSimulationStep.Invoke(10);
|
||||
};
|
||||
|
||||
step3_btn = new TextButton(left_row_layout);
|
||||
step3_btn->Size({100_percent, UDim(row_height, 0)});
|
||||
step3_btn->SetContent("Step 100");
|
||||
step3_btn->BGColor(Colors::LightGray);
|
||||
step3_btn->BaseBGColor(Colors::LightGray);
|
||||
step3_btn->Disable();
|
||||
step3_btn->OnClickEvent += [&, this] (auto a, auto b) mutable {
|
||||
TileSimulationStep.Invoke(100);
|
||||
};
|
||||
|
||||
BrushSizeChanged += [this] (float value) {
|
||||
BrushSizeChanged += [this] (float value) mutable {
|
||||
brush_radius = value;
|
||||
};
|
||||
|
||||
BrushPercentChanged += [this] (float value) {
|
||||
BrushPercentChanged += [this] (float value) mutable {
|
||||
brush_density = value;
|
||||
};
|
||||
|
||||
|
@@ -1,3 +1,9 @@
|
||||
{
|
||||
|
||||
"veins": {
|
||||
"clay": {
|
||||
"hi-pass-scale-x": 200,
|
||||
"hi-pass-scale-y": 205,
|
||||
"hi-pass-offset": 0
|
||||
}
|
||||
}
|
||||
}
|
@@ -21,27 +21,33 @@
|
||||
},
|
||||
{
|
||||
"mnemonic-id": "copper-bar",
|
||||
"display-name": "Copper Bar"
|
||||
"display-name": "Copper Bar",
|
||||
"sprite:" : "ingot"
|
||||
},
|
||||
{
|
||||
"mnemonic-id": "iron-bar",
|
||||
"display-name": "Iron Bar"
|
||||
"display-name": "Iron Bar",
|
||||
"sprite:" : "ingot"
|
||||
},
|
||||
{
|
||||
"mnemonic-id": "silver-bar",
|
||||
"display-name": "Silver Bar"
|
||||
"display-name": "Silver Bar",
|
||||
"sprite:" : "ingot"
|
||||
},
|
||||
{
|
||||
"mnemonic-id": "tungsten-bar",
|
||||
"display-name": "Tungsten Bar"
|
||||
"display-name": "Tungsten Bar",
|
||||
"sprite:" : "ingot"
|
||||
},
|
||||
{
|
||||
"mnemonic-id": "platinum-bar",
|
||||
"display-name": "Platinum Bar"
|
||||
"display-name": "Platinum Bar",
|
||||
"sprite:" : "ingot.png"
|
||||
},
|
||||
{
|
||||
"mnemonic-id": "gold-bar",
|
||||
"display-name": "Gold Bar"
|
||||
"display-name": "Gold Bar",
|
||||
"sprite:" : "ingot.png"
|
||||
},
|
||||
{
|
||||
"mnemonic-id": "lead-bar",
|
||||
@@ -84,5 +90,11 @@
|
||||
"stack": 1,
|
||||
|
||||
"tags": ["dagger", "blade", "melee", "metal", "iron", "rusty"]
|
||||
},
|
||||
{
|
||||
"mnemonic-id": "smoke-n-dip"
|
||||
},
|
||||
{
|
||||
"mnemonic-id": "blick-axe"
|
||||
}
|
||||
]
|
18
ClientApp/assets/data/manifest.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"textures": [
|
||||
["ingot", "assets/textures/ingot.png"],
|
||||
["player", "assets/textures/player.png"],
|
||||
["bg", "assets/textures/bg.png"],
|
||||
["explosion", "assets/textures/explosion.png"],
|
||||
["redacted", "assets/textures/redacted.png"],
|
||||
["title", "assets/textures/title_1.png"],
|
||||
["gill_potion", "assets/textures/gill_potion.png"],
|
||||
["honey_jar", "assets/textures/honey_jar.png"],
|
||||
["hp_potion", "assets/textures/hp_potion.png"],
|
||||
["hp_potion_2x", "assets/textures/hp_potion_2x.png"],
|
||||
["hp_potion_3x", "assets/textures/hp_potion_3x.png"]
|
||||
],
|
||||
"music": [
|
||||
|
||||
]
|
||||
}
|
@@ -133,7 +133,7 @@
|
||||
"forced-ticc-func": "sand-grav",
|
||||
"solid": true,
|
||||
"color": [102, 118, 124],
|
||||
"pallet": [[92, 102, 128], [89, 116, 123], [121, 95, 108]]
|
||||
"pallet": [[92, 102, 128], [82, 82, 82], [102, 102, 102], [132, 132, 132], [89, 116, 123], [121, 95, 108]]
|
||||
},
|
||||
{
|
||||
"mnemonic-id" : "white-sand",
|
||||
|
BIN
ClientApp/assets/textures/gill_potion.png
Normal file
After Width: | Height: | Size: 402 B |
BIN
ClientApp/assets/textures/honey_jar.png
Normal file
After Width: | Height: | Size: 730 B |
BIN
ClientApp/assets/textures/hp_potion.png
Normal file
After Width: | Height: | Size: 691 B |
BIN
ClientApp/assets/textures/hp_potion_2x.png
Normal file
After Width: | Height: | Size: 748 B |
BIN
ClientApp/assets/textures/hp_potion_3x.png
Normal file
After Width: | Height: | Size: 779 B |
BIN
ClientApp/assets/textures/hp_potion_4x.png
Normal file
After Width: | Height: | Size: 818 B |
BIN
ClientApp/assets/textures/ingot.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
ClientApp/assets/textures/speedball.png
Normal file
After Width: | Height: | Size: 718 B |
@@ -65,7 +65,8 @@ namespace CaveGame::ClientApp {
|
||||
/// This function performs rendering routines, once per refresh.
|
||||
void Draw();
|
||||
|
||||
bool ReadyToClose() const { return wanna_die; }
|
||||
/// @return True when a flag is set that indicates the game is "preparing" to close. Certain procedures may still be taking place, such as saving and serialization.
|
||||
bool ReadyToClose() const;
|
||||
|
||||
/// Returns the game's console GUI, which accepts commands and displays log messages.
|
||||
Client::Console* Console();
|
||||
@@ -85,14 +86,23 @@ namespace CaveGame::ClientApp {
|
||||
|
||||
public:
|
||||
#pragma region Input Callbacks
|
||||
/// Called by the window on each frame.
|
||||
void OnRefresh(float elapsed) override;
|
||||
/// Called by the window upon the user pressing a mouse button.
|
||||
void OnMouseButtonDown(const ReWindow::MouseButtonDownEvent &ev) override;
|
||||
/// Called by the window upon the user releasing a mouse button.
|
||||
void OnMouseButtonUp(const ReWindow::MouseButtonUpEvent &ev) override;
|
||||
/// Called by the window upon the user scrolling a mouse wheel.
|
||||
void OnMouseWheel(const ReWindow::MouseWheelEvent &ev) override;
|
||||
/// Called by the window upon the user releasing a keyboard key.
|
||||
void OnKeyUp(const ReWindow::KeyUpEvent &ev) override;
|
||||
/// Called by the window upon the user pressing a keyboard key.
|
||||
void OnKeyDown(const ReWindow::KeyDownEvent& ev) override;
|
||||
/// Called by the window upon the user moving their pointer device, currently just mice.
|
||||
void OnMouseMove(const ReWindow::MouseMoveEvent &ev) override;
|
||||
/// Called by the window when it receives a request from the operating-system to resize.
|
||||
bool OnResizeRequest(const ReWindow::WindowResizeRequestEvent &ev) override;
|
||||
/// Called by the window **before** it closes.
|
||||
void OnClosing() override;
|
||||
#pragma endregion
|
||||
public:
|
||||
@@ -107,7 +117,7 @@ namespace CaveGame::ClientApp {
|
||||
/// Runs exactly one iteration of the game loop. Currently, this is one call to Update(), and then to Draw().
|
||||
/// @see Refresh().
|
||||
void Step();
|
||||
|
||||
/// Creates the in-game console menu.
|
||||
void create_console_window();
|
||||
void create_stats_window();
|
||||
void create_settings_window();
|
||||
@@ -118,9 +128,16 @@ namespace CaveGame::ClientApp {
|
||||
/// Constructs the Splash screen, Main Menu screen, and In-game session.
|
||||
void CreateContexts();
|
||||
|
||||
|
||||
|
||||
// TODO: Refactor this into irrelevance.
|
||||
void InGameControls(float elapsed);
|
||||
void OnConsoleCommandInput(const std::string &command);
|
||||
|
||||
/// Toggles tile simulation if we are in-game.
|
||||
bool ToggleTileSim(const CommandArgs& args);
|
||||
/// Opens a singleplayer session.
|
||||
/// @param info A structure containing information for joining a singleplayer world.
|
||||
void OpenWorld(Client::SingleplayerSessionInfo info);
|
||||
|
||||
/// Logs help information to the console. Called when the user runs the 'help' command.
|
||||
bool HelpCommand(const CommandArgs& args);
|
||||
@@ -128,8 +145,11 @@ namespace CaveGame::ClientApp {
|
||||
bool ListCommand(const CommandArgs& args);
|
||||
bool TileListCmd(const CommandArgs& args);
|
||||
bool ItemListCmd(const CommandArgs& args);
|
||||
/// Toggles tile simulation if we are
|
||||
bool ToggleTileSim(const CommandArgs& args);
|
||||
|
||||
|
||||
bool NoclipCmd(const CommandArgs &args);
|
||||
|
||||
bool FpsLimitCmd(const CommandArgs &args);
|
||||
|
||||
/// This table defines the supported console commands, their aliases, and the callback lambda.
|
||||
#pragma region Commands
|
||||
@@ -252,10 +272,6 @@ namespace CaveGame::ClientApp {
|
||||
float our_avg = 0.f;
|
||||
float max_fps = 60.f;
|
||||
|
||||
void OpenWorld(Client::SingleplayerSessionInfo info);
|
||||
|
||||
bool NoclipCmd(const CommandArgs &args);
|
||||
|
||||
bool FpsLimitCmd(const CommandArgs &args);
|
||||
};
|
||||
}
|
@@ -23,6 +23,8 @@ namespace CaveGame::ClientApp {
|
||||
{
|
||||
Logs::Info("Parsing Tile Data.");
|
||||
CaveGame::Core::LoadTileMetadata();
|
||||
Logs::Info("Parsing Item Data.");
|
||||
CaveGame::Core::LoadItemMetadata();
|
||||
Logs::Info("Creating game window.");
|
||||
|
||||
CreateContexts();
|
||||
@@ -116,17 +118,21 @@ namespace CaveGame::ClientApp {
|
||||
this->SetResizable(true);
|
||||
this->SetVsyncEnabled(false);
|
||||
|
||||
this->assets.PreloadCertainAssets();
|
||||
this->assets.ParseManifest();
|
||||
|
||||
// TODO: Replace w/ constructor?
|
||||
this->assets.TempLoadSimple();
|
||||
this->assets.EnqueueDefaultAssetsFolder();
|
||||
|
||||
//for (int i = 0; i < 10; i++)
|
||||
//{
|
||||
assets.EnqueueTexture("assets/textures/redacted.png");
|
||||
assets.EnqueueTexture("assets/textures/bg.png");
|
||||
assets.EnqueueTexture("assets/textures/player.png");
|
||||
assets.EnqueueTexture("assets/textures/explosion.png");
|
||||
assets.EnqueueTexture("assets/textures/title_1.png");
|
||||
assets.EnqueueTexture("assets/textures/ash_wip_potions.png");
|
||||
//assets.EnqueueTexture("assets/textures/redacted.png");
|
||||
//assets.EnqueueTexture("assets/textures/bg.png");
|
||||
//assets.EnqueueTexture("assets/textures/player.png");
|
||||
//assets.EnqueueTexture("assets/textures/explosion.png");
|
||||
//assets.EnqueueTexture("assets/textures/title_1.png");
|
||||
//assets.EnqueueTexture("assets/textures/ash_wip_potions.png");
|
||||
//}
|
||||
|
||||
|
||||
@@ -356,9 +362,15 @@ namespace CaveGame::ClientApp {
|
||||
}
|
||||
|
||||
if (ev.key == Keys::Escape) {
|
||||
GameSession()->SaveAndExit();
|
||||
// TODO: "Pause menu"
|
||||
|
||||
if (Console()->IsOpen())
|
||||
Console()->SetOpen(false);
|
||||
|
||||
|
||||
//GameSession()->SaveAndExit();
|
||||
// TODO: GameContext needs mechanism to **inform** the higher-level object that we are done.
|
||||
ChangeScene(menu_ctx);
|
||||
//ChangeScene(menu_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -626,6 +638,8 @@ namespace CaveGame::ClientApp {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CaveGameWindow::ReadyToClose() const { return wanna_die; }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@@ -38,6 +38,7 @@ namespace CaveGame::Core {
|
||||
virtual void Draw() = 0;
|
||||
|
||||
virtual void Update(float elapsed) = 0;
|
||||
virtual void PhysicsUpdate(float elapsed) {}
|
||||
|
||||
Vector2 Position() const;
|
||||
|
||||
|
@@ -162,7 +162,6 @@ namespace CaveGame::Core
|
||||
|
||||
unsigned int ColorMap(int range, int wx, int wy);
|
||||
|
||||
|
||||
// TODO: Implement SecondPass, the catch is, it **may** need to load an arbitrary amount of adjacent chunks to correctly place structures.
|
||||
// TODO: Expert Mode: How do we keep it threaded separately while still accomplishing the above?
|
||||
|
||||
@@ -183,7 +182,7 @@ namespace CaveGame::Core
|
||||
float GetPrecomputedWhiteNoise2D(int x, int y) const;
|
||||
|
||||
protected:
|
||||
int seed = 0;
|
||||
int seed = 42069;
|
||||
SimplexNoise simplex;
|
||||
PerlinNoise perlin;
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <J3ML/Math.hpp>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
//#include <Core/Registry.hpp>
|
||||
|
||||
namespace CaveGame::Core
|
||||
|
@@ -31,7 +31,7 @@ namespace CaveGame::Core
|
||||
|
||||
void Accelerate(const Vector2& vector);
|
||||
|
||||
virtual void PhysicsUpdate(float elapsed);
|
||||
void PhysicsUpdate(float elapsed) override;
|
||||
|
||||
// TODO: Mechanism for figuring out if you're already stuck inside of tiles: i.e. sand
|
||||
void CollisionTest(ITileMap* map, float elapsed) override;
|
||||
|
@@ -26,16 +26,17 @@ namespace CaveGame::Core {
|
||||
void Jump(float elapsed) {
|
||||
// TODO: Make it so the player falls **slightly** slower
|
||||
|
||||
|
||||
Vector2 current_velocity = this->Velocity();
|
||||
|
||||
float horiz = 0;
|
||||
if (current_velocity.x > 10.f)
|
||||
horiz = Math::Clamp(current_velocity.x, 10.f, 300.f);
|
||||
|
||||
if (current_velocity.x < -10.f)
|
||||
horiz = Math::Clamp(current_velocity.x, -300.f, 10.f);
|
||||
|
||||
if (on_ground) {
|
||||
Vector2 projection = Vector2(horiz, -16000*elapsed);
|
||||
Vector2 projection = Vector2(horiz*elapsed, -16000*elapsed);
|
||||
|
||||
Accelerate(projection);
|
||||
on_ground = false;
|
||||
|
@@ -28,6 +28,7 @@ namespace CaveGame::Core {
|
||||
|
||||
constexpr static unsigned int RandomTileTickCoefficient = 128;
|
||||
constexpr static float PeriodicAutosaveIntervalSeconds = 30.f;
|
||||
constexpr static float PhysicsTickrate = 100.f; // Desired physics Ticks per second.
|
||||
World() = default;
|
||||
~World() = default;
|
||||
|
||||
@@ -184,6 +185,7 @@ namespace CaveGame::Core {
|
||||
ConcurrentQueue<Core::Chunk*> ServedChunks;
|
||||
|
||||
float tile_ticc_counter;
|
||||
float physics_ticc = 0;
|
||||
|
||||
// Ticcs per second.
|
||||
float tile_ticc_frequency = 24.f;
|
||||
|
@@ -3,6 +3,7 @@
|
||||
#include <filesystem>
|
||||
#include <JJX/JSON.hpp>
|
||||
#include <Core/JsonConversions.hpp>
|
||||
#include "Core/Loggers.hpp"
|
||||
|
||||
namespace CaveGame::Core
|
||||
{
|
||||
@@ -28,13 +29,15 @@ namespace CaveGame::Core
|
||||
if (entry_obj.contains("tags"))
|
||||
item.tags = JsonConversions::parse_string_list(entry_obj["tags"]);
|
||||
|
||||
|
||||
// TODO: Support multiple overlaid "Sprites" with assigned colors.
|
||||
// TODO: Support animated sprites.
|
||||
std::string sprite_name;
|
||||
|
||||
Items().Register(item);
|
||||
|
||||
}
|
||||
|
||||
for (auto [name, item] : Items().GetItemMap()) {
|
||||
std::cout << name << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -45,6 +48,9 @@ namespace CaveGame::Core
|
||||
}
|
||||
|
||||
void ItemRegistry::Register(const Item& data) {
|
||||
|
||||
Logs::Info(std::format("\tRegister Item: id:{} display_name:{} stack:{} value:{}", data.mnemonic, data.display_name, data.max_stack, data.value));
|
||||
|
||||
registered_items.emplace(data.mnemonic, data);
|
||||
}
|
||||
|
||||
|
@@ -108,6 +108,8 @@ namespace CaveGame::Logs {
|
||||
SetIncludeTimestampAll(false);
|
||||
}
|
||||
|
||||
// TODO: This is duplicated here and in ReCaveGame::Loggers.cpp
|
||||
// Bring into jlog as utility functions.
|
||||
std::string format_timestamp(Timestamp ts) {
|
||||
return std::format(
|
||||
"{}-{}-{} {}:{}:{}.{}",
|
||||
@@ -120,6 +122,8 @@ namespace CaveGame::Logs {
|
||||
ts.Millisecond().count());
|
||||
}
|
||||
|
||||
// TODO: This is duplicated here and in ReCaveGame::Loggers.cpp
|
||||
// Bring into jlog as utility functions.
|
||||
std::string format_source_location(const std::source_location &location) {
|
||||
return std::format("{} @ {}:{}", location.function_name(), location.file_name(), location.line());
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ namespace CaveGame::Core
|
||||
airtime = 0;
|
||||
|
||||
// TODO: Sophisticated mechanism to maintain locked-timestep, multiple-iteration physics steps.
|
||||
PhysicsUpdate(elapsed);
|
||||
//PhysicsUpdate(elapsed);
|
||||
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ namespace CaveGame::Core
|
||||
|
||||
if (normal.y == 1) {
|
||||
velocity.y = -velocity.y*0.5f;
|
||||
std::cout << "Touched your head" << std::endl;
|
||||
//std::cout << "Touched your head" << std::endl;
|
||||
}
|
||||
|
||||
if (normal.x == -1)
|
||||
|
@@ -103,7 +103,7 @@ namespace CaveGame::Core {
|
||||
void SandGravTiccFunc(const Tile &data, ITileMap *world, int x, int y) {
|
||||
static TileID air = Tiles()["air"].numeric_id;
|
||||
static TileID water = Tiles()["water"].numeric_id;
|
||||
static TileID sand = data.numeric_id;
|
||||
TileID sand = data.numeric_id;
|
||||
|
||||
TileID below = world->GetTile(x, y + 1);
|
||||
if (below == air || below == water) {
|
||||
|
@@ -33,7 +33,7 @@ namespace CaveGame::Core
|
||||
|
||||
void TileRegistry::Register(TileID ID, const Tile& data)
|
||||
{
|
||||
Logs::Info(std::format("\tid:{} mnemonic:{} display-name:{}", data.numeric_id, data.mnemonic_id, data.display_name));
|
||||
Logs::Info(std::format("\tRegister Tile:: id:{} mnemonic:{} display-name:{}", data.numeric_id, data.mnemonic_id, data.display_name));
|
||||
|
||||
registered_tiles[ID] = data;
|
||||
|
||||
@@ -91,6 +91,7 @@ namespace CaveGame::Core
|
||||
|
||||
bool LoadTileMetadata(const std::filesystem::path &path) {
|
||||
|
||||
// TODO: Move to it's own thing.
|
||||
ticc_funcs.insert({"sand-grav", SandGravTiccFunc});
|
||||
ticc_funcs.insert({"liquid-settle", LiquidSettleTiccFunc});
|
||||
ticc_funcs.insert({"grass-random", GrassRandomTiccFunc});
|
||||
|
@@ -56,10 +56,34 @@ namespace CaveGame::Core {
|
||||
if (simulate_tiles)
|
||||
SimulateTiles(elapsed);
|
||||
|
||||
|
||||
physics_ticc+= elapsed;
|
||||
|
||||
static float PhysicsTickrateReciprocal = 1.f / PhysicsTickrate;
|
||||
|
||||
bool do_physics_tick_this_frame = false;
|
||||
int physics_accumulator = 0;
|
||||
|
||||
// Fixed timestep physics within variable timestep gameloop.
|
||||
while (physics_ticc > PhysicsTickrateReciprocal) {
|
||||
do_physics_tick_this_frame = true;
|
||||
physics_accumulator++;
|
||||
physics_ticc -= PhysicsTickrateReciprocal;
|
||||
}
|
||||
|
||||
// Max iterations per frame.
|
||||
if (physics_accumulator > 10)
|
||||
physics_accumulator = 10;
|
||||
|
||||
for (auto* entity : entities) {
|
||||
entity->Update(elapsed);
|
||||
entity->CollisionTest(this, elapsed);
|
||||
|
||||
if (physics_accumulator > 0) {
|
||||
for (int iters = 0; iters < physics_accumulator; iters++) {
|
||||
entity->CollisionTest(this, PhysicsTickrateReciprocal);
|
||||
entity->PhysicsUpdate(PhysicsTickrateReciprocal);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,11 +6,9 @@
|
||||
#include "Sockets/UdpServer.hpp"
|
||||
|
||||
|
||||
namespace CaveGame::Server
|
||||
{
|
||||
namespace CaveGame::Server {
|
||||
|
||||
struct ServerInfoPacket
|
||||
{
|
||||
struct ServerInfoPacket {
|
||||
|
||||
};
|
||||
|
||||
|