1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#include "game.h"
#include "transform_system.h"
#include "animation_system.h"
#include "character_system.h"
#include "camera_system.h"
#include "script_system.h"
int Game::emplaceSprite(std::string alias) {
int id;
if (idsToReuse_.empty()) {
id = sprites_.size();
sprites_.emplace_back();
sprites_.back().alias = alias;
} else {
id = idsToReuse_.front();
idsToReuse_.pop_front();
sprites_[id] = Sprite();
sprites_[id].alias = alias;
}
spriteIds_.insert(id);
spritesByAlias_[alias] = id;
return id;
}
void Game::destroySprite(int id) {
for (std::unique_ptr<System>& system : systems_) {
system->destroySprite(id);
}
spriteIds_.erase(id);
idsToReuse_.push_back(id);
spritesByAlias_.erase(sprites_.at(id).alias);
}
void Game::loadMap(std::string filename) {
// Clear out non-persistent sprites.
std::list<int> spritesToDelete;
for (int spriteId : spriteIds_) {
Sprite& sprite = sprites_.at(spriteId);
if (!sprite.persistent) {
spritesToDelete.push_back(spriteId);
}
}
for (int spriteId : spritesToDelete) {
destroySprite(spriteId);
}
// Load the new map.
map_ = std::make_unique<Map>(filename);
std::vector<std::tuple<int, std::string>> backgroundScripts;
for (const Prototype& p : map_->getPrototypes()) {
if (spritesByAlias_.count(p.name)) continue;
int spriteId = emplaceSprite(p.name);
getSystem<TransformSystem>().initSprite(spriteId, p.pos, p.masked ? SpriteLayer::Mask : SpriteLayer::Normal);
getSystem<TransformSystem>().setUpCollision(spriteId, p.collisionOffset, p.collisionSize, true);
if (!p.animationFilename.empty()) {
getSystem<AnimationSystem>().initSprite(spriteId, p.animationFilename);
getSprite(spriteId).normallyHasShadow = p.shadow;
if (!p.animName.empty()) {
getSystem<AnimationSystem>().setSpriteAnimation(spriteId, p.animName);
}
getSystem<AnimationSystem>().setSpriteDirection(spriteId, p.dir);
}
getSprite(spriteId).interactionScript = p.interactionScript;
if (p.movementSpeed != -1) {
getSystem<CharacterSystem>().initSprite(spriteId, p.movementSpeed);
if (p.wander) {
getSprite(spriteId).behaviourType = BehaviourType::Wander;
}
if (!p.bumpPlayerScript.empty()) {
getSprite(spriteId).bumpPlayerScript = p.bumpPlayerScript;
}
}
if (!p.enclosureZone.empty()) {
getSprite(spriteId).enclosureZone = p.enclosureZone;
}
if (p.mirrorType != MirrorType::None) {
getSprite(spriteId).mirrorType = p.mirrorType;
getSprite(spriteId).mirrorAxis = p.mirrorAxis;
getSprite(spriteId).mirroredSpriteId = getSpriteByAlias(p.spriteToMirror);
}
if (!p.backgroundScript.empty()) {
backgroundScripts.push_back({spriteId, p.backgroundScript});
}
getSprite(spriteId).floating = p.floating;
}
for (const Trigger& t : map_->getTriggers()) {
if (spritesByAlias_.count(t.name)) continue;
int spriteId = emplaceSprite(t.name);
getSystem<TransformSystem>().initSprite(spriteId, t.pos);
getSystem<TransformSystem>().setUpCollision(spriteId, {0, 0}, t.size, false);
getSprite(spriteId).walkthroughScript = t.script;
}
// Run the map's init script.
if (getSystem<ScriptSystem>().mapHasScript(map_->getName(), "init")) {
getSystem<ScriptSystem>().runScript(map_->getName(), "init");
}
// Run any background scripts associated with new sprites.
for (auto& [spriteId, scriptName] : backgroundScripts) {
getSystem<ScriptSystem>().runScript(map_->getName(), scriptName, spriteId);
}
}
|