修改渲染底层,新增场景摄像机逻辑,地图可行区域逻辑

This commit is contained in:
2025-10-08 23:58:15 +08:00
parent df2cacdb92
commit 1b011b9b68
23 changed files with 5350 additions and 40 deletions

View File

@@ -52,6 +52,7 @@ add_subdirectory(Library/SDL_ttf)
# 收集源文件 # 收集源文件
file(GLOB_RECURSE SOURCES file(GLOB_RECURSE SOURCES
"Library/src/*.c"
"source/*.cpp" "source/*.cpp"
"source_game/*.cpp" "source_game/*.cpp"
) )

View File

@@ -0,0 +1,311 @@
#ifndef __khrplatform_h_
#define __khrplatform_h_
/*
** Copyright (c) 2008-2018 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are 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 Materials.
**
** THE MATERIALS ARE 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
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/
/* Khronos platform-specific types and definitions.
*
* The master copy of khrplatform.h is maintained in the Khronos EGL
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
* The last semantic modification to khrplatform.h was at commit ID:
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
*
* Adopters may modify this file to suit their platform. Adopters are
* encouraged to submit platform specific modifications to the Khronos
* group so that they can be included in future versions of this file.
* Please submit changes by filing pull requests or issues on
* the EGL Registry repository linked above.
*
*
* See the Implementer's Guidelines for information about where this file
* should be located on your system and for more details of its use:
* http://www.khronos.org/registry/implementers_guide.pdf
*
* This file should be included as
* #include <KHR/khrplatform.h>
* by Khronos client API header files that use its types and defines.
*
* The types in khrplatform.h should only be used to define API-specific types.
*
* Types defined in khrplatform.h:
* khronos_int8_t signed 8 bit
* khronos_uint8_t unsigned 8 bit
* khronos_int16_t signed 16 bit
* khronos_uint16_t unsigned 16 bit
* khronos_int32_t signed 32 bit
* khronos_uint32_t unsigned 32 bit
* khronos_int64_t signed 64 bit
* khronos_uint64_t unsigned 64 bit
* khronos_intptr_t signed same number of bits as a pointer
* khronos_uintptr_t unsigned same number of bits as a pointer
* khronos_ssize_t signed size
* khronos_usize_t unsigned size
* khronos_float_t signed 32 bit floating point
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
* nanoseconds
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
* khronos_boolean_enum_t enumerated boolean type. This should
* only be used as a base type when a client API's boolean type is
* an enum. Client APIs which use an integer or other type for
* booleans cannot use this as the base type for their boolean.
*
* Tokens defined in khrplatform.h:
*
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
*
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
*
* Calling convention macros defined in this file:
* KHRONOS_APICALL
* KHRONOS_APIENTRY
* KHRONOS_APIATTRIBUTES
*
* These may be used in function prototypes as:
*
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
* int arg1,
* int arg2) KHRONOS_APIATTRIBUTES;
*/
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
# define KHRONOS_STATIC 1
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APICALL
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
#if defined(KHRONOS_STATIC)
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
* header compatible with static linking. */
# define KHRONOS_APICALL
#elif defined(_WIN32)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
#elif defined(__ANDROID__)
# define KHRONOS_APICALL __attribute__((visibility("default")))
#else
# define KHRONOS_APICALL
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIENTRY
*-------------------------------------------------------------------------
* This follows the return type of the function and precedes the function
* name in the function prototype.
*/
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
/* Win32 but not WinCE */
# define KHRONOS_APIENTRY __stdcall
#else
# define KHRONOS_APIENTRY
#endif
/*-------------------------------------------------------------------------
* Definition of KHRONOS_APIATTRIBUTES
*-------------------------------------------------------------------------
* This follows the closing parenthesis of the function prototype arguments.
*/
#if defined (__ARMCC_2__)
#define KHRONOS_APIATTRIBUTES __softfp
#else
#define KHRONOS_APIATTRIBUTES
#endif
/*-------------------------------------------------------------------------
* basic type definitions
*-----------------------------------------------------------------------*/
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
/*
* Using <stdint.h>
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
/*
* To support platform where unsigned long cannot be used interchangeably with
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
* unsigned long long or similar (this results in different C++ name mangling).
* To avoid changes for existing platforms, we restrict usage of intptr_t to
* platforms where the size of a pointer is larger than the size of long.
*/
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
#define KHRONOS_USE_INTPTR_T
#endif
#endif
#elif defined(__VMS ) || defined(__sgi)
/*
* Using <inttypes.h>
*/
#include <inttypes.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
/*
* Win32
*/
typedef __int32 khronos_int32_t;
typedef unsigned __int32 khronos_uint32_t;
typedef __int64 khronos_int64_t;
typedef unsigned __int64 khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif defined(__sun__) || defined(__digital__)
/*
* Sun or Digital
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#if defined(__arch64__) || defined(_LP64)
typedef long int khronos_int64_t;
typedef unsigned long int khronos_uint64_t;
#else
typedef long long int khronos_int64_t;
typedef unsigned long long int khronos_uint64_t;
#endif /* __arch64__ */
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#elif 0
/*
* Hypothetical platform with no float or int64 support
*/
typedef int khronos_int32_t;
typedef unsigned int khronos_uint32_t;
#define KHRONOS_SUPPORT_INT64 0
#define KHRONOS_SUPPORT_FLOAT 0
#else
/*
* Generic fallback
*/
#include <stdint.h>
typedef int32_t khronos_int32_t;
typedef uint32_t khronos_uint32_t;
typedef int64_t khronos_int64_t;
typedef uint64_t khronos_uint64_t;
#define KHRONOS_SUPPORT_INT64 1
#define KHRONOS_SUPPORT_FLOAT 1
#endif
/*
* Types that are (so far) the same on all platforms
*/
typedef signed char khronos_int8_t;
typedef unsigned char khronos_uint8_t;
typedef signed short int khronos_int16_t;
typedef unsigned short int khronos_uint16_t;
/*
* Types that differ between LLP64 and LP64 architectures - in LLP64,
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
* to be the only LLP64 architecture in current use.
*/
#ifdef KHRONOS_USE_INTPTR_T
typedef intptr_t khronos_intptr_t;
typedef uintptr_t khronos_uintptr_t;
#elif defined(_WIN64)
typedef signed long long int khronos_intptr_t;
typedef unsigned long long int khronos_uintptr_t;
#else
typedef signed long int khronos_intptr_t;
typedef unsigned long int khronos_uintptr_t;
#endif
#if defined(_WIN64)
typedef signed long long int khronos_ssize_t;
typedef unsigned long long int khronos_usize_t;
#else
typedef signed long int khronos_ssize_t;
typedef unsigned long int khronos_usize_t;
#endif
#if KHRONOS_SUPPORT_FLOAT
/*
* Float type
*/
typedef float khronos_float_t;
#endif
#if KHRONOS_SUPPORT_INT64
/* Time types
*
* These types can be used to represent a time interval in nanoseconds or
* an absolute Unadjusted System Time. Unadjusted System Time is the number
* of nanoseconds since some arbitrary system event (e.g. since the last
* time the system booted). The Unadjusted System Time is an unsigned
* 64 bit value that wraps back to 0 every 584 years. Time intervals
* may be either signed or unsigned.
*/
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
typedef khronos_int64_t khronos_stime_nanoseconds_t;
#endif
/*
* Dummy value used to pad enum types to 32 bits.
*/
#ifndef KHRONOS_MAX_ENUM
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
#endif
/*
* Enumerated boolean type
*
* Values other than zero should be considered to be true. Therefore
* comparisons should not be made against KHRONOS_TRUE.
*/
typedef enum {
KHRONOS_FALSE = 0,
KHRONOS_TRUE = 1,
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
} khronos_boolean_enum_t;
#endif /* __khrplatform_h_ */

3202
Library/include/glad/glad.h Normal file

File diff suppressed because it is too large Load Diff

1545
Library/src/glad.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -60,6 +60,7 @@ void Game::Init(std::function<void()> CallBack)
} }
// 启用渲染器的混合功能(必须,否则纹理混合模式无效) // 启用渲染器的混合功能(必须,否则纹理混合模式无效)
SDL_SetRenderDrawBlendMode(m_renderer, SDL_BLENDMODE_BLEND); SDL_SetRenderDrawBlendMode(m_renderer, SDL_BLENDMODE_BLEND);
// SDL_RenderSetScale(m_renderer, 1.2, 1.2);
IMG_Init(IMG_INIT_PNG); IMG_Init(IMG_INIT_PNG);
// 初始化SDL_mixer支持OGG格式 // 初始化SDL_mixer支持OGG格式

View File

@@ -77,7 +77,11 @@ private:
RefPtr<Scene> m_uiScene; RefPtr<Scene> m_uiScene;
// 帧数 // 帧数
int m_fps = 10000; #ifdef __SWITCH__
int m_fps = 60;
#else
int m_fps = 2000;
#endif
u32 m_frameTime; u32 m_frameTime;
float m_deltaTime; float m_deltaTime;
// 新增:帧率统计变量 // 新增:帧率统计变量

View File

@@ -4,16 +4,16 @@
Debug_Actor::Debug_Actor() Debug_Actor::Debug_Actor()
{ {
m_debugFont = TTF_OpenFont("Fonts/GasinamuNew.ttf", 16); m_debugFont = TTF_OpenFont("Fonts/VonwaonBitmap-12px.ttf", 12);
if (m_debugFont == nullptr) if (m_debugFont == nullptr)
{ {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load debug font: %s", TTF_GetError()); SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Failed to load debug font: %s", TTF_GetError());
} }
FPS_Text = new Text("Current FPS:", m_debugFont, SDL_Color{255, 255, 255, 255}); FPS_Text = new Text("当 前 帧 数 :", m_debugFont, SDL_Color{255, 255, 255, 255});
DT_Text = new Text("DeltaTime :", m_debugFont, SDL_Color{255, 255, 255, 255}); DT_Text = new Text("帧 时 间 :", m_debugFont, SDL_Color{255, 255, 255, 255});
RC_Text = new Text("Render Calls:", m_debugFont, SDL_Color{255, 255, 255, 255}); RC_Text = new Text("渲 染 调 用 次 数:", m_debugFont, SDL_Color{255, 255, 255, 255});
if (FPS_Text != nullptr) if (FPS_Text != nullptr)
{ {
SDL_Point Pos{26, 26}; SDL_Point Pos{26, 26};
@@ -50,11 +50,11 @@ void Debug_Actor::Update(float deltaTime)
if (FPS_Text != nullptr) if (FPS_Text != nullptr)
{ {
std::string fpsText = "Current FPS: " + std::to_string(FPS); std::string fpsText = "当前帧数 : " + std::to_string(FPS);
FPS_Text->SetText(fpsText); FPS_Text->SetText(fpsText);
std::string dtText = "DeltaTime: " + std::to_string((int)(deltaTime * 1000)); std::string dtText = "帧时间 : " + std::to_string((int)(deltaTime * 1000));
DT_Text->SetText(dtText); DT_Text->SetText(dtText);
std::string rcText = "Render Calls: " + std::to_string(RenderCount); std::string rcText = "渲染调用次数 : " + std::to_string(RenderCount);
RC_Text->SetText(rcText); RC_Text->SetText(rcText);
} }
} }

View File

@@ -92,6 +92,7 @@ int BaseNode::GetRenderZOrder()
void BaseNode::SetRenderZOrder(int zOrder) void BaseNode::SetRenderZOrder(int zOrder)
{ {
m_RenderZOrder = zOrder; m_RenderZOrder = zOrder;
Reorder();
} }
void BaseNode::Reorder() void BaseNode::Reorder()

View File

@@ -118,7 +118,7 @@ public:
// 获取大小 // 获取大小
VecSize GetSize(); VecSize GetSize();
// 设置是否显示 // 设置是否显示
void SetVisible(bool visible); virtual void SetVisible(bool visible);
// 获取是否显示 // 获取是否显示
bool GetVisible(); bool GetVisible();
}; };

View File

@@ -147,6 +147,16 @@ void Animation::Clear()
{ {
} }
void Animation::SetVisible(bool visible)
{
// 设置启用的时候要更新一下当前帧的渲染信息 避免因为延迟造成的坐标闪烁
if (visible)
{
CurrentFrame->CalcRenderInfoLogic();
}
Actor::SetVisible(visible);
}
void Animation::FlushFrame(int Index) void Animation::FlushFrame(int Index)
{ {
// 关闭旧帧显示 // 关闭旧帧显示

View File

@@ -30,6 +30,7 @@ public:
void Render() override; void Render() override;
void OnAdded(BaseNode *node) override; void OnAdded(BaseNode *node) override;
void Clear() override; void Clear() override;
void SetVisible(bool visible) override;
public: public:
void FlushFrame(int Index); void FlushFrame(int Index);

View File

@@ -291,6 +291,24 @@ void GameMap::InitMapAnimation()
} }
} }
void GameMap::InitVirtualMovableArea()
{
std::vector<int> Info = std::get<std::vector<int>>(_MapInfo["virtual_movable_area"]);
if (Info.size() > 0)
{
for (int i = 0; i < Info.size(); i += 4)
{
float x = Info[i];
float y = Info[i + 1];
float w = Info[i + 2];
float h = Info[i + 3];
if (_DebugMode)
_LayerMap["max"]->AddDebugFeasibleAreaInfo(VecFPos(x, y), VecSize(w, h));
_MovableArea.push_back(SDL_FRect{x, y, w, h});
}
}
}
void GameMap::LoadMap(std::string mapName) void GameMap::LoadMap(std::string mapName)
{ {
// 读取脚本配置 // 读取脚本配置
@@ -301,11 +319,8 @@ void GameMap::LoadMap(std::string mapName)
InitBackgroundAnimation(); InitBackgroundAnimation();
// 初始化场景Ani // 初始化场景Ani
InitMapAnimation(); InitMapAnimation();
// 初始化可行区域
RefPtr<CharacterObject> obj = new CharacterObject(); InitVirtualMovableArea();
obj->SetPosition({620, 200, 0});
obj->Construction(0);
_LayerMap["normal"]->AddObject(obj);
} }
void GameMap::Enter(Scene *scene) void GameMap::Enter(Scene *scene)
@@ -321,7 +336,7 @@ void GameMap::Enter(Scene *scene)
scene->AddChild(_LayerMap["max"]); scene->AddChild(_LayerMap["max"]);
// TODO // TODO
int HSU = 230; int HSU = 0;
_LayerMap["contact"]->SetPos(VecFPos{0, HSU}); _LayerMap["contact"]->SetPos(VecFPos{0, HSU});
_LayerMap["distantback"]->SetPos(VecFPos{0, HSU}); _LayerMap["distantback"]->SetPos(VecFPos{0, HSU});
_LayerMap["middleback"]->SetPos(VecFPos{0, HSU}); _LayerMap["middleback"]->SetPos(VecFPos{0, HSU});
@@ -367,3 +382,67 @@ void GameMap::Update(float deltaTime)
// } // }
// } // }
} }
void GameMap::AddObject(RefPtr<BaseObject> object)
{
object->_AffMap = this;
_LayerMap["normal"]->AddObject(object);
}
VecFPos3 GameMap::CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset)
{
// 初始化结果为原坐标(默认不移动)
VecFPos3 result = CurPos;
// 如果没有可移动区域限制,直接全量位移
if (_MovableArea.empty())
{
result.x += PosOffset.x;
result.y += PosOffset.y;
result.z += PosOffset.z; // Z轴不受限
return result;
}
// 计算X轴单独位移后的目标位置
float targetX = CurPos.x + PosOffset.x;
// 计算Y轴单独位移后的目标位置
float targetY = CurPos.y + PosOffset.y;
// 检查X轴位移是否合法固定Y为当前值仅移动X
SDL_FPoint xTestPoint{targetX, CurPos.y};
bool isXValid = false;
for (auto &area : _MovableArea)
{
if (SDL_PointInFRect(&xTestPoint, &area))
{
isXValid = true;
break;
}
}
// 检查Y轴位移是否合法固定X为当前值仅移动Y
SDL_FPoint yTestPoint{CurPos.x, targetY};
bool isYValid = false;
for (auto &area : _MovableArea)
{
if (SDL_PointInFRect(&yTestPoint, &area))
{
isYValid = true;
break;
}
}
// 应用合法的位移
if (isXValid)
{
result.x = targetX; // X轴允许移动
}
if (isYValid)
{
result.y = targetY; // Y轴允许移动
}
// Z轴不受限制直接应用位移
result.z += PosOffset.z;
return result;
}

View File

@@ -62,6 +62,10 @@ public:
int _MapLength = 0; int _MapLength = 0;
// 地图高度 // 地图高度
int _MapHeight = 0; int _MapHeight = 0;
// 可行区域
std::vector<SDL_FRect> _MovableArea;
// 调试模式
bool _DebugMode = true;
public: public:
// 图层Map 图层类型 显示对象 // 图层Map 图层类型 显示对象
@@ -79,9 +83,13 @@ public:
void InitTile(); void InitTile();
void InitBackgroundAnimation(); void InitBackgroundAnimation();
void InitMapAnimation(); void InitMapAnimation();
void InitVirtualMovableArea();
void Enter(Scene *scene); void Enter(Scene *scene);
void HandleEvents(SDL_Event *e); void HandleEvents(SDL_Event *e);
void Update(float deltaTime); void Update(float deltaTime);
void AddObject(RefPtr<BaseObject> object);
public: public:
// 检查是否可移动
VecFPos3 CheckIsItMovable(VecFPos3 CurPos, VecFPos3 PosOffset);
}; };

View File

@@ -1,4 +1,5 @@
#include "GameMapCamera.h" #include "GameMapCamera.h"
#include "EngineCore/Game.h"
#include "Actor/Map/GameMap.h" #include "Actor/Map/GameMap.h"
#include "Actor/Object/BaseObject.h" #include "Actor/Object/BaseObject.h"
#include <algorithm> #include <algorithm>
@@ -45,10 +46,23 @@ void GameMapCamera::SyncPosByFromParent(float deltaTime)
{ {
if (this->_FromActor != nullptr) if (this->_FromActor != nullptr)
{ {
// int R_X, R_Y, R_Z; float width_Separate = Game::GetInstance().Screen_W / 2;
// R_X = std::min(std::max(this->_FromActor->X, 533), MovableAreaX - 533); float height_Separate = Game::GetInstance().Screen_H / 2;
// R_Y = std::min(std::max(this->_FromActor->Y, 300), MovableAreaY - 300); int R_X, R_Y, R_Z;
// R_Z = 0; R_X = std::fmin(std::fmax(this->_FromActor->Position.x, width_Separate), _ParentMap->_MapLength - width_Separate);
R_Y = std::fmin(std::fmax(this->_FromActor->Position.y, height_Separate), _ParentMap->_MapHeight - height_Separate);
R_Z = 0;
// SDL_Log("R_X: %d, R_Y: %d, R_Z: %d", R_X, R_Y, R_Z);
// SetPos(R_X, R_Y, R_Z); // SetPos(R_X, R_Y, R_Z);
for (auto Layer : _ParentMap->_LayerMap)
{
if (Layer.first == "distantback")
{
Layer.second->SetPos(VecFPos((-R_X + width_Separate) * BackgroundMoveSpeed, -R_Y + R_Z + height_Separate + 120 + BackgroundOffset));
}
else
Layer.second->SetPos(VecFPos((-R_X + width_Separate), -R_Y + R_Z + height_Separate + 120 + BackgroundOffset));
}
} }
} }

View File

@@ -20,7 +20,7 @@ public:
// 背景偏移量 // 背景偏移量
int BackgroundOffset = 0; int BackgroundOffset = 0;
// 背景层移动速率 // 背景层移动速率
int BackgroundMoveSpeed = 1.0; int BackgroundMoveSpeed = 1.03;
// 人物中线长度 // 人物中线长度
int CharacterLineLength = 0; int CharacterLineLength = 0;
// 摄像机朝向 // 摄像机朝向

View File

@@ -1,4 +1,5 @@
#include "GameMapLayer.h" #include "GameMapLayer.h"
#include "EngineCore/Game.h"
GameMapLayer::GameMapLayer() GameMapLayer::GameMapLayer()
{ {
@@ -8,6 +9,37 @@ GameMapLayer::~GameMapLayer()
{ {
} }
void GameMapLayer::Render()
{
Actor::Render();
SDL_Renderer *renderer = Game::GetInstance().GetRenderer();
// 设置绘制颜色
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 128);
// 自身坐标
float Xpos = GetIterationPos().x + GetPos().x;
float Ypos = GetIterationPos().y + GetPos().y;
for (auto &info : this->FeasibleAreaInfoList)
{
SDL_Rect buf;
buf.x = info.x + Xpos;
buf.y = info.y + Ypos;
buf.w = info.w;
buf.h = info.h;
// 绘制填充矩形
SDL_RenderFillRect(renderer, &buf);
}
}
void GameMapLayer::AddDebugFeasibleAreaInfo(VecFPos pos, VecSize size)
{
SDL_Rect info;
info.x = pos.x;
info.y = pos.y;
info.w = size.width;
info.h = size.height;
this->FeasibleAreaInfoList.push_back(info);
}
void GameMapLayer::AddObject(RefPtr<Actor> obj) void GameMapLayer::AddObject(RefPtr<Actor> obj)
{ {
this->AddChild(obj); this->AddChild(obj);

View File

@@ -9,11 +9,18 @@ class GameMapLayer : public Actor
private: private:
// 地图对象 // 地图对象
std::vector<RefPtr<Component>> ObjectManager; std::vector<RefPtr<Component>> ObjectManager;
// 可行区域信息
std::vector<SDL_Rect> FeasibleAreaInfoList;
public: public:
GameMapLayer(/* args */); GameMapLayer(/* args */);
~GameMapLayer(); ~GameMapLayer();
// 重载Render以实现绘制可行区域
void Render() override;
// 添加调试可行区域信息
void AddDebugFeasibleAreaInfo(VecFPos pos, VecSize size);
public: public:
void AddObject(RefPtr<Actor> obj); // 添加对象 void AddObject(RefPtr<Actor> obj); // 添加对象
}; };

View File

@@ -45,6 +45,6 @@ void ActiveObject::Update(float deltaTime)
SetPosition(Position); SetPosition(Position);
SDL_LogError(0, "修正Z轴"); SDL_LogError(0, "修正Z轴");
} }
// 执行父对象的更新 // 执行父的更新
BaseObject::Update(deltaTime); BaseObject::Update(deltaTime);
} }

View File

@@ -1,5 +1,5 @@
#include "BaseObject.h" #include "BaseObject.h"
#include "Actor/Map/GameMap.h"
BaseObject::BaseObject() BaseObject::BaseObject()
{ {
Init(); // 调用了RenderBase的Init函数 对象才会被执行回调 Init(); // 调用了RenderBase的Init函数 对象才会被执行回调
@@ -12,6 +12,10 @@ BaseObject::~BaseObject()
void BaseObject::SetPosition(VecFPos3 pos) void BaseObject::SetPosition(VecFPos3 pos)
{ {
if (pos.y != this->Position.y)
{
SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序
}
this->Position = pos; this->Position = pos;
Actor::SetPos(VecFPos{this->Position.x, this->Position.y - this->Position.z}); Actor::SetPos(VecFPos{this->Position.x, this->Position.y - this->Position.z});
} }
@@ -29,6 +33,10 @@ void BaseObject::SetXpos(float x)
void BaseObject::SetYpos(float y) void BaseObject::SetYpos(float y)
{ {
if (y != this->Position.y)
{
SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序
}
this->Position.y = y; this->Position.y = y;
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z}); Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
} }
@@ -56,17 +64,25 @@ int BaseObject::GetZpos()
void BaseObject::MoveBy(VecFPos3 pos) void BaseObject::MoveBy(VecFPos3 pos)
{ {
this->Position.x += pos.x; // 只有moveby移动时判断所在地图中是否能够这样移动
this->Position.y += pos.y; VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), pos);
this->Position.z += pos.z; if (pos.y != 0)
{
SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序
}
this->Position = RealPos;
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z}); Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
} }
void BaseObject::MoveBy(float x, float y, float z) void BaseObject::MoveBy(float x, float y, float z)
{ {
this->Position.x += x; // 只有moveby移动时判断所在地图中是否能够这样移动
this->Position.y += y; VecFPos3 RealPos = this->_AffMap->CheckIsItMovable(GetPosition(), VecFPos3({x, y, z}));
this->Position.z += z; if (y != 0)
{
SetRenderZOrder((int)(this->Position.y)); // 设置渲染顺序
}
this->Position = RealPos;
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z}); Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
} }

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "EngineFrame/Actor/Actor.h" #include "EngineFrame/Actor/Actor.h"
#include "Asset/Common/ObjectVars.h" #include "Asset/Common/ObjectVars.h"
class GameMap;
class BaseObject : public Actor class BaseObject : public Actor
{ {
private: private:
@@ -8,6 +9,7 @@ private:
public: public:
VecFPos3 Position; // 位置 VecFPos3 Position; // 位置
int Direction = 0; // 方向 int Direction = 0; // 方向
GameMap *_AffMap = nullptr; // 所在地图
public: public:
BaseObject(/* args */); BaseObject(/* args */);

View File

@@ -115,6 +115,71 @@ void Chr_Controller::HandleEvents(SDL_Event *e)
} }
break; break;
} }
case SDL_KEYDOWN:
{
switch (e->key.keysym.sym)
{
case SDLK_UP: // 上方向键
LeftStick.y = -1.0f;
break;
case SDLK_DOWN: // 下方向键
LeftStick.y = 1.0f;
break;
case SDLK_LEFT: // 左方向键
LeftStick.x = -1.0f;
break;
case SDLK_RIGHT: // 右方向键
LeftStick.x = 1.0f;
break;
default:
break;
}
// 如果父对象存在 调用父对象的消息处理
if (m_pCharacter)
{
m_pCharacter->ControllerMsg(CONTROLLER_MSG_TYPE::CONTROLLER_MSG_TYPE_LEFT_JOYSTICK_MOVE, &LeftStick);
}
break;
}
case SDL_KEYUP:
{
switch (e->key.keysym.sym)
{
case SDLK_UP: // 上方向键
{
if (LeftStick.y < 0.f)
LeftStick.y = 0.f;
break;
}
case SDLK_DOWN: // 下方向键
{
if (LeftStick.y > 0.f)
LeftStick.y = 0.f;
break;
}
case SDLK_LEFT: // 左方向键
{
if (LeftStick.x < 0.f)
LeftStick.x = 0.f;
break;
}
case SDLK_RIGHT: // 右方向键
{
if (LeftStick.x > 0.f)
LeftStick.x = 0.f;
break;
}
default:
break;
}
// 如果父对象存在 调用父对象的消息处理
if (m_pCharacter)
{
m_pCharacter->ControllerMsg(CONTROLLER_MSG_TYPE::CONTROLLER_MSG_TYPE_LEFT_JOYSTICK_MOVE, &LeftStick);
}
break;
}
default: default:
// 可以处理其他类型的事件或忽略 // 可以处理其他类型的事件或忽略
break; break;

View File

@@ -10,7 +10,8 @@ Global_Game::~Global_Game()
void Global_Game::Init() void Global_Game::Init()
{ {
// 初始化ttf字体资源 // 初始化ttf字体资源
TTF_Font *FontBuf = TTF_OpenFont("Fonts/LXGWWenKai-Regular.ttf", 24); // TTF_Font *FontBuf = TTF_OpenFont("Fonts/LXGWWenKai-Regular.ttf", 24);
TTF_Font *FontBuf = TTF_OpenFont("Fonts/VonwaonBitmap-12px.ttf", 24);
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/Gothica-Book.ttf", 24); // TTF_Font *FontBuf = TTF_OpenFont("Fonts/Gothica-Book.ttf", 24);
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/Gasinamu.ttf", 24); // TTF_Font *FontBuf = TTF_OpenFont("Fonts/Gasinamu.ttf", 24);
if (!FontBuf) if (!FontBuf)

View File

@@ -4,6 +4,7 @@
#include "EngineFrame/Component/Animation.h" #include "EngineFrame/Component/Animation.h"
#include "Actor/Map/GameMap.h" #include "Actor/Map/GameMap.h"
#include "Actor/Map/GameMapCamera.h" #include "Actor/Map/GameMapCamera.h"
#include "Actor/Object/CharacterObject.h"
class Scene_SelectCharacter_UI : public Scene class Scene_SelectCharacter_UI : public Scene
{ {
private: private:
@@ -26,21 +27,30 @@ public:
map->LoadMap("map/cataclysm/town/elvengard/new_elvengard.map"); map->LoadMap("map/cataclysm/town/elvengard/new_elvengard.map");
map->Enter(this); map->Enter(this);
RefPtr<CharacterObject> obj = new CharacterObject();
obj->SetPosition({620, 200, 0});
// 构造为鬼剑士
obj->Construction(0);
map->AddObject(obj);
camera = new GameMapCamera; camera = new GameMapCamera;
camera->SetParentMap(map);
camera->SetFromActor(obj.Get());
AddChild(camera); AddChild(camera);
return;
RefPtr<Actor> actor = new Actor;
actor->SetPos(VecFPos{450, 350});
// actor->SetAnchor(VecFPos{0.5, 0.5});
actor->SetScale(VecFPos{-1.f, 1.f});
AddChild(actor);
RefPtr<Actor> actor2 = new Actor; // RefPtr<Actor> actor = new Actor;
actor->AddChild(actor2); // actor->SetPos(VecFPos{450, 350});
// // actor->SetAnchor(VecFPos{0.5, 0.5});
// actor->SetScale(VecFPos{-1.f, 1.f});
// AddChild(actor);
RefPtr<Animation> ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani"); // RefPtr<Actor> actor2 = new Actor;
// ani4->SetScale(VecFPos{-1.0, 1.0}); // actor->AddChild(actor2);
actor2->AddChild(ani4);
// RefPtr<Animation> ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani");
// // ani4->SetScale(VecFPos{-1.0, 1.0});
// actor2->AddChild(ani4);
// RefPtr<Animation> ani3 = new Animation("map/cataclysm/town/elvengard/animation/obj/serialight01_right.ani"); // RefPtr<Animation> ani3 = new Animation("map/cataclysm/town/elvengard/animation/obj/serialight01_right.ani");
// ani3->SetPos(VecPos{300, 300}); // ani3->SetPos(VecPos{300, 300});