Wire engine services into game skeleton

This commit is contained in:
2026-06-09 21:47:07 +08:00
parent 562f9618c4
commit 45a8712b00
11 changed files with 381 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
#include "stage_map_resource.h"
#include <frostbite2D/resource/asset.h>
#include <frostbite2D/resource/pvf_archive.h>
#include <frostbite2D/resource/script_parser.h>
#include <SDL2/SDL.h>
namespace ns_game {
namespace {
std::string assetFallbackPath(const std::string& path) {
if (path.rfind("assets/", 0) == 0) {
return path;
}
return "assets/" + path;
}
bool isLikelyPvfScript(const frostbite2D::RawData& rawData) {
if (!rawData.data || rawData.size < 7) {
return false;
}
const auto opcode = static_cast<unsigned char>(rawData.data[2]);
switch (static_cast<frostbite2D::ScriptOpcode>(opcode)) {
case frostbite2D::ScriptOpcode::Integer:
case frostbite2D::ScriptOpcode::Float:
case frostbite2D::ScriptOpcode::StringRef5:
case frostbite2D::ScriptOpcode::StringRef6:
case frostbite2D::ScriptOpcode::StringRef7:
case frostbite2D::ScriptOpcode::StringRef8:
case frostbite2D::ScriptOpcode::ExtendedString9:
case frostbite2D::ScriptOpcode::ExtendedString10:
return true;
default:
return false;
}
}
} // namespace
std::optional<StageMapResource> LoadStageMapResource(const std::string& path) {
frostbite2D::Asset& asset = frostbite2D::Asset::get();
if (auto content = asset.readFileToString(path)) {
StageMapResource resource;
resource.source = StageMapResourceSource::AssetText;
resource.path = path;
resource.text = *content;
return resource;
}
const std::string fallbackPath = assetFallbackPath(path);
if (fallbackPath != path) {
if (auto content = asset.readFileToString(fallbackPath)) {
StageMapResource resource;
resource.source = StageMapResourceSource::AssetText;
resource.path = fallbackPath;
resource.text = *content;
return resource;
}
}
frostbite2D::PvfArchive& pvf = frostbite2D::PvfArchive::get();
if (pvf.isOpen()) {
if (auto rawData = pvf.getFileRawData(path);
rawData && isLikelyPvfScript(*rawData)) {
frostbite2D::ScriptParser parser(*rawData, path);
if (parser.isValid()) {
StageMapResource resource;
resource.source = StageMapResourceSource::PvfBinaryScript;
resource.path = path;
for (const frostbite2D::ScriptValue& value : parser.parseAll()) {
resource.scriptValues.push_back(value.toString());
}
return resource;
}
}
if (auto content = pvf.getFileContent(path)) {
StageMapResource resource;
resource.source = StageMapResourceSource::PvfText;
resource.path = path;
resource.text = *content;
return resource;
}
}
SDL_Log("StageMapResource: map not found: %s", path.c_str());
return std::nullopt;
}
} // namespace ns_game
+29
View File
@@ -0,0 +1,29 @@
#pragma once
#include <optional>
#include <string>
#include <vector>
namespace ns_game {
enum class StageMapResourceSource {
None,
AssetText,
PvfText,
PvfBinaryScript
};
struct StageMapResource {
StageMapResourceSource source = StageMapResourceSource::None;
std::string path;
std::string text;
std::vector<std::string> scriptValues;
bool hasContent() const {
return !text.empty() || !scriptValues.empty();
}
};
std::optional<StageMapResource> LoadStageMapResource(const std::string& path);
} // namespace ns_game
+13
View File
@@ -1,8 +1,21 @@
#include "level_definition.h"
#include "stage_map_resource.h"
#include <SDL2/SDL.h>
namespace ns_game {
LevelDefinition CreateWhiteboxLevel() {
if (auto mapResource = LoadStageMapResource("map/stage_01.map")) {
SDL_Log("CreateWhiteboxLevel: loaded %s map resource: %s",
mapResource->source == StageMapResourceSource::AssetText ? "asset"
: mapResource->source == StageMapResourceSource::PvfText ? "pvf-text"
: mapResource->source == StageMapResourceSource::PvfBinaryScript
? "pvf-script"
: "unknown",
mapResource->path.c_str());
}
LevelDefinition level;
level.worldWidth = 3200.0f;
level.worldHeight = 720.0f;