diff --git a/CMakeLists.txt b/CMakeLists.txt index 82ffaa9..b7130f9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,32 +20,40 @@ include(CTest) enable_testing() add_executable(${PROJECT_NAME} - main.cpp - def.cpp - def.h - InteractManager.cpp - InteractManager.h - Renderer.cpp - Renderer.h - Game.cpp - Game.h - Window.cpp - Window.h - Hud.cpp - Hud.h - IText.cpp - IText.h - exception.cpp - exception.h - File.h - File.cpp - TextureManager.cpp - TextureManager.h + src/main.cpp + src/def.h + src/def.cpp + src/interact/InteractManager.h + src/interact/InteractManager.cpp + src/render/Renderer.h + src/render/Renderer.cpp + src/game/Game.h + src/game/Game.cpp + src/ui/Window.h + src/ui/Window.cpp + src/ui/Hud.h + src/ui/Hud.cpp + src/utils/IText.h + src/utils/IText.cpp + src/utils/exception.h + src/utils/exception.cpp + src/utils/File.h + src/utils/File.cpp + src/render/TextureManager.h + src/render/TextureManager.cpp - includes.h - Chars.h - xWindows.h - TestCode.h + src/includes.h + src/utils/Chars.h + src/ui/xWindows.h + src/utils/TestCode.h + src/game/entity/Entity.h + src/game/entity/Player.h + src/game/entity/Player.cpp + src/game/entity/Damage.h + src/utils/math.h + src/game/world/World.h + src/game/world/Location.h + src/game/world/Block.h ) set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION}) diff --git a/dev.txt b/dev.txt new file mode 100644 index 0000000..ee08ef6 --- /dev/null +++ b/dev.txt @@ -0,0 +1,4 @@ +Module: + File(30%), including Log, Save, Config, Language + Translator(30%), with File + KeyBinding(20%) diff --git a/includes.h b/includes.h deleted file mode 100644 index 3dea687..0000000 --- a/includes.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by EmsiaetKadosh on 25-1-14. -// - -#pragma once - -#include "warnings.h" - -#include "def.h" -#include "File.h" -#include "exception.h" -#include "gc.h" -#include "utils.h" -#include "hbp.h" -#include "Chars.h" -#include "Task.h" - -#include "Renderer.h" -#include "Animation.h" -#include "InteractManager.h" -#include "TextureManager.h" -#include "IText.h" -#include "Hud.h" -#include "Window.h" - -#include "Game.h" - -#include "xWindows.h" diff --git a/def.cpp b/src/def.cpp similarity index 96% rename from def.cpp rename to src/def.cpp index 5daefb1..7572e52 100644 --- a/def.cpp +++ b/src/def.cpp @@ -4,9 +4,8 @@ #include "def.h" -#include "Chars.h" -#include "exception.h" -#include "Game.h" +#include "utils\Chars.h" +#include "utils\exception.h" template template requires std::is_base_of_v && TypeName void ObjectHolder::set(const T& value) { diff --git a/def.h b/src/def.h similarity index 99% rename from def.h rename to src/def.h index dbba7fc..200018a 100644 --- a/def.h +++ b/src/def.h @@ -134,7 +134,6 @@ template T* deallocating$(T* value) { #define deallocating(val) val #endif - template class ObjectHolder { Base* value; bool hasValue; diff --git a/Animation.h b/src/game/Animation.h similarity index 99% rename from Animation.h rename to src/game/Animation.h index 7413f7b..5d778e6 100644 --- a/Animation.h +++ b/src/game/Animation.h @@ -4,7 +4,7 @@ #pragma once -#include "def.h" +#include "..\def.h" class Animation { public: diff --git a/Game.cpp b/src/game/Game.cpp similarity index 64% rename from Game.cpp rename to src/game/Game.cpp index 686b908..87cc292 100644 --- a/Game.cpp +++ b/src/game/Game.cpp @@ -4,6 +4,13 @@ #include "Game.h" +#include "world\World.h" +#include "..\ui\xWindows.h" + +void Game::initialize() { + worldManager = allocatedFor(new WorldManager); + game.setWindow(StartWindow::create()); +} Game::Game() : caption{ allocatedFor(new CaptionWindow()) }, floatWindow{ allocatedFor(new FloatWindow()) } { Logger.put(L"Game created"); @@ -14,6 +21,7 @@ Game::~Game() { setWindow(nullptr); delete deallocating(floatWindow); delete deallocating(caption); + delete deallocating(worldManager); } inline Game game = Game(); diff --git a/Game.h b/src/game/Game.h similarity index 89% rename from Game.h rename to src/game/Game.h index e963eaf..1c6a3fc 100644 --- a/Game.h +++ b/src/game/Game.h @@ -4,10 +4,12 @@ #pragma once -#include "gc.h" -#include "Hud.h" -#include "Task.h" -#include "Window.h" +#include "../utils/gc.h" +#include "../ui/Hud.h" +#include "../utils/Task.h" +#include "../ui/Window.h" + +class [[carlbeks::predecl, carlbeks::defineat("World.h")]] WorldManager; class Game final /* : public IRenderable, public ITickable */ { friend void gameThread(); @@ -20,7 +22,9 @@ class Game final /* : public IRenderable, public ITickable */ { public: TaskScheduler tasks; // 8 std::minstd_rand random; + WorldManager* worldManager = nullptr; + void initialize(); Game(); ~Game(); diff --git a/src/game/entity/Damage.h b/src/game/entity/Damage.h new file mode 100644 index 0000000..d7a5837 --- /dev/null +++ b/src/game/entity/Damage.h @@ -0,0 +1,43 @@ +// +// Created by EmsiaetKadosh on 25-3-21. +// + +#pragma once + +#include "..\..\def.h" + +class [[carlbeks::predecl, carlbeks::defineat("Entity.h")]] Entity; + +struct DamageTypeEnum { + enum : unsigned char { + NONE, // 无伤害 + SYSTEMATIC_DAMAGE, // 系统伤害 + PHYSICAL_DAMAGE, // 物理伤害 + MAGICAL_DAMAGE, // 魔法伤害 + TRUE_DAMAGE, // 真实伤害 + DENY_DAMAGE, // 否定伤害 + RETURN_DAMAGE, // 回敬伤害 + BLOOD_PRESSURE_DAMAGE, // 降压伤害 + } value; + + static constexpr QWORD elementCount() { return BLOOD_PRESSURE_DAMAGE + 1; } +}; + +struct DamageFormEnum { + enum : unsigned char { + NONE, + MELEE_DAMAGE, // 近战伤害 + REMOTE_DAMAGE, // 远程伤害 + PROJECTILE_DAMAGE, // 弹射物伤害 + EXECUTE_DAMAGE, // 处决伤害 + FINAL_DAMAGE, + } value; + + static constexpr QWORD elementCount() { return FINAL_DAMAGE + 1; } +}; + +struct Damage { + double damages[DamageTypeEnum::elementCount()]; + DamageFormEnum form; + +}; diff --git a/src/game/entity/Entity.h b/src/game/entity/Entity.h new file mode 100644 index 0000000..6f13447 --- /dev/null +++ b/src/game/entity/Entity.h @@ -0,0 +1,61 @@ +// +// Created by EmsiaetKadosh on 25-3-21. +// + +#pragma once + +#include "..\..\utils\math.h" +#include "..\world\Location.h" +#include "Damage.h" + +class Entity; +class World; + +interface IDamageable { +protected: + double maxHealth = 0; + double health = 0; + +public: + virtual ~IDamageable() = default; + virtual void Damage(Damage&) = 0; + virtual void onDeath() = 0; +}; + +interface IMoveable { +protected: + double maxSpeed = 1.0; + Vector2D velocity; + + virtual ~IMoveable() = default; +public: + void setVelocity(const Vector2D& velocity) { this->velocity = velocity; } + [[nodiscard]] Vector2D getVelocity() const { return this->velocity; } +}; + +interface IArtificialIntelligent { +protected: + virtual ~IArtificialIntelligent() = default; + virtual void aiProcess() {} +}; + +class Entity { + friend class World; + Location location; + QWORD id = 0; + +protected: + Entity(const Location& location) : location(location) {} + Entity(Location&& location) : location(std::move(location)) {} + virtual ~Entity() = default; + +public: + virtual void tick() {} + virtual void onRemove() {} +}; + +class Enemy : public Entity, public IDamageable, public IMoveable, public IArtificialIntelligent { +protected: + Enemy(const Location& location) : Entity(location) {} + Enemy(Location&& location) : Entity(std::move(location)) {} +}; diff --git a/src/game/entity/Player.cpp b/src/game/entity/Player.cpp new file mode 100644 index 0000000..0485d52 --- /dev/null +++ b/src/game/entity/Player.cpp @@ -0,0 +1,5 @@ +// +// Created by EmsiaetKadosh on 25-3-21. +// + +#include "Player.h" diff --git a/src/game/entity/Player.h b/src/game/entity/Player.h new file mode 100644 index 0000000..fe1708b --- /dev/null +++ b/src/game/entity/Player.h @@ -0,0 +1,13 @@ +// +// Created by EmsiaetKadosh on 25-3-21. +// + +#pragma once + +#include "Entity.h" + +class Player : public Entity, public IMoveable, public IDamageable { +public: + Player(const Location& location) : Entity(location) {} + Player(Location&& location) : Entity(std::move(location)) {} +}; diff --git a/src/game/world/Block.h b/src/game/world/Block.h new file mode 100644 index 0000000..edf5ad6 --- /dev/null +++ b/src/game/world/Block.h @@ -0,0 +1,12 @@ +// +// Created by EmsiaetKadosh on 25-3-21. +// + +#pragma once + +#include "Location.h" + +class Block { +public: + +}; diff --git a/src/game/world/Location.h b/src/game/world/Location.h new file mode 100644 index 0000000..f271071 --- /dev/null +++ b/src/game/world/Location.h @@ -0,0 +1,42 @@ +// +// Created by EmsiaetKadosh on 25-3-21. +// + +#pragma once + +#include "..\..\utils\math.h" + +using WorldID = QWORD; +class Location; +class BlockLocation; + +class Location { + Vector2D position; + WorldID idWorld; + +public: + Location(const Vector2D& position, const WorldID idWorld) : position(position), idWorld(idWorld) {} + Location(Vector2D&& position, const WorldID idWorld) : position(position), idWorld(idWorld) {} + [[nodiscard]] Vector2D getPosition() const { return position; } + [[nodiscard]] WorldID getWorld() const { return idWorld; } + [[nodiscard]] double getX() const { return position.getX(); } + [[nodiscard]] double getY() const { return position.getY(); } + [[nodiscard]] BlockLocation getBlockLocation() const; +}; + +class BlockLocation { + long long x, y; + WorldID idWorld; + +public: + BlockLocation(const long long x, const long long y, const WorldID idWorld) : x(x), y(y), idWorld(idWorld) {} + BlockLocation(const Vector2D& position, const WorldID idWorld) : x(static_cast(std::floor(position.getX()))), y(static_cast(std::floor(position.getY()))), idWorld(idWorld) {} + [[nodiscard]] Vector2D getPosition() const { return Vector2D(static_cast(x), static_cast(y)); } + [[nodiscard]] WorldID getWorld() const { return idWorld; } + [[nodiscard]] long long getX() const { return x; } + [[nodiscard]] long long getY() const { return y; } + [[nodiscard]] Location toLocation() const { return Location({ static_cast(x), static_cast(y) }, idWorld); } +}; + +inline BlockLocation Location::getBlockLocation() const { return BlockLocation(position, idWorld); } + diff --git a/src/game/world/World.h b/src/game/world/World.h new file mode 100644 index 0000000..740f2c7 --- /dev/null +++ b/src/game/world/World.h @@ -0,0 +1,39 @@ +// +// Created by EmsiaetKadosh on 25-3-21. +// + +#pragma once + +#include "..\..\def.h" +#include "..\entity\Entity.h" + +class World { + QWORD idEntity = 0; + Map entities; + using IterEntity = Map::const_iterator; + +public: + World() = default; + + int addEntity(Entity* entity) { + if (!entity) Failed(); + if (entity->id) Failed(); + entities.emplace(++idEntity, entity); + Success(); + } + + int removeEntity(Entity* entity) { + if (!entity) Failed(); + if (!entity->id) Failed(); + const IterEntity iter = entities.find(entity->id); + if (iter != entities.end()) Failed(); + entities.erase(iter); + entity->onRemove(); + entity->id = 0; + Success(); + } +}; + +class WorldManager { +public: +}; diff --git a/hbp.h b/src/hbp.h similarity index 100% rename from hbp.h rename to src/hbp.h diff --git a/src/includes.h b/src/includes.h new file mode 100644 index 0000000..30d42df --- /dev/null +++ b/src/includes.h @@ -0,0 +1,39 @@ +// +// Created by EmsiaetKadosh on 25-1-14. +// + +#pragma once + +#include "warnings.h" + +// Any include +#include "def.h" +#include "utils\math.h" +#include "utils\File.h" +#include "utils\exception.h" + +// utils serialized +#include "utils\gc.h" +#include "utils\utils.h" +#include "hbp.h" +#include "utils\Chars.h" +#include "utils\Task.h" + +// game basic +#include "interact\InteractManager.h" +#include "utils\IText.h" +#include "render\Renderer.h" +#include "game\Animation.h" +#include "render\TextureManager.h" +#include "ui\Hud.h" +#include "ui\Window.h" + +// game +#include "game\Game.h" + +// game extension +#include "ui\xWindows.h" +#include "game\world\Location.h" +#include "game\entity\Entity.h" +#include "game\world\World.h" +#include "game\entity\Player.h" diff --git a/InteractManager.cpp b/src/interact/InteractManager.cpp similarity index 99% rename from InteractManager.cpp rename to src/interact/InteractManager.cpp index 178ce1a..865650c 100644 --- a/InteractManager.cpp +++ b/src/interact/InteractManager.cpp @@ -4,7 +4,7 @@ #include "InteractManager.h" -#include "Window.h" +#include "..\ui\Window.h" InteractManager::InteractManager() { keyStatus[0x00].name = L"NONE"; diff --git a/InteractManager.h b/src/interact/InteractManager.h similarity index 99% rename from InteractManager.h rename to src/interact/InteractManager.h index e17aed9..22b8edb 100644 --- a/InteractManager.h +++ b/src/interact/InteractManager.h @@ -4,8 +4,8 @@ #pragma once -#include "def.h" -#include "hbp.h" +#include "..\hbp.h" +#include "..\def.h" struct KeyStatus { String name; diff --git a/main.cpp b/src/main.cpp similarity index 99% rename from main.cpp rename to src/main.cpp index 1b7736a..10a14f3 100644 --- a/main.cpp +++ b/src/main.cpp @@ -1,7 +1,6 @@ #include "includes.h" -#include "IText.h" -#include "TestCode.h" +#include "utils/TestCode.h" LRESULT __stdcall WndProc(const HWND hwnd, const UINT uMsg, const WPARAM wParam, const LPARAM lParam) { switch (uMsg) { @@ -248,7 +247,6 @@ int __stdcall wWinMain(const HINSTANCE hInstance, const HINSTANCE, [[maybe_unuse Logger.info(L"wWinMain started"); SetConsoleOutputCP(65001); translator.initialize(); - game.setWindow(StartWindow::create()); // 次序提前至最先 Logger.info(L"--------Program Start--------"); for (const auto& [addr, info] : memoryManager.allocated) { Logger.print(L" using", addr, info.size, L"B", info.msg); } WNDCLASSEX wc = {}; @@ -295,6 +293,7 @@ int __stdcall wWinMain(const HINSTANCE hInstance, const HINSTANCE, [[maybe_unuse if (!hook) Logger.error(Logger.of(L"SetWindowsHookW failed. LastError:", GetLastError())); test(); { + game.initialize(); interactManager.initialize(); GameThread = Thread(gameThread); RenderThread = Thread(renderThread); diff --git a/Renderer.cpp b/src/render/Renderer.cpp similarity index 97% rename from Renderer.cpp rename to src/render/Renderer.cpp index 449e607..eafb633 100644 --- a/Renderer.cpp +++ b/src/render/Renderer.cpp @@ -4,9 +4,9 @@ #include "Renderer.h" -#include "Game.h" -#include "hbp.h" -#include "InteractManager.h" +#include "..\game\Game.h" +#include "..\hbp.h" +#include "..\interact\InteractManager.h" void Renderer::gameStartRender() noexcept { isRendering = true; diff --git a/Renderer.h b/src/render/Renderer.h similarity index 97% rename from Renderer.h rename to src/render/Renderer.h index 2eb3853..8def5e3 100644 --- a/Renderer.h +++ b/src/render/Renderer.h @@ -4,16 +4,16 @@ #pragma once -#include "def.h" -#include "exception.h" -#include "Task.h" +#include "..\def.h" +#include "..\utils\exception.h" +#include "..\utils\Task.h" class Game; /** * 用于标记相对位置。 */ -enum class Location : char { LEFT_TOP, LEFT, LEFT_BOTTOM, TOP, CENTER, BOTTOM, RIGHT_TOP, RIGHT, RIGHT_BOTTOM }; +enum class UILocation : char { LEFT_TOP, LEFT, LEFT_BOTTOM, TOP, CENTER, BOTTOM, RIGHT_TOP, RIGHT, RIGHT_BOTTOM }; interface IRenderable { virtual ~IRenderable() = default; diff --git a/TextureManager.cpp b/src/render/TextureManager.cpp similarity index 100% rename from TextureManager.cpp rename to src/render/TextureManager.cpp diff --git a/TextureManager.h b/src/render/TextureManager.h similarity index 94% rename from TextureManager.h rename to src/render/TextureManager.h index 0d0049b..7d2cf95 100644 --- a/TextureManager.h +++ b/src/render/TextureManager.h @@ -4,7 +4,7 @@ #pragma once -#include "def.h" +#include "..\def.h" class ITexture {}; diff --git a/Hud.cpp b/src/ui/Hud.cpp similarity index 100% rename from Hud.cpp rename to src/ui/Hud.cpp diff --git a/Hud.h b/src/ui/Hud.h similarity index 87% rename from Hud.h rename to src/ui/Hud.h index d4638f6..cca536c 100644 --- a/Hud.h +++ b/src/ui/Hud.h @@ -3,7 +3,8 @@ // #pragma once -#include "Renderer.h" + +#include "..\render\Renderer.h" class Hud final : public IRenderable, public ITickable { public: diff --git a/Window.cpp b/src/ui/Window.cpp similarity index 90% rename from Window.cpp rename to src/ui/Window.cpp index 553866a..315ecd7 100644 --- a/Window.cpp +++ b/src/ui/Window.cpp @@ -4,9 +4,9 @@ #include "Window.h" -#include "Animation.h" -#include "Game.h" -#include "InteractManager.h" +#include "..\game\Animation.h" +#include "..\game\Game.h" +#include "..\interact\InteractManager.h" int Window::pop() noexcept { gc.submit(this); @@ -45,7 +45,7 @@ void WindowManager::clear() noexcept { } CaptionWindow::CaptionWindow() { - Widget* close = widgets.emplace_back(Button(0, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, L"\\f\1\u2716"_literal)); + Widget* close = widgets.emplace_back(Button(0, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, UILocation::RIGHT_TOP, L"\\f\1\u2716"_literal)); close->mouseClick = [](Widget&, MouseButtonCode) { DestroyWindow(MainWindowHandle); }; close->onTick = [](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(TranslatableText(L"hbp.caption.close").getRenderableString()); }; close->absolute(); @@ -58,7 +58,7 @@ CaptionWindow::CaptionWindow() { close->foregroundColor.inactive = 0xff000000; close->foregroundColor.clicked = 0xff000000; - Widget* maxRestore = widgets.emplace_back(Button(-interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, IsZoomed(MainWindowHandle) ? L"\\f\1🗗"_literal : L"\\f\1🗖"_literal )); + Widget* maxRestore = widgets.emplace_back(Button(-interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, UILocation::RIGHT_TOP, IsZoomed(MainWindowHandle) ? L"\\f\1🗗"_literal : L"\\f\1🗖"_literal )); maxRestore->mouseClick = [](Widget&, MouseButtonCode) {}; maxRestore->mouseClick = [](Widget& self, MouseButtonCode) { if ((self.unused[1] = static_cast(IsZoomed(MainWindowHandle)))) ShowWindow(MainWindowHandle, SW_RESTORE); @@ -76,7 +76,7 @@ CaptionWindow::CaptionWindow() { maxRestore->foregroundColor.inactive = 0xff000000; maxRestore->foregroundColor.clicked = 0xff000000; - Widget* hide = widgets.emplace_back(Button(-2 * interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::RIGHT_TOP, L"\\f\1🗕"_literal)); + Widget* hide = widgets.emplace_back(Button(-2 * interactSettings.actual.captionHeight, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, UILocation::RIGHT_TOP, L"\\f\1🗕"_literal)); hide->onTick = [](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(TranslatableText(L"hbp.caption.minimize").getRenderableString()); }; hide->mouseClick = [](Widget&, MouseButtonCode) { ShowWindow(MainWindowHandle, SW_MINIMIZE); }; hide->absolute(); @@ -89,7 +89,7 @@ CaptionWindow::CaptionWindow() { hide->foregroundColor.inactive = 0xff000000; hide->foregroundColor.clicked = 0xff000000; - Widget* options = widgets.emplace_back(Button(0, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, Location::LEFT_TOP, L"\\f\1⛭"_literal)); + Widget* options = widgets.emplace_back(Button(0, 0, interactSettings.actual.captionHeight, interactSettings.actual.captionHeight, UILocation::LEFT_TOP, L"\\f\1⛭"_literal)); options->onTick = [](const Widget& self, MouseButtonCode) { if (self.containsMouse()) { game.getFloatWindow().push(TranslatableText(L"hbp.float.settings").getRenderableString()); @@ -122,11 +122,11 @@ void CaptionWindow::onResize() { widget->w = interactSettings.actual.captionHeight; widget->h = interactSettings.actual.captionHeight; switch (widget->location) { - case Location::LEFT_TOP: + case UILocation::LEFT_TOP: widget->x = left; left += interactSettings.actual.captionHeight; break; - case Location::RIGHT_TOP: + case UILocation::RIGHT_TOP: widget->x = right; right -= interactSettings.actual.captionHeight; break; @@ -187,39 +187,39 @@ void Widget::onResize() { width = static_cast(w); height = static_cast(h); switch (location) { - case Location::LEFT_TOP: + case UILocation::LEFT_TOP: left = static_cast(x); top = static_cast(y); break; - case Location::LEFT: + case UILocation::LEFT: left = static_cast(x); top = static_cast(y) + (renderer.getHeight() - height >> 1); break; - case Location::LEFT_BOTTOM: + case UILocation::LEFT_BOTTOM: left = static_cast(x); top = static_cast(y) + renderer.getHeight() - height; break; - case Location::TOP: + case UILocation::TOP: left = static_cast(x) + (renderer.getWidth() - width >> 1); top = static_cast(y); break; - case Location::CENTER: + case UILocation::CENTER: left = static_cast(x) + (renderer.getWidth() - width >> 1); top = static_cast(y) + (renderer.getHeight() - height >> 1); break; - case Location::BOTTOM: + case UILocation::BOTTOM: left = static_cast(x) + (renderer.getWidth() - width >> 1); top = static_cast(y) + renderer.getHeight() - height; break; - case Location::RIGHT_TOP: + case UILocation::RIGHT_TOP: left = static_cast(x) + renderer.getWidth() - width; top = static_cast(y); break; - case Location::RIGHT: + case UILocation::RIGHT: left = static_cast(x) + renderer.getWidth() - width; top = static_cast(y) + (renderer.getHeight() - height >> 1); break; - case Location::RIGHT_BOTTOM: + case UILocation::RIGHT_BOTTOM: left = static_cast(x) + renderer.getWidth() - width; top = static_cast(y) + renderer.getHeight() - height; break; @@ -228,39 +228,39 @@ void Widget::onResize() { width = static_cast(renderer.getWidth() * w); height = static_cast(renderer.getHeight() * h); switch (location) { - case Location::LEFT_TOP: + case UILocation::LEFT_TOP: left = static_cast(renderer.getWidth() * x); top = static_cast(renderer.getHeight() * y); break; - case Location::LEFT: + case UILocation::LEFT: left = static_cast(renderer.getWidth() * x); top = static_cast(renderer.getHeight() * y) + (renderer.getHeight() - height >> 1); break; - case Location::LEFT_BOTTOM: + case UILocation::LEFT_BOTTOM: left = static_cast(renderer.getWidth() * x); top = static_cast(renderer.getHeight() * y) + renderer.getHeight() - height; break; - case Location::TOP: + case UILocation::TOP: left = static_cast(renderer.getWidth() * x) + (renderer.getWidth() - width >> 1); top = static_cast(renderer.getHeight() * y); break; - case Location::CENTER: + case UILocation::CENTER: left = static_cast(renderer.getWidth() * x) + (renderer.getWidth() - width >> 1); top = static_cast(renderer.getHeight() * y) + (renderer.getHeight() - height >> 1); break; - case Location::BOTTOM: + case UILocation::BOTTOM: left = static_cast(renderer.getWidth() * x) + (renderer.getWidth() - width >> 1); top = static_cast(renderer.getHeight() * y) + renderer.getHeight() - height; break; - case Location::RIGHT_TOP: + case UILocation::RIGHT_TOP: left = static_cast(renderer.getWidth() * x) + renderer.getWidth() - width; top = static_cast(renderer.getHeight() * y); break; - case Location::RIGHT: + case UILocation::RIGHT: left = static_cast(renderer.getWidth() * x) + renderer.getWidth() - width; top = static_cast(renderer.getHeight() * y) + (renderer.getHeight() - height >> 1); break; - case Location::RIGHT_BOTTOM: + case UILocation::RIGHT_BOTTOM: left = static_cast(renderer.getWidth() * x) + renderer.getWidth() - width; top = static_cast(renderer.getHeight() * y) + renderer.getHeight() - height; break; @@ -274,8 +274,8 @@ void Button::render() const noexcept { } ConfirmWindow& ConfirmWindow::requireConfirm(const Function& func) { - confirm = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0, 0.4, 0.08, Location::CENTER, TranslatableText(L"hbp.confirm.confirm")))).ptr()); - confirm->location = Location::CENTER; + confirm = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0, 0.4, 0.08, UILocation::CENTER, TranslatableText(L"hbp.confirm.confirm")))).ptr()); + confirm->location = UILocation::CENTER; confirm->backgroundColor.active = 0x99000000; confirm->backgroundColor.hover = 0x9900ff00; confirm->backgroundColor.clicked = 0xff00ee00; @@ -302,14 +302,14 @@ ConfirmWindow& ConfirmWindow::requireConfirm(const Function& func } ConfirmWindow& ConfirmWindow::requireCancel(const Function& func) { - cancel = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.1, 0.4, 0.08, Location::CENTER, TranslatableText(L"hbp.confirm.cancel")))).ptr()); + cancel = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.1, 0.4, 0.08, UILocation::CENTER, TranslatableText(L"hbp.confirm.cancel")))).ptr()); cancel->mouseClick = [this](Widget&, MouseButtonCode) { game.tasks.pushNewed(allocatedFor(new Task([this](Task& self) { if (game.closeWindow(this)) this->onClose(); self.pop(); }))); }; - cancel->location = Location::CENTER; + cancel->location = UILocation::CENTER; cancel->backgroundColor.active = 0x99000000; cancel->backgroundColor.hover = 0x99ff0000; cancel->backgroundColor.clicked = 0xffee0000; diff --git a/Window.h b/src/ui/Window.h similarity index 91% rename from Window.h rename to src/ui/Window.h index 6403a8c..f391ad2 100644 --- a/Window.h +++ b/src/ui/Window.h @@ -4,11 +4,11 @@ #pragma once -#include "Animation.h" -#include "def.h" -#include "gc.h" -#include "Renderer.h" -#include "IText.h" +#include "..\def.h" +#include "..\utils\gc.h" +#include "..\render\Renderer.h" +#include "..\game\Animation.h" +#include "..\utils\IText.h" class WindowManager; @@ -58,21 +58,21 @@ protected: bool isAbsoluteLocation = false; public: - Location location; - Location textLocation = Location::CENTER; // 多余字节预声明备用 + UILocation location; + UILocation textLocation = UILocation::CENTER; // 多余字节预声明备用 char unused[2]{}; // [0]: [1]: maxRestore_flag_IsZoomed - Widget(const double x, const double y, const double w, const double h, const Location location) : x(x), y(y), w(w), h(h), location(location) {} + Widget(const double x, const double y, const double w, const double h, const UILocation location) : x(x), y(y), w(w), h(h), location(location) {} unsigned int colorSelector(const Color& clr) const; void render() const noexcept override; - Widget& alignLocation(const Location loc) noexcept { + Widget& alignLocation(const UILocation loc) noexcept { location = loc; return *this; } - Widget& alignTextLocation(const Location loc) noexcept { + Widget& alignTextLocation(const UILocation loc) noexcept { textLocation = loc; return *this; } @@ -220,8 +220,8 @@ class Button : public Widget { public: ObjectHolder name; Animation animation = Animation().features(Animation::AS_CUBIC).setDuration(20); - Button(const double x, const double y, const double w, const double h, const Location location, const ObjectHolder& text) : Widget(x, y, w, h, location), name(text) {} - Button(const double x, const double y, const double w, const double h, const Location location, ObjectHolder&& text) : Widget(x, y, w, h, location), name(std::move(text)) {} + Button(const double x, const double y, const double w, const double h, const UILocation location, const ObjectHolder& text) : Widget(x, y, w, h, location), name(text) {} + Button(const double x, const double y, const double w, const double h, const UILocation location, ObjectHolder&& text) : Widget(x, y, w, h, location), name(std::move(text)) {} void render() const noexcept override; }; diff --git a/xWindows.h b/src/ui/xWindows.h similarity index 88% rename from xWindows.h rename to src/ui/xWindows.h index a78f622..d0183fd 100644 --- a/xWindows.h +++ b/src/ui/xWindows.h @@ -10,7 +10,7 @@ class StartWindow final : public Window { TranslatableText title = TranslatableText(L"hbp.title"); StartWindow() { - Button* start = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.1, 0.4, 0.08, Location::CENTER, L"hbp.button.exit"_translates))).ptr()); + Button* start = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.1, 0.4, 0.08, UILocation::CENTER, L"hbp.button.exit"_translates))).ptr()); start->onTick = [](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(L"hbp.float.exit"_translates.getRenderableString()); }; start->mouseClick = [](Widget&, MouseButtonCode) { game.setWindow(&ConfirmWindow::of(L"hbp.confirming.exit"_translates)->requireCancel().requireConfirm([](Button& confirm) { @@ -18,9 +18,9 @@ class StartWindow final : public Window { confirm.onTick = [](Widget& self, MouseButtonCode) { if (self.containsMouse()) self.backgroundColor.hover = static_cast(self).animation.adaptsColor(0x99008800, 0x9900ff00); }; })); }; - Button* optn = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.2, 0.4, 0.08, Location::CENTER, L"hbp.button.settings"_translates))).ptr()); + Button* optn = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.2, 0.4, 0.08, UILocation::CENTER, L"hbp.button.settings"_translates))).ptr()); optn->onTick = [](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(L"hbp.float.settings"_translates.getRenderableString()); }; - Button* exit = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.3, 0.4, 0.08, Location::CENTER, L"hbp.button.start"_translates))).ptr()); + Button* exit = dynamic_cast(widgets.emplace_back(std::move(Button(0, 0.3, 0.4, 0.08, UILocation::CENTER, L"hbp.button.start"_translates))).ptr()); exit->onTick = [](const Widget& self, MouseButtonCode) { if (self.containsMouse()) game.getFloatWindow().push(L"hbp.float.start"_translates.getRenderableString()); }; exit->mouseClick = [](Widget&, MouseButtonCode) { game.setWindow(&ConfirmWindow::of(L"hbp.confirming.start"_translates)->requireCancel().requireConfirm([](Button& confirm) { diff --git a/Chars.h b/src/utils/Chars.h similarity index 99% rename from Chars.h rename to src/utils/Chars.h index 11a3629..de8e227 100644 --- a/Chars.h +++ b/src/utils/Chars.h @@ -4,7 +4,7 @@ #pragma once -#include "def.h" +#include "..\def.h" [[nodiscard]] inline unsigned int wtouib16(const wchar* string) noexcept { unsigned int ret = 0; diff --git a/File.cpp b/src/utils/File.cpp similarity index 94% rename from File.cpp rename to src/utils/File.cpp index 711ada2..f8184d2 100644 --- a/File.cpp +++ b/src/utils/File.cpp @@ -1,5 +1,5 @@ -#include "def.h" +#include "..\def.h" #include "exception.h" #include "File.h" diff --git a/File.h b/src/utils/File.h similarity index 99% rename from File.h rename to src/utils/File.h index d797ce8..06dedb5 100644 --- a/File.h +++ b/src/utils/File.h @@ -4,6 +4,8 @@ #pragma once +#include "..\def.h" + class File final { public: String path{}; diff --git a/IText.cpp b/src/utils/IText.cpp similarity index 99% rename from IText.cpp rename to src/utils/IText.cpp index ad2d594..63dd2d7 100644 --- a/IText.cpp +++ b/src/utils/IText.cpp @@ -4,8 +4,8 @@ #include "IText.h" -#include "def.h" -#include "Renderer.h" +#include "..\def.h" +#include "..\render\Renderer.h" int RenderableString::getHeight() const noexcept { int height = 0; diff --git a/IText.h b/src/utils/IText.h similarity index 99% rename from IText.h rename to src/utils/IText.h index da83a0d..4cdcc1c 100644 --- a/IText.h +++ b/src/utils/IText.h @@ -5,10 +5,10 @@ #pragma once -#include "def.h" +#include "..\def.h" #include "Chars.h" #include "exception.h" -#include "InteractManager.h" +#include "..\interact\InteractManager.h" class LiteralText; class Translator; diff --git a/Task.h b/src/utils/Task.h similarity index 100% rename from Task.h rename to src/utils/Task.h diff --git a/TestCode.h b/src/utils/TestCode.h similarity index 100% rename from TestCode.h rename to src/utils/TestCode.h diff --git a/exception.cpp b/src/utils/exception.cpp similarity index 83% rename from exception.cpp rename to src/utils/exception.cpp index 9601749..9295b1b 100644 --- a/exception.cpp +++ b/src/utils/exception.cpp @@ -4,9 +4,9 @@ #pragma once -#include "def.h" +#include "..\def.h" #include "exception.h" -#include "Game.h" +#include "..\game\Game.h" String PublicLogger::build(const String& msg, const String& type) const { return L"T-" + qwtowb10(game.getTick(), 8) + name + type + msg + L"\n"; diff --git a/exception.h b/src/utils/exception.h similarity index 99% rename from exception.h rename to src/utils/exception.h index 04845b2..525d871 100644 --- a/exception.h +++ b/src/utils/exception.h @@ -4,7 +4,8 @@ #pragma once -#include "warnings.h" +#include "..\warnings.h" +#include "..\def.h" #include "File.h" class Exception : public std::exception { diff --git a/gc.cpp b/src/utils/gc.cpp similarity index 100% rename from gc.cpp rename to src/utils/gc.cpp diff --git a/gc.h b/src/utils/gc.h similarity index 98% rename from gc.h rename to src/utils/gc.h index 218f291..1a1f03a 100644 --- a/gc.h +++ b/src/utils/gc.h @@ -4,8 +4,8 @@ #pragma once -#include "warnings.h" -#include "def.h" +#include "..\warnings.h" +#include "..\def.h" #include "exception.h" struct IGarbage; diff --git a/src/utils/math.h b/src/utils/math.h new file mode 100644 index 0000000..b63fbcb --- /dev/null +++ b/src/utils/math.h @@ -0,0 +1,154 @@ +// +// Created by EmsiaetKadosh on 25-3-21. +// + +#pragma once + +#include "..\warnings.h" + +class Vector3D; +class Vector2D; + +class Vector3D { + double x, y, z; + +public: + Vector3D(const double x, const double y, const double z) noexcept : x(x), y(y), z(z) {} + Vector3D() noexcept : x(0), y(0), z(0) {} + Vector3D(const Vector3D& other) noexcept = default; + Vector3D(Vector3D&& other) noexcept = default; + Vector3D& operator=(const Vector3D& other) noexcept = default; + Vector3D& operator=(Vector3D&& other) noexcept = default; + ~Vector3D() noexcept = default; + + [[nodiscard]] double getX() const noexcept { return x; } + [[nodiscard]] double getY() const noexcept { return y; } + [[nodiscard]] double getZ() const noexcept { return z; } + + [[nodiscard]] Vector3D operator+(const Vector3D& other) const noexcept { return Vector3D(x + other.x, y + other.y, z + other.z); } + [[nodiscard]] Vector3D operator-(const Vector3D& other) const noexcept { return Vector3D(x - other.x, y - other.y, z - other.z); } + [[nodiscard]] Vector3D operator*(const double scalar) const noexcept { return Vector3D(x * scalar, y * scalar, z * scalar); } + [[nodiscard]] Vector3D operator/(const double scalar) const noexcept { return Vector3D(x / scalar, y / scalar, z / scalar); } + [[nodiscard]] double operator*(const Vector3D& other) const noexcept { return x * other.x + y * other.y + z * other.z; } + + Vector3D& operator+=(const Vector3D& other) noexcept { + x += other.x; + y += other.y; + z += other.z; + return *this; + } + + Vector3D& operator-=(const Vector3D& other) noexcept { + x -= other.x; + y -= other.y; + z -= other.z; + return *this; + } + + Vector3D& operator*=(const double scalar) noexcept { + x *= scalar; + y *= scalar; + z *= scalar; + return *this; + } + + Vector3D& operator/=(const double scalar) noexcept { + x /= scalar; + y /= scalar; + z /= scalar; + return *this; + } + + [[nodiscard]] Vector3D operator-() const noexcept { return Vector3D(-x, -y, -z); } + bool operator==(const Vector3D& other) const noexcept { return x == other.x && y == other.y && z == other.z; } + bool operator!=(const Vector3D& other) const noexcept { return x != other.x || y != other.y || z != other.z; } + + [[nodiscard]] double length() const noexcept { return std::sqrt(x * x + y * y + z * z); } + + [[nodiscard]] Vector3D getNormalized() const noexcept { + if (x == 0.0 && y == 0.0 && z == 0) return Vector3D(0.0, 0.0, 0.0); + const double length = this->length(); + return Vector3D(x / length, y / length, z / length); + } + + Vector3D& normalize() noexcept { + if (x == 0 && y == 0 && z == 0) return *this; + const double length = this->length(); + x /= length; + y /= length; + z /= length; + return *this; + } + + [[nodiscard]] double dot(const Vector3D& other) const noexcept { return x * other.x + y * other.y + z * other.z; } + [[nodiscard]] Vector3D cross(const Vector3D& other) const noexcept { return Vector3D(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x); } +}; + +class Vector2D { + double x, y; + +public: + Vector2D(const double x, const double y) noexcept : x(x), y(y) {} + Vector2D() noexcept : x(0), y(0) {} + Vector2D(const Vector2D& other) noexcept = default; + Vector2D(Vector2D&& other) noexcept = default; + Vector2D& operator=(const Vector2D& other) noexcept = default; + Vector2D& operator=(Vector2D&& other) noexcept = default; + ~Vector2D() noexcept = default; + + [[nodiscard]] double getX() const noexcept { return x; } + [[nodiscard]] double getY() const noexcept { return y; } + + [[nodiscard]] Vector2D operator+(const Vector2D& other) const noexcept { return Vector2D(x + other.x, y + other.y); } + [[nodiscard]] Vector2D operator-(const Vector2D& other) const noexcept { return Vector2D(x - other.x, y - other.y); } + [[nodiscard]] Vector2D operator*(const double scalar) const noexcept { return Vector2D(x * scalar, y * scalar); } + [[nodiscard]] Vector2D operator/(const double scalar) const noexcept { return Vector2D(x / scalar, y / scalar); } + [[nodiscard]] double operator*(const Vector2D& other) const noexcept { return x * other.x + y * other.y; } + + Vector2D& operator+=(const Vector2D& other) noexcept { + x += other.x; + y += other.y; + return *this; + } + + Vector2D& operator-=(const Vector2D& other) noexcept { + x -= other.x; + y -= other.y; + return *this; + } + + Vector2D& operator*=(const double scalar) noexcept { + x *= scalar; + y *= scalar; + return *this; + } + + Vector2D& operator/=(const double scalar) noexcept { + x /= scalar; + y /= scalar; + return *this; + } + + [[nodiscard]] Vector2D operator-() const noexcept { return Vector2D(-x, -y); } + bool operator==(const Vector2D& other) const noexcept { return x == other.x && y == other.y; } + bool operator!=(const Vector2D& other) const noexcept { return x != other.x || y != other.y; } + + [[nodiscard]] double length() const noexcept { return std::sqrt(x * x + y * y); } + + [[nodiscard]] Vector2D getNormalized() const noexcept { + if (x == 0.0 && y == 0.0) return Vector2D(0.0, 0.0); + const double length = this->length(); + return Vector2D(x / length, y / length); + } + + Vector2D& normalize() noexcept { + if (x == 0 && y == 0) return *this; + const double length = this->length(); + x /= length; + y /= length; + return *this; + } + + [[nodiscard]] double dot(const Vector2D& other) const noexcept { return x * other.x + y * other.y; } + [[nodiscard]] Vector3D cross(const Vector2D& other) const noexcept { return Vector3D(0, 0, x * other.y - y * other.x); } +}; diff --git a/utils.h b/src/utils/utils.h similarity index 100% rename from utils.h rename to src/utils/utils.h diff --git a/warnings.h b/src/warnings.h similarity index 100% rename from warnings.h rename to src/warnings.h