diff options
-rw-r--r-- | res/maps/map2.tmx | 5 | ||||
-rw-r--r-- | res/scripts/common.lua | 24 | ||||
-rw-r--r-- | res/scripts/map2.lua | 9 | ||||
-rw-r--r-- | res/sprites/lightning.png | bin | 0 -> 11405 bytes | |||
-rw-r--r-- | res/sprites/lightning_anim.txt | 3 | ||||
-rw-r--r-- | res/sprites/lightning_frames.txt | 14 | ||||
-rw-r--r-- | res/sprites/lucas_anim.txt | 3 | ||||
-rw-r--r-- | src/animation_system.cpp | 13 | ||||
-rw-r--r-- | src/camera_system.cpp | 6 | ||||
-rw-r--r-- | src/camera_system.h | 2 | ||||
-rw-r--r-- | src/character_system.cpp | 7 | ||||
-rw-r--r-- | src/character_system.h | 2 | ||||
-rw-r--r-- | src/consts.h | 2 | ||||
-rw-r--r-- | src/game.cpp | 12 | ||||
-rw-r--r-- | src/game.h | 7 | ||||
-rw-r--r-- | src/main.cpp | 2 | ||||
-rw-r--r-- | src/renderer.cpp | 34 | ||||
-rw-r--r-- | src/renderer.h | 4 | ||||
-rw-r--r-- | src/script_system.cpp | 33 | ||||
-rw-r--r-- | src/sprite.h | 8 | ||||
-rw-r--r-- | src/system.h | 2 | ||||
-rw-r--r-- | src/transform_system.cpp | 22 | ||||
-rw-r--r-- | src/transform_system.h | 12 |
23 files changed, 190 insertions, 36 deletions
diff --git a/res/maps/map2.tmx b/res/maps/map2.tmx index 6316ef5..f6d6dd2 100644 --- a/res/maps/map2.tmx +++ b/res/maps/map2.tmx | |||
@@ -1,5 +1,5 @@ | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <map version="1.4" tiledversion="1.4.3" orientation="orthogonal" renderorder="right-down" width="64" height="64" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="6"> | 2 | <map version="1.4" tiledversion="1.4.3" orientation="orthogonal" renderorder="right-down" width="64" height="64" tilewidth="16" tileheight="16" infinite="0" nextlayerid="3" nextobjectid="7"> |
3 | <tileset firstgid="1" name="fromRom" tilewidth="16" tileheight="16" tilecount="180" columns="10"> | 3 | <tileset firstgid="1" name="fromRom" tilewidth="16" tileheight="16" tilecount="180" columns="10"> |
4 | <image source="map2_tiles.png" width="160" height="288"/> | 4 | <image source="map2_tiles.png" width="160" height="288"/> |
5 | <tile id="61"> | 5 | <tile id="61"> |
@@ -657,6 +657,9 @@ | |||
657 | </properties> | 657 | </properties> |
658 | <point/> | 658 | <point/> |
659 | </object> | 659 | </object> |
660 | <object id="6" name="debugWarp_mailboxes" type="warp" x="598.667" y="420.667"> | ||
661 | <point/> | ||
662 | </object> | ||
660 | </objectgroup> | 663 | </objectgroup> |
661 | <layer id="1" name="Layer 0" width="64" height="64"> | 664 | <layer id="1" name="Layer 0" width="64" height="64"> |
662 | <data encoding="csv"> | 665 | <data encoding="csv"> |
diff --git a/res/scripts/common.lua b/res/scripts/common.lua index 3db1b26..04f6c5a 100644 --- a/res/scripts/common.lua +++ b/res/scripts/common.lua | |||
@@ -25,6 +25,11 @@ CharacterState = { | |||
25 | RUNNING = 3 | 25 | RUNNING = 3 |
26 | } | 26 | } |
27 | 27 | ||
28 | SpriteLayer = { | ||
29 | NORMAL = 0, | ||
30 | ABOVE = 1 | ||
31 | } | ||
32 | |||
28 | function StartCutscene() | 33 | function StartCutscene() |
29 | local playerId = getPlayerSprite() | 34 | local playerId = getPlayerSprite() |
30 | local playerSprite = getSprite(playerId) | 35 | local playerSprite = getSprite(playerId) |
@@ -59,6 +64,12 @@ function HideCutsceneBars() | |||
59 | playerSprite.controllable = true | 64 | playerSprite.controllable = true |
60 | end | 65 | end |
61 | 66 | ||
67 | function GetPosition(spriteName) | ||
68 | local spriteId = getSpriteByAlias(spriteName) | ||
69 | local sprite = getSprite(spriteId) | ||
70 | return sprite.loc | ||
71 | end | ||
72 | |||
62 | function SetDirection(spriteName, dir) | 73 | function SetDirection(spriteName, dir) |
63 | local spriteId = getSpriteByAlias(spriteName) | 74 | local spriteId = getSpriteByAlias(spriteName) |
64 | animation():setSpriteDirection(spriteId, dir) | 75 | animation():setSpriteDirection(spriteId, dir) |
@@ -137,3 +148,16 @@ function ChangeMap(map, warp) | |||
137 | RemoveFadeout(150) | 148 | RemoveFadeout(150) |
138 | newPlayerSprite.controllable = true | 149 | newPlayerSprite.controllable = true |
139 | end | 150 | end |
151 | |||
152 | function CreateAnimatedSpriteAtPosition(alias, character, x, y, animName, direction, layer) | ||
153 | local spriteId = emplaceSprite(alias) | ||
154 | transform():initSprite(spriteId, x, y, layer) | ||
155 | animation():initSprite(spriteId, "../res/sprites/" .. character .. "_anim.txt") | ||
156 | animation():setSpriteDirection(spriteId, direction) | ||
157 | animation():setSpriteAnimation(spriteId, animName) | ||
158 | end | ||
159 | |||
160 | function DestroyNamedSprite(alias) | ||
161 | local spriteId = getSpriteByAlias(alias) | ||
162 | destroySprite(spriteId) | ||
163 | end | ||
diff --git a/res/scripts/map2.lua b/res/scripts/map2.lua index 3bc9eff..1ef1235 100644 --- a/res/scripts/map2.lua +++ b/res/scripts/map2.lua | |||
@@ -29,8 +29,15 @@ function map2.mailbox_lightning() | |||
29 | DisplayMessage("* ...?", "", SpeakerType.NONE) | 29 | DisplayMessage("* ...?", "", SpeakerType.NONE) |
30 | WaitForEndOfMessage() | 30 | WaitForEndOfMessage() |
31 | 31 | ||
32 | local lucasPos = GetPosition("lucas") | ||
33 | CreateAnimatedSpriteAtPosition("lightning_from_mailbox", "lightning", lucasPos:x() + 56, lucasPos:y() - 72, "strike", Direction.DOWN_LEFT, SpriteLayer.ABOVE) | ||
34 | |||
32 | SetDirection("lucas", Direction.DOWN) | 35 | SetDirection("lucas", Direction.DOWN) |
33 | SetAnimation("lucas", "electrocute!") | 36 | SetAnimation("lucas", "lightning_electrocute!") |
37 | WaitForAnimation("lucas") | ||
38 | |||
39 | DestroyNamedSprite("lightning_from_mailbox") | ||
40 | SetAnimation("lucas", "lightning_collapse!") | ||
34 | WaitForAnimation("lucas") | 41 | WaitForAnimation("lucas") |
35 | 42 | ||
36 | DisplayMessage("* It was lightning.\n\fAh.", "", SpeakerType.NONE) | 43 | DisplayMessage("* It was lightning.\n\fAh.", "", SpeakerType.NONE) |
diff --git a/res/sprites/lightning.png b/res/sprites/lightning.png new file mode 100644 index 0000000..c456338 --- /dev/null +++ b/res/sprites/lightning.png | |||
Binary files differ | |||
diff --git a/res/sprites/lightning_anim.txt b/res/sprites/lightning_anim.txt new file mode 100644 index 0000000..bafb68d --- /dev/null +++ b/res/sprites/lightning_anim.txt | |||
@@ -0,0 +1,3 @@ | |||
1 | ../res/sprites/lightning.png | ||
2 | ../res/sprites/lightning_frames.txt | ||
3 | strike[down_left]: 0,1,3,2 \ No newline at end of file | ||
diff --git a/res/sprites/lightning_frames.txt b/res/sprites/lightning_frames.txt new file mode 100644 index 0000000..4a8fee5 --- /dev/null +++ b/res/sprites/lightning_frames.txt | |||
@@ -0,0 +1,14 @@ | |||
1 | 160,128 cell size | ||
2 | 10 frames per row | ||
3 | 10 frames | ||
4 | |||
5 | 112,128,60,56 | ||
6 | 128,128,72,64 | ||
7 | 116,128,64,64 | ||
8 | 116,128,64,64 | ||
9 | 88,96,40,96 | ||
10 | 88,96,40,96 | ||
11 | 80,96,40,96 | ||
12 | 160,32,123,83 | ||
13 | 160,32,123,91 | ||
14 | 160,32,123,91 | ||
diff --git a/res/sprites/lucas_anim.txt b/res/sprites/lucas_anim.txt index 12a373e..d03e213 100644 --- a/res/sprites/lucas_anim.txt +++ b/res/sprites/lucas_anim.txt | |||
@@ -32,4 +32,5 @@ run[up]: 71,79,87,95 | |||
32 | run[up_right]: 72,80,88,96 | 32 | run[up_right]: 72,80,88,96 |
33 | run[right]: 73,81,89,97 | 33 | run[right]: 73,81,89,97 |
34 | run[down_right]: 74,82,90,98 | 34 | run[down_right]: 74,82,90,98 |
35 | electrocute![down]: 116,117,118,116,117,118,116,117,118,119,120,121,122 \ No newline at end of file | 35 | lightning_electrocute![down]: 116,117,118,116,117,118,116,117,118,116 |
36 | lightning_collapse![down]: 119,120,121,122 \ No newline at end of file | ||
diff --git a/src/animation_system.cpp b/src/animation_system.cpp index 3f3f22a..c43d0ca 100644 --- a/src/animation_system.cpp +++ b/src/animation_system.cpp | |||
@@ -65,7 +65,7 @@ void AnimationSystem::initSprite(int spriteId, std::string_view filename) { | |||
65 | std::string animLine; | 65 | std::string animLine; |
66 | std::getline(datafile, animLine); // blank | 66 | std::getline(datafile, animLine); // blank |
67 | while (std::getline(datafile, animLine)) { | 67 | while (std::getline(datafile, animLine)) { |
68 | std::regex re(R"(([a-z!]+)\[([a-z_]+)\]: ([0-9,]+))"); | 68 | std::regex re(R"(([a-z!_]+)\[([a-z_]+)\]: ([0-9,]+))"); |
69 | std::smatch m; | 69 | std::smatch m; |
70 | std::regex_match(animLine, m, re); | 70 | std::regex_match(animLine, m, re); |
71 | 71 | ||
@@ -96,14 +96,13 @@ void AnimationSystem::tick(double dt) { | |||
96 | for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { | 96 | for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { |
97 | if (sprite.isAnimated && !sprite.animFinished) { | 97 | if (sprite.isAnimated && !sprite.animFinished) { |
98 | sprite.animationFrame++; | 98 | sprite.animationFrame++; |
99 | if (sprite.animations[sprite.animationId].looping) { | 99 | |
100 | if (sprite.animationFrame >= sprite.animations[sprite.animationId].frameIndices.size()) { | 100 | if (sprite.animationFrame >= sprite.animations[sprite.animationId].frameIndices.size()) { |
101 | if (sprite.animations[sprite.animationId].looping) { | ||
101 | sprite.animationFrame = 0; | 102 | sprite.animationFrame = 0; |
102 | } | 103 | } else { |
103 | } else { | ||
104 | if (sprite.animationFrame >= sprite.animations[sprite.animationId].frameIndices.size() - 1) { | ||
105 | sprite.animationFrame = sprite.animations[sprite.animationId].frameIndices.size() - 1; | ||
106 | sprite.animFinished = true; | 104 | sprite.animFinished = true; |
105 | sprite.animationFrame = sprite.animations[sprite.animationId].frameIndices.size() - 1; | ||
107 | } | 106 | } |
108 | } | 107 | } |
109 | } | 108 | } |
diff --git a/src/camera_system.cpp b/src/camera_system.cpp index a6e8fca..b7627b1 100644 --- a/src/camera_system.cpp +++ b/src/camera_system.cpp | |||
@@ -26,6 +26,12 @@ void CameraSystem::tick(double dt) { | |||
26 | } | 26 | } |
27 | } | 27 | } |
28 | 28 | ||
29 | void CameraSystem::destroySprite(int spriteId) { | ||
30 | if (followingSprite_ == spriteId) { | ||
31 | followingSprite_ = -1; | ||
32 | } | ||
33 | } | ||
34 | |||
29 | void CameraSystem::clearSpriteCache() { | 35 | void CameraSystem::clearSpriteCache() { |
30 | followingSprite_ = -1; | 36 | followingSprite_ = -1; |
31 | } | 37 | } |
diff --git a/src/camera_system.h b/src/camera_system.h index 77d813f..37ff8b4 100644 --- a/src/camera_system.h +++ b/src/camera_system.h | |||
@@ -26,6 +26,8 @@ public: | |||
26 | 26 | ||
27 | void tick(double dt) override; | 27 | void tick(double dt) override; |
28 | 28 | ||
29 | void destroySprite(int spriteId) override; | ||
30 | |||
29 | void clearSpriteCache() override; | 31 | void clearSpriteCache() override; |
30 | 32 | ||
31 | private: | 33 | private: |
diff --git a/src/character_system.cpp b/src/character_system.cpp index a0572b0..d0c416e 100644 --- a/src/character_system.cpp +++ b/src/character_system.cpp | |||
@@ -260,6 +260,13 @@ void CharacterSystem::halt(int spriteId) { | |||
260 | } | 260 | } |
261 | } | 261 | } |
262 | 262 | ||
263 | void CharacterSystem::destroySprite(int spriteId) { | ||
264 | Sprite& sprite = game_.getSprite(spriteId); | ||
265 | if (sprite.runningSfxChannel != -1) { | ||
266 | stopRunningSound(sprite); | ||
267 | } | ||
268 | } | ||
269 | |||
263 | void CharacterSystem::clearSpriteCache() { | 270 | void CharacterSystem::clearSpriteCache() { |
264 | for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { | 271 | for (Sprite& sprite : game_.getSprites() | game_.spriteView()) { |
265 | if (sprite.runningSfxChannel != -1) { | 272 | if (sprite.runningSfxChannel != -1) { |
diff --git a/src/character_system.h b/src/character_system.h index c6d4e6d..72a2585 100644 --- a/src/character_system.h +++ b/src/character_system.h | |||
@@ -35,6 +35,8 @@ public: | |||
35 | 35 | ||
36 | void halt(int spriteId); | 36 | void halt(int spriteId); |
37 | 37 | ||
38 | void destroySprite(int spriteId) override; | ||
39 | |||
38 | void clearSpriteCache() override; | 40 | void clearSpriteCache() override; |
39 | 41 | ||
40 | private: | 42 | private: |
diff --git a/src/consts.h b/src/consts.h index 12b9e8f..38e0ef8 100644 --- a/src/consts.h +++ b/src/consts.h | |||
@@ -12,4 +12,6 @@ const int PARTY_FRAME_DELAY = 10;// / MOVEMENT_SPEED; | |||
12 | 12 | ||
13 | const int MESSAGE_TEXT_WIDTH = 196; | 13 | const int MESSAGE_TEXT_WIDTH = 196; |
14 | 14 | ||
15 | const int NUM_SPRITE_LAYERS = 2; | ||
16 | |||
15 | #endif /* end of include guard: CONSTS_H_9561E49C */ | 17 | #endif /* end of include guard: CONSTS_H_9561E49C */ |
diff --git a/src/game.cpp b/src/game.cpp index d1e5b8e..b7ca869 100644 --- a/src/game.cpp +++ b/src/game.cpp | |||
@@ -7,11 +7,21 @@ | |||
7 | int Game::emplaceSprite(std::string alias) { | 7 | int Game::emplaceSprite(std::string alias) { |
8 | int id = sprites_.size(); | 8 | int id = sprites_.size(); |
9 | sprites_.emplace_back(); | 9 | sprites_.emplace_back(); |
10 | spriteIds_.push_back(id); | 10 | sprites_.back().alias = alias; |
11 | spriteIds_.insert(id); | ||
11 | spritesByAlias_[alias] = id; | 12 | spritesByAlias_[alias] = id; |
12 | return id; | 13 | return id; |
13 | } | 14 | } |
14 | 15 | ||
16 | void Game::destroySprite(int id) { | ||
17 | for (std::unique_ptr<System>& system : systems_) { | ||
18 | system->destroySprite(id); | ||
19 | } | ||
20 | |||
21 | spriteIds_.erase(id); | ||
22 | spritesByAlias_.erase(sprites_.at(id).alias); | ||
23 | } | ||
24 | |||
15 | void Game::clearSprites() { | 25 | void Game::clearSprites() { |
16 | for (std::unique_ptr<System>& system : systems_) { | 26 | for (std::unique_ptr<System>& system : systems_) { |
17 | system->clearSpriteCache(); | 27 | system->clearSpriteCache(); |
diff --git a/src/game.h b/src/game.h index 84114ca..c7926bf 100644 --- a/src/game.h +++ b/src/game.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <vector> | 6 | #include <vector> |
7 | #include <memory> | 7 | #include <memory> |
8 | #include <map> | 8 | #include <map> |
9 | #include <set> | ||
9 | #include "sprite.h" | 10 | #include "sprite.h" |
10 | #include "map.h" | 11 | #include "map.h" |
11 | #include "consts.h" | 12 | #include "consts.h" |
@@ -45,6 +46,8 @@ public: | |||
45 | 46 | ||
46 | int emplaceSprite(std::string alias); | 47 | int emplaceSprite(std::string alias); |
47 | 48 | ||
49 | void destroySprite(int id); | ||
50 | |||
48 | const Sprite& getSprite(int id) const { | 51 | const Sprite& getSprite(int id) const { |
49 | return sprites_.at(id); | 52 | return sprites_.at(id); |
50 | } | 53 | } |
@@ -53,7 +56,7 @@ public: | |||
53 | return sprites_.at(id); | 56 | return sprites_.at(id); |
54 | } | 57 | } |
55 | 58 | ||
56 | const std::vector<int>& getSprites() { | 59 | const std::set<int>& getSprites() { |
57 | return spriteIds_; | 60 | return spriteIds_; |
58 | } | 61 | } |
59 | 62 | ||
@@ -93,7 +96,7 @@ private: | |||
93 | std::list<std::unique_ptr<System>> systems_; | 96 | std::list<std::unique_ptr<System>> systems_; |
94 | std::map<SystemKey, System*> systemByKey_; | 97 | std::map<SystemKey, System*> systemByKey_; |
95 | 98 | ||
96 | std::vector<int> spriteIds_; | 99 | std::set<int> spriteIds_; |
97 | std::vector<Sprite> sprites_; | 100 | std::vector<Sprite> sprites_; |
98 | std::map<std::string, int> spritesByAlias_; | 101 | std::map<std::string, int> spritesByAlias_; |
99 | std::unique_ptr<Map> map_; | 102 | std::unique_ptr<Map> map_; |
diff --git a/src/main.cpp b/src/main.cpp index c9bfaf1..592b3be 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
@@ -22,7 +22,7 @@ void loop(Renderer& renderer) { | |||
22 | game.emplaceSystem<CameraSystem>(); | 22 | game.emplaceSystem<CameraSystem>(); |
23 | game.emplaceSystem<MessageSystem>(); | 23 | game.emplaceSystem<MessageSystem>(); |
24 | 24 | ||
25 | game.loadMap("map1", "spawn", Direction::down); | 25 | game.loadMap("map2", "debugWarp_mailboxes", Direction::down); |
26 | game.getSprite(game.getSpriteByAlias("lucas")).controllable = true; | 26 | game.getSprite(game.getSpriteByAlias("lucas")).controllable = true; |
27 | 27 | ||
28 | renderer.render(game); | 28 | renderer.render(game); |
diff --git a/src/renderer.cpp b/src/renderer.cpp index a7169e9..0e5f8f1 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp | |||
@@ -94,6 +94,21 @@ texture_ptr Renderer::renderMapLayer(const Map& map, int layer) { | |||
94 | return canvas; | 94 | return canvas; |
95 | } | 95 | } |
96 | 96 | ||
97 | void Renderer::renderSprite(const Sprite& sprite) { | ||
98 | if (sprite.isAnimated) { | ||
99 | if (sprite.hasShadow) { | ||
100 | int shadowTexId = loadImageFromFile("../res/shadow.png"); | ||
101 | const SDL_Rect shadowDest { sprite.loc.x() - 8, sprite.loc.y() - 8, 16, 8 }; | ||
102 | SDL_RenderCopy(ren_.get(), textures_.at(shadowTexId).get(), nullptr, &shadowDest); | ||
103 | } | ||
104 | |||
105 | const SpriteFrame& frame = sprite.frames.at(sprite.animations.at(sprite.animationId).frameIndices.at(sprite.animationFrame)); | ||
106 | const SDL_Rect& src = frame.srcRect; | ||
107 | SDL_Rect dest { sprite.loc.x() - frame.center.x(), sprite.loc.y() - frame.center.y(), frame.size.w(), frame.size.h() }; | ||
108 | SDL_RenderCopy(ren_.get(), textures_.at(loadImageFromFile(sprite.spritesheet)).get(), &src, &dest); | ||
109 | } | ||
110 | } | ||
111 | |||
97 | void Renderer::render(Game& game) { | 112 | void Renderer::render(Game& game) { |
98 | if (cachedMapName_ != game.getMap().getName()) { | 113 | if (cachedMapName_ != game.getMap().getName()) { |
99 | cachedMapName_ = game.getMap().getName(); | 114 | cachedMapName_ = game.getMap().getName(); |
@@ -122,23 +137,16 @@ void Renderer::render(Game& game) { | |||
122 | 137 | ||
123 | SDL_RenderCopy(ren_.get(), renLay1_.get(), nullptr, nullptr); | 138 | SDL_RenderCopy(ren_.get(), renLay1_.get(), nullptr, nullptr); |
124 | 139 | ||
125 | int shadowTexId = loadImageFromFile("../res/shadow.png"); | 140 | for (const Sprite& sprite : game.getSystem<TransformSystem>().getSpritesByY(SpriteLayer::Normal) | game.spriteView()) { |
126 | for (const Sprite& sprite : game.getSystem<TransformSystem>().getSpritesByY() | game.spriteView()) { | 141 | renderSprite(sprite); |
127 | if (sprite.isAnimated) { | ||
128 | if (sprite.hasShadow) { | ||
129 | const SDL_Rect shadowDest { sprite.loc.x() - 8, sprite.loc.y() - 8, 16, 8 }; | ||
130 | SDL_RenderCopy(ren_.get(), textures_.at(shadowTexId).get(), nullptr, &shadowDest); | ||
131 | } | ||
132 | |||
133 | const SpriteFrame& frame = sprite.frames.at(sprite.animations.at(sprite.animationId).frameIndices.at(sprite.animationFrame)); | ||
134 | const SDL_Rect& src = frame.srcRect; | ||
135 | SDL_Rect dest { sprite.loc.x() - frame.center.x(), sprite.loc.y() - frame.center.y(), frame.size.w(), frame.size.h() }; | ||
136 | SDL_RenderCopy(ren_.get(), textures_.at(loadImageFromFile(sprite.spritesheet)).get(), &src, &dest); | ||
137 | } | ||
138 | } | 142 | } |
139 | 143 | ||
140 | SDL_RenderCopy(ren_.get(), renLay0_.get(), nullptr, nullptr); | 144 | SDL_RenderCopy(ren_.get(), renLay0_.get(), nullptr, nullptr); |
141 | 145 | ||
146 | for (const Sprite& sprite : game.getSystem<TransformSystem>().getSpritesByY(SpriteLayer::Above) | game.spriteView()) { | ||
147 | renderSprite(sprite); | ||
148 | } | ||
149 | |||
142 | SDL_Rect cameraField { | 150 | SDL_Rect cameraField { |
143 | game.getSystem<CameraSystem>().getCameraPosition().x(), | 151 | game.getSystem<CameraSystem>().getCameraPosition().x(), |
144 | game.getSystem<CameraSystem>().getCameraPosition().y(), | 152 | game.getSystem<CameraSystem>().getCameraPosition().y(), |
diff --git a/src/renderer.h b/src/renderer.h index 1684a0c..54dae1c 100644 --- a/src/renderer.h +++ b/src/renderer.h | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | class Game; | 12 | class Game; |
13 | class Map; | 13 | class Map; |
14 | class Sprite; | ||
14 | 15 | ||
15 | class sdl_error : public std::logic_error { | 16 | class sdl_error : public std::logic_error { |
16 | public: | 17 | public: |
@@ -133,6 +134,9 @@ private: | |||
133 | std::vector<texture_ptr> textures_; | 134 | std::vector<texture_ptr> textures_; |
134 | std::map<std::string, int> filenameToTexId_; | 135 | std::map<std::string, int> filenameToTexId_; |
135 | 136 | ||
137 | // Sprite rendering | ||
138 | void renderSprite(const Sprite& sprite); | ||
139 | |||
136 | // Map rendering | 140 | // Map rendering |
137 | texture_ptr renderMapLayer(const Map& map, int layer); | 141 | texture_ptr renderMapLayer(const Map& map, int layer); |
138 | 142 | ||
diff --git a/src/script_system.cpp b/src/script_system.cpp index 3f89290..08d66d4 100644 --- a/src/script_system.cpp +++ b/src/script_system.cpp | |||
@@ -4,6 +4,8 @@ | |||
4 | #include "message_system.h" | 4 | #include "message_system.h" |
5 | #include "animation_system.h" | 5 | #include "animation_system.h" |
6 | #include "character_system.h" | 6 | #include "character_system.h" |
7 | #include "transform_system.h" | ||
8 | #include "vector.h" | ||
7 | 9 | ||
8 | ScriptSystem::ScriptSystem(Game& game) : game_(game) { | 10 | ScriptSystem::ScriptSystem(Game& game) : game_(game) { |
9 | engine_.open_libraries( | 11 | engine_.open_libraries( |
@@ -11,8 +13,14 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { | |||
11 | sol::lib::coroutine, | 13 | sol::lib::coroutine, |
12 | sol::lib::math); | 14 | sol::lib::math); |
13 | 15 | ||
16 | engine_.new_usertype<vec2i>( | ||
17 | "vec2i", | ||
18 | "x", [] (const vec2i& v) { return v.x(); }, | ||
19 | "y", [] (const vec2i& v) { return v.y(); }); | ||
20 | |||
14 | engine_.new_usertype<Sprite>( | 21 | engine_.new_usertype<Sprite>( |
15 | "sprite", | 22 | "sprite", |
23 | "loc", &Sprite::loc, | ||
16 | "dir", &Sprite::dir, | 24 | "dir", &Sprite::dir, |
17 | "followers", &Sprite::followers, | 25 | "followers", &Sprite::followers, |
18 | "characterState", &Sprite::characterState, | 26 | "characterState", &Sprite::characterState, |
@@ -29,6 +37,7 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { | |||
29 | 37 | ||
30 | engine_.new_usertype<AnimationSystem>( | 38 | engine_.new_usertype<AnimationSystem>( |
31 | "animation", | 39 | "animation", |
40 | "initSprite", &AnimationSystem::initSprite, | ||
32 | "setSpriteAnimation", &AnimationSystem::setSpriteAnimation, | 41 | "setSpriteAnimation", &AnimationSystem::setSpriteAnimation, |
33 | "setSpriteDirection", &AnimationSystem::setSpriteDirection); | 42 | "setSpriteDirection", &AnimationSystem::setSpriteDirection); |
34 | 43 | ||
@@ -37,6 +46,12 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { | |||
37 | "startRunning", &CharacterSystem::startRunning, | 46 | "startRunning", &CharacterSystem::startRunning, |
38 | "halt", &CharacterSystem::halt); | 47 | "halt", &CharacterSystem::halt); |
39 | 48 | ||
49 | engine_.new_usertype<TransformSystem>( | ||
50 | "transform", | ||
51 | "initSprite", [] (TransformSystem& transform, int spriteId, int x, int y, SpriteLayer layer) { | ||
52 | transform.initSprite(spriteId, vec2i{x, y}, layer); | ||
53 | }); | ||
54 | |||
40 | engine_.new_usertype<Mixer>( | 55 | engine_.new_usertype<Mixer>( |
41 | "mixer", | 56 | "mixer", |
42 | "playSound", &Mixer::playSound, | 57 | "playSound", &Mixer::playSound, |
@@ -62,12 +77,30 @@ ScriptSystem::ScriptSystem(Game& game) : game_(game) { | |||
62 | }); | 77 | }); |
63 | 78 | ||
64 | engine_.set_function( | 79 | engine_.set_function( |
80 | "transform", | ||
81 | [&] () -> TransformSystem& { | ||
82 | return game_.getSystem<TransformSystem>(); | ||
83 | }); | ||
84 | |||
85 | engine_.set_function( | ||
65 | "mixer", | 86 | "mixer", |
66 | [&] () -> Mixer& { | 87 | [&] () -> Mixer& { |
67 | return game_.getMixer(); | 88 | return game_.getMixer(); |
68 | }); | 89 | }); |
69 | 90 | ||
70 | engine_.set_function( | 91 | engine_.set_function( |
92 | "emplaceSprite", | ||
93 | [&] (std::string alias) -> int { | ||
94 | return game_.emplaceSprite(alias); | ||
95 | }); | ||
96 | |||
97 | engine_.set_function( | ||
98 | "destroySprite", | ||
99 | [&] (int spriteId) { | ||
100 | game_.destroySprite(spriteId); | ||
101 | }); | ||
102 | |||
103 | engine_.set_function( | ||
71 | "getSpriteByAlias", | 104 | "getSpriteByAlias", |
72 | [&] (std::string alias) -> int { | 105 | [&] (std::string alias) -> int { |
73 | return game_.getSpriteByAlias(alias); | 106 | return game_.getSpriteByAlias(alias); |
diff --git a/src/sprite.h b/src/sprite.h index fcf7e1d..84b161f 100644 --- a/src/sprite.h +++ b/src/sprite.h | |||
@@ -10,6 +10,11 @@ | |||
10 | #include "vector.h" | 10 | #include "vector.h" |
11 | #include "step_type.h" | 11 | #include "step_type.h" |
12 | 12 | ||
13 | enum class SpriteLayer { | ||
14 | Normal, | ||
15 | Above | ||
16 | }; | ||
17 | |||
13 | struct SpriteFrame { | 18 | struct SpriteFrame { |
14 | SDL_Rect srcRect; | 19 | SDL_Rect srcRect; |
15 | vec2i center; | 20 | vec2i center; |
@@ -36,8 +41,11 @@ struct Movement { | |||
36 | class Sprite { | 41 | class Sprite { |
37 | public: | 42 | public: |
38 | 43 | ||
44 | std::string alias; | ||
45 | |||
39 | // Transform | 46 | // Transform |
40 | vec2i loc { 0, 0 }; | 47 | vec2i loc { 0, 0 }; |
48 | SpriteLayer layer = SpriteLayer::Normal; | ||
41 | bool collidable = false; | 49 | bool collidable = false; |
42 | bool solid = false; | 50 | bool solid = false; |
43 | vec2i collisionOffset; | 51 | vec2i collisionOffset; |
diff --git a/src/system.h b/src/system.h index 93b903e..3e84537 100644 --- a/src/system.h +++ b/src/system.h | |||
@@ -16,6 +16,8 @@ public: | |||
16 | 16 | ||
17 | virtual void tick(double dt) {} | 17 | virtual void tick(double dt) {} |
18 | 18 | ||
19 | virtual void destroySprite(int spriteId) {} | ||
20 | |||
19 | virtual void clearSpriteCache() {} | 21 | virtual void clearSpriteCache() {} |
20 | }; | 22 | }; |
21 | 23 | ||
diff --git a/src/transform_system.cpp b/src/transform_system.cpp index e5b0363..6e04d70 100644 --- a/src/transform_system.cpp +++ b/src/transform_system.cpp | |||
@@ -2,10 +2,11 @@ | |||
2 | #include "game.h" | 2 | #include "game.h" |
3 | #include "map.h" | 3 | #include "map.h" |
4 | 4 | ||
5 | void TransformSystem::initSprite(int spriteId, vec2i loc) { | 5 | void TransformSystem::initSprite(int spriteId, vec2i loc, SpriteLayer layer) { |
6 | Sprite& sprite = game_.getSprite(spriteId); | 6 | Sprite& sprite = game_.getSprite(spriteId); |
7 | sprite.loc = loc; | 7 | sprite.loc = loc; |
8 | spritesByY_.emplace(loc.y(), spriteId); | 8 | sprite.layer = layer; |
9 | spritesByY_[static_cast<size_t>(layer)].emplace(loc.y(), spriteId); | ||
9 | } | 10 | } |
10 | 11 | ||
11 | void TransformSystem::setUpCollision(int spriteId, vec2i offset, vec2i size, bool solid) { | 12 | void TransformSystem::setUpCollision(int spriteId, vec2i offset, vec2i size, bool solid) { |
@@ -26,11 +27,11 @@ void TransformSystem::moveSprite(int spriteId, vec2i newLoc) { | |||
26 | 27 | ||
27 | bool changedY = (sprite.loc.y() != newLoc.y()); | 28 | bool changedY = (sprite.loc.y() != newLoc.y()); |
28 | if (changedY) { | 29 | if (changedY) { |
29 | spritesByY_.erase(std::make_tuple(sprite.loc.y(), spriteId)); | 30 | spritesByY_[static_cast<size_t>(sprite.layer)].erase(std::make_tuple(sprite.loc.y(), spriteId)); |
30 | } | 31 | } |
31 | sprite.loc = newLoc; | 32 | sprite.loc = newLoc; |
32 | if (changedY) { | 33 | if (changedY) { |
33 | spritesByY_.emplace(newLoc.y(), spriteId); | 34 | spritesByY_[static_cast<size_t>(sprite.layer)].emplace(newLoc.y(), spriteId); |
34 | } | 35 | } |
35 | if (sprite.collidable) { | 36 | if (sprite.collidable) { |
36 | addCollidable(spriteId); | 37 | addCollidable(spriteId); |
@@ -216,8 +217,19 @@ void TransformSystem::removeCollidable(int spriteId) { | |||
216 | downCollidables_.erase({ colUL.y(), spriteId }); | 217 | downCollidables_.erase({ colUL.y(), spriteId }); |
217 | } | 218 | } |
218 | 219 | ||
220 | void TransformSystem::destroySprite(int spriteId) { | ||
221 | Sprite& sprite = game_.getSprite(spriteId); | ||
222 | spritesByY_[static_cast<size_t>(sprite.layer)].erase(std::make_tuple(sprite.loc.y(), spriteId)); | ||
223 | |||
224 | if (sprite.collidable) { | ||
225 | removeCollidable(spriteId); | ||
226 | } | ||
227 | } | ||
228 | |||
219 | void TransformSystem::clearSpriteCache() { | 229 | void TransformSystem::clearSpriteCache() { |
220 | spritesByY_.clear(); | 230 | for (auto& layer : spritesByY_) { |
231 | layer.clear(); | ||
232 | } | ||
221 | leftCollidables_.clear(); | 233 | leftCollidables_.clear(); |
222 | rightCollidables_.clear(); | 234 | rightCollidables_.clear(); |
223 | upCollidables_.clear(); | 235 | upCollidables_.clear(); |
diff --git a/src/transform_system.h b/src/transform_system.h index 46b6877..a21b93b 100644 --- a/src/transform_system.h +++ b/src/transform_system.h | |||
@@ -8,6 +8,8 @@ | |||
8 | #include "direction.h" | 8 | #include "direction.h" |
9 | #include "system.h" | 9 | #include "system.h" |
10 | #include "vector.h" | 10 | #include "vector.h" |
11 | #include "sprite.h" | ||
12 | #include "consts.h" | ||
11 | 13 | ||
12 | class Game; | 14 | class Game; |
13 | 15 | ||
@@ -29,26 +31,28 @@ public: | |||
29 | 31 | ||
30 | TransformSystem(Game& game) : game_(game) {} | 32 | TransformSystem(Game& game) : game_(game) {} |
31 | 33 | ||
32 | void initSprite(int spriteId, vec2i loc); | 34 | void initSprite(int spriteId, vec2i loc, SpriteLayer layer = SpriteLayer::Normal); |
33 | 35 | ||
34 | void setUpCollision(int spriteId, vec2i offset, vec2i size, bool solid); | 36 | void setUpCollision(int spriteId, vec2i offset, vec2i size, bool solid); |
35 | 37 | ||
36 | void moveSprite(int spriteId, vec2i newLoc); | 38 | void moveSprite(int spriteId, vec2i newLoc); |
37 | 39 | ||
38 | auto getSpritesByY() const { | 40 | auto getSpritesByY(SpriteLayer layer) const { |
39 | return spritesByY_ | ranges::views::transform([] (const std::tuple<int, int>& val) { | 41 | return spritesByY_[static_cast<size_t>(layer)] | ranges::views::transform([] (const std::tuple<int, int>& val) { |
40 | return std::get<1>(val); | 42 | return std::get<1>(val); |
41 | }); | 43 | }); |
42 | } | 44 | } |
43 | 45 | ||
44 | CollisionResult checkCollision(int spriteId, vec2i newLoc, Direction dir); | 46 | CollisionResult checkCollision(int spriteId, vec2i newLoc, Direction dir); |
45 | 47 | ||
48 | void destroySprite(int spriteId) override; | ||
49 | |||
46 | void clearSpriteCache() override; | 50 | void clearSpriteCache() override; |
47 | 51 | ||
48 | private: | 52 | private: |
49 | 53 | ||
50 | Game& game_; | 54 | Game& game_; |
51 | std::set<std::tuple<int, int>> spritesByY_; | 55 | std::set<std::tuple<int, int>> spritesByY_[NUM_SPRITE_LAYERS]; |
52 | 56 | ||
53 | struct Collidable { | 57 | struct Collidable { |
54 | int lower; | 58 | int lower; |