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; |
