summary refs log tree commit diff stats
diff options
context:
space:
mode:
-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;