建档
This commit is contained in:
369
source_game/Actor/Map/GameMap.cpp
Normal file
369
source_game/Actor/Map/GameMap.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
#include "GameMap.h"
|
||||
#include "Asset/AssetManager.h"
|
||||
#include "EngineFrame/Scene/Scene.h"
|
||||
#include "EngineFrame/Component/Animation.h"
|
||||
#include "Actor/Map/GameMapCamera.h"
|
||||
#include "Actor/Object/CharacterObject.h"
|
||||
|
||||
GameMap::GameMap()
|
||||
{
|
||||
_LayerMap["contact"] = new GameMapLayer();
|
||||
_LayerMap["distantback"] = new GameMapLayer();
|
||||
_LayerMap["middleback"] = new GameMapLayer();
|
||||
_LayerMap["bottom"] = new GameMapLayer();
|
||||
_LayerMap["closeback"] = new GameMapLayer();
|
||||
_LayerMap["normal"] = new GameMapLayer();
|
||||
_LayerMap["close"] = new GameMapLayer();
|
||||
_LayerMap["cover"] = new GameMapLayer();
|
||||
_LayerMap["max"] = new GameMapLayer();
|
||||
|
||||
// 设置图层渲染顺序
|
||||
_LayerMap["contact"]->SetRenderZOrder(10000);
|
||||
_LayerMap["distantback"]->SetRenderZOrder(50000);
|
||||
_LayerMap["middleback"]->SetRenderZOrder(100000);
|
||||
_LayerMap["bottom"]->SetRenderZOrder(150000);
|
||||
_LayerMap["closeback"]->SetRenderZOrder(200000);
|
||||
_LayerMap["normal"]->SetRenderZOrder(250000);
|
||||
_LayerMap["close"]->SetRenderZOrder(300000);
|
||||
_LayerMap["cover"]->SetRenderZOrder(350000);
|
||||
_LayerMap["max"]->SetRenderZOrder(400000);
|
||||
}
|
||||
|
||||
GameMap::~GameMap()
|
||||
{
|
||||
}
|
||||
|
||||
void GameMap::InitConfiguration(std::string mapName)
|
||||
{
|
||||
ScriptData Data = AssetManager::GetInstance().GetScriptInfo(mapName);
|
||||
_MapInfo["wide_mode_camer_vertical_correction"] = 0;
|
||||
_MapInfo["background_pos"] = 0;
|
||||
_MapPath = mapName;
|
||||
_MapDir = mapName.substr(0, mapName.find_last_of("/") + 1);
|
||||
while (!Data.IsEnd())
|
||||
{
|
||||
std::string Segment = Data.Get();
|
||||
if (Segment == "[background pos]")
|
||||
{
|
||||
_MapInfo["background_pos"] = std::stoi(Data.Get());
|
||||
}
|
||||
else if (Segment == "[map name]")
|
||||
{
|
||||
_MapInfo["name"] = Data.Get();
|
||||
}
|
||||
else if (Segment == "[wide mode camera vertical correction]")
|
||||
{
|
||||
_MapInfo["wide_mode_camer_vertical_correction"] = std::stoi(Data.Get());
|
||||
}
|
||||
else if (Segment == "[tile]")
|
||||
{
|
||||
std::vector<std::string> tileArry;
|
||||
while (true)
|
||||
{
|
||||
auto tiledata = Data.Get();
|
||||
if (tiledata == "[/tile]")
|
||||
break;
|
||||
tileArry.push_back(_MapDir + Tool_toLowerCase(tiledata));
|
||||
}
|
||||
_MapInfo["tile"] = tileArry;
|
||||
}
|
||||
else if (Segment == "[extended tile]")
|
||||
{
|
||||
std::vector<std::string> tileArry;
|
||||
while (true)
|
||||
{
|
||||
auto tiledata = Data.Get();
|
||||
if (tiledata == "[/extended tile]")
|
||||
break;
|
||||
tileArry.push_back(_MapDir + Tool_toLowerCase(tiledata));
|
||||
}
|
||||
_MapInfo["extended_tile"] = tileArry;
|
||||
}
|
||||
else if (Segment == "[far sight scroll]" || Segment == "[middle sight scroll]" || Segment == "[near sight scroll]")
|
||||
{
|
||||
_MapInfo[Segment.substr(1, Segment.length() - 2)] = std::stoi(Data.Get());
|
||||
}
|
||||
else if (Segment == "[background animation]")
|
||||
{
|
||||
std::vector<BackGroundAni> Arr;
|
||||
while (true)
|
||||
{
|
||||
std::string aniData = Data.Get();
|
||||
if (aniData == "[/background animation]")
|
||||
break;
|
||||
if (aniData == "[ani info]")
|
||||
{
|
||||
BackGroundAni ani;
|
||||
Data.Get();
|
||||
ani.filename = _MapDir + Tool_toLowerCase(Data.Get());
|
||||
Data.Get();
|
||||
ani.layer = Data.Get();
|
||||
Data.Get();
|
||||
ani.order = Data.Get();
|
||||
Arr.push_back(ani);
|
||||
}
|
||||
}
|
||||
_MapInfo["background_animation"] = Arr;
|
||||
}
|
||||
else if (Segment == "[sound]")
|
||||
{
|
||||
std::vector<std::string> soundArry;
|
||||
while (true)
|
||||
{
|
||||
std::string sounddata = Data.Get();
|
||||
if (sounddata == "[/sound]")
|
||||
break;
|
||||
soundArry.push_back(sounddata);
|
||||
}
|
||||
_MapInfo["sound"] = soundArry;
|
||||
}
|
||||
else if (Segment == "[animation]")
|
||||
{
|
||||
std::vector<MapAni> aniArry;
|
||||
while (true)
|
||||
{
|
||||
std::string aniData = Data.Get();
|
||||
if (aniData == "[/animation]")
|
||||
break;
|
||||
MapAni info;
|
||||
info.filename = Tool_RegRealPath(_MapDir + Tool_toLowerCase(aniData));
|
||||
info.layer = Data.Get();
|
||||
info.XPos = std::stoi(Data.Get());
|
||||
info.YPos = std::stoi(Data.Get());
|
||||
info.ZPos = std::stoi(Data.Get());
|
||||
aniArry.push_back(info);
|
||||
}
|
||||
_MapInfo["animation"] = aniArry;
|
||||
}
|
||||
else if (Segment == "[NPC]")
|
||||
{
|
||||
std::vector<MapNpc> npcArry;
|
||||
while (true)
|
||||
{
|
||||
std::string npcData = Data.Get();
|
||||
if (npcData == "[/NPC]")
|
||||
break;
|
||||
MapNpc info;
|
||||
info.id = std::stoi(npcData);
|
||||
info.direction = Data.Get();
|
||||
info.XPos = std::stoi(Data.Get());
|
||||
info.YPos = std::stoi(Data.Get());
|
||||
info.ZPos = std::stoi(Data.Get());
|
||||
npcArry.push_back(info);
|
||||
}
|
||||
_MapInfo["NPC"] = npcArry;
|
||||
}
|
||||
else if (Segment == "[town movable area]")
|
||||
{
|
||||
std::vector<int> town_movable_area;
|
||||
std::vector<MapMoveArea> town_movable_area_info;
|
||||
while (true)
|
||||
{
|
||||
std::string areadata = Data.Get();
|
||||
if (areadata == "[/town movable area]")
|
||||
break;
|
||||
town_movable_area.push_back(std::stoi(areadata));
|
||||
town_movable_area.push_back(std::stoi(areadata));
|
||||
town_movable_area.push_back(std::stoi(areadata));
|
||||
town_movable_area.push_back(std::stoi(areadata));
|
||||
MapMoveArea T;
|
||||
T.town = std::stoi(areadata);
|
||||
T.area = std::stoi(areadata);
|
||||
town_movable_area_info.push_back(T);
|
||||
}
|
||||
_MapInfo["town_movable_area"] = town_movable_area;
|
||||
_MapInfo["town_movable_area_info"] = town_movable_area_info;
|
||||
}
|
||||
else if (Segment == "[virtual movable area]")
|
||||
{
|
||||
std::vector<int> virtual_movable_area;
|
||||
while (true)
|
||||
{
|
||||
std::string areadata = Data.Get();
|
||||
if (areadata == "[/virtual movable area]")
|
||||
break;
|
||||
virtual_movable_area.push_back(std::stoi(areadata));
|
||||
virtual_movable_area.push_back(std::stoi(Data.Get()));
|
||||
virtual_movable_area.push_back(std::stoi(Data.Get()));
|
||||
virtual_movable_area.push_back(std::stoi(Data.Get()));
|
||||
}
|
||||
_MapInfo["virtual_movable_area"] = virtual_movable_area;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameMap::InitTile()
|
||||
{
|
||||
if (!_MapInfo.count("tile"))
|
||||
return;
|
||||
int NormalTileCount = 0;
|
||||
std::vector<std::string> tileArr = std::get<std::vector<std::string>>(_MapInfo["tile"]);
|
||||
if (tileArr.size() > 0)
|
||||
{
|
||||
NormalTileCount = tileArr.size();
|
||||
_MapLength = NormalTileCount * 224;
|
||||
for (int i = 0; i < NormalTileCount; i++)
|
||||
{
|
||||
std::string path = tileArr[i];
|
||||
RefPtr<Tile> tile = new Tile(path);
|
||||
tile->SetPos(VecFPos{i * 224, -200 - std::get<int>(_MapInfo["background_pos"])});
|
||||
_LayerMap["bottom"]->AddComponent(tile);
|
||||
}
|
||||
_MapHeight = 560;
|
||||
}
|
||||
if (_MapInfo.count("extended_tile"))
|
||||
{
|
||||
std::vector<std::string> extileArr = std::get<std::vector<std::string>>(_MapInfo["extended_tile"]);
|
||||
if (extileArr.size() > 0)
|
||||
{
|
||||
int ExTileCount = extileArr.size();
|
||||
int Buffer = (ExTileCount / NormalTileCount);
|
||||
_MapHeight += (Buffer < 1 ? 1 : Buffer) * 40;
|
||||
for (int i = 0; i < ExTileCount; i++)
|
||||
{
|
||||
std::string path = extileArr[i];
|
||||
RefPtr<Tile> tile = new Tile(path);
|
||||
int xbuf = i % NormalTileCount * 224;
|
||||
int ybuf = 560 - 200 - std::get<int>(_MapInfo["background_pos"]) + 40 * (i / NormalTileCount);
|
||||
tile->SetPos(VecFPos{xbuf, ybuf});
|
||||
_LayerMap["bottom"]->AddComponent(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameMap::InitBackgroundAnimation()
|
||||
{
|
||||
float Rate = _MapInfo.count("far_sight_scroll") ? std::get<int>(_MapInfo["far_sight_scroll"]) / 100.0f : 1.0f;
|
||||
(void)Rate;
|
||||
// TODO 摄像机
|
||||
if (_MapInfo.count("background_animation"))
|
||||
{
|
||||
std::vector<BackGroundAni> aniArr = std::get<std::vector<BackGroundAni>>(_MapInfo["background_animation"]);
|
||||
for (auto &ani : aniArr)
|
||||
{
|
||||
std::string path = ani.filename;
|
||||
std::vector<RefPtr<Animation>> AniList;
|
||||
RefPtr<Animation> AniObj = new Animation(path);
|
||||
int width = AniObj->GetSize().width;
|
||||
AniList.push_back(AniObj);
|
||||
for (int i = 0; i < (_MapLength * Rate) / width; i++)
|
||||
{
|
||||
RefPtr<Animation> AniObj = new Animation(path);
|
||||
AniList.push_back(AniObj);
|
||||
}
|
||||
for (int i = 0; i < (int)AniList.size(); i++)
|
||||
{
|
||||
AniList[i]->SetPos(VecFPos{i * width, -120});
|
||||
AniList[i]->SetRenderZOrder(-1000000);
|
||||
std::string layer = ani.layer;
|
||||
layer = layer.substr(1, layer.length() - 2);
|
||||
if (_LayerMap.count(layer))
|
||||
{
|
||||
_LayerMap[layer]->AddChild(AniList[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameMap::InitMapAnimation()
|
||||
{
|
||||
if (_MapInfo.count("animation"))
|
||||
{
|
||||
std::vector<MapAni> aniArr = std::get<std::vector<MapAni>>(_MapInfo["animation"]);
|
||||
for (auto &ani : aniArr)
|
||||
{
|
||||
std::string path = ani.filename;
|
||||
RefPtr<Animation> AniObj = new Animation(path);
|
||||
AniObj->SetPos(VecFPos{ani.XPos, ani.YPos - ani.ZPos});
|
||||
AniObj->SetRenderZOrder(ani.YPos);
|
||||
std::string layer = ani.layer;
|
||||
layer = layer.substr(1, layer.length() - 2);
|
||||
if (_LayerMap.count(layer))
|
||||
{
|
||||
_LayerMap[layer]->AddChild(AniObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameMap::LoadMap(std::string mapName)
|
||||
{
|
||||
// 读取脚本配置
|
||||
InitConfiguration(mapName);
|
||||
// 初始化地板
|
||||
InitTile();
|
||||
// 初始化背景动画
|
||||
InitBackgroundAnimation();
|
||||
// 初始化场景Ani
|
||||
InitMapAnimation();
|
||||
|
||||
RefPtr<CharacterObject> obj = new CharacterObject();
|
||||
obj->SetPosition({620, 200, 0});
|
||||
obj->Construction(0);
|
||||
_LayerMap["normal"]->AddObject(obj);
|
||||
}
|
||||
|
||||
void GameMap::Enter(Scene *scene)
|
||||
{
|
||||
scene->AddChild(_LayerMap["contact"]);
|
||||
scene->AddChild(_LayerMap["distantback"]);
|
||||
scene->AddChild(_LayerMap["middleback"]);
|
||||
scene->AddChild(_LayerMap["bottom"]);
|
||||
scene->AddChild(_LayerMap["closeback"]);
|
||||
scene->AddChild(_LayerMap["normal"]);
|
||||
scene->AddChild(_LayerMap["close"]);
|
||||
scene->AddChild(_LayerMap["cover"]);
|
||||
scene->AddChild(_LayerMap["max"]);
|
||||
|
||||
// TODO
|
||||
int HSU = 230;
|
||||
_LayerMap["contact"]->SetPos(VecFPos{0, HSU});
|
||||
_LayerMap["distantback"]->SetPos(VecFPos{0, HSU});
|
||||
_LayerMap["middleback"]->SetPos(VecFPos{0, HSU});
|
||||
_LayerMap["bottom"]->SetPos(VecFPos{0, HSU});
|
||||
_LayerMap["closeback"]->SetPos(VecFPos{0, HSU});
|
||||
_LayerMap["normal"]->SetPos(VecFPos{0, HSU});
|
||||
_LayerMap["close"]->SetPos(VecFPos{0, HSU});
|
||||
_LayerMap["cover"]->SetPos(VecFPos{0, HSU});
|
||||
_LayerMap["max"]->SetPos(VecFPos{0, HSU});
|
||||
}
|
||||
|
||||
void GameMap::HandleEvents(SDL_Event *e)
|
||||
{
|
||||
}
|
||||
|
||||
void GameMap::Update(float deltaTime)
|
||||
{
|
||||
// this->_Camera->Update(deltaTime);
|
||||
|
||||
// if (this->_Camera)
|
||||
// {
|
||||
// int CamearXpos = this->_Camera->X;
|
||||
// int CamearYpos = this->_Camera->Y;
|
||||
// int CamearZpos = this->_Camera->Z;
|
||||
|
||||
// SDL_Log("Camera Pos: %d, %d", CamearXpos, CamearYpos);
|
||||
// // 遍历
|
||||
// for (auto &pair : _LayerMap)
|
||||
// {
|
||||
// // pair.first 是 key(std::string)
|
||||
// std::string key = pair.first;
|
||||
// // pair.second 是 value(RefPtr<GameMapLayer>)
|
||||
// RefPtr<GameMapLayer> &value = pair.second;
|
||||
|
||||
// if (key == "distantback")
|
||||
// {
|
||||
// value->SetPos(VecPos{(-CamearXpos + 553), (-CamearYpos + CamearZpos + 300 + 120 + 80)});
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// value->SetPos(VecPos{(-CamearXpos + 553), (-CamearYpos + CamearZpos + 300 + 120 + 80)});
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
87
source_game/Actor/Map/GameMap.h
Normal file
87
source_game/Actor/Map/GameMap.h
Normal file
@@ -0,0 +1,87 @@
|
||||
#pragma once
|
||||
#include "Actor/Map/GameMapLayer.h"
|
||||
#include "Asset/Asset_Script.h"
|
||||
#include "Actor/Map/Tile.h"
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
|
||||
class BaseObject;
|
||||
class GameMapCamera;
|
||||
class GameMap
|
||||
{
|
||||
struct BackGroundAni
|
||||
{
|
||||
std::string filename;
|
||||
std::string layer;
|
||||
std::string order;
|
||||
};
|
||||
|
||||
struct MapAni
|
||||
{
|
||||
std::string filename;
|
||||
std::string layer;
|
||||
int XPos;
|
||||
int YPos;
|
||||
int ZPos;
|
||||
};
|
||||
|
||||
struct MapNpc
|
||||
{
|
||||
int id;
|
||||
std::string direction;
|
||||
int XPos;
|
||||
int YPos;
|
||||
int ZPos;
|
||||
};
|
||||
|
||||
struct MapMoveArea
|
||||
{
|
||||
int town;
|
||||
int area;
|
||||
};
|
||||
|
||||
using MapInfoBody = std::variant<
|
||||
int,
|
||||
std::string,
|
||||
std::vector<BackGroundAni>,
|
||||
std::vector<MapAni>,
|
||||
std::vector<MapNpc>,
|
||||
std::vector<MapMoveArea>,
|
||||
std::vector<int>,
|
||||
std::vector<std::string>>;
|
||||
|
||||
public:
|
||||
// 地图信息
|
||||
std::unordered_map<std::string, MapInfoBody> _MapInfo;
|
||||
// 地图路径
|
||||
std::string _MapPath;
|
||||
// 地图文件夹
|
||||
std::string _MapDir;
|
||||
// 地图宽度
|
||||
int _MapLength = 0;
|
||||
// 地图高度
|
||||
int _MapHeight = 0;
|
||||
|
||||
public:
|
||||
// 图层Map 图层类型 显示对象
|
||||
std::unordered_map<std::string, RefPtr<GameMapLayer>> _LayerMap;
|
||||
// 摄像机对象
|
||||
GameMapCamera *_Camera;
|
||||
|
||||
|
||||
public:
|
||||
GameMap(/* args */);
|
||||
~GameMap();
|
||||
|
||||
void LoadMap(std::string mapName);
|
||||
void InitConfiguration(std::string mapName);
|
||||
void InitTile();
|
||||
void InitBackgroundAnimation();
|
||||
void InitMapAnimation();
|
||||
void Enter(Scene *scene);
|
||||
void HandleEvents(SDL_Event *e);
|
||||
void Update(float deltaTime);
|
||||
|
||||
public:
|
||||
};
|
||||
54
source_game/Actor/Map/GameMapCamera.cpp
Normal file
54
source_game/Actor/Map/GameMapCamera.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "GameMapCamera.h"
|
||||
#include "Actor/Map/GameMap.h"
|
||||
#include "Actor/Object/BaseObject.h"
|
||||
#include <algorithm>
|
||||
|
||||
GameMapCamera::GameMapCamera()
|
||||
{
|
||||
}
|
||||
|
||||
GameMapCamera::~GameMapCamera()
|
||||
{
|
||||
}
|
||||
|
||||
void GameMapCamera::SetParentMap(GameMap *map)
|
||||
{
|
||||
this->_ParentMap = map;
|
||||
_ParentMap->_Camera = this;
|
||||
}
|
||||
|
||||
void GameMapCamera::SetFromActor(BaseObject *actor)
|
||||
{
|
||||
this->_FromActor = actor;
|
||||
}
|
||||
|
||||
void GameMapCamera::Update(float deltaTime)
|
||||
{
|
||||
SyncPosByFromParent(deltaTime);
|
||||
}
|
||||
|
||||
void GameMapCamera::SetPos(int x, int y, int z)
|
||||
{
|
||||
this->X = x;
|
||||
this->Y = y;
|
||||
this->Z = z;
|
||||
}
|
||||
|
||||
void GameMapCamera::AddPos(int x, int y, int z)
|
||||
{
|
||||
this->X += x;
|
||||
this->Y += y;
|
||||
this->Z += z;
|
||||
}
|
||||
|
||||
void GameMapCamera::SyncPosByFromParent(float deltaTime)
|
||||
{
|
||||
if (this->_FromActor != nullptr)
|
||||
{
|
||||
// int R_X, R_Y, R_Z;
|
||||
// R_X = std::min(std::max(this->_FromActor->X, 533), MovableAreaX - 533);
|
||||
// R_Y = std::min(std::max(this->_FromActor->Y, 300), MovableAreaY - 300);
|
||||
// R_Z = 0;
|
||||
// SetPos(R_X, R_Y, R_Z);
|
||||
}
|
||||
}
|
||||
45
source_game/Actor/Map/GameMapCamera.h
Normal file
45
source_game/Actor/Map/GameMapCamera.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Actor/Actor.h"
|
||||
class GameMap;
|
||||
class BaseObject;
|
||||
class GameMapCamera : public Actor
|
||||
{
|
||||
private:
|
||||
GameMap *_ParentMap = nullptr;
|
||||
// 跟随对象
|
||||
BaseObject *_FromActor = nullptr;
|
||||
|
||||
public:
|
||||
// 摄像机坐标
|
||||
int X = 0;
|
||||
int Y = 0;
|
||||
int Z = 0;
|
||||
// 镜头可行坐标
|
||||
int MovableAreaX = 0;
|
||||
int MovableAreaY = 0;
|
||||
// 背景偏移量
|
||||
int BackgroundOffset = 0;
|
||||
// 背景层移动速率
|
||||
int BackgroundMoveSpeed = 1.0;
|
||||
// 人物中线长度
|
||||
int CharacterLineLength = 0;
|
||||
// 摄像机朝向
|
||||
int Direction = 1;
|
||||
// 摄像机朝向时间
|
||||
float DirectionTime = 0.f;
|
||||
// 缩放比率
|
||||
float CameraRate = 1.0;
|
||||
|
||||
public:
|
||||
GameMapCamera();
|
||||
~GameMapCamera();
|
||||
|
||||
void SetParentMap(GameMap *map);
|
||||
void SetFromActor(BaseObject *actor);
|
||||
void Update(float deltaTime);
|
||||
|
||||
void SetPos(int x, int y, int z);
|
||||
void AddPos(int x, int y, int z);
|
||||
|
||||
void SyncPosByFromParent(float deltaTime);
|
||||
};
|
||||
14
source_game/Actor/Map/GameMapLayer.cpp
Normal file
14
source_game/Actor/Map/GameMapLayer.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "GameMapLayer.h"
|
||||
|
||||
GameMapLayer::GameMapLayer()
|
||||
{
|
||||
}
|
||||
|
||||
GameMapLayer::~GameMapLayer()
|
||||
{
|
||||
}
|
||||
|
||||
void GameMapLayer::AddObject(RefPtr<Actor> obj)
|
||||
{
|
||||
this->AddChild(obj);
|
||||
}
|
||||
19
source_game/Actor/Map/GameMapLayer.h
Normal file
19
source_game/Actor/Map/GameMapLayer.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "EngineFrame/Actor/Actor.h"
|
||||
#include "EngineFrame/Component/Sprite.h"
|
||||
|
||||
class BaseObject;
|
||||
class GameMapLayer : public Actor
|
||||
{
|
||||
private:
|
||||
// 地图对象
|
||||
std::vector<RefPtr<Component>> ObjectManager;
|
||||
|
||||
public:
|
||||
GameMapLayer(/* args */);
|
||||
~GameMapLayer();
|
||||
|
||||
public:
|
||||
void AddObject(RefPtr<Actor> obj); // 添加对象
|
||||
};
|
||||
45
source_game/Actor/Map/Tile.cpp
Normal file
45
source_game/Actor/Map/Tile.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "Tile.h"
|
||||
#include "Tool/Tool_String.h"
|
||||
Tile::Tile()
|
||||
{
|
||||
}
|
||||
|
||||
Tile::Tile(std::string Path) : Sprite()
|
||||
{
|
||||
InitInfo(Path);
|
||||
if (std::get<std::string>(m_data["path"]) == "")
|
||||
m_data["path"] = "sprite/character/common/circlecooltime.img";
|
||||
|
||||
m_texture = new Texture(std::get<std::string>(m_data["path"]), std::get<int>(m_data["idx"]));
|
||||
Sprite::Init();
|
||||
}
|
||||
|
||||
Tile::~Tile()
|
||||
{
|
||||
}
|
||||
|
||||
void Tile::SetPos(VecFPos pos)
|
||||
{
|
||||
pos.y += std::get<int>(m_data["pos"]);
|
||||
Sprite::SetPos(pos);
|
||||
}
|
||||
|
||||
void Tile::InitInfo(std::string Path)
|
||||
{
|
||||
ScriptData Data = AssetManager::GetInstance().GetScriptInfo(Path);
|
||||
m_data["pos"] = 0;
|
||||
while (!Data.IsEnd())
|
||||
{
|
||||
std::string Segment = Data.Get();
|
||||
if (Segment == "[IMAGE]")
|
||||
{
|
||||
std::string PathBuf = Tool_toLowerCase(Data.Get());
|
||||
m_data["path"] = "sprite/" + PathBuf;
|
||||
m_data["idx"] = std::stoi(Data.Get());
|
||||
}
|
||||
else if (Segment == "[img pos]")
|
||||
{
|
||||
m_data["pos"] = std::stoi(Data.Get());
|
||||
}
|
||||
}
|
||||
}
|
||||
22
source_game/Actor/Map/Tile.h
Normal file
22
source_game/Actor/Map/Tile.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
#include "Asset/AssetManager.h"
|
||||
#include "EngineFrame/Component/Sprite.h"
|
||||
class Tile : public Sprite
|
||||
{
|
||||
|
||||
using TileInfoBody = std::variant<
|
||||
int,
|
||||
std::string>;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, TileInfoBody> m_data;
|
||||
|
||||
public:
|
||||
Tile(/* args */);
|
||||
Tile(std::string Path);
|
||||
~Tile();
|
||||
|
||||
void SetPos(VecFPos pos) override;
|
||||
|
||||
void InitInfo(std::string Path);
|
||||
};
|
||||
50
source_game/Actor/Object/ActiveObject.cpp
Normal file
50
source_game/Actor/Object/ActiveObject.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "ActiveObject.h"
|
||||
|
||||
void ActiveObject::SetPosition(VecFPos3 pos)
|
||||
{
|
||||
BaseObject::SetPosition(pos);
|
||||
BaseObject::SetRenderZOrder(this->Position.y);
|
||||
}
|
||||
|
||||
void ActiveObject::SetYpos(float y)
|
||||
{
|
||||
BaseObject::SetYpos(y);
|
||||
BaseObject::SetRenderZOrder(this->Position.y);
|
||||
}
|
||||
|
||||
void ActiveObject::SetSpeed(VecSpeed3 speed)
|
||||
{
|
||||
this->Speed = speed;
|
||||
}
|
||||
|
||||
VecSpeed3 ActiveObject::GetSpeed()
|
||||
{
|
||||
return this->Speed;
|
||||
}
|
||||
|
||||
void ActiveObject::Update(float deltaTime)
|
||||
{
|
||||
// X Y 轴方向的加速度计算
|
||||
if (Speed.x != 0 || Speed.y != 0)
|
||||
{
|
||||
MoveBy(Speed.x * deltaTime, Speed.y * deltaTime, 0);
|
||||
}
|
||||
// Z轴只在Z轴大于0时 或者 Z轴速度向上时才会有重力
|
||||
if (Position.z > 0 || Speed.z > 0)
|
||||
{
|
||||
// TODO 还没有写角色属性 要读了角色属性以后才是正确的
|
||||
float Gravity = 68000.0 / 1000.0 * 15.0;
|
||||
Speed.z -= Gravity * deltaTime;
|
||||
MoveBy(0, 0, Speed.z * deltaTime);
|
||||
}
|
||||
// Z轴小于0时要修正
|
||||
else if (Position.z < 0)
|
||||
{
|
||||
Position.z = 0;
|
||||
Speed.z = 0;
|
||||
SetPosition(Position);
|
||||
SDL_LogError(0, "修正Z轴");
|
||||
}
|
||||
// 执行父对象的更新
|
||||
BaseObject::Update(deltaTime);
|
||||
}
|
||||
19
source_game/Actor/Object/ActiveObject.h
Normal file
19
source_game/Actor/Object/ActiveObject.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include "Actor/Object/BaseObject.h"
|
||||
|
||||
class ActiveObject : public BaseObject
|
||||
{
|
||||
|
||||
public:
|
||||
VecSpeed3 Speed;
|
||||
|
||||
public:
|
||||
void SetPosition(VecFPos3 pos) override;
|
||||
void SetYpos(float y) override;
|
||||
|
||||
void SetSpeed(VecSpeed3 speed);
|
||||
VecSpeed3 GetSpeed();
|
||||
|
||||
public:
|
||||
void Update(float deltaTime) override;
|
||||
};
|
||||
97
source_game/Actor/Object/BaseObject.cpp
Normal file
97
source_game/Actor/Object/BaseObject.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "BaseObject.h"
|
||||
|
||||
BaseObject::BaseObject()
|
||||
{
|
||||
Init(); // 调用了RenderBase的Init函数 对象才会被执行回调
|
||||
SetAnchor({0.5f, 0.5f});
|
||||
}
|
||||
|
||||
BaseObject::~BaseObject()
|
||||
{
|
||||
}
|
||||
|
||||
void BaseObject::SetPosition(VecFPos3 pos)
|
||||
{
|
||||
this->Position = pos;
|
||||
Actor::SetPos(VecFPos{this->Position.x, this->Position.y - this->Position.z});
|
||||
}
|
||||
|
||||
VecFPos3 BaseObject::GetPosition()
|
||||
{
|
||||
return this->Position;
|
||||
}
|
||||
|
||||
void BaseObject::SetXpos(float x)
|
||||
{
|
||||
this->Position.x = x;
|
||||
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
|
||||
}
|
||||
|
||||
void BaseObject::SetYpos(float y)
|
||||
{
|
||||
this->Position.y = y;
|
||||
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
|
||||
}
|
||||
|
||||
void BaseObject::SetZpos(float z)
|
||||
{
|
||||
this->Position.z = z;
|
||||
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
|
||||
}
|
||||
|
||||
int BaseObject::GetXpos()
|
||||
{
|
||||
return this->Position.x;
|
||||
}
|
||||
|
||||
int BaseObject::GetYpos()
|
||||
{
|
||||
return this->Position.y;
|
||||
}
|
||||
|
||||
int BaseObject::GetZpos()
|
||||
{
|
||||
return this->Position.z;
|
||||
}
|
||||
|
||||
void BaseObject::MoveBy(VecFPos3 pos)
|
||||
{
|
||||
this->Position.x += pos.x;
|
||||
this->Position.y += pos.y;
|
||||
this->Position.z += pos.z;
|
||||
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
|
||||
}
|
||||
|
||||
void BaseObject::MoveBy(float x, float y, float z)
|
||||
{
|
||||
this->Position.x += x;
|
||||
this->Position.y += y;
|
||||
this->Position.z += z;
|
||||
Actor::SetPos({this->Position.x, this->Position.y - this->Position.z});
|
||||
}
|
||||
|
||||
void BaseObject::SetDirection(int dir)
|
||||
{
|
||||
this->Direction = dir;
|
||||
VecFPos sc = GetScale();
|
||||
// 朝右
|
||||
if (dir == 0)
|
||||
{
|
||||
SetScale(VecFPos({SDL_fabsf(sc.x), sc.y}));
|
||||
}
|
||||
// 朝左
|
||||
else if (dir == 1)
|
||||
{
|
||||
SetScale(VecFPos({-SDL_fabsf(sc.x), sc.y}));
|
||||
}
|
||||
}
|
||||
|
||||
int BaseObject::GetDirection()
|
||||
{
|
||||
return this->Direction;
|
||||
}
|
||||
|
||||
ObjectVars &BaseObject::GetObjectVars()
|
||||
{
|
||||
return _ObjectVars;
|
||||
}
|
||||
37
source_game/Actor/Object/BaseObject.h
Normal file
37
source_game/Actor/Object/BaseObject.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Actor/Actor.h"
|
||||
#include "Asset/Common/ObjectVars.h"
|
||||
class BaseObject : public Actor
|
||||
{
|
||||
private:
|
||||
/* data */
|
||||
public:
|
||||
VecFPos3 Position; // 位置
|
||||
int Direction = 0; // 方向
|
||||
|
||||
public:
|
||||
BaseObject(/* args */);
|
||||
~BaseObject();
|
||||
|
||||
// 数据储存器
|
||||
ObjectVars _ObjectVars;
|
||||
|
||||
public:
|
||||
virtual void SetPosition(VecFPos3 pos);
|
||||
virtual void SetXpos(float x);
|
||||
virtual void SetYpos(float y);
|
||||
virtual void SetZpos(float z);
|
||||
|
||||
VecFPos3 GetPosition();
|
||||
int GetXpos();
|
||||
int GetYpos();
|
||||
int GetZpos();
|
||||
|
||||
void MoveBy(VecFPos3 pos);
|
||||
void MoveBy(float x, float y, float z);
|
||||
|
||||
void SetDirection(int dir);
|
||||
int GetDirection();
|
||||
|
||||
ObjectVars &GetObjectVars();
|
||||
};
|
||||
57
source_game/Actor/Object/CharacterObject.cpp
Normal file
57
source_game/Actor/Object/CharacterObject.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include "CharacterObject.h"
|
||||
#include "Asset/Squirrel/SquirrelManager.h"
|
||||
|
||||
CharacterObject::~CharacterObject()
|
||||
{
|
||||
}
|
||||
|
||||
void CharacterObject::Update(float deltaTime)
|
||||
{
|
||||
ActiveObject::Update(deltaTime);
|
||||
}
|
||||
|
||||
void CharacterObject::Render()
|
||||
{
|
||||
ActiveObject::Render();
|
||||
}
|
||||
|
||||
void CharacterObject::Construction(int job)
|
||||
{
|
||||
// 创建装备管理器
|
||||
_EquipmentManager = new Chr_Equipment();
|
||||
_EquipmentManager->Init(this);
|
||||
// 创建动画管理器(一定要先创建装备管理器再创建动画管理器 因为需要读取身上的装备)
|
||||
_AnimationManager = new Chr_Animation();
|
||||
_AnimationManager->Init(this);
|
||||
// 创建状态机
|
||||
_StateMachine = new Chr_StateMachine();
|
||||
_StateMachine->Init(this);
|
||||
|
||||
// 开启控制器
|
||||
EnableController();
|
||||
}
|
||||
|
||||
void CharacterObject::EnableController()
|
||||
{
|
||||
this->_Controller = new Chr_Controller();
|
||||
_Controller->Init(this);
|
||||
AddChild(_Controller);
|
||||
}
|
||||
|
||||
void CharacterObject::DisableController()
|
||||
{
|
||||
this->RemoveChild(_Controller);
|
||||
this->_Controller = nullptr;
|
||||
}
|
||||
|
||||
void CharacterObject::ControllerMsg(CONTROLLER_MSG_TYPE msgType, void *msgData)
|
||||
{
|
||||
// 摇杆移动(左)
|
||||
if (msgType == CONTROLLER_MSG_TYPE::CONTROLLER_MSG_TYPE_LEFT_JOYSTICK_MOVE)
|
||||
{
|
||||
VecFPos *pos = (VecFPos *)msgData;
|
||||
std::vector<float> movedata = {pos->x, pos->y};
|
||||
this->GetObjectVars().SetArray("_move_data_", movedata);
|
||||
this->_StateMachine->ChangeState(BASE_STATE::MOVE);
|
||||
}
|
||||
}
|
||||
39
source_game/Actor/Object/CharacterObject.h
Normal file
39
source_game/Actor/Object/CharacterObject.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
#include "Actor/Object/ActiveObject.h"
|
||||
#include "Asset/Character/Chr_Animation.h"
|
||||
#include "Asset/Character/Chr_Equipment.h"
|
||||
#include "Asset/Character/Chr_Controller.h"
|
||||
#include "Asset/Character/Chr_StateMachine.h"
|
||||
#include "Global/Global_Enum.h"
|
||||
class CharacterObject : public ActiveObject
|
||||
{
|
||||
public:
|
||||
// 角色动画管理器
|
||||
RefPtr<Chr_Animation> _AnimationManager = nullptr;
|
||||
// 装备管理器
|
||||
RefPtr<Chr_Equipment> _EquipmentManager = nullptr;
|
||||
// 角色控制器
|
||||
RefPtr<Chr_Controller> _Controller = nullptr;
|
||||
// 角色状态机
|
||||
RefPtr<Chr_StateMachine> _StateMachine = nullptr;
|
||||
// 职业
|
||||
int Job = 0;
|
||||
// 转职职业 如果是-1则没有转职
|
||||
int GrowType = -1;
|
||||
|
||||
public:
|
||||
~CharacterObject();
|
||||
|
||||
public:
|
||||
void Update(float deltaTime) override;
|
||||
void Render() override;
|
||||
|
||||
// 通过职业创建角色
|
||||
void Construction(int job);
|
||||
// 开启控制器
|
||||
void EnableController();
|
||||
// 关闭控制器
|
||||
void DisableController();
|
||||
// 控制器信息
|
||||
void ControllerMsg(CONTROLLER_MSG_TYPE msgType, void* msgData);
|
||||
};
|
||||
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();
|
||||
};
|
||||
36
source_game/Global/Global_Enum.h
Normal file
36
source_game/Global/Global_Enum.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
// 交易类型
|
||||
enum ATTACH_TYPE
|
||||
{
|
||||
FREE, // 无限制
|
||||
SEALING, // 封装
|
||||
TRADE, // 不可交易
|
||||
ACCOUNT, // 账号绑定
|
||||
TRADE_DELETE, // 无法交易、删除
|
||||
SEALING_TRADE // 封装且不可交易
|
||||
};
|
||||
|
||||
// 控制器消息类型
|
||||
enum CONTROLLER_MSG_TYPE
|
||||
{
|
||||
// 摇杆移动(左)
|
||||
CONTROLLER_MSG_TYPE_LEFT_JOYSTICK_MOVE,
|
||||
// 摇杆移动(右)
|
||||
CONTROLLER_MSG_TYPE_RIGHT_JOYSTICK_MOVE
|
||||
};
|
||||
|
||||
// 基础状态
|
||||
enum BASE_STATE
|
||||
{
|
||||
REST, // 站立
|
||||
MOVE, // 移动
|
||||
DASH, // 冲刺
|
||||
JUMP, // 跳跃
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
37
source_game/Global/Global_Game.cpp
Normal file
37
source_game/Global/Global_Game.cpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#include "Global_Game.h"
|
||||
|
||||
Global_Game::Global_Game()
|
||||
{
|
||||
}
|
||||
Global_Game::~Global_Game()
|
||||
{
|
||||
}
|
||||
|
||||
void Global_Game::Init()
|
||||
{
|
||||
// 初始化ttf字体资源
|
||||
TTF_Font *FontBuf = TTF_OpenFont("Fonts/LXGWWenKai-Regular.ttf", 24);
|
||||
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/Gothica-Book.ttf", 24);
|
||||
// TTF_Font *FontBuf = TTF_OpenFont("Fonts/Gasinamu.ttf", 24);
|
||||
if (!FontBuf)
|
||||
{
|
||||
SDL_LogError(0, "字体加载失败: %s", TTF_GetError());
|
||||
}
|
||||
Fonts.push_back(FontBuf);
|
||||
}
|
||||
|
||||
void Global_Game::InitGame()
|
||||
{
|
||||
// 读取角色配置文件
|
||||
CharacterConfigs = GlobalCharacterScript::InitCharacterLst();
|
||||
// 读取装备配置文件
|
||||
EquipmentPathMap = GlobalEquipmentScript::InitEquipmentLst();
|
||||
|
||||
// 初始化松鼠脚本管理器
|
||||
SquirrelManager::GetInstance().Init();
|
||||
|
||||
// 读取存档
|
||||
SavaManager::GetInstance().Init();
|
||||
// 游戏初始化完成标志
|
||||
InitFlag = true;
|
||||
}
|
||||
45
source_game/Global/Global_Game.h
Normal file
45
source_game/Global/Global_Game.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#include "EngineCore/Game.h"
|
||||
#include "Global/Script/CharacterConfig.h"
|
||||
#include "Global/Script/EquipmentConfig.h"
|
||||
#include "Global/Save/SavaManager.h"
|
||||
#include "Asset/Squirrel/SquirrelManager.h"
|
||||
class Global_Game
|
||||
{
|
||||
|
||||
public:
|
||||
Global_Game(const Global_Game &) = delete;
|
||||
Global_Game &operator=(const Global_Game &) = delete;
|
||||
Global_Game(Global_Game &&) = delete;
|
||||
Global_Game &operator=(Global_Game &&) = delete;
|
||||
// 全局访问点
|
||||
static Global_Game &GetInstance()
|
||||
{
|
||||
static Global_Game instance; // 局部静态变量,保证只初始化一次
|
||||
return instance;
|
||||
}
|
||||
|
||||
// 游戏资源加载之前的初始化
|
||||
void Init();
|
||||
// 游戏资源加载之后的初始化
|
||||
void InitGame();
|
||||
|
||||
public:
|
||||
// 当前游戏状态 0未初始化
|
||||
int game_state = 0;
|
||||
|
||||
public:
|
||||
// 字体资源
|
||||
std::vector<TTF_Font *> Fonts;
|
||||
// 角色配置文件
|
||||
std::vector<GlobalCharacterScript::CharacterConfig> CharacterConfigs;
|
||||
// 装备路径Map
|
||||
std::map<int, std::string> EquipmentPathMap;
|
||||
|
||||
// 游戏资源初始化标志
|
||||
bool InitFlag = false;
|
||||
|
||||
private:
|
||||
Global_Game(/* args */);
|
||||
~Global_Game();
|
||||
};
|
||||
10
source_game/Global/Global_Type.h
Normal file
10
source_game/Global/Global_Type.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <variant>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
// 定义变量类型变体
|
||||
using ObjectVarsType = std::variant<int, float, bool, std::string>;
|
||||
// 定义对象变量映射类型
|
||||
using ObjectVarsMap = std::map<std::string, std::vector<ObjectVarsType>>;
|
||||
59
source_game/Global/Save/SavaManager.cpp
Normal file
59
source_game/Global/Save/SavaManager.cpp
Normal file
@@ -0,0 +1,59 @@
|
||||
#include "SavaManager.h"
|
||||
#include <json.hpp>
|
||||
#include <dirent.h>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <SDL.h>
|
||||
SavaManager::SavaManager()
|
||||
{
|
||||
}
|
||||
|
||||
SavaManager::~SavaManager()
|
||||
{
|
||||
}
|
||||
|
||||
void SavaManager::Init()
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
std::string path = "Save/";
|
||||
dir = opendir(path.c_str());
|
||||
|
||||
while ((ent = readdir(dir)))
|
||||
{
|
||||
// 跳过.和..目录
|
||||
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
|
||||
continue;
|
||||
std::string RealPath = path + ent->d_name;
|
||||
SDL_Log("RealPath: %s", RealPath.c_str());
|
||||
}
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
void SavaManager::Save()
|
||||
{
|
||||
int Level = 1;
|
||||
int Job = 0;
|
||||
int GrowType = -1;
|
||||
int Exp = 0;
|
||||
int Fatigue = 0;
|
||||
|
||||
nlohmann::json SaveJson;
|
||||
SaveJson["Level"] = Level;
|
||||
SaveJson["Job"] = Job;
|
||||
SaveJson["GrowType"] = GrowType;
|
||||
SaveJson["Exp"] = Exp;
|
||||
SaveJson["Fatigue"] = Fatigue;
|
||||
|
||||
SaveJson["WearEquipment"] = nlohmann::json::object();
|
||||
|
||||
nlohmann::json weapon;
|
||||
weapon["id"] = 26058;
|
||||
|
||||
SaveJson["WearEquipment"]["weapon"] = weapon;
|
||||
|
||||
std::ofstream OutFile("Save/Save_0.sav");
|
||||
OutFile << SaveJson.dump(4);
|
||||
OutFile.close();
|
||||
}
|
||||
29
source_game/Global/Save/SavaManager.h
Normal file
29
source_game/Global/Save/SavaManager.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
class SavaManager
|
||||
{
|
||||
public:
|
||||
// 删除拷贝构造和赋值运算符,确保无法复制
|
||||
SavaManager(const SavaManager &) = delete;
|
||||
SavaManager &operator=(const SavaManager &) = delete;
|
||||
|
||||
// 移动构造和赋值也删除,避免意外转移
|
||||
SavaManager(SavaManager &&) = delete;
|
||||
SavaManager &operator=(SavaManager &&) = delete;
|
||||
|
||||
// 全局访问点
|
||||
static SavaManager &GetInstance()
|
||||
{
|
||||
static SavaManager instance; // 局部静态变量,保证只初始化一次
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
// 构造函数和析构函数设为私有,防止外部创建和销毁
|
||||
SavaManager();
|
||||
~SavaManager();
|
||||
|
||||
public:
|
||||
void Init();
|
||||
void Save();
|
||||
};
|
||||
135
source_game/Global/Script/CharacterConfig.cpp
Normal file
135
source_game/Global/Script/CharacterConfig.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
#include "CharacterConfig.h"
|
||||
#include "Asset/AssetManager.h"
|
||||
#include "Tool/Tool_String.h"
|
||||
namespace GlobalCharacterScript
|
||||
{
|
||||
JobConfig InitJobConfig(std::string JobInfoPath)
|
||||
{
|
||||
JobConfig Config;
|
||||
ScriptData Data = AssetManager::GetInstance().GetScriptInfo(JobInfoPath);
|
||||
while (!Data.IsEnd())
|
||||
{
|
||||
std::string Segment = Data.Get();
|
||||
if (Segment == "[职业名称]")
|
||||
Config.name = Data.Get();
|
||||
else if (Segment == "[生命值上限]")
|
||||
Config.maxHP = std::stof(Data.Get());
|
||||
else if (Segment == "[魔法值上限]")
|
||||
Config.maxMP = std::stof(Data.Get());
|
||||
else if (Segment == "[生命值回复速率]")
|
||||
Config.hpRecoverRate = std::stof(Data.Get());
|
||||
else if (Segment == "[魔法值回复速率]")
|
||||
Config.mpRecoverRate = std::stof(Data.Get());
|
||||
else if (Segment == "[力量]")
|
||||
Config.strength = std::stof(Data.Get());
|
||||
else if (Segment == "[智力]")
|
||||
Config.intelligence = std::stof(Data.Get());
|
||||
else if (Segment == "[体力]")
|
||||
Config.stamina = std::stof(Data.Get());
|
||||
else if (Segment == "[精神]")
|
||||
Config.spirit = std::stof(Data.Get());
|
||||
else if (Segment == "[移动速度]")
|
||||
Config.moveSpeed = std::stof(Data.Get());
|
||||
else if (Segment == "[攻击速度]")
|
||||
Config.attackSpeed = std::stof(Data.Get());
|
||||
else if (Segment == "[释放速度]")
|
||||
Config.castSpeed = std::stof(Data.Get());
|
||||
else if (Segment == "[硬直]")
|
||||
Config.stunResist = std::stof(Data.Get());
|
||||
else if (Segment == "[跳跃力]")
|
||||
Config.jumpPower = std::stof(Data.Get());
|
||||
else if (Segment == "[跳跃速度]")
|
||||
Config.jumpSpeed = std::stof(Data.Get());
|
||||
else if (Segment == "[火属性抗性]")
|
||||
Config.fireResist = std::stof(Data.Get());
|
||||
else if (Segment == "[冰属性抗性]")
|
||||
Config.iceResist = std::stof(Data.Get());
|
||||
else if (Segment == "[光属性抗性]")
|
||||
Config.lightResist = std::stof(Data.Get());
|
||||
else if (Segment == "[暗属性抗性]")
|
||||
Config.darkResist = std::stof(Data.Get());
|
||||
else if (Segment == "[默认技能]")
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::string Ret = Data.Get();
|
||||
if (Ret == "[/默认技能]")
|
||||
break;
|
||||
Config.skillList.push_back(std::stoi(Ret));
|
||||
}
|
||||
}
|
||||
else if (Segment == "[默认时装]")
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::string Ret = Data.Get();
|
||||
if (Ret == "[/默认时装]")
|
||||
break;
|
||||
std::string Index = Data.Get();
|
||||
Config.defaultAvatarList[Ret] = std::stoi(Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Config;
|
||||
}
|
||||
|
||||
CharacterConfig InitCharacterConfig(std::string JobInfoPath)
|
||||
{
|
||||
CharacterConfig Config;
|
||||
ScriptData Data = AssetManager::GetInstance().GetScriptInfo(std::string("character/") + JobInfoPath);
|
||||
while (!Data.IsEnd())
|
||||
{
|
||||
std::string Segment = Data.Get();
|
||||
if (Segment == "[职业标签]")
|
||||
{
|
||||
std::string JobTab = Data.Get();
|
||||
Config.jobTag = JobTab.substr(1, JobTab.size() - 2);
|
||||
}
|
||||
else if (Segment == "[基础职业属性]")
|
||||
{
|
||||
Config.baseGrowtypePath = Data.Get();
|
||||
Config.baseJobConfig = InitJobConfig(Tool_toLowerCase(Config.baseGrowtypePath));
|
||||
}
|
||||
else if (Segment == "[转职职业属性]")
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::string Ret = Data.Get();
|
||||
if (Ret == "[/转职职业属性]")
|
||||
break;
|
||||
Config.growtypePath.push_back(Ret);
|
||||
Config.growtypeJobConfig.push_back(InitJobConfig(Tool_toLowerCase(Ret)));
|
||||
}
|
||||
}
|
||||
else if (Segment == "[动作动画]")
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
std::string Ret = Data.Get();
|
||||
if (Ret == "[/动作动画]")
|
||||
break;
|
||||
std::string path = Data.Get();
|
||||
Config.animationPath[Ret] = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Config;
|
||||
}
|
||||
|
||||
std::vector<CharacterConfig> InitCharacterLst()
|
||||
{
|
||||
std::vector<CharacterConfig> Config;
|
||||
// 先读取角色职业lst
|
||||
ScriptData Data = AssetManager::GetInstance().GetScriptInfo("character/character.lst");
|
||||
while (!Data.IsEnd())
|
||||
{
|
||||
std::string Index = Data.Get();
|
||||
std::string JobInfoPath = Data.Get();
|
||||
// 读取职业 //TODO 现在只有鬼剑士更改了文件 其他职业读了会炸
|
||||
if (std::stoi(Index) <= 0)
|
||||
Config.push_back(InitCharacterConfig(Tool_toLowerCase(JobInfoPath)));
|
||||
}
|
||||
return Config;
|
||||
}
|
||||
}
|
||||
79
source_game/Global/Script/CharacterConfig.h
Normal file
79
source_game/Global/Script/CharacterConfig.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
namespace GlobalCharacterScript
|
||||
{
|
||||
|
||||
// 职业配置
|
||||
struct JobConfig
|
||||
{
|
||||
// 职业名称
|
||||
std::string name;
|
||||
// HP最大值
|
||||
float maxHP;
|
||||
// MP最大值
|
||||
float maxMP;
|
||||
// HP恢复速率
|
||||
float hpRecoverRate;
|
||||
// MP恢复速率
|
||||
float mpRecoverRate;
|
||||
// 力量
|
||||
float strength;
|
||||
// 智力
|
||||
float intelligence;
|
||||
// 体力
|
||||
float stamina;
|
||||
// 精神
|
||||
float spirit;
|
||||
// 移动速度
|
||||
float moveSpeed;
|
||||
// 攻击速度
|
||||
float attackSpeed;
|
||||
// 释放速度
|
||||
float castSpeed;
|
||||
// 硬直
|
||||
float stunResist;
|
||||
// 跳跃力
|
||||
float jumpPower;
|
||||
// 跳跃速度
|
||||
float jumpSpeed;
|
||||
// 火属性抗性
|
||||
float fireResist;
|
||||
// 冰属性抗性
|
||||
float iceResist;
|
||||
// 光属性抗性
|
||||
float lightResist;
|
||||
// 暗属性抗性
|
||||
float darkResist;
|
||||
|
||||
// 初始技能列表
|
||||
std::vector<int> skillList;
|
||||
// 默认时装列表
|
||||
std::map<std::string, int> defaultAvatarList;
|
||||
};
|
||||
|
||||
// 角色类信息
|
||||
struct CharacterConfig
|
||||
{
|
||||
// 基础职业标识
|
||||
std::string jobTag;
|
||||
// 基础职业路径
|
||||
std::string baseGrowtypePath;
|
||||
// 基础职业配置
|
||||
JobConfig baseJobConfig;
|
||||
// 转职配置路径
|
||||
std::vector<std::string> growtypePath;
|
||||
// 转职职业配置
|
||||
std::vector<JobConfig> growtypeJobConfig;
|
||||
// 动画路径
|
||||
std::map<std::string, std::string> animationPath;
|
||||
};
|
||||
|
||||
// 读取角色Lst信息
|
||||
std::vector<CharacterConfig> InitCharacterLst();
|
||||
// 读取角色信息
|
||||
CharacterConfig InitCharacterConfig(std::string JobInfoPath);
|
||||
// 读取职业信息
|
||||
JobConfig InitJobConfig(std::string JobConfigPath);
|
||||
}
|
||||
19
source_game/Global/Script/EquipmentConfig.cpp
Normal file
19
source_game/Global/Script/EquipmentConfig.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "EquipmentConfig.h"
|
||||
#include "Asset/AssetManager.h"
|
||||
#include "Tool/Tool_String.h"
|
||||
namespace GlobalEquipmentScript
|
||||
{
|
||||
|
||||
std::map<int, std::string> InitEquipmentLst()
|
||||
{
|
||||
std::map<int, std::string> EquipList;
|
||||
ScriptData Data = AssetManager::GetInstance().GetScriptInfo("equipment/equipment.lst");
|
||||
while (!Data.IsEnd())
|
||||
{
|
||||
std::string Index = Data.Get();
|
||||
std::string EquipInfoPath = std::string("equipment/") + Data.Get();
|
||||
EquipList[std::stoi(Index)] = EquipInfoPath;
|
||||
}
|
||||
return EquipList;
|
||||
}
|
||||
}
|
||||
9
source_game/Global/Script/EquipmentConfig.h
Normal file
9
source_game/Global/Script/EquipmentConfig.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
namespace GlobalEquipmentScript
|
||||
{
|
||||
|
||||
std::map<int, std::string> InitEquipmentLst();
|
||||
}
|
||||
65
source_game/Scene/Scene_Loading_UI.cpp
Normal file
65
source_game/Scene/Scene_Loading_UI.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
#include "Scene/Scene_Loading_UI.h"
|
||||
#include "Scene/Scene_SelectCharacter_UI.hpp"
|
||||
#include "Scene/Scene_Test.h"
|
||||
#include "Scene_Loading_UI.h"
|
||||
#include "EngineFrame/Component/Sprite.h"
|
||||
#include "EngineFrame/Component/Text.h"
|
||||
#include "Global/Global_Game.h"
|
||||
#include "Asset/Asset_Script.h"
|
||||
|
||||
void Scene_Loading_UI::Enter()
|
||||
{
|
||||
// 加载OGG文件
|
||||
music = Mix_LoadMUS("Music/characterSelectStage.ogg");
|
||||
if (music)
|
||||
{
|
||||
Mix_PlayMusic(music, 1);
|
||||
}
|
||||
|
||||
RefPtr<Actor> actor = new Actor;
|
||||
AddChild(actor);
|
||||
|
||||
RefPtr<Sprite> BackGroundSp = new Sprite("ImagePacks2/Loading1.png");
|
||||
actor->AddComponent(BackGroundSp);
|
||||
RefPtr<Sprite> BackGround2Sp = new Sprite("ImagePacks2/Loading0.png");
|
||||
BackGround2Sp->SetPos(VecFPos{0, 686});
|
||||
actor->AddComponent(BackGround2Sp);
|
||||
RefPtr<Sprite> LoadCircleSp = new Sprite("ImagePacks2/Loading2.png");
|
||||
LoadCircleSp->SetName("LoadCircle");
|
||||
LoadCircleSp->SetPos(VecFPos{1280 - 60, 686 - 60});
|
||||
LoadCircleSp->SetBlendMode(SDL_BLENDMODE_ADD);
|
||||
LoadCircleSp->SetAnchor(VecFPos{0.5f, 0.5f});
|
||||
actor->AddComponent(LoadCircleSp);
|
||||
|
||||
actor->SetCallbackOnUpdate([LoadCircleSp](float deltaTime) mutable
|
||||
{
|
||||
float angle = LoadCircleSp->GetRotation();
|
||||
LoadCircleSp->SetRotation(angle + 180.0f * deltaTime); });
|
||||
|
||||
// 文字测试
|
||||
// RefPtr<Text> text = new Text("测试文字加载中...", Global_Game::GetInstance().Fonts[0], SDL_Color{255, 255, 255, 255}, SDL_Color{0, 0, 0, 255}, 4);
|
||||
// actor->AddComponent(text);
|
||||
}
|
||||
|
||||
void Scene_Loading_UI::Update(float deltaTime)
|
||||
{
|
||||
Scene::Update(deltaTime);
|
||||
if (Global_Game::GetInstance().InitFlag)
|
||||
{
|
||||
// 设定游戏层场景
|
||||
RefPtr<Scene_Test> scene = new Scene_Test;
|
||||
Game::GetInstance().ChangeScene(scene);
|
||||
// 设定UI层场景
|
||||
RefPtr<Scene_SelectCharacter_UI> sceneUI = new Scene_SelectCharacter_UI;
|
||||
Game::GetInstance().ChangeUIScene(sceneUI);
|
||||
}
|
||||
}
|
||||
|
||||
void Scene_Loading_UI::Exit()
|
||||
{
|
||||
if (music)
|
||||
{
|
||||
Mix_FreeMusic(music);
|
||||
music = nullptr;
|
||||
}
|
||||
}
|
||||
17
source_game/Scene/Scene_Loading_UI.h
Normal file
17
source_game/Scene/Scene_Loading_UI.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Scene/Scene.h"
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
|
||||
class Scene_Loading_UI : public Scene
|
||||
{
|
||||
private:
|
||||
/* data */
|
||||
|
||||
public:
|
||||
void Enter() override;
|
||||
void Update(float deltaTime) override;
|
||||
void Exit() override;
|
||||
|
||||
// 加载界面音乐
|
||||
Mix_Music *music = nullptr;
|
||||
};
|
||||
88
source_game/Scene/Scene_SelectCharacter_UI.hpp
Normal file
88
source_game/Scene/Scene_SelectCharacter_UI.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Scene/Scene.h"
|
||||
#include "Asset/AssetManager.h"
|
||||
#include "EngineFrame/Component/Animation.h"
|
||||
#include "Actor/Map/GameMap.h"
|
||||
#include "Actor/Map/GameMapCamera.h"
|
||||
class Scene_SelectCharacter_UI : public Scene
|
||||
{
|
||||
private:
|
||||
/* data */
|
||||
GameMap *map;
|
||||
RefPtr<GameMapCamera> camera = nullptr;
|
||||
|
||||
public:
|
||||
Scene_SelectCharacter_UI(/* args */) {
|
||||
|
||||
};
|
||||
~Scene_SelectCharacter_UI() {
|
||||
|
||||
};
|
||||
|
||||
public:
|
||||
void Enter() override
|
||||
{
|
||||
map = new GameMap;
|
||||
map->LoadMap("map/cataclysm/town/elvengard/new_elvengard.map");
|
||||
map->Enter(this);
|
||||
|
||||
camera = new GameMapCamera;
|
||||
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;
|
||||
actor->AddChild(actor2);
|
||||
|
||||
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");
|
||||
// ani3->SetPos(VecPos{300, 300});
|
||||
// actor->AddChild(ani3);
|
||||
|
||||
// RefPtr<Animation> ani4 = new Animation("map/cataclysm/town/hendonmyre/animation/object/gateall_02.ani");
|
||||
// ani4->SetPos(VecPos{300, 500});
|
||||
// actor->AddChild(ani4);
|
||||
|
||||
// for (size_t i = 0; i < 400; i++)
|
||||
// {
|
||||
// RefPtr<Actor> actor = new Actor;
|
||||
// AddChild(actor);
|
||||
|
||||
// // RefPtr<Animation> ani3 = new Animation("common/commoneffect/animation/priestslowheal1.ani");
|
||||
// // actor->AddComponent(ani3);
|
||||
// // ani3->SetRenderZOrder(1000);
|
||||
|
||||
// // RefPtr<Animation> ani = new Animation("common/anton/main.ani");
|
||||
// // actor->AddComponent(ani);
|
||||
// // ani->SetRenderZOrder(500);
|
||||
|
||||
// RefPtr<Sprite> sprite = new Sprite("sprite/item/avatar/swordman/0sm_acap.img", 0);
|
||||
// actor->AddComponent(sprite);
|
||||
// // RefPtr<Animation> ani2 = new Animation("common/anton/face/0/0.ani");
|
||||
// // actor->AddComponent(ani2);
|
||||
// // ani2->SetRenderZOrder(1000);
|
||||
// }
|
||||
|
||||
// SDL_Log("进入了选择角色场景!");
|
||||
};
|
||||
|
||||
void HandleEvents(SDL_Event *e) override
|
||||
{
|
||||
Scene::HandleEvents(e);
|
||||
map->HandleEvents(e);
|
||||
};
|
||||
void Update(float deltaTime) override
|
||||
{
|
||||
Scene::Update(deltaTime);
|
||||
map->Update(deltaTime);
|
||||
};
|
||||
// void Render() override;
|
||||
// void Exit() override;
|
||||
};
|
||||
33
source_game/Scene/Scene_Test.cpp
Normal file
33
source_game/Scene/Scene_Test.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "Scene_Test.h"
|
||||
#include <memory>
|
||||
#include <EngineCore/Game.h>
|
||||
Scene_Test::Scene_Test()
|
||||
{
|
||||
}
|
||||
|
||||
Scene_Test::~Scene_Test()
|
||||
{
|
||||
SDL_Log("Scene_Test::我的ID是%d --- 我被释放了!", this->MyId);
|
||||
}
|
||||
|
||||
void Scene_Test::Enter()
|
||||
{
|
||||
SDL_Log("进入测试场景!");
|
||||
}
|
||||
|
||||
void Scene_Test::HandleEvents(SDL_Event *e)
|
||||
{
|
||||
}
|
||||
|
||||
void Scene_Test::Update(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
void Scene_Test::Render()
|
||||
{
|
||||
}
|
||||
|
||||
void Scene_Test::Exit()
|
||||
{
|
||||
SDL_Log("Scene_Test::退出测试场景!当前引用计数%d", this->GetRefCount());
|
||||
}
|
||||
21
source_game/Scene/Scene_Test.h
Normal file
21
source_game/Scene/Scene_Test.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
#include "EngineFrame/Scene/Scene.h"
|
||||
|
||||
class Scene_Test : public Scene
|
||||
{
|
||||
private:
|
||||
/* data */
|
||||
public:
|
||||
Scene_Test(/* args */);
|
||||
~Scene_Test();
|
||||
|
||||
public:
|
||||
void Enter() override;
|
||||
void HandleEvents(SDL_Event *e) override;
|
||||
void Update(float deltaTime) override;
|
||||
void Render() override;
|
||||
void Exit() override;
|
||||
|
||||
public:
|
||||
int MyId = 0;
|
||||
};
|
||||
90
source_game/main.cpp
Normal file
90
source_game/main.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
// 电脑的IP地址和端口
|
||||
#define PC_IP "192.168.200.3"
|
||||
#define PC_SCRIPT_PORT "39018"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef __SWITCH__
|
||||
#include <switch.h>
|
||||
#include <sys/socket.h>
|
||||
#include <curl/curl.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "Asset/Asset_ImagePack.h"
|
||||
#include "Asset/Asset_Script.h"
|
||||
#include "squirrel/SquirrelEx.h"
|
||||
#include "Tool/Logger.h"
|
||||
#include "EngineCore/Game.h"
|
||||
#include "Scene/Scene_Loading_UI.h"
|
||||
#include "Tool/RefPtr.h"
|
||||
#include "Global/Global_Game.h"
|
||||
#include "Tool/ThreadPool.h"
|
||||
|
||||
void InitScript()
|
||||
{
|
||||
// 初始化脚本资源系统
|
||||
Asset_Script::GetInstance().Init();
|
||||
// 初始化Image资源系统
|
||||
Asset_ImagePack::GetInstance().Init();
|
||||
|
||||
// 更改全局游戏类初始化标志
|
||||
Global_Game::GetInstance().InitGame();
|
||||
}
|
||||
|
||||
void RunSetup()
|
||||
{
|
||||
// 初始化全局游戏类
|
||||
Global_Game::GetInstance().Init();
|
||||
// 初始化Squirrel脚本引擎
|
||||
SquirrelEx::GetInstance().Run();
|
||||
|
||||
// 设定UI层场景
|
||||
RefPtr<Scene_Loading_UI> sceneUI = new Scene_Loading_UI;
|
||||
Game::GetInstance().ChangeUIScene(sceneUI);
|
||||
|
||||
ThreadPool::GetInstance().enqueueToThread(2, InitScript);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef __SWITCH__
|
||||
socketInitializeDefault();
|
||||
nxlinkStdio(); // 启用nxlink调试输出
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT); // 初始化libcurl
|
||||
chdir("/switch/Lenheart/");
|
||||
#else
|
||||
AllocConsole();
|
||||
SetConsoleTitleA("Yosin & Engine");
|
||||
SetConsoleOutputCP(65001);
|
||||
#endif
|
||||
|
||||
// 初始化Image资源系统
|
||||
Asset_ImagePack::GetInstance();
|
||||
// 初始化脚本资源系统
|
||||
Asset_Script::GetInstance();
|
||||
// 初始化线程池
|
||||
ThreadPool::GetInstance();
|
||||
|
||||
// 初始化日志系统
|
||||
// Logger::GetInstance().Init();
|
||||
// 初始化Squirrel脚本系统
|
||||
SquirrelEx::GetInstance().Init();
|
||||
// 初始化游戏引擎
|
||||
Game &game = Game::GetInstance();
|
||||
// 初始化各项目
|
||||
game.Init(RunSetup);
|
||||
// 进入游戏循环逻辑
|
||||
game.Run();
|
||||
game.Clear();
|
||||
|
||||
#ifdef __SWITCH__
|
||||
socketExit();
|
||||
curl_global_cleanup();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user