Compare commits
8 Commits
hotkeymenu
...
45c9e5180f
| Author | SHA1 | Date | |
|---|---|---|---|
|
45c9e5180f
|
|||
|
19ebe7b64f
|
|||
|
d9baf7c5ef
|
|||
|
701dd6b120
|
|||
|
2225151f72
|
|||
|
aef0cf4d95
|
|||
|
550ff3aeec
|
|||
|
127fa1fcb8
|
1721
assets/zombie.fbx
Normal file
1721
assets/zombie.fbx
Normal file
File diff suppressed because it is too large
Load Diff
BIN
assets/zombie.png
Normal file
BIN
assets/zombie.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 994 B |
@@ -12,6 +12,7 @@ class GameState : public ClientState {
|
||||
game::WorldPtr m_World;
|
||||
sim::ClientSimulation m_Simulation;
|
||||
float m_CurrentLerp;
|
||||
float m_ElapsedTime;
|
||||
|
||||
public:
|
||||
GameState(Client& a_Client, const game::WorldPtr& a_World, std::uint64_t a_StepTime, const std::vector<protocol::LockStep> a_FirstSteps);
|
||||
@@ -23,6 +24,10 @@ class GameState : public ClientState {
|
||||
return m_CurrentLerp;
|
||||
}
|
||||
|
||||
float GetElapsedTime() const {
|
||||
return m_ElapsedTime;
|
||||
}
|
||||
|
||||
game::WorldPtr GetWorld() const {
|
||||
return m_World;
|
||||
}
|
||||
|
||||
@@ -183,6 +183,51 @@ T Lerp(T v0, T v1, T t) {
|
||||
|
||||
} // namespace maths
|
||||
|
||||
template<typename T>
|
||||
Vec2<T> operator+(const Vec2<T>& vect, const Vec2<T>& other) {
|
||||
return {vect.x + other.x, vect.y + other.y};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec2<T> operator- (const Vec2<T>& vect) {
|
||||
return { -vect.x, -vect.y };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec2<T> operator- (const Vec2<T>& vect, const Vec2<T>& other) {
|
||||
return vect + (-other);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec3<T> operator- (const Vec3<T>& vect) {
|
||||
return { -vect.x, -vect.y, -vect.z };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec3<T> operator+ (const Vec3<T>& vect, const Vec3<T>& other) {
|
||||
return { vect.x + other.x, vect.y + other.y, vect.z + other.z };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec3<T> operator- (const Vec3<T>& vect, const Vec3<T>& other) {
|
||||
return vect + (-other);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec4<T> operator- (const Vec4<T>& vect) {
|
||||
return { -vect.x, -vect.y, -vect.z, -vect.w };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec4<T> operator+ (const Vec4<T>& vect, const Vec4<T>& other) {
|
||||
return { vect.x + other.x, vect.y + other.y, vect.z + other.z, vect.w + other.w };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Vec4<T> operator- (const Vec4<T>& vect, const Vec4<T>& other) {
|
||||
return vect + (-other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
sp::DataBuffer& operator<<(sp::DataBuffer& a_Buffer, const Vec2<T>& a_Vec) {
|
||||
return a_Buffer << a_Vec.x << a_Vec.y;
|
||||
|
||||
@@ -21,6 +21,8 @@ class DebugWorldState : public DisplayState {
|
||||
std::vector<std::unique_ptr<client::Client>> m_FakeClients;
|
||||
std::shared_ptr<server::FakeSocket> m_ServerSocket;
|
||||
|
||||
unsigned int m_PlaySpeed = 1;
|
||||
|
||||
public:
|
||||
DebugWorldState(Display& a_Display);
|
||||
~DebugWorldState();
|
||||
|
||||
@@ -35,6 +35,7 @@ class Camera {
|
||||
void UpdatePerspective(float a_AspectRatio);
|
||||
|
||||
void SetCamPos(const Vec3f& a_NewPos);
|
||||
const Vec3f& GetCamPos() const;
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <td/misc/SlotGuard.h>
|
||||
#include <td/render/Camera.h>
|
||||
#include <td/render/loader/FbxLoader.h>
|
||||
#include <td/render/loader/GLLoader.h>
|
||||
#include <td/render/shader/CameraShaderProgram.h>
|
||||
#include <td/misc/SlotGuard.h>
|
||||
|
||||
namespace td {
|
||||
namespace render {
|
||||
@@ -15,6 +16,7 @@ class BasicRenderer {
|
||||
virtual ~BasicRenderer() {}
|
||||
|
||||
void Render(const GL::VertexArray& a_Vao);
|
||||
void Render(const Model& a_Model);
|
||||
};
|
||||
|
||||
template <typename TShader>
|
||||
@@ -66,7 +68,7 @@ class RenderPipeline {
|
||||
|
||||
template <typename TShader>
|
||||
Renderer<TShader>::Renderer(Camera& a_Camera) : m_Shader(std::make_unique<TShader>()), m_Camera(a_Camera) {
|
||||
Connect(a_Camera.OnPerspectiveChange, [this](){
|
||||
Connect(a_Camera.OnPerspectiveChange, [this]() {
|
||||
m_Shader->Start();
|
||||
m_Shader->SetProjectionMatrix(m_Camera.GetProjectionMatrix());
|
||||
});
|
||||
|
||||
19
include/td/render/loader/FbxLoader.h
Normal file
19
include/td/render/loader/FbxLoader.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <td/render/loader/GLLoader.h>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace td {
|
||||
|
||||
struct Model {
|
||||
std::vector<std::unique_ptr<GL::VertexArray>> m_Vaos;
|
||||
};
|
||||
|
||||
namespace ModelLoader {
|
||||
|
||||
Model LoadModel(const std::string& fileName);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <td/render/loader/FbxLoader.h>
|
||||
#include <td/render/Renderer.h>
|
||||
#include <td/render/shader/EntityShader.h>
|
||||
#include <td/game/World.h>
|
||||
@@ -10,7 +11,7 @@ namespace render {
|
||||
class EntityRenderer : public Renderer<shader::EntityShader> {
|
||||
private:
|
||||
game::WorldPtr m_World;
|
||||
std::unique_ptr<GL::VertexArray> m_EntityVao;
|
||||
Model m_EntityModel;
|
||||
|
||||
public:
|
||||
EntityRenderer(Camera& a_Camera, const game::WorldPtr& a_World);
|
||||
|
||||
@@ -1,357 +0,0 @@
|
||||
// ImHotKey v1.0
|
||||
// https://github.com/CedricGuillemet/ImHotKey
|
||||
//
|
||||
// The MIT License(MIT)
|
||||
//
|
||||
// Copyright(c) 2019 Cedric Guillemet
|
||||
//
|
||||
// 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
|
||||
|
||||
#define SDL_h_
|
||||
|
||||
/*
|
||||
How to use it?
|
||||
|
||||
// Get some hotkeys composed of:
|
||||
// - hotkey name
|
||||
// - hotkey comment/lib
|
||||
// - hotkey scancodes. Computed by the editor. Store that value in your app.
|
||||
|
||||
static std::vector<ImHotKey::HotKey> hotkeys = { { "Layout", "Reorder nodes in a simpler layout", 0xFFFF261D}
|
||||
,{"Save", "Save the current graph", 0xFFFF1F1D}
|
||||
,{"Load", "Load an existing graph file", 0xFFFF181D}
|
||||
,{"Play/Stop", "Play or stop the animation from the current graph", 0xFFFFFF3F}
|
||||
,{"SetKey", "Make a new animation key with the current parameters values at the current time", 0xFFFFFF1F}
|
||||
};
|
||||
|
||||
// The editor is a modal window. bring it with something like that
|
||||
if (ImGui::Button("Edit Hotkeys"))
|
||||
{
|
||||
ImGui::OpenPopup("HotKeys Editor");
|
||||
}
|
||||
ImHotKey::Edit(hotkeys.data(), hotkeys.size(), "HotKeys Editor");
|
||||
|
||||
// ImHotKey also provides a way to retrieve HotKey
|
||||
int hotkey = ImHotKey::GetHotKey(hotkeys.data(), hotkeys.size());
|
||||
if (hotkey != -1)
|
||||
{
|
||||
// handle the hotkey index!
|
||||
}
|
||||
|
||||
Awesome, you are done!
|
||||
To help you integrate in your app, you can get a text (like "Ctrl + O") to integrate in your menu
|
||||
static void GetHotKeyLib(unsigned int functionKeys, char* buffer, size_t bufferSize);
|
||||
|
||||
*/
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_internal.h"
|
||||
|
||||
namespace ImHotKey
|
||||
{
|
||||
struct HotKey
|
||||
{
|
||||
const char *functionName;
|
||||
const char *functionLib;
|
||||
unsigned int functionKeys;
|
||||
};
|
||||
|
||||
struct Key
|
||||
{
|
||||
const char* lib = nullptr;
|
||||
unsigned int order;
|
||||
unsigned int scanCodePage1 = 0; // win32 scancode
|
||||
unsigned int scanCodePage7 = 0; // HID (SDL,...)
|
||||
float offset = 0;
|
||||
float width = 40;
|
||||
};
|
||||
|
||||
static const Key Keys[6][18] = {
|
||||
{ {"Esc", 4, 0x1, 0x29, 18}, {"F1", 5, 0x3B, 0x3A, 18}, {"F2", 6, 0x3C, 0x3B}, {"F3", 7, 0x3D, 0x3C}, {"F4", 8, 0x3E, 0x3D}, {"F5", 9, 0x3F, 0x3E, 24}, {"F6", 10, 0x40, 0x3F}, {"F7", 11, 0x41, 0x40}, {"F8", 12, 0x42, 0x41}, {"F9", 13, 0x43, 0x42, 24}, {"F10", 14, 0x44, 0x43}, {"F11", 15, 0x57, 0x44}, {"F12", 16, 0x58, 0x45}, {"PrSn", 17, 0x37, 0x46, 24}, {"ScLk", 18, 0x46}, {"Brk", 19, 126, 0x47} },
|
||||
{ {"~", 20, 0x29, 0x35}, {"1", 21, 0x2, 0x1E}, {"2", 22, 0x3, 0x1F}, {"3", 23, 0x4, 0x20}, {"4", 24, 0x5, 0x21}, {"5", 25, 0x6, 0x22}, {"6", 26, 0x7, 0x23}, {"7", 27, 0x8, 0x24}, {"8", 28, 0x9, 0x25}, {"9", 29, 0xA, 0x26}, {"0", 30, 0xB, 0x27}, {"-", 31, 0xC, 0x2D}, {"+", 32, 0xD, 0x2E},{"Backspace", 33, 0xE, 0x2A, 0, 80}, {"Ins", 34, 0x52, 0x49, 24}, {"Hom", 35, 0x47, 0x4A}, {"PgU", 36, 0x49, 0x4B} },
|
||||
{ {"Tab", 3, 0xF, 0x2B, 0, 60}, {"Q", 37, 0x10, 0x14}, {"W", 38, 0x11, 0x1A}, {"E", 39, 0x12, 0x08}, {"R", 40, 0x13, 0x15}, {"T", 41, 0x14, 0x17}, {"Y", 42, 0x15, 0x1C}, {"U", 43, 0x16, 0x18}, {"I", 44, 0x17, 0x0C}, {"O", 45, 0x18, 0x12}, {"P", 46, 0x19, 0x13}, {"[", 47, 0x1A, 0x2F}, {"]", 48, 0x1B, 0x30}, {"|", 49, 0x2B, 0x31, 0, 60}, {"Del", 50, 0x53, 0x4C, 24}, {"End", 51, 0x4F, 0x4D}, {"PgD", 52, 0x51, 0x4E} },
|
||||
{ {"Caps Lock", 53, 0x3A, 0x39, 0, 80}, {"A", 54, 0x1E, 0x04}, {"S", 55, 0x1F, 0x16}, {"D", 56, 0x20, 0x07}, {"F", 57, 0x21, 0x09}, {"G", 58, 0x22, 0x0A}, {"H", 59, 0x23, 0x0B}, {"J", 60, 0x24, 0x0D}, {"K", 61, 0x25, 0x0E}, {"L", 62, 0x26, 0x0F}, {";", 63, 0x27, 0x33}, {"'", 64, 0x28, 0x34}, {"Ret", 65, 0x1C, 0X28, 0, 84} },
|
||||
{ {"Shift", 2, 0x2A, 0xE1, 0, 104}, {"Z", 66, 0x2C, 0x1D}, {"X", 67, 0x2D, 0x1B}, {"C", 68, 0x2E, 0x06}, {"V", 69, 0x2F, 0x19}, {"B", 70, 0x30, 0x05}, {"N", 71, 0x31, 0x11}, {"M", 72, 0x32, 0x10}, {",", 73, 0x33, 0x36}, {".", 74, 0x34, 0x37}, {"/", 75, 0x35, 0x38}, {"Shift", 2, 0x2A, 0xE5, 0, 104}, {"Up", 76, 0x48, 0x52, 68} },
|
||||
{ {"Ctrl", 0, 0x1D, 0xE0, 0, 60}, {"Alt", 1, 0x38, 0xE2, 68, 60}, {"Space", 77, 0x39, 0X2c, 0, 260}, {"Alt", 1, 0x38, 0xE6, 0, 60}, {"Ctrl", 0, 0x1D, 0xE4, 68, 60}, {"Left", 78, 0x4B, 0x50, 24}, {"Down", 79, 0x50, 0x51}, {"Right", 80, 0x4D, 0x52} }
|
||||
};
|
||||
|
||||
static const Key& GetKeyForScanCode(unsigned int scancode)
|
||||
{
|
||||
for (unsigned int y = 0; y < 6; y++)
|
||||
{
|
||||
int x = 0;
|
||||
while (Keys[y][x].lib)
|
||||
{
|
||||
#ifdef SDL_h_
|
||||
if (Keys[y][x].scanCodePage7 == scancode)
|
||||
#elif WIN32
|
||||
if (Keys[y][x].scanCodePage1 == scancode)
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
return Keys[y][x];
|
||||
x++;
|
||||
}
|
||||
}
|
||||
return Keys[0][0];
|
||||
}
|
||||
|
||||
static unsigned int GetOrderedScanCodes(unsigned char scanCodes[4], unsigned char order[4])
|
||||
{
|
||||
for (int pass = 0; pass < 2; pass++)
|
||||
{
|
||||
for (int o = 0; o < 3; o++)
|
||||
{
|
||||
if (order[o] > order[o + 1])
|
||||
{
|
||||
ImSwap(order[o], order[o + 1]); ImSwap(scanCodes[o], scanCodes[o + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (scanCodes[3] << 24) + (scanCodes[2] << 16) + (scanCodes[1] << 8) + scanCodes[0];
|
||||
}
|
||||
|
||||
static void HotKeySPrintf(char* buffer, size_t bufferSize, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
ImFormatStringV(buffer, bufferSize, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void GetHotKeyLib(unsigned int functionKeys, char* buffer, size_t bufferSize, const char *functionLib = nullptr)
|
||||
{
|
||||
static const char* str[4] = { "%s", "%s + %s", "%s + %s +%s", "%s + %s + %s + %s" };
|
||||
static const char* strLib[4] = { "%s (%s)", "%s (%s + %s)", "%s (%s + %s +%s)", "%s (%s + %s + %s + %s)" };
|
||||
static const char* lib[4];
|
||||
int scanCodeCount = 0;
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
unsigned char scanCode = (unsigned char)(functionKeys >> i * 8);
|
||||
if (scanCode == 0xFF)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
lib[scanCodeCount] = GetKeyForScanCode(scanCode).lib;
|
||||
scanCodeCount++;
|
||||
}
|
||||
if (!scanCodeCount)
|
||||
{
|
||||
buffer[0] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (functionLib)
|
||||
{
|
||||
const char* fmt = strLib[scanCodeCount - 1];
|
||||
HotKeySPrintf(buffer, bufferSize, fmt, functionLib, lib[0], lib[1], lib[2], lib[3]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* fmt = str[scanCodeCount - 1];
|
||||
HotKeySPrintf(buffer, bufferSize, fmt, lib[0], lib[1], lib[2], lib[3]);
|
||||
}
|
||||
}
|
||||
|
||||
static void Edit(HotKey *hotkey, size_t hotkeyCount, const char *popupModal)
|
||||
{
|
||||
static int editingHotkey = -1;
|
||||
if (!hotkeyCount)
|
||||
return;
|
||||
static bool keyDown[512] = {};
|
||||
|
||||
ImGui::SetNextWindowSize(ImVec2(1060, 400));
|
||||
if (!ImGui::BeginPopupModal(popupModal, NULL, ImGuiWindowFlags_NoResize))
|
||||
return;
|
||||
|
||||
ImGui::BeginChildFrame(127, ImVec2(220, -1));
|
||||
for(size_t i = 0;i< hotkeyCount;i++)
|
||||
{
|
||||
char hotKeyLib[128];
|
||||
GetHotKeyLib(hotkey[i].functionKeys, hotKeyLib, sizeof(hotKeyLib), hotkey[i].functionName);
|
||||
if (ImGui::Selectable(hotKeyLib, editingHotkey == int(i)) || editingHotkey == -1)
|
||||
{
|
||||
editingHotkey = int(i);
|
||||
memset(keyDown, 0, sizeof(keyDown));
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
int scan = (hotkey[editingHotkey].functionKeys >> (8 * j)) & 0xFF;
|
||||
if (scan != 0xFF)
|
||||
{
|
||||
keyDown[scan] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndChildFrame();
|
||||
ImGui::SameLine();
|
||||
ImGui::BeginGroup();
|
||||
|
||||
for (int i = ImGuiKey_NamedKey_BEGIN; i < ImGuiKey_NamedKey_END; i++)
|
||||
{
|
||||
if (ImGui::IsKeyPressed(ImGuiKey(i), false))
|
||||
{
|
||||
int imKey;
|
||||
#ifdef SDL_h_
|
||||
imKey = i;
|
||||
#elif WIN32
|
||||
imKey = MapVirtualKeyA(i, MAPVK_VK_TO_VSC);
|
||||
#else
|
||||
imKey = i;
|
||||
#endif
|
||||
keyDown[imKey - ImGuiKey_NamedKey_BEGIN] = !keyDown[imKey - ImGuiKey_NamedKey_BEGIN];
|
||||
}
|
||||
}
|
||||
for (unsigned int y = 0; y < 6; y++)
|
||||
{
|
||||
int x = 0;
|
||||
ImGui::BeginGroup();
|
||||
while (Keys[y][x].lib)
|
||||
{
|
||||
const Key& key = Keys[y][x];
|
||||
const float ofs = key.offset + (x?4.f:0.f);
|
||||
|
||||
const float width = key.width;
|
||||
if (x)
|
||||
{
|
||||
ImGui::SameLine(0.f, ofs);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ofs >= 1.f)
|
||||
{
|
||||
ImGui::Indent(ofs);
|
||||
}
|
||||
}
|
||||
#ifdef SDL_h_
|
||||
bool& butSwtch = keyDown[key.scanCodePage7];
|
||||
#elif WIN32
|
||||
bool& butSwtch = keyDown[key.scanCodePage1];
|
||||
#else
|
||||
#error
|
||||
#endif
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, butSwtch ? 0xFF1040FF : 0x80000000);
|
||||
if (ImGui::Button(Keys[y][x].lib, ImVec2(width, 40)))
|
||||
{
|
||||
butSwtch = !butSwtch;
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
x++;
|
||||
}
|
||||
ImGui::EndGroup();
|
||||
}
|
||||
ImGui::InvisibleButton("space", ImVec2(10, 55));
|
||||
ImGui::BeginChildFrame(18, ImVec2(540, 40));
|
||||
ImGui::Text("%s :", hotkey[editingHotkey].functionName);
|
||||
ImGui::SameLine();
|
||||
ImGui::TextWrapped("%s", hotkey[editingHotkey].functionLib);
|
||||
ImGui::EndChildFrame();
|
||||
ImGui::SameLine();
|
||||
int keyDownCount = 0;
|
||||
for (auto d : keyDown)
|
||||
{
|
||||
keyDownCount += d ? 1 : 0;
|
||||
}
|
||||
if (ImGui::Button("Clear", ImVec2(80, 40)))
|
||||
{
|
||||
memset(keyDown, 0, sizeof(keyDown));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (keyDownCount && keyDownCount < 5)
|
||||
{
|
||||
if (ImGui::Button("Set", ImVec2(80, 40)))
|
||||
{
|
||||
unsigned char scanCodes[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
unsigned char order[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
int scanCodeCount = 0;
|
||||
hotkey[editingHotkey].functionKeys = 0;
|
||||
for (int i = 1; i < sizeof(keyDown); i++)
|
||||
{
|
||||
if (keyDown[i])
|
||||
{
|
||||
scanCodes[scanCodeCount] = (unsigned char)i;
|
||||
order[scanCodeCount] = (unsigned char)GetKeyForScanCode(i).order;
|
||||
scanCodeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
hotkey[editingHotkey].functionKeys = GetOrderedScanCodes(scanCodes, order);
|
||||
}
|
||||
ImGui::SameLine(0.f, 20.f);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::SameLine(0.f, 100.f);
|
||||
}
|
||||
|
||||
if (ImGui::Button("Done", ImVec2(80, 40))) { ImGui::CloseCurrentPopup(); }
|
||||
ImGui::EndGroup();
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
static int GetHotKey(HotKey *hotkey, size_t hotkeyCount)
|
||||
{
|
||||
static unsigned int lastHotKey = 0xFFFFFFFF;
|
||||
unsigned char scanCodes[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
unsigned char order[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
int scanCodeCount = 0;
|
||||
for (int i = ImGuiKey_Aliases_BEGIN; i < ImGuiKey_Aliases_END; i++)
|
||||
{
|
||||
if (ImGui::IsKeyDown(ImGuiKey(i)))
|
||||
{
|
||||
int imKey;
|
||||
#ifdef SDL_h_
|
||||
imKey = i - ImGuiKey_NamedKey_BEGIN;
|
||||
#elif WIN32
|
||||
imKey = MapVirtualKeyA(i, MAPVK_VK_TO_VSC);
|
||||
#else
|
||||
imKey = i;
|
||||
#endif
|
||||
scanCodes[scanCodeCount] = (unsigned char)imKey;
|
||||
order[scanCodeCount] = (unsigned char)GetKeyForScanCode(imKey).order;
|
||||
scanCodeCount++;
|
||||
if (scanCodeCount == 4)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int newHotKey = GetOrderedScanCodes(scanCodes, order);
|
||||
|
||||
if (scanCodeCount)
|
||||
{
|
||||
if (newHotKey != lastHotKey)
|
||||
{
|
||||
for (size_t i = 0; i < hotkeyCount; i++)
|
||||
{
|
||||
if (hotkey[i].functionKeys == newHotKey)
|
||||
{
|
||||
lastHotKey = newHotKey;
|
||||
return int(i);
|
||||
}
|
||||
}
|
||||
lastHotKey = 0xFFFFFFFF;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
lastHotKey = 0xFFFFFFFF;
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
@@ -1,20 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "client/state/GameState.h"
|
||||
#include <td/render/Renderer.h>
|
||||
#include <client/PlayerManager.h>
|
||||
|
||||
namespace td {
|
||||
namespace render {
|
||||
|
||||
/**
|
||||
* \brief This is a debug class
|
||||
*/
|
||||
class HotkeysRenderer : public BasicRenderer {
|
||||
class TimerRenderer : public BasicRenderer {
|
||||
private:
|
||||
const client::GameState& m_State;
|
||||
public:
|
||||
virtual void Render(float a_Lerp) override;
|
||||
|
||||
HotkeysRenderer();
|
||||
~HotkeysRenderer() {}
|
||||
TimerRenderer(const client::GameState& a_State);
|
||||
~TimerRenderer() {}
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
@@ -17,6 +17,9 @@ class WorldRenderer : public Renderer<shader::WorldShader> {
|
||||
virtual ~WorldRenderer();
|
||||
|
||||
virtual void Render(float a_Lerp) override;
|
||||
|
||||
private:
|
||||
void UpdateControls();
|
||||
};
|
||||
|
||||
} // namespace render
|
||||
|
||||
@@ -20,6 +20,7 @@ void GameState::Handle(const protocol::packets::LockStepResponsePacket& a_LockSt
|
||||
|
||||
void GameState::Update(float a_Delta) {
|
||||
m_CurrentLerp = m_Simulation.Update(a_Delta);
|
||||
m_ElapsedTime += a_Delta;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#include <chrono>
|
||||
#include <td/display/state/DebugWorldState.h>
|
||||
#include <td/display/state/MainMenuState.h>
|
||||
#include <td/misc/Time.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
// init GL context
|
||||
td::Display display(1920, 1080, "Tower-Defense 2");
|
||||
|
||||
display.ChangeState<td::DebugWorldState>();
|
||||
display.ChangeState<td::MainMenuState>();
|
||||
|
||||
td::Timer timer;
|
||||
while (!display.IsCloseRequested()) {
|
||||
|
||||
@@ -25,8 +25,8 @@ void GameState::Update(float a_Delta) {
|
||||
// TODO: don't make STEP_TIME constant
|
||||
static const float stepTimeSecond = static_cast<float>(STEP_TIME) / 1000.0f;
|
||||
m_Time += a_Delta;
|
||||
if (m_Time > stepTimeSecond) {
|
||||
m_Time = std::fmod(m_Time, stepTimeSecond);
|
||||
while (m_Time > stepTimeSecond) {
|
||||
m_Time -= stepTimeSecond;
|
||||
auto lockStepPacket = m_Simulation.Update();
|
||||
BroadcastPacket(lockStepPacket);
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include <td/game/World.h>
|
||||
#include <td/protocol/packet/Packets.h>
|
||||
#include <td/render/renderer/EntityRenderer.h>
|
||||
#include <td/render/renderer/HotkeysRenderer.h>
|
||||
#include <td/render/renderer/PlayerListRenderer.h>
|
||||
#include <td/render/renderer/TimerRenderer.h>
|
||||
#include <td/render/renderer/TowerRenderer.h>
|
||||
#include <td/render/renderer/WorldRenderer.h>
|
||||
|
||||
@@ -23,8 +23,6 @@
|
||||
#include <td/display/Display.h>
|
||||
#include <td/display/state/DebugWorldState.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace td {
|
||||
|
||||
DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) {
|
||||
@@ -44,7 +42,7 @@ DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) {
|
||||
m_Renderer.AddRenderer<render::WorldRenderer>(m_Camera, clientWorld);
|
||||
m_Renderer.AddRenderer<render::EntityRenderer>(m_Camera, clientWorld);
|
||||
m_Renderer.AddRenderer<render::TowerRenderer>(m_Camera, clientWorld);
|
||||
m_Renderer.AddRenderer<render::HotkeysRenderer>();
|
||||
m_Renderer.AddRenderer<render::TimerRenderer>(*gameState);
|
||||
|
||||
auto& list = m_Renderer.AddRenderer<render::PlayerListRenderer>(m_Client->GetPlayers());
|
||||
|
||||
@@ -77,8 +75,8 @@ DebugWorldState::DebugWorldState(Display& a_Display) : DisplayState(a_Display) {
|
||||
}
|
||||
|
||||
void DebugWorldState::Update(float a_Delta) {
|
||||
m_Server->Update(a_Delta);
|
||||
m_Client->Update(a_Delta);
|
||||
m_Server->Update(a_Delta * m_PlaySpeed);
|
||||
m_Client->Update(a_Delta * m_PlaySpeed);
|
||||
if (m_ClientState)
|
||||
m_Renderer.Render(m_ClientState->GetCurrentLerp());
|
||||
}
|
||||
@@ -89,6 +87,7 @@ void DebugWorldState::OnAspectRatioChange(float a_Ratio) {
|
||||
|
||||
void DebugWorldState::OnKeyDown(SDL_Keycode a_Key) {
|
||||
// temporary tests
|
||||
constexpr int SECONDS = 10;
|
||||
switch (a_Key) {
|
||||
case SDLK_A:
|
||||
m_Client->SendPacket(td::protocol::packets::SpawnTroopPacket(td::EntityType::Zombie, 1));
|
||||
@@ -98,6 +97,15 @@ void DebugWorldState::OnKeyDown(SDL_Keycode a_Key) {
|
||||
m_Client->SendPacket(td::protocol::packets::PlaceTowerPacket(td::TowerType::Archer, td::TowerCoords(77, 13)));
|
||||
break;
|
||||
|
||||
case SDLK_F:
|
||||
m_Server->Update(SECONDS);
|
||||
m_Client->Update(SECONDS);
|
||||
break;
|
||||
|
||||
case SDLK_P:
|
||||
m_PlaySpeed = 1 - m_PlaySpeed;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
#include <cassert>
|
||||
#include <td/Maths.h>
|
||||
#include <td/game/World.h>
|
||||
#include <td/game/WorldTypes.h>
|
||||
|
||||
#include <td/simulation/WorldTicker.h>
|
||||
#include <td/protocol/packet/PacketSerialize.h>
|
||||
#include <td/simulation/WorldTicker.h>
|
||||
|
||||
namespace td {
|
||||
namespace game {
|
||||
@@ -89,5 +92,14 @@ void World::ResetSnapshots(std::shared_ptr<sim::WorldSnapshot>& a_Current, std::
|
||||
m_NextState = a_Next;
|
||||
}
|
||||
|
||||
TilePtr World::GetTile(std::int32_t x, std::int32_t y) const {
|
||||
ChunkCoord coords{static_cast<std::int16_t>(x / Chunk::ChunkWidth), static_cast<std::int16_t>(y / Chunk::ChunkHeight)};
|
||||
auto it = m_Chunks.find(coords);
|
||||
assert(it != m_Chunks.end());
|
||||
auto chunk = it->second;
|
||||
Vec2i inchunkCoords{x % Chunk::ChunkWidth, y % Chunk::ChunkHeight};
|
||||
return GetTilePtr(chunk->GetTileIndex(inchunkCoords.y * Chunk::ChunkWidth + inchunkCoords.x));
|
||||
}
|
||||
|
||||
} // namespace game
|
||||
} // namespace td
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "td/Maths.h"
|
||||
#include <td/render/Camera.h>
|
||||
|
||||
#include <cmath>
|
||||
@@ -24,5 +25,9 @@ void Camera::SetCamPos(const Vec3f& a_NewPos) {
|
||||
OnViewChange();
|
||||
}
|
||||
|
||||
const Vec3f& Camera::GetCamPos() const {
|
||||
return m_CamPos;
|
||||
}
|
||||
|
||||
} // namespace render
|
||||
} // namespace td
|
||||
|
||||
@@ -8,10 +8,17 @@ namespace render {
|
||||
void BasicRenderer::Render(const GL::VertexArray& a_Vao) {
|
||||
a_Vao.Bind();
|
||||
glDrawArrays(GL_TRIANGLES, 0, a_Vao.GetVertexCount());
|
||||
// glDrawElements(GL_TRIANGLES, a_Vao.GetVertexCount(), GL_UNSIGNED_INT, nullptr);
|
||||
a_Vao.Unbind();
|
||||
}
|
||||
|
||||
void BasicRenderer::Render(const Model& a_Model) {
|
||||
for (const auto& vao : a_Model.m_Vaos) {
|
||||
vao->Bind();
|
||||
glDrawElements(GL_TRIANGLES, vao->GetVertexCount(), GL_UNSIGNED_INT, nullptr);
|
||||
vao->Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
RenderPipeline::RenderPipeline() {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
128
src/td/render/loader/FbxLoader.cpp
Normal file
128
src/td/render/loader/FbxLoader.cpp
Normal file
@@ -0,0 +1,128 @@
|
||||
#include <td/render/loader/FbxLoader.h>
|
||||
|
||||
#include <assimp/Importer.hpp> // C++ importer interface
|
||||
#include <assimp/postprocess.h> // Post processing flags
|
||||
#include <assimp/scene.h> // Output data structure
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <sp/common/DataBuffer.h>
|
||||
#include <td/render/loader/GLLoader.h>
|
||||
#include <vector>
|
||||
|
||||
#define VERTEX_SIZE 3
|
||||
#define UV_SIZE 2
|
||||
|
||||
#define VERTEX_POSITION_INDEX 0
|
||||
#define VERTEX_UV_INDEX 1
|
||||
#define VERTEX_NORMAL_INDEX 2
|
||||
|
||||
namespace td {
|
||||
namespace ModelLoader {
|
||||
|
||||
static std::unique_ptr<GL::VertexArray> ProcessMesh(aiMesh* mesh, const aiScene* scene, const aiMatrix4x4& transform) {
|
||||
std::vector<float> positions;
|
||||
std::vector<float> textureCoords;
|
||||
std::vector<float> normals;
|
||||
|
||||
std::vector<unsigned int> indicies;
|
||||
|
||||
aiFace* faces = mesh->mFaces;
|
||||
std::size_t faceNumber = mesh->mNumFaces;
|
||||
|
||||
for (std::size_t j = 0; j < faceNumber; j++) {
|
||||
std::size_t offset = indicies.size();
|
||||
std::size_t numIndices = faces[j].mNumIndices;
|
||||
|
||||
indicies.resize(indicies.size() + numIndices);
|
||||
std::memcpy(indicies.data() + offset, faces[j].mIndices, numIndices * sizeof(unsigned int));
|
||||
}
|
||||
|
||||
std::size_t vertNumber = mesh->mNumVertices;
|
||||
aiVector3D* vertecies = mesh->mVertices;
|
||||
|
||||
for (std::size_t j = 0; j < vertNumber; j++) {
|
||||
aiVector3D vertex = transform * vertecies[j];
|
||||
|
||||
positions.push_back(vertex.x);
|
||||
positions.push_back(vertex.y);
|
||||
positions.push_back(vertex.z);
|
||||
}
|
||||
|
||||
if (mesh->HasNormals()) {
|
||||
aiVector3D* vertexNormals = mesh->mNormals;
|
||||
|
||||
for (std::size_t j = 0; j < vertNumber; j++) {
|
||||
aiVector3D normal = transform * vertexNormals[j];
|
||||
|
||||
normals.push_back(normal.x);
|
||||
normals.push_back(normal.y);
|
||||
normals.push_back(normal.z);
|
||||
}
|
||||
}
|
||||
|
||||
aiVector3D** vertexTexture = mesh->mTextureCoords;
|
||||
|
||||
for (std::size_t j = 0; j < vertNumber; j++) {
|
||||
textureCoords.push_back(vertexTexture[0][j].x);
|
||||
textureCoords.push_back(vertexTexture[0][j].y);
|
||||
}
|
||||
|
||||
GL::VertexBuffer positionVBO(positions, VERTEX_SIZE);
|
||||
positionVBO.AddVertexAttribPointer(VERTEX_POSITION_INDEX, VERTEX_SIZE, 0);
|
||||
|
||||
GL::VertexBuffer textureVBO(textureCoords, UV_SIZE);
|
||||
textureVBO.AddVertexAttribPointer(VERTEX_UV_INDEX, UV_SIZE, 0);
|
||||
|
||||
GL::VertexBuffer normalVBO(normals, VERTEX_SIZE);
|
||||
normalVBO.AddVertexAttribPointer(VERTEX_NORMAL_INDEX, VERTEX_SIZE, 0);
|
||||
|
||||
auto Vao = std::make_unique<GL::VertexArray>(GL::ElementBuffer{indicies});
|
||||
Vao->Bind();
|
||||
Vao->BindVertexBuffer(std::move(positionVBO));
|
||||
Vao->BindVertexBuffer(std::move(textureVBO));
|
||||
Vao->BindVertexBuffer(std::move(normalVBO));
|
||||
Vao->Unbind();
|
||||
|
||||
return Vao;
|
||||
}
|
||||
|
||||
static void ProcessNode(
|
||||
aiNode* node, const aiScene* scene, std::vector<std::unique_ptr<GL::VertexArray>>& meshes, const aiMatrix4x4& transform) {
|
||||
// recursive
|
||||
for (unsigned int i = 0; i < node->mNumChildren; i++) {
|
||||
ProcessNode(node->mChildren[i], scene, meshes, transform * node->mTransformation);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < node->mNumMeshes; i++) {
|
||||
aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
|
||||
meshes.push_back(ProcessMesh(mesh, scene, transform * node->mTransformation));
|
||||
}
|
||||
}
|
||||
|
||||
Model LoadModel(const std::string& fileName) {
|
||||
// DataBuffer fileData = utils::AssetsManager::GetAsset(fileName);
|
||||
sp::DataBuffer fileData;
|
||||
fileData.ReadFile(fileName);
|
||||
|
||||
Assimp::Importer importer;
|
||||
|
||||
const aiScene* scene = importer.ReadFile(fileName, aiProcess_CalcTangentSpace | aiProcess_Triangulate | aiProcess_SortByPType |
|
||||
aiProcess_OptimizeGraph | aiProcess_OptimizeMeshes | aiProcess_GlobalScale);
|
||||
|
||||
if (!scene) {
|
||||
std::cerr << "[ModelLoader] Failed to load model !\n";
|
||||
return {};
|
||||
}
|
||||
|
||||
// utils::LOGD(utils::Format("[ModelLoader]\tModel nodes : %i", scene->mRootNode->mNumMeshes));
|
||||
|
||||
Model model;
|
||||
ProcessNode(scene->mRootNode, scene, model.m_Vaos, {});
|
||||
|
||||
std::cout << "Loaded " << model.m_Vaos.size() << " vaos !\n";
|
||||
|
||||
return model;
|
||||
}
|
||||
|
||||
} // namespace ModelLoader
|
||||
} // namespace td
|
||||
@@ -1,3 +1,4 @@
|
||||
#include "td/render/Renderer.h"
|
||||
#include <td/render/renderer/EntityRenderer.h>
|
||||
|
||||
#include <td/render/loader/WorldLoader.h>
|
||||
@@ -6,7 +7,7 @@ namespace td {
|
||||
namespace render {
|
||||
|
||||
EntityRenderer::EntityRenderer(Camera& a_Camera, const game::WorldPtr& a_World) : Renderer(a_Camera), m_World(a_World) {
|
||||
m_EntityVao = std::make_unique<GL::VertexArray>(WorldLoader::LoadMobModel());
|
||||
m_EntityModel = ModelLoader::LoadModel("assets/zombie.fbx");
|
||||
m_Shader->Start();
|
||||
m_Shader->SetColorEffect({1, 0, 1});
|
||||
}
|
||||
@@ -22,8 +23,8 @@ void EntityRenderer::Render(float a_Lerp) {
|
||||
float x = Lerp<game::Mob>(*mob, a_Lerp, [](const game::Mob& a_Mob) { return static_cast<float>(a_Mob.m_Position.x); });
|
||||
float z = Lerp<game::Mob>(*mob, a_Lerp, [](const game::Mob& a_Mob) { return static_cast<float>(a_Mob.m_Position.y); });
|
||||
|
||||
m_Shader->SetModelPos({x, 1, z});
|
||||
Renderer::Render(*m_EntityVao);
|
||||
m_Shader->SetModelPos({x, .001, z});
|
||||
Renderer::Render(m_EntityModel);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#include <imgui_internal.h>
|
||||
#include <td/render/renderer/HotkeysRenderer.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <optional>
|
||||
|
||||
#include <td/render/renderer/ImHotkey.h>
|
||||
|
||||
namespace td {
|
||||
namespace render {
|
||||
|
||||
void HotkeysRenderer::Render(float a_Lerp) {
|
||||
ImGui::Begin("Hotkeys");
|
||||
static std::vector<ImHotKey::HotKey> hotkeys = {{"Layout", "Reorder nodes in a simpler layout", 0xFFFF261D},
|
||||
{"Save", "Save the current graph", 0xFFFF1F1D}, {"Load", "Load an existing graph file", 0xFFFF181D},
|
||||
{"Play/Stop", "Play or stop the animation from the current graph", 0xFFFFFF3F},
|
||||
{"SetKey", "Make a new animation key with the current parameters values at the current time", 0xFFFFFF1F}};
|
||||
|
||||
// The editor is a modal window. bring it with something like that
|
||||
if (ImGui::Button("Edit Hotkeys")) {
|
||||
ImGui::OpenPopup("HotKeys Editor");
|
||||
}
|
||||
ImHotKey::Edit(hotkeys.data(), hotkeys.size(), "HotKeys Editor");
|
||||
|
||||
// ImHotKey also provides a way to retrieve HotKey
|
||||
int hotkey = ImHotKey::GetHotKey(hotkeys.data(), hotkeys.size());
|
||||
if (hotkey != -1) {
|
||||
// handle the hotkey index!
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
HotkeysRenderer::HotkeysRenderer() {}
|
||||
|
||||
} // namespace render
|
||||
} // namespace td
|
||||
18
src/td/render/renderer/TimerRenderer.cpp
Normal file
18
src/td/render/renderer/TimerRenderer.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <client/state/GameState.h>
|
||||
#include <td/render/renderer/TimerRenderer.h>
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
namespace td {
|
||||
namespace render {
|
||||
|
||||
void TimerRenderer::Render(float a_Lerp) {
|
||||
ImGui::Begin("Timer");
|
||||
ImGui::Text("Time : %02d:%02d", static_cast<int>(m_State.GetElapsedTime()) / 60, static_cast<int>(m_State.GetElapsedTime()) % 60);
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
TimerRenderer::TimerRenderer(const client::GameState& a_State) : m_State(a_State) {}
|
||||
|
||||
} // namespace render
|
||||
} // namespace td
|
||||
@@ -18,7 +18,7 @@ TowerRenderer::~TowerRenderer() {}
|
||||
void TowerRenderer::Render(float a_Lerp) {
|
||||
m_Shader->Start();
|
||||
for (const auto& tower : m_World->GetTowers()) {
|
||||
m_Shader->SetModelPos({tower->GetCenterX(), 1, tower->GetCenterY()});
|
||||
m_Shader->SetModelPos({tower->GetCenterX(), .001, tower->GetCenterY()});
|
||||
Renderer::Render(*m_EntityVao);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <td/Maths.h>
|
||||
#include <td/render/renderer/WorldRenderer.h>
|
||||
|
||||
#include <td/render/loader/WorldLoader.h>
|
||||
@@ -13,7 +14,17 @@ WorldRenderer::WorldRenderer(Camera& a_Camera, const game::WorldPtr& a_World) :
|
||||
|
||||
WorldRenderer::~WorldRenderer() {}
|
||||
|
||||
void WorldRenderer::UpdateControls() {
|
||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
|
||||
constexpr float sensitivity = 1.0f;
|
||||
float delta = ImGui::GetIO().DeltaTime;
|
||||
auto mouseDelta = ImGui::GetIO().MouseDelta;
|
||||
m_Camera.SetCamPos(m_Camera.GetCamPos() + Vec3f{-mouseDelta.x * delta * sensitivity, 0, -mouseDelta.y * delta * sensitivity});
|
||||
}
|
||||
}
|
||||
|
||||
void WorldRenderer::Render(float a_Lerp) {
|
||||
UpdateControls();
|
||||
m_Shader->Start();
|
||||
Renderer::Render(*m_WorldVao);
|
||||
}
|
||||
|
||||
@@ -51,8 +51,8 @@ float ClientSimulation::Update(float a_Delta) {
|
||||
// TODO: handle freezes (m_CurrentTime > 2 * m_StepTime)
|
||||
static const float stepTimeSecond = static_cast<float>(m_StepTime) / 1000.0f;
|
||||
m_CurrentTime += a_Delta;
|
||||
if (m_CurrentTime > stepTimeSecond) {
|
||||
m_CurrentTime = std::fmod(m_CurrentTime, stepTimeSecond);
|
||||
while (m_CurrentTime > stepTimeSecond) {
|
||||
m_CurrentTime -= stepTimeSecond;
|
||||
Step();
|
||||
}
|
||||
return (float)m_CurrentTime / stepTimeSecond;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <td/Types.h>
|
||||
#include <td/simulation/CommandApply.h>
|
||||
|
||||
namespace td {
|
||||
@@ -6,7 +7,7 @@ namespace sim {
|
||||
CommandApply::CommandApply(const game::World& a_World, WorldSnapshot& a_Snapshot) : m_World(a_World), m_Snapshot(a_Snapshot) {}
|
||||
|
||||
void CommandApply::Handle(const protocol::commands::EndCommand& a_End) {
|
||||
(void) m_World;
|
||||
(void)m_World;
|
||||
}
|
||||
|
||||
void CommandApply::Handle(const protocol::commands::PlaceTowerCommand& a_PlaceTower) {
|
||||
@@ -24,6 +25,10 @@ void CommandApply::Handle(const protocol::commands::PlayerJoinCommand& a_PlayerJ
|
||||
void CommandApply::Handle(const protocol::commands::SpawnTroopCommand& a_SpawnTroop) {
|
||||
auto zombie = std::make_shared<game::Zombie>();
|
||||
zombie->m_Position = a_SpawnTroop->m_Position;
|
||||
|
||||
// TODO: make it spawn dependant
|
||||
zombie->m_Direction = Direction::PositiveY;
|
||||
|
||||
m_Snapshot.m_Mobs.push_back(zombie);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,61 @@
|
||||
#include <td/Maths.h>
|
||||
#include <td/Types.h>
|
||||
#include <td/game/WorldTypes.h>
|
||||
#include <td/simulation/system/EntityMove.h>
|
||||
|
||||
#include <td/game/World.h>
|
||||
|
||||
namespace td {
|
||||
namespace sim {
|
||||
|
||||
static Vec2i GetUnitDirection(Direction a_Direction) {
|
||||
switch (a_Direction) {
|
||||
case Direction::PositiveX:
|
||||
return {1, 0};
|
||||
case Direction::NegativeX:
|
||||
return {-1, 0};
|
||||
case Direction::PositiveY:
|
||||
return {0, 1};
|
||||
case Direction::NegativeY:
|
||||
return {0, -1};
|
||||
}
|
||||
return {0, 0};
|
||||
}
|
||||
|
||||
class DirectionTileVisitor : public game::TileHandler {
|
||||
private:
|
||||
Direction m_Direction;
|
||||
|
||||
public:
|
||||
DirectionTileVisitor() {}
|
||||
|
||||
virtual void Handle(const game::EmptyTile& a_Tile) override {}
|
||||
|
||||
virtual void Handle(const game::TowerTile& a_Tile) override {}
|
||||
|
||||
virtual void Handle(const game::DecorationTile& a_Tile) override {}
|
||||
|
||||
virtual void Handle(const game::WalkableTile& a_Tile) override {
|
||||
m_Direction = a_Tile->m_Direction;
|
||||
}
|
||||
|
||||
const Direction GetDirection() {
|
||||
return m_Direction;
|
||||
}
|
||||
};
|
||||
|
||||
void EntityMove::Tick(const game::World& a_World, WorldSnapshot& a_State, FpFloat a_Delta) {
|
||||
for (auto& mob : a_State.m_Mobs) {
|
||||
mob->m_Position.x += a_Delta;
|
||||
auto tile = a_World.GetTile(static_cast<std::int32_t>(mob->m_Position.x), static_cast<std::int32_t>(mob->m_Position.y));
|
||||
Direction direction = mob->m_Direction;
|
||||
if (tile) {
|
||||
DirectionTileVisitor visitor;
|
||||
tile->Dispatch(visitor);
|
||||
direction = visitor.GetDirection();
|
||||
}
|
||||
auto directVector = GetUnitDirection(direction);
|
||||
mob->m_Position.x += directVector.x * a_Delta;
|
||||
mob->m_Position.y += directVector.y * a_Delta;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ add_rules("mode.debug", "mode.release")
|
||||
add_repositories("persson-repo https://git.ale-pri.com/Persson-dev/xmake-repo.git")
|
||||
|
||||
add_requires("imgui 1.92.0", {configs = {sdl3 = true, opengl3 = true}})
|
||||
add_requires("libsdl3 3.2.16", "splib 2.3.2", "zlib", "glew", "fpm", "enet6")
|
||||
add_requires("libsdl3 3.2.16", "splib 2.3.2", "zlib", "glew", "fpm", "enet6", "assimp")
|
||||
|
||||
set_languages("c++20")
|
||||
|
||||
@@ -21,7 +21,7 @@ target("Tower-Defense2")
|
||||
add_includedirs("include", {public = true})
|
||||
set_kind("binary")
|
||||
add_files("src/**.cpp")
|
||||
add_packages("libsdl3", "imgui", "glew", "splib", "zlib", "fpm", "enet6", {public = true})
|
||||
add_packages("libsdl3", "imgui", "glew", "splib", "zlib", "fpm", "assimp", "enet6", {public = true})
|
||||
set_rundir(".")
|
||||
add_defines("TD_GL_LOADER_GLEW")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user