feat: 实现游戏地图和城镇系统基础架构

新增GameMap和GameTown类实现游戏地图和城镇的核心功能
添加GameWorld作为游戏世界管理器处理场景切换
完善音频系统支持从路径加载音乐和音效
重构PVF资源系统增加路径规范化功能
添加.gitignore排除游戏资源目录
This commit is contained in:
2026-04-01 09:53:06 +08:00
parent 42e5579cc3
commit d55808d80f
20 changed files with 1288 additions and 25 deletions

View File

@@ -0,0 +1,76 @@
#pragma once
#include <frostbite2D/types/type_math.h>
#include <map>
#include <string>
#include <vector>
namespace frostbite2D::game {
struct AreaConfig {
std::string mapPath;
std::string mapType;
Vec2 generatePos = Vec2(-1.0f, -1.0f);
};
struct TownConfig {
std::string townName;
std::string enteringTitle;
std::string enteringCutscene;
int needQuestId = -1;
int needLevel = -1;
std::map<int, AreaConfig> areas;
};
struct BackgroundAnimationConfig {
std::string filename;
std::string layer;
std::string order;
};
struct MapAnimationConfig {
std::string filename;
std::string layer;
int xPos = 0;
int yPos = 0;
int zPos = 0;
};
struct MoveAreaTarget {
int town = -2;
int area = -2;
};
struct TileInfo {
std::string spritePath;
int spriteIndex = 0;
int imgPos = 0;
};
struct MapConfig {
std::string name;
std::string mapPath;
std::string mapDir;
int backgroundPos = 0;
int farSightScroll = 100;
bool hasCameraLimit = false;
int cameraLimitMinX = -1;
int cameraLimitMaxX = -1;
int cameraLimitMinY = -1;
int cameraLimitMaxY = -1;
std::vector<std::string> tilePaths;
std::vector<std::string> extendedTilePaths;
std::vector<BackgroundAnimationConfig> backgroundAnimations;
std::vector<MapAnimationConfig> mapAnimations;
std::vector<std::string> soundIds;
std::vector<Rect> virtualMovableAreas;
std::vector<Rect> townMovableAreas;
std::vector<MoveAreaTarget> townMovableAreaTargets;
};
std::map<int, std::string> loadTownList();
bool loadTownConfig(const std::string& townPath, TownConfig& outConfig);
bool loadMapConfig(const std::string& mapPath, MapConfig& outConfig);
bool loadTileInfo(const std::string& path, TileInfo& outInfo);
} // namespace frostbite2D::game

View File

@@ -0,0 +1,55 @@
#pragma once
#include "GameDataLoader.h"
#include "GameMapLayer.h"
#include <frostbite2D/2d/actor.h>
#include <frostbite2D/audio/music.h>
#include <unordered_map>
namespace frostbite2D {
class GameMap : public Actor {
public:
using MapMoveArea = game::MoveAreaTarget;
GameMap();
~GameMap() override = default;
bool LoadMap(const std::string& mapName);
void Enter();
void Update(float deltaTime) override;
void AddObject(RefPtr<Actor> object);
Vec3 CheckIsItMovable(const Vec3& curPos, const Vec3& posOffset) const;
MapMoveArea CheckIsItMoveArea(const Vec3& curPos) const;
const std::vector<MapMoveArea>& GetMoveAreaInfo() const;
Rect GetMovablePositionArea(size_t index) const;
int GetMapLength() const { return mapLength_; }
int GetMapHeight() const { return mapHeight_; }
private:
void initLayers();
void clearLayerChildren();
void InitTile();
void InitBackgroundAnimation();
void InitMapAnimation();
void InitVirtualMovableArea();
void InitMoveArea();
void updateCamera();
void updateLayerPositions(const Vec2& cameraPos);
game::MapConfig mapConfig_;
std::unordered_map<std::string, RefPtr<GameMapLayer>> layerMap_;
std::vector<Rect> movableArea_;
std::vector<Rect> moveArea_;
int mapLength_ = 0;
int mapHeight_ = 0;
int mapOffsetY_ = 0;
bool debugMode_ = false;
Vec2 cameraFocus_ = Vec2::Zero();
Ptr<Music> currentMusic_;
};
} // namespace frostbite2D

View File

@@ -0,0 +1,20 @@
#pragma once
#include <frostbite2D/2d/actor.h>
#include <vector>
namespace frostbite2D {
class GameMapLayer : public Actor {
public:
void Render() override;
void AddDebugFeasibleAreaInfo(const Rect& rect, int type);
void AddObject(RefPtr<Actor> obj);
private:
std::vector<Rect> feasibleAreaInfoList_;
std::vector<Rect> moveAreaInfoList_;
};
} // namespace frostbite2D

View File

@@ -1,12 +1,43 @@
#pragma once
#include "GameDataLoader.h"
#include "GameMap.h"
#include <frostbite2D/2d/actor.h>
#include <vector>
namespace frostbite2D {
class GameTown : public Actor {
class GameTown : public Actor {
public:
struct MapInfo {
int areaId = -1;
RefPtr<GameMap> map;
std::string type;
Vec2 generatePos = Vec2(-1.0f, -1.0f);
};
GameTown();
~GameTown();
~GameTown() override = default;
bool Init(int index, const std::string& townPath);
void AddCharacter(RefPtr<Actor> actor, int areaIndex = -2);
int GetCurAreaIndex() const { return curMapIndex_; }
RefPtr<GameMap> GetArea(int index) const;
const std::vector<MapInfo>& GetAreas() const { return mapList_; }
void Update(float deltaTime) override;
private:
std::string name_;
std::string enteringTitle_;
std::string enteringCutscene_;
int needQuestId_ = -1;
int needLevel_ = -1;
int sariaRoomId_ = -1;
Vec2 sariaRoomPos_ = Vec2(-1.0f, -1.0f);
std::vector<MapInfo> mapList_;
int curMapIndex_ = -1;
};
} // namespace frostbite2D

View File

@@ -1,18 +1,32 @@
#pragma once
#include "GameTown.h"
#include <frostbite2D/scene/scene.h>
#include <map>
#include "GameTown.h"
namespace frostbite2D {
class GameWorld : public Scene {
private:
/**城镇Map */
std::map<int, RefPtr<GameTown>> m_TownMap;
public:
GameWorld();
~GameWorld();
~GameWorld() override = default;
void onEnter() override;
void onExit() override;
void AddCharacter(RefPtr<Actor> actor, int townId);
void MoveCharacter(RefPtr<Actor> actor, int townId, int area);
static GameWorld* GetWorld();
private:
bool InitWorld();
std::map<int, std::string> townPathMap_;
std::map<int, RefPtr<GameTown>> townMap_;
RefPtr<Actor> mainActor_;
int curTown_ = -1;
bool initialized_ = false;
};
} // namespace frostbite2D