summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2021-02-13 20:50:21 -0500
committerKelly Rauchenberger <fefferburbia@gmail.com>2021-02-13 20:50:21 -0500
commit470b1d43fb6f8e17624ee90f87270de5bd6ff77e (patch)
tree966f1e18d496f12c3273684be299573e4bf443ec
parented933607765a6e010689aaaf85184053ff6e8a2b (diff)
downloadtanetane-470b1d43fb6f8e17624ee90f87270de5bd6ff77e.tar.gz
tanetane-470b1d43fb6f8e17624ee90f87270de5bd6ff77e.tar.bz2
tanetane-470b1d43fb6f8e17624ee90f87270de5bd6ff77e.zip
Added lightning sprite to mailbox event
Sprites can be destroyed now, which really just means that their index is removed from the list of active sprites. The actual memory is not freed until all sprites are deleted on map change.

Sprite layers are introduced. All sprites by default are on layer 0 (Normal) which renders them in between the lower and upper map layers. There is also a layer 1 (Above) that renders above the upper map layer, and the sprite for the lightning strike uses this layer in order to not be hidden by the trees.

Fixed a bug where waiting for the end of a non-looping animation would trip the flag immediately upon the final frame activating, instead of waiting the length of the last frame.
-rw-r--r--res/maps/map2.tmx5
-rw-r--r--res/scripts/common.lua24
-rw-r--r--res/scripts/map2.lua9
-rw-r--r--res/sprites/lightning.pngbin0 -> 11405 bytes
-rw-r--r--res/sprites/lightning_anim.txt3
-rw-r--r--res/sprites/lightning_frames.txt14
-rw-r--r--res/sprites/lucas_anim.txt3
-rw-r--r--src/animation_system.cpp13
-rw-r--r--src/camera_system.cpp6
-rw-r--r--src/camera_system.h2
-rw-r--r--src/character_system.cpp7
-rw-r--r--src/character_system.h2
-rw-r--r--src/consts.h2
-rw-r--r--src/game.cpp12
-rw-r--r--src/game.h7
-rw-r--r--src/main.cpp2
-rw-r--r--src/renderer.cpp34
-rw-r--r--src/renderer.h4
-rw-r--r--src/script_system.cpp33
-rw-r--r--src/sprite.h8
-rw-r--r--src/system.h2
-rw-r--r--src/transform_system.cpp22
-rw-r--r--src/transform_system.h12
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
28SpriteLayer = {
29 NORMAL = 0,
30 ABOVE = 1
31}
32
28function StartCutscene() 33function 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
60end 65end
61 66
67function GetPosition(spriteName)
68 local spriteId = getSpriteByAlias(spriteName)
69 local sprite = getSprite(spriteId)
70 return sprite.loc
71end
72
62function SetDirection(spriteName, dir) 73function 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
139end 150end
151
152function 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)
158end
159
160function DestroyNamedSprite(alias)
161 local spriteId = getSpriteByAlias(alias)
162 destroySprite(spriteId)
163end
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
3strike[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 @@
1160,128 cell size
210 frames per row
310 frames
4
5112,128,60,56
6128,128,72,64
7116,128,64,64
8116,128,64,64
988,96,40,96
1088,96,40,96
1180,96,40,96
12160,32,123,83
13160,32,123,91
14160,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
32run[up_right]: 72,80,88,96 32run[up_right]: 72,80,88,96
33run[right]: 73,81,89,97 33run[right]: 73,81,89,97
34run[down_right]: 74,82,90,98 34run[down_right]: 74,82,90,98
35electrocute![down]: 116,117,118,116,117,118,116,117,118,119,120,121,122 \ No newline at end of file 35lightning_electrocute![down]: 116,117,118,116,117,118,116,117,118,116
36lightning_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
29void CameraSystem::destroySprite(int spriteId) {
30 if (followingSprite_ == spriteId) {
31 followingSprite_ = -1;
32 }
33}
34
29void CameraSystem::clearSpriteCache() { 35void 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
31private: 33private:
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
263void CharacterSystem::destroySprite(int spriteId) {
264 Sprite& sprite = game_.getSprite(spriteId);
265 if (sprite.runningSfxChannel != -1) {
266 stopRunningSound(sprite);
267 }
268}
269
263void CharacterSystem::clearSpriteCache() { 270void 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
40private: 42private:
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
13const int MESSAGE_TEXT_WIDTH = 196; 13const int MESSAGE_TEXT_WIDTH = 196;
14 14
15const 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 @@
7int Game::emplaceSprite(std::string alias) { 7int 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
16void 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
15void Game::clearSprites() { 25void 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
97void 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
97void Renderer::render(Game& game) { 112void 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
12class Game; 12class Game;
13class Map; 13class Map;
14class Sprite;
14 15
15class sdl_error : public std::logic_error { 16class sdl_error : public std::logic_error {
16public: 17public:
@@ -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
8ScriptSystem::ScriptSystem(Game& game) : game_(game) { 10ScriptSystem::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
13enum class SpriteLayer {
14 Normal,
15 Above
16};
17
13struct SpriteFrame { 18struct SpriteFrame {
14 SDL_Rect srcRect; 19 SDL_Rect srcRect;
15 vec2i center; 20 vec2i center;
@@ -36,8 +41,11 @@ struct Movement {
36class Sprite { 41class Sprite {
37public: 42public:
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
5void TransformSystem::initSprite(int spriteId, vec2i loc) { 5void 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
11void TransformSystem::setUpCollision(int spriteId, vec2i offset, vec2i size, bool solid) { 12void 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
220void 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
219void TransformSystem::clearSpriteCache() { 229void 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
12class Game; 14class 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
48private: 52private:
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;