建档
This commit is contained in:
116
source_game/Asset/Character/Chr_Animation.cpp
Normal file
116
source_game/Asset/Character/Chr_Animation.cpp
Normal file
@@ -0,0 +1,116 @@
|
||||
#include "Chr_Animation.h"
|
||||
#include "Global/Global_Game.h"
|
||||
#include "Actor/Object/CharacterObject.h"
|
||||
#include "Asset/Character/Chr_Equipment.h"
|
||||
|
||||
std::string Chr_Animation::FormatImgPath(std::string ImgPath, Animation::ReplaceData data)
|
||||
{
|
||||
size_t pos = ImgPath.find("%04d");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
ImgPath.replace(pos, 4, "%02d%02d");
|
||||
}
|
||||
char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), ImgPath.c_str(), data.Param1, data.Param2);
|
||||
std::string newPath = buffer;
|
||||
return newPath;
|
||||
}
|
||||
|
||||
void Chr_Animation::CreateSkinmationBySlot(std::string actionName, std::string slotName, std::string path)
|
||||
{
|
||||
// 皮肤在没有穿戴的情况下 格式化参数为0
|
||||
if (slotName == "skin_avatar")
|
||||
{
|
||||
// 如果穿戴了皮肤时装 读取variation
|
||||
RefPtr<Equipment> Equip = ((CharacterObject *)m_Parent)->_EquipmentManager->GetEquip(slotName);
|
||||
if (Equip)
|
||||
{
|
||||
Animation::ReplaceData Data(0, 0);
|
||||
for (auto &Variation : Equip->JobAni[this->chr_parent->Job])
|
||||
{
|
||||
Data.Param1 = Variation.ImgFormat[0];
|
||||
Data.Param2 = Variation.ImgFormat[1];
|
||||
// 构造好Ani以后 统一设置为不可见 然后放入ActionAnis表
|
||||
RefPtr<Animation> Ani = new Animation(path, FormatImgPath, Data);
|
||||
Ani->SetVisible(false);
|
||||
Ani->SetRenderZOrder(Variation.Layer);
|
||||
this->AddChild(Ani);
|
||||
ActionAnis[actionName].push_back(Ani);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RefPtr<Equipment> Equip = ((CharacterObject *)m_Parent)->_EquipmentManager->GetEquip(slotName);
|
||||
if (Equip)
|
||||
{
|
||||
// SDL_Log("CreateSkinmationBySlot %s", slotName.c_str());
|
||||
Animation::ReplaceData Data(0, 0);
|
||||
for (auto &Variation : Equip->JobAni[this->chr_parent->Job])
|
||||
{
|
||||
Data.Param1 = Variation.ImgFormat[0];
|
||||
Data.Param2 = Variation.ImgFormat[1];
|
||||
|
||||
// 读取装备路径
|
||||
std::string EquipPath = Tool_TruncatePath(Equip->m_EquipmentPath);
|
||||
// 组装动画路径
|
||||
std::string AniPath = EquipPath + Variation.AnimationGroup + path.substr(path.find_last_of("/"), path.length());
|
||||
|
||||
// 构造好Ani以后 统一设置为不可见 然后放入ActionAnis表
|
||||
RefPtr<Animation> Ani = new Animation(AniPath, FormatImgPath, Data);
|
||||
Ani->SetVisible(false);
|
||||
Ani->SetRenderZOrder(Variation.Layer);
|
||||
this->AddChild(Ani);
|
||||
ActionAnis[actionName].push_back(Ani);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Chr_Animation::Init(CharacterObject *parent)
|
||||
{
|
||||
// 调用RenderBase类的初始化 才能挂上标签
|
||||
RenderBase::Init();
|
||||
parent->AddChild(this);
|
||||
chr_parent = parent;
|
||||
GlobalCharacterScript::CharacterConfig Config = Global_Game::GetInstance().CharacterConfigs[parent->Job];
|
||||
|
||||
// 遍历所有动作Ani路径
|
||||
for (const auto &pair : Config.animationPath)
|
||||
{
|
||||
std::string ActionName = pair.first;
|
||||
std::string Path = std::string("character/" + Config.jobTag + "/" + Tool_toLowerCase(pair.second));
|
||||
|
||||
// 遍历所有时装部位构造Ani
|
||||
for (auto &AvatarPartPair : AvatarPart)
|
||||
{
|
||||
std::string AvatarPartName = AvatarPartPair.first;
|
||||
CreateSkinmationBySlot(ActionName, AvatarPartName, Path);
|
||||
}
|
||||
}
|
||||
// 设置初始动作
|
||||
SetAction("rest");
|
||||
}
|
||||
|
||||
void Chr_Animation::SetAction(std::string actionName)
|
||||
{
|
||||
// 先将原动作的Ani设置为不可见
|
||||
for (auto Ani : ActionAnis[CurrentActionTag])
|
||||
{
|
||||
Ani->Reset();
|
||||
Ani->SetVisible(false);
|
||||
}
|
||||
// 再将新动作的Ani设置为可见
|
||||
for (auto Ani : ActionAnis[actionName])
|
||||
{
|
||||
Ani->SetVisible(true);
|
||||
}
|
||||
CurrentActionTag = actionName;
|
||||
}
|
||||
|
||||
void Chr_Animation::Update(float deltaTime)
|
||||
{
|
||||
RenderBase::Update(deltaTime);
|
||||
// SDL_Log("Position %d %d", this->GetTransform().position.x, this->GetTransform().position.y);
|
||||
// SDL_Log("IterPosition %d %d", this->GetIterationTransform().position.x, this->GetIterationTransform().position.y);
|
||||
}
|
||||
50
source_game/Asset/Character/Chr_Animation.h
Normal file
50
source_game/Asset/Character/Chr_Animation.h
Normal file
@@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Component/Animation.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
class CharacterObject;
|
||||
class Chr_Animation : public RenderBase
|
||||
{
|
||||
// 动作动画集合
|
||||
using ActionAniList = std::map<std::string, std::vector<RefPtr<Animation>>>;
|
||||
|
||||
public:
|
||||
inline static const std::unordered_map<std::string, std::string>
|
||||
AvatarPart = {
|
||||
{"weapon_avatar", "武器装扮"},
|
||||
{"aurora_avatar", "光环装扮"},
|
||||
{"hair_avatar", "头部装扮"},
|
||||
{"hat_avatar", "帽子装扮"},
|
||||
{"face_avatar", "脸部装扮"},
|
||||
{"breast_avatar", "胸部装扮"},
|
||||
{"coat_avatar", "上衣装扮"},
|
||||
{"skin_avatar", "皮肤装扮"},
|
||||
{"waist_avatar", "腰部装扮"},
|
||||
{"pants_avatar", "下装装扮"},
|
||||
{"shoes_avatar", "鞋子装扮"},
|
||||
{"weapon", "武器"},
|
||||
};
|
||||
|
||||
private:
|
||||
// 父对象
|
||||
CharacterObject *chr_parent;
|
||||
// 时装部位对应的动作动画集合
|
||||
ActionAniList ActionAnis;
|
||||
// 当前动作Tag
|
||||
std::string CurrentActionTag = "waiting";
|
||||
|
||||
public:
|
||||
static std::string FormatImgPath(std::string path, Animation::ReplaceData data);
|
||||
|
||||
public:
|
||||
void CreateSkinmationBySlot(std::string actionName, std::string slotName, std::string path);
|
||||
|
||||
public:
|
||||
// 初始化时 只完成基础的职业皮肤设置
|
||||
void Init(CharacterObject *parent);
|
||||
// 设置动作
|
||||
void SetAction(std::string actionName);
|
||||
|
||||
void Update(float deltaTime) override;
|
||||
};
|
||||
122
source_game/Asset/Character/Chr_Controller.cpp
Normal file
122
source_game/Asset/Character/Chr_Controller.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
#include "Chr_Controller.h"
|
||||
#include "Actor/Object/CharacterObject.h"
|
||||
|
||||
float Chr_Controller::ConvertAxisValue(Sint16 rawValue)
|
||||
{
|
||||
float value = 0.f;
|
||||
// SDL的轴值范围通常是-32768到32767
|
||||
if (rawValue > 0)
|
||||
{
|
||||
value = static_cast<float>(rawValue) / 32767.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
value = static_cast<float>(rawValue) / 32768.0f;
|
||||
}
|
||||
// 小于0.1的值视为0
|
||||
if (fabs(value) < 0.1f)
|
||||
{
|
||||
value = 0.f;
|
||||
}
|
||||
// 大于0.95的值视为1
|
||||
else if (fabs(value) > 0.95f)
|
||||
{
|
||||
value = (value > 0) ? 1.f : -1.f;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void Chr_Controller::Init(CharacterObject *pCharacter)
|
||||
{
|
||||
addTag(Tag::HANDEL_EVENT);
|
||||
m_pCharacter = pCharacter;
|
||||
}
|
||||
|
||||
void Chr_Controller::HandleEvents(SDL_Event *e)
|
||||
{
|
||||
// 处理控制器相关事件
|
||||
switch (e->type)
|
||||
{
|
||||
case SDL_CONTROLLERDEVICEADDED:
|
||||
{
|
||||
SDL_Log("手柄连接 - 设备ID: %d", e->cdevice.which);
|
||||
int deviceIndex = e->cdevice.which;
|
||||
if (SDL_IsGameController(deviceIndex))
|
||||
{
|
||||
SDL_GameController *controller = SDL_GameControllerOpen(deviceIndex);
|
||||
if (controller)
|
||||
{
|
||||
SDL_Log("已连接并打开控制器: %s", SDL_GameControllerName(controller));
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_Log("连接了控制器但无法打开! SDL错误: %s", SDL_GetError());
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_CONTROLLERDEVICEREMOVED:
|
||||
{
|
||||
SDL_Log("手柄断开 - 设备ID: %d", e->cdevice.which);
|
||||
break;
|
||||
}
|
||||
case SDL_CONTROLLERDEVICEREMAPPED:
|
||||
{
|
||||
SDL_Log("手柄重映射 - 设备ID: %d", e->cdevice.which);
|
||||
break;
|
||||
}
|
||||
case SDL_CONTROLLERBUTTONDOWN:
|
||||
{
|
||||
SDL_Log("手柄按钮按下 - 控制器ID: %d, 按钮: %d",
|
||||
e->cbutton.which, e->cbutton.button);
|
||||
break;
|
||||
}
|
||||
case SDL_CONTROLLERBUTTONUP:
|
||||
{
|
||||
SDL_Log("手柄按钮释放 - 控制器ID: %d, 按钮: %d",
|
||||
e->cbutton.which, e->cbutton.button);
|
||||
break;
|
||||
}
|
||||
case SDL_CONTROLLERAXISMOTION:
|
||||
{
|
||||
// 转换原始轴值到-1到1范围
|
||||
float value = ConvertAxisValue(e->caxis.value);
|
||||
// 根据不同的轴更新对应的摇杆位置
|
||||
switch (e->caxis.axis)
|
||||
{
|
||||
case SDL_CONTROLLER_AXIS_LEFTX:
|
||||
LeftStick.x = value;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_LEFTY:
|
||||
LeftStick.y = value;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTX:
|
||||
RightStick.x = value;
|
||||
break;
|
||||
case SDL_CONTROLLER_AXIS_RIGHTY:
|
||||
RightStick.y = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
// 如果父对象存在 调用父对象的消息处理
|
||||
if (m_pCharacter)
|
||||
{
|
||||
// 左摇杆变动时
|
||||
if (e->caxis.axis == SDL_CONTROLLER_AXIS_LEFTX || e->caxis.axis == SDL_CONTROLLER_AXIS_LEFTY)
|
||||
{
|
||||
m_pCharacter->ControllerMsg(CONTROLLER_MSG_TYPE::CONTROLLER_MSG_TYPE_LEFT_JOYSTICK_MOVE, &LeftStick);
|
||||
}
|
||||
// 右摇杆变动时
|
||||
else if (e->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX || e->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTY)
|
||||
{
|
||||
m_pCharacter->ControllerMsg(CONTROLLER_MSG_TYPE::CONTROLLER_MSG_TYPE_RIGHT_JOYSTICK_MOVE, &RightStick);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// 可以处理其他类型的事件或忽略
|
||||
break;
|
||||
}
|
||||
}
|
||||
24
source_game/Asset/Character/Chr_Controller.h
Normal file
24
source_game/Asset/Character/Chr_Controller.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Base/BaseNode.h"
|
||||
#include "Tool/Common.h"
|
||||
class CharacterObject;
|
||||
class Chr_Controller : public BaseNode
|
||||
{
|
||||
private:
|
||||
CharacterObject *m_pCharacter = nullptr;
|
||||
|
||||
public:
|
||||
VecFPos LeftStick = {0.f, 0.f};
|
||||
VecFPos RightStick = {0.f, 0.f};
|
||||
|
||||
// 用于将SDL的轴值(-32768到32767)转换为-1到1之间的浮点数
|
||||
float ConvertAxisValue(Sint16 rawValue);
|
||||
|
||||
public:
|
||||
void Init(CharacterObject *pCharacter);
|
||||
void HandleEvents(SDL_Event *e) override;
|
||||
|
||||
// 获取摇杆位置的方法
|
||||
const VecFPos &GetLeftStick() const { return LeftStick; }
|
||||
const VecFPos &GetRightStick() const { return RightStick; }
|
||||
};
|
||||
38
source_game/Asset/Character/Chr_Equipment.cpp
Normal file
38
source_game/Asset/Character/Chr_Equipment.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
#include "Chr_Equipment.h"
|
||||
#include "Global/Global_Game.h"
|
||||
#include "Actor/Object/CharacterObject.h"
|
||||
|
||||
void Chr_Equipment::Init(CharacterObject *parent)
|
||||
{
|
||||
// 判断是否转职读取不同的配置
|
||||
GlobalCharacterScript::JobConfig JobInfo;
|
||||
if (parent->GrowType == -1)
|
||||
{
|
||||
JobInfo = Global_Game::GetInstance().CharacterConfigs[parent->Job].baseJobConfig;
|
||||
}
|
||||
else
|
||||
{
|
||||
GlobalCharacterScript::CharacterConfig Config = Global_Game::GetInstance().CharacterConfigs[parent->Job];
|
||||
JobInfo = Config.growtypeJobConfig[parent->GrowType];
|
||||
}
|
||||
|
||||
// 读取默认时装
|
||||
for (auto &pair : JobInfo.defaultAvatarList)
|
||||
{
|
||||
std::string PartName = pair.first;
|
||||
int Index = pair.second;
|
||||
RefPtr<Equipment> equip = new Equipment();
|
||||
equip->Init(Index);
|
||||
this->_default_equip[PartName] = equip;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<Equipment> Chr_Equipment::GetEquip(std::string part)
|
||||
{
|
||||
// 先看真实穿戴 如果没有 看默认 如果没有 返回空
|
||||
if (_real_equip.count(part) > 0)
|
||||
return _real_equip[part];
|
||||
if (_default_equip.count(part) > 0)
|
||||
return _default_equip[part];
|
||||
return nullptr;
|
||||
}
|
||||
19
source_game/Asset/Character/Chr_Equipment.h
Normal file
19
source_game/Asset/Character/Chr_Equipment.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Component/Component.h"
|
||||
#include "Asset/Common/Equipment.h"
|
||||
|
||||
class CharacterObject;
|
||||
class Chr_Equipment : public Component
|
||||
{
|
||||
public:
|
||||
// 默认装备
|
||||
std::map<std::string, RefPtr<Equipment>> _default_equip;
|
||||
// 真实穿戴装备
|
||||
std::map<std::string, RefPtr<Equipment>> _real_equip;
|
||||
|
||||
public:
|
||||
// 初始化
|
||||
void Init(CharacterObject *parent);
|
||||
// 获取部位穿戴的装备
|
||||
RefPtr<Equipment> GetEquip(std::string part);
|
||||
};
|
||||
75
source_game/Asset/Character/Chr_StateMachine.cpp
Normal file
75
source_game/Asset/Character/Chr_StateMachine.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
#include "Chr_StateMachine.h"
|
||||
#include "Actor/Object/CharacterObject.h"
|
||||
#include "Asset/Squirrel/SquirrelManager.h"
|
||||
|
||||
void Chr_StateMachine::Init(CharacterObject *parent)
|
||||
{
|
||||
chr_Parent = parent;
|
||||
addTag(Tag::UPDATE);
|
||||
parent->AddChild(this);
|
||||
}
|
||||
void Chr_StateMachine::ChangeState(int state)
|
||||
{
|
||||
// 对象存在
|
||||
if (chr_Parent)
|
||||
{
|
||||
// 检查是否可以切换状态
|
||||
SQBool CheckFlag = SQFalse;
|
||||
HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM();
|
||||
SQInteger top = sq_gettop(v);
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, _SC("StateMachine_checkCanChangeState"), -1);
|
||||
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushuserpointer(v, chr_Parent);
|
||||
sq_pushinteger(v, chr_Parent->Job);
|
||||
sq_pushinteger(v, state);
|
||||
sq_call(v, 4, SQTrue, SQTrue);
|
||||
sq_getbool(v, -1, &CheckFlag);
|
||||
}
|
||||
sq_settop(v, top);
|
||||
|
||||
if (CheckFlag == SQTrue)
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, _SC("StateMachine_SetState"), -1);
|
||||
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushuserpointer(v, chr_Parent);
|
||||
sq_pushinteger(v, chr_Parent->Job);
|
||||
sq_pushinteger(v, state);
|
||||
sq_call(v, 4, SQFalse, SQTrue);
|
||||
}
|
||||
sq_settop(v, top);
|
||||
this->State = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Chr_StateMachine::Update(float deltaTime)
|
||||
{
|
||||
if (deltaTime == 0.f)
|
||||
return;
|
||||
if (chr_Parent)
|
||||
{
|
||||
if (this->State != -1)
|
||||
{
|
||||
HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM();
|
||||
SQInteger top = sq_gettop(v);
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, _SC("StateMachine_ProcState"), -1);
|
||||
if (SQ_SUCCEEDED(sq_get(v, -2)))
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushuserpointer(v, chr_Parent);
|
||||
sq_pushinteger(v, chr_Parent->Job);
|
||||
sq_pushinteger(v, this->State);
|
||||
sq_pushfloat(v, deltaTime);
|
||||
sq_call(v, 5, SQFalse, SQTrue);
|
||||
}
|
||||
sq_settop(v, top);
|
||||
}
|
||||
}
|
||||
}
|
||||
22
source_game/Asset/Character/Chr_StateMachine.h
Normal file
22
source_game/Asset/Character/Chr_StateMachine.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Component/Component.h"
|
||||
#include "Global/Global_Enum.h"
|
||||
|
||||
class CharacterObject;
|
||||
class Chr_StateMachine : public Component
|
||||
{
|
||||
private:
|
||||
// 父对象
|
||||
CharacterObject *chr_Parent;
|
||||
// 状态
|
||||
int State = -1;
|
||||
// 状态时间
|
||||
int StateTime = 0;
|
||||
|
||||
public:
|
||||
void Init(CharacterObject *parent);
|
||||
void ChangeState(int state);
|
||||
int GetState() { return State; };
|
||||
|
||||
void Update(float deltaTime);
|
||||
};
|
||||
169
source_game/Asset/Common/Equipment.cpp
Normal file
169
source_game/Asset/Common/Equipment.cpp
Normal file
@@ -0,0 +1,169 @@
|
||||
#include "Equipment.h"
|
||||
#include "Global/Global_Game.h"
|
||||
#include "Asset/AssetManager.h"
|
||||
|
||||
int Equipment::GetJobIndex(std::string JobName)
|
||||
{
|
||||
if (JobName == "[swordman]")
|
||||
return 0;
|
||||
else if (JobName == "[fighter]")
|
||||
return 1;
|
||||
else if (JobName == "[gunner]")
|
||||
return 2;
|
||||
else if (JobName == "[mage]")
|
||||
return 3;
|
||||
else if (JobName == "[priest]")
|
||||
return 4;
|
||||
else if (JobName == "[atgunner]")
|
||||
return 5;
|
||||
else if (JobName == "[thief]")
|
||||
return 6;
|
||||
else if (JobName == "[atfighter]")
|
||||
return 7;
|
||||
else if (JobName == "[atmage]")
|
||||
return 8;
|
||||
else if (JobName == "[demonic swordman]")
|
||||
return 9;
|
||||
else if (JobName == "[creatormage]")
|
||||
return 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
ATTACH_TYPE Equipment::GetTradeType(std::string TradeType)
|
||||
{
|
||||
if (TradeType == "[free]")
|
||||
return ATTACH_TYPE::FREE;
|
||||
else if (TradeType == "[sealing]")
|
||||
return ATTACH_TYPE::SEALING;
|
||||
else if (TradeType == "[trade]")
|
||||
return ATTACH_TYPE::TRADE;
|
||||
else if (TradeType == "[account]")
|
||||
return ATTACH_TYPE::ACCOUNT;
|
||||
else if (TradeType == "[trade delete]")
|
||||
return ATTACH_TYPE::TRADE_DELETE;
|
||||
else if (TradeType == "[sealing trade]")
|
||||
return ATTACH_TYPE::SEALING_TRADE;
|
||||
return ATTACH_TYPE::FREE;
|
||||
}
|
||||
|
||||
bool Equipment::IsEmpty()
|
||||
{
|
||||
if (m_EquipmentPath.empty())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Equipment::Init(int Index)
|
||||
{
|
||||
ConstructionByIndex(Index);
|
||||
}
|
||||
|
||||
void Equipment::Init(int Index, int Quality)
|
||||
{
|
||||
this->m_Quality = Quality;
|
||||
ConstructionByIndex(Index);
|
||||
}
|
||||
|
||||
void Equipment::ConstructionByIndex(int Index)
|
||||
{
|
||||
// 检查装备list有没有这件装备
|
||||
if (Global_Game::GetInstance().EquipmentPathMap.count(Index))
|
||||
{
|
||||
m_EquipmentPath = Global_Game::GetInstance().EquipmentPathMap[Index];
|
||||
// 读取装备信息
|
||||
ScriptData Data = AssetManager::GetInstance().GetScriptInfo(m_EquipmentPath);
|
||||
while (!Data.IsEnd())
|
||||
{
|
||||
std::string Segment = Data.Get();
|
||||
if (Segment == "[name]")
|
||||
{
|
||||
this->Name = Data.Get();
|
||||
}
|
||||
else if (Segment == "[name2]")
|
||||
{
|
||||
this->Name2 = Data.Get();
|
||||
}
|
||||
else if (Segment == "[grade]")
|
||||
{
|
||||
this->Grade = std::stoi(Data.Get());
|
||||
}
|
||||
else if (Segment == "[rarity]")
|
||||
{
|
||||
this->Rarity = std::stoi(Data.Get());
|
||||
}
|
||||
else if (Segment == "[usable job]")
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::string Buf = Data.Get();
|
||||
if (Buf == "[/usable job]")
|
||||
break;
|
||||
this->UsableJob[GetJobIndex(Buf)] = true;
|
||||
}
|
||||
}
|
||||
else if (Segment == "[attach type]")
|
||||
{
|
||||
this->TradeType = GetTradeType(Data.Get());
|
||||
}
|
||||
else if (Segment == "[minimum level]")
|
||||
{
|
||||
this->MinimumLevel = std::stoi(Data.Get());
|
||||
}
|
||||
else if (Segment == "[price]")
|
||||
{
|
||||
this->Price = std::stoi(Data.Get());
|
||||
}
|
||||
else if (Segment == "[repair price]")
|
||||
{
|
||||
this->RepairPrice = std::stoi(Data.Get());
|
||||
}
|
||||
else if (Segment == "[animation job]")
|
||||
{
|
||||
std::string JobString = Data.Get();
|
||||
int JobIndex = GetJobIndex(JobString);
|
||||
this->JobAni[JobIndex].clear();
|
||||
if (Data.Get() == "[variation]")
|
||||
{
|
||||
int Parm1 = std::stoi(Data.Get());
|
||||
int Parm2 = std::stoi(Data.Get());
|
||||
|
||||
while (true)
|
||||
{
|
||||
JobAnimation JobAniBuffer;
|
||||
JobAniBuffer.ImgFormat.clear();
|
||||
JobAniBuffer.ImgFormat.push_back(Parm1);
|
||||
JobAniBuffer.ImgFormat.push_back(Parm2);
|
||||
|
||||
std::string buf = Data.Get();
|
||||
if (buf == "[layer variation]")
|
||||
{
|
||||
JobAniBuffer.Layer = std::stoi(Data.Get());
|
||||
JobAniBuffer.AnimationGroup = Data.Get();
|
||||
this->JobAni[JobIndex].push_back(JobAniBuffer);
|
||||
// 调用两次 跳过原来的 [equipment ani script] 这个没有用
|
||||
std::string B1 = Data.Get();
|
||||
std::string B2 = Data.Get();
|
||||
}
|
||||
// 皮肤没有图层也没有动画组名称
|
||||
else if (m_EquipmentPath.find("skin") != std::string::npos)
|
||||
{
|
||||
JobAniBuffer.Layer = 0;
|
||||
JobAniBuffer.AnimationGroup = "null";
|
||||
this->JobAni[JobIndex].push_back(JobAniBuffer);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data.Back();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_LogError(0, "没有编号为: %d 这件装备", Index);
|
||||
}
|
||||
}
|
||||
62
source_game/Asset/Common/Equipment.h
Normal file
62
source_game/Asset/Common/Equipment.h
Normal file
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Component/Component.h"
|
||||
#include "Global/Global_Enum.h"
|
||||
class Equipment : public Component
|
||||
{
|
||||
public:
|
||||
// 职业动画结构体
|
||||
struct JobAnimation
|
||||
{
|
||||
// 图层
|
||||
int Layer;
|
||||
// 动画组名称
|
||||
std::string AnimationGroup;
|
||||
// IMG替换编号
|
||||
std::vector<int> ImgFormat = {0, 0};
|
||||
};
|
||||
|
||||
public:
|
||||
// 装备在PVF中的路径
|
||||
std::string m_EquipmentPath;
|
||||
|
||||
// 装备的品质
|
||||
int m_Quality = -1;
|
||||
|
||||
public:
|
||||
// 编号
|
||||
int Index = -1;
|
||||
// 名字
|
||||
std::string Name;
|
||||
// 别名
|
||||
std::string Name2;
|
||||
// 等级组
|
||||
int Grade = -1;
|
||||
// 稀有度
|
||||
int Rarity = -1;
|
||||
// 可用职业
|
||||
std::map<int, bool> UsableJob;
|
||||
// 交易类型
|
||||
ATTACH_TYPE TradeType;
|
||||
// 最小佩戴等级
|
||||
int MinimumLevel = 1;
|
||||
// 价值
|
||||
int Price = 0;
|
||||
// 维修价格
|
||||
int RepairPrice = 0;
|
||||
|
||||
// 职业动画
|
||||
std::map<int, std::vector<JobAnimation>> JobAni;
|
||||
|
||||
// 装备的属性
|
||||
|
||||
public:
|
||||
// 通过职业名字获取职业编号
|
||||
int GetJobIndex(std::string JobName);
|
||||
// 通过交易类型文字获取枚举值
|
||||
ATTACH_TYPE GetTradeType(std::string TradeType);
|
||||
bool IsEmpty();
|
||||
void Init(int Index);
|
||||
void Init(int Index, int Quality);
|
||||
// 通过装备编号构造装备
|
||||
void ConstructionByIndex(int Index);
|
||||
};
|
||||
126
source_game/Asset/Common/ObjectVars.h
Normal file
126
source_game/Asset/Common/ObjectVars.h
Normal file
@@ -0,0 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
#include "Global/Global_Type.h"
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
|
||||
class ObjectVars
|
||||
{
|
||||
private:
|
||||
// 底层存储:key -> 数组(始终是vector,即使只有一个元素)
|
||||
ObjectVarsMap _data;
|
||||
|
||||
public:
|
||||
ObjectVars() = default;
|
||||
~ObjectVars() = default;
|
||||
|
||||
// 禁止拷贝(按需开启)
|
||||
ObjectVars(const ObjectVars &) = delete;
|
||||
ObjectVars &operator=(const ObjectVars &) = delete;
|
||||
|
||||
// 允许移动
|
||||
ObjectVars(ObjectVars &&) = default;
|
||||
ObjectVars &operator=(ObjectVars &&) = default;
|
||||
|
||||
// 1. 向key对应的数组添加元素(核心接口,无论添加几个元素都用这个)
|
||||
template <typename T>
|
||||
void Add(const std::string &key, const T &value)
|
||||
{
|
||||
static_assert(std::is_constructible_v<ObjectVarsType, T>, "不支持的类型(未在ObjectVarsType中定义)");
|
||||
_data[key].push_back(ObjectVarsType{value}); // 直接追加到数组,保证始终是数组形式
|
||||
}
|
||||
|
||||
// 2. 批量添加元素(一次添加多个值到数组)
|
||||
template <typename T>
|
||||
void AddAll(const std::string &key, const std::vector<T> &values)
|
||||
{
|
||||
static_assert(std::is_constructible_v<ObjectVarsType, T>, "不支持的类型(未在ObjectVarsType中定义)");
|
||||
for (const auto &val : values)
|
||||
{
|
||||
_data[key].push_back(ObjectVarsType{val});
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 替换key对应的整个数组(覆盖原有所有元素)
|
||||
template <typename T>
|
||||
void SetArray(const std::string &key, const std::vector<T> &values)
|
||||
{
|
||||
static_assert(std::is_constructible_v<ObjectVarsType, T>, "不支持的类型(未在ObjectVarsType中定义)");
|
||||
// 先清空原有数据,再添加新数组
|
||||
_data[key].clear();
|
||||
AddAll(key, values);
|
||||
}
|
||||
|
||||
// 4. 获取key对应的整个数组(返回指定类型的vector,类型不匹配的元素会被过滤)
|
||||
template <typename T>
|
||||
std::vector<T> GetArray(const std::string &key) const
|
||||
{
|
||||
std::vector<T> result;
|
||||
auto it = _data.find(key);
|
||||
if (it == _data.end())
|
||||
{
|
||||
return result; // key不存在,返回空数组
|
||||
}
|
||||
// 只提取类型匹配的元素
|
||||
for (const auto &var : it->second)
|
||||
{
|
||||
if (const auto *val = std::get_if<T>(&var))
|
||||
{
|
||||
result.push_back(*val);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 5. 获取数组中指定索引的元素(返回optional,索引越界或类型不匹配则返回nullopt)
|
||||
template <typename T>
|
||||
std::optional<T> GetAt(const std::string &key, size_t index) const
|
||||
{
|
||||
auto it = _data.find(key);
|
||||
if (it == _data.end() || index >= it->second.size())
|
||||
{
|
||||
return std::nullopt; // key不存在或索引越界
|
||||
}
|
||||
// 检查类型是否匹配
|
||||
if (const auto *val = std::get_if<T>(&it->second[index]))
|
||||
{
|
||||
return *val;
|
||||
}
|
||||
return std::nullopt; // 类型不匹配
|
||||
}
|
||||
|
||||
// 6. 检查key是否存在(无论数组是否为空)
|
||||
bool Has(const std::string &key) const
|
||||
{
|
||||
return _data.find(key) != _data.end();
|
||||
}
|
||||
|
||||
// 7. 获取数组长度(key不存在则返回0)
|
||||
size_t GetSize(const std::string &key) const
|
||||
{
|
||||
auto it = _data.find(key);
|
||||
return (it != _data.end()) ? it->second.size() : 0;
|
||||
}
|
||||
|
||||
// 8. 清空key对应的数组(保留key但数组为空)
|
||||
void ClearArray(const std::string &key)
|
||||
{
|
||||
auto it = _data.find(key);
|
||||
if (it != _data.end())
|
||||
{
|
||||
it->second.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// 9. 删除整个key(包括数组)
|
||||
void Remove(const std::string &key)
|
||||
{
|
||||
_data.erase(key);
|
||||
}
|
||||
|
||||
// 10. 清空所有数据
|
||||
void ClearAll()
|
||||
{
|
||||
_data.clear();
|
||||
}
|
||||
};
|
||||
57
source_game/Asset/Squirrel/Sqr_ActiveObject.hpp
Normal file
57
source_game/Asset/Squirrel/Sqr_ActiveObject.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include "squirrel/SquirrelEx.h"
|
||||
#include "Actor/Object/ActiveObject.h"
|
||||
|
||||
static ActiveObject *GetActiveObject(HSQUIRRELVM v)
|
||||
{
|
||||
SQUserPointer ptr;
|
||||
sq_getuserpointer(v, 2, &ptr);
|
||||
ActiveObject *obj = (ActiveObject *)ptr;
|
||||
return obj;
|
||||
}
|
||||
|
||||
static SQInteger SQR_SetSpeed(HSQUIRRELVM v)
|
||||
{
|
||||
ActiveObject *obj = GetActiveObject(v);
|
||||
SQFloat speedX, speedY, speedZ;
|
||||
sq_getfloat(v, 3, &speedX);
|
||||
sq_getfloat(v, 4, &speedY);
|
||||
sq_getfloat(v, 5, &speedZ);
|
||||
obj->SetSpeed(VecSpeed3(speedX, speedY, speedZ));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SQInteger SQR_GetSpeed(HSQUIRRELVM v)
|
||||
{
|
||||
ActiveObject *obj = GetActiveObject(v);
|
||||
VecSpeed3 speed = obj->GetSpeed();
|
||||
sq_newtable(v);
|
||||
sq_pushstring(v, _SC("x"), -1);
|
||||
sq_pushfloat(v, speed.x);
|
||||
sq_newslot(v, 3, SQFalse);
|
||||
sq_pushstring(v, _SC("y"), -1);
|
||||
sq_pushfloat(v, speed.y);
|
||||
sq_newslot(v, 3, SQFalse);
|
||||
sq_pushstring(v, _SC("z"), -1);
|
||||
sq_pushfloat(v, speed.z);
|
||||
sq_newslot(v, 3, SQFalse);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void RegisterActiveObjectNutApi(const SQChar *funcName, SQFUNCTION funcAddr, HSQUIRRELVM v)
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, funcName, -1);
|
||||
sq_newclosure(v, funcAddr, 0);
|
||||
sq_newslot(v, -3, false);
|
||||
sq_poptop(v);
|
||||
}
|
||||
|
||||
static void RegisterActiveObject()
|
||||
{
|
||||
SDL_Log("初始化 动态对象-松鼠脚本!");
|
||||
HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM();
|
||||
// 设置速度
|
||||
RegisterActiveObjectNutApi(_SC("sq_SetSpeed"), SQR_SetSpeed, v);
|
||||
RegisterActiveObjectNutApi(_SC("sq_GetSpeed"), SQR_GetSpeed, v);
|
||||
}
|
||||
197
source_game/Asset/Squirrel/Sqr_BaseObject.hpp
Normal file
197
source_game/Asset/Squirrel/Sqr_BaseObject.hpp
Normal file
@@ -0,0 +1,197 @@
|
||||
#pragma once
|
||||
#include "squirrel/SquirrelEx.h"
|
||||
#include "Actor/Object/BaseObject.h"
|
||||
|
||||
static BaseObject *GetBaseObject(HSQUIRRELVM v)
|
||||
{
|
||||
SQUserPointer ptr;
|
||||
sq_getuserpointer(v, 2, &ptr);
|
||||
BaseObject *obj = (BaseObject *)ptr;
|
||||
return obj;
|
||||
}
|
||||
|
||||
static SQInteger SQR_GetPosition(HSQUIRRELVM v)
|
||||
{
|
||||
SQUserPointer ptr;
|
||||
sq_getuserpointer(v, 2, &ptr);
|
||||
BaseObject *obj = (BaseObject *)ptr;
|
||||
VecFPos3 Pos = obj->GetPosition();
|
||||
|
||||
sq_newtable(v);
|
||||
sq_pushstring(v, _SC("x"), -1);
|
||||
sq_pushfloat(v, Pos.x);
|
||||
sq_newslot(v, 3, SQFalse);
|
||||
sq_pushstring(v, _SC("y"), -1);
|
||||
sq_pushfloat(v, Pos.y);
|
||||
sq_newslot(v, 3, SQFalse);
|
||||
sq_pushstring(v, _SC("z"), -1);
|
||||
sq_pushfloat(v, Pos.z);
|
||||
sq_newslot(v, 3, SQFalse);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger SQR_SetPosition(HSQUIRRELVM v)
|
||||
{
|
||||
SQUserPointer ptr;
|
||||
sq_getuserpointer(v, 2, &ptr);
|
||||
BaseObject *obj = (BaseObject *)ptr;
|
||||
SQFloat PosX, PosY, PosZ;
|
||||
sq_getfloat(v, 3, &PosX);
|
||||
sq_getfloat(v, 4, &PosY);
|
||||
sq_getfloat(v, 5, &PosZ);
|
||||
obj->SetPosition(VecFPos3(PosX, PosY, PosZ));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SQInteger SQR_GetDirection(HSQUIRRELVM v)
|
||||
{
|
||||
BaseObject *obj = GetBaseObject(v);
|
||||
sq_pushinteger(v, obj->GetDirection());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger SQR_SetDirection(HSQUIRRELVM v)
|
||||
{
|
||||
BaseObject *obj = GetBaseObject(v);
|
||||
SQInteger Dir;
|
||||
sq_getinteger(v, 3, &Dir);
|
||||
obj->SetDirection(Dir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SQInteger SQR_GetVars(HSQUIRRELVM v)
|
||||
{
|
||||
SQUserPointer ptr;
|
||||
sq_getuserpointer(v, 2, &ptr);
|
||||
BaseObject *obj = (BaseObject *)ptr;
|
||||
const SQChar *KeyBuf;
|
||||
const SQChar *TypeBuf;
|
||||
sq_getstring(v, 3, &KeyBuf);
|
||||
sq_getstring(v, 4, &TypeBuf);
|
||||
std::string Key(KeyBuf);
|
||||
std::string Type(TypeBuf);
|
||||
|
||||
if (Type == "int")
|
||||
{
|
||||
std::vector<int> ArrBuf = obj->GetObjectVars().GetArray<int>(Key);
|
||||
sq_newarray(v, 0);
|
||||
for (int i = 0; i < ArrBuf.size(); i++)
|
||||
{
|
||||
sq_pushinteger(v, ArrBuf[i]);
|
||||
sq_arrayappend(v, -2);
|
||||
}
|
||||
}
|
||||
else if (Type == "float")
|
||||
{
|
||||
std::vector<float> ArrBuf = obj->GetObjectVars().GetArray<float>(Key);
|
||||
sq_newarray(v, 0);
|
||||
for (int i = 0; i < ArrBuf.size(); i++)
|
||||
{
|
||||
sq_pushfloat(v, ArrBuf[i]);
|
||||
sq_arrayappend(v, -2);
|
||||
}
|
||||
}
|
||||
else if (Type == "string")
|
||||
{
|
||||
std::vector<std::string> ArrBuf = obj->GetObjectVars().GetArray<std::string>(Key);
|
||||
sq_newarray(v, 0);
|
||||
for (int i = 0; i < ArrBuf.size(); i++)
|
||||
{
|
||||
sq_pushstring(v, ArrBuf[i].c_str(), -1);
|
||||
sq_arrayappend(v, -2);
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger SQR_SetVars(HSQUIRRELVM v)
|
||||
{
|
||||
SQUserPointer ptr;
|
||||
sq_getuserpointer(v, 2, &ptr);
|
||||
BaseObject *obj = (BaseObject *)ptr;
|
||||
const SQChar *KeyBuf;
|
||||
const SQChar *TypeBuf;
|
||||
sq_getstring(v, 3, &KeyBuf);
|
||||
sq_getstring(v, 4, &TypeBuf);
|
||||
std::string Key(KeyBuf);
|
||||
std::string Type(TypeBuf);
|
||||
|
||||
if (Type == "int")
|
||||
{
|
||||
std::vector<int> ArrBuf;
|
||||
sq_pushnull(v); // null iterator
|
||||
while (SQ_SUCCEEDED(sq_next(v, 5)))
|
||||
{
|
||||
SQInteger value;
|
||||
sq_getinteger(v, -1, &value);
|
||||
const SQChar *key;
|
||||
sq_getstring(v, -2, &key);
|
||||
|
||||
ArrBuf.push_back(value);
|
||||
sq_pop(v, 2);
|
||||
}
|
||||
sq_pop(v, 1);
|
||||
obj->GetObjectVars().AddAll(Key, ArrBuf);
|
||||
}
|
||||
else if (Type == "float")
|
||||
{
|
||||
std::vector<float> ArrBuf;
|
||||
sq_pushnull(v); // null iterator
|
||||
while (SQ_SUCCEEDED(sq_next(v, 5)))
|
||||
{
|
||||
SQFloat value;
|
||||
sq_getfloat(v, -1, &value);
|
||||
const SQChar *key;
|
||||
sq_getstring(v, -2, &key);
|
||||
|
||||
ArrBuf.push_back(value);
|
||||
sq_pop(v, 2);
|
||||
}
|
||||
sq_pop(v, 1);
|
||||
obj->GetObjectVars().SetArray(Key, ArrBuf);
|
||||
}
|
||||
else if (Type == "string")
|
||||
{
|
||||
std::vector<std::string> ArrBuf;
|
||||
sq_pushnull(v); // null iterator
|
||||
while (SQ_SUCCEEDED(sq_next(v, 5)))
|
||||
{
|
||||
const SQChar *value;
|
||||
sq_getstring(v, -1, &value);
|
||||
const SQChar *key;
|
||||
sq_getstring(v, -2, &key);
|
||||
|
||||
ArrBuf.push_back(value);
|
||||
sq_pop(v, 2);
|
||||
}
|
||||
sq_pop(v, 1);
|
||||
obj->GetObjectVars().AddAll(Key, ArrBuf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void RegisterBaseObjectNutApi(const SQChar *funcName, SQFUNCTION funcAddr, HSQUIRRELVM v)
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, funcName, -1);
|
||||
sq_newclosure(v, funcAddr, 0);
|
||||
sq_newslot(v, -3, false);
|
||||
sq_poptop(v);
|
||||
}
|
||||
|
||||
static void RegisterBaseObject()
|
||||
{
|
||||
SDL_Log("初始化 基础对象-松鼠脚本!");
|
||||
HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM();
|
||||
// 坐标
|
||||
RegisterBaseObjectNutApi(_SC("sq_GetPosition"), SQR_GetPosition, v);
|
||||
RegisterBaseObjectNutApi(_SC("sq_SetPosition"), SQR_SetPosition, v);
|
||||
// 朝向
|
||||
RegisterBaseObjectNutApi(_SC("sq_GetDirection"), SQR_GetDirection, v);
|
||||
RegisterBaseObjectNutApi(_SC("sq_SetDirection"), SQR_SetDirection, v);
|
||||
// 数据储存器
|
||||
RegisterBaseObjectNutApi(_SC("sq_GetVars"), SQR_GetVars, v);
|
||||
RegisterBaseObjectNutApi(_SC("sq_SetVars"), SQR_SetVars, v);
|
||||
}
|
||||
57
source_game/Asset/Squirrel/Sqr_CharacterObject.hpp
Normal file
57
source_game/Asset/Squirrel/Sqr_CharacterObject.hpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#pragma once
|
||||
#include "squirrel/SquirrelEx.h"
|
||||
#include "Actor/Object/CharacterObject.h"
|
||||
|
||||
static CharacterObject *GetCharacterObject(HSQUIRRELVM v)
|
||||
{
|
||||
SQUserPointer ptr;
|
||||
sq_getuserpointer(v, 2, &ptr);
|
||||
CharacterObject *obj = (CharacterObject *)ptr;
|
||||
return obj;
|
||||
}
|
||||
|
||||
static SQInteger SQR_GetState(HSQUIRRELVM v)
|
||||
{
|
||||
CharacterObject *obj = GetCharacterObject(v);
|
||||
sq_pushinteger(v, obj->_StateMachine->GetState());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger SQR_SetState(HSQUIRRELVM v)
|
||||
{
|
||||
CharacterObject *obj = GetCharacterObject(v);
|
||||
SQInteger state;
|
||||
sq_getinteger(v, 3, &state);
|
||||
obj->_StateMachine->ChangeState(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SQInteger SQR_SetAction(HSQUIRRELVM v)
|
||||
{
|
||||
CharacterObject *obj = GetCharacterObject(v);
|
||||
const SQChar *ActionNameBuf;
|
||||
sq_getstring(v, 3, &ActionNameBuf);
|
||||
obj->_AnimationManager->SetAction(ActionNameBuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void RegisterCharacterObjectNutApi(const SQChar *funcName, SQFUNCTION funcAddr, HSQUIRRELVM v)
|
||||
{
|
||||
sq_pushroottable(v);
|
||||
sq_pushstring(v, funcName, -1);
|
||||
sq_newclosure(v, funcAddr, 0);
|
||||
sq_newslot(v, -3, false);
|
||||
sq_poptop(v);
|
||||
}
|
||||
|
||||
static void RegisterCharacterObject()
|
||||
{
|
||||
SDL_Log("初始化 角色对象-松鼠脚本!");
|
||||
HSQUIRRELVM v = SquirrelEx::GetInstance().GetSquirrelVM();
|
||||
// 获取状态
|
||||
RegisterCharacterObjectNutApi(_SC("sq_GetState"), SQR_GetState, v);
|
||||
// 设置状态
|
||||
RegisterCharacterObjectNutApi(_SC("sq_SetState"), SQR_SetState, v);
|
||||
// 设置动画
|
||||
RegisterCharacterObjectNutApi(_SC("sq_SetAction"), SQR_SetAction, v);
|
||||
}
|
||||
12
source_game/Asset/Squirrel/SquirrelManager.cpp
Normal file
12
source_game/Asset/Squirrel/SquirrelManager.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "SquirrelManager.h"
|
||||
|
||||
void SquirrelManager::Init()
|
||||
{
|
||||
SDL_Log("开始初始化sqr管理器!");
|
||||
// 基础对象
|
||||
RegisterBaseObject();
|
||||
// 动态对象
|
||||
RegisterActiveObject();
|
||||
// 角色对象
|
||||
RegisterCharacterObject();
|
||||
}
|
||||
31
source_game/Asset/Squirrel/SquirrelManager.h
Normal file
31
source_game/Asset/Squirrel/SquirrelManager.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include "Asset/Squirrel/Sqr_BaseObject.hpp"
|
||||
#include "Asset/Squirrel/Sqr_ActiveObject.hpp"
|
||||
#include "Asset/Squirrel/Sqr_CharacterObject.hpp"
|
||||
class SquirrelManager
|
||||
{
|
||||
public:
|
||||
// 删除拷贝构造和赋值运算符,确保无法复制
|
||||
SquirrelManager(const SquirrelManager &) = delete;
|
||||
SquirrelManager &operator=(const SquirrelManager &) = delete;
|
||||
|
||||
// 移动构造和赋值也删除,避免意外转移
|
||||
SquirrelManager(SquirrelManager &&) = delete;
|
||||
SquirrelManager &operator=(SquirrelManager &&) = delete;
|
||||
|
||||
// 全局访问点
|
||||
static SquirrelManager &GetInstance()
|
||||
{
|
||||
static SquirrelManager instance; // 局部静态变量,保证只初始化一次
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
// 构造函数和析构函数设为私有,防止外部创建和销毁
|
||||
SquirrelManager() = default;
|
||||
~SquirrelManager() = default;
|
||||
|
||||
public:
|
||||
// 初始化
|
||||
void Init();
|
||||
};
|
||||
Reference in New Issue
Block a user