diff options
author | Kelly Rauchenberger <fefferburbia@gmail.com> | 2021-01-30 13:01:01 -0500 |
---|---|---|
committer | Kelly Rauchenberger <fefferburbia@gmail.com> | 2021-01-30 13:01:01 -0500 |
commit | f3166702d7dd30312b5a401f52941aad43ac51c3 (patch) | |
tree | 08f15a0fde9ee7be08c9b4fe510dfa6ed04d4a78 | |
parent | 763bd80603dbace9f14c25309159ed07ec6e9a93 (diff) | |
download | tanetane-f3166702d7dd30312b5a401f52941aad43ac51c3.tar.gz tanetane-f3166702d7dd30312b5a401f52941aad43ac51c3.tar.bz2 tanetane-f3166702d7dd30312b5a401f52941aad43ac51c3.zip |
Added standing/walking animations
-rw-r--r-- | res/lucas.png | bin | 1663 -> 5334 bytes | |||
-rw-r--r-- | res/lucas_anim.txt | 18 | ||||
-rw-r--r-- | src/direction.h | 30 | ||||
-rw-r--r-- | src/game.h | 14 | ||||
-rw-r--r-- | src/main.cpp | 18 | ||||
-rw-r--r-- | src/party.cpp | 33 | ||||
-rw-r--r-- | src/party.h | 1 | ||||
-rw-r--r-- | src/renderer.cpp | 5 | ||||
-rw-r--r-- | src/sprite.cpp | 79 | ||||
-rw-r--r-- | src/sprite.h | 24 | ||||
-rw-r--r-- | src/util.h | 39 |
11 files changed, 252 insertions, 9 deletions
diff --git a/res/lucas.png b/res/lucas.png index 9c5a067..4ac7157 100644 --- a/res/lucas.png +++ b/res/lucas.png | |||
Binary files differ | |||
diff --git a/res/lucas_anim.txt b/res/lucas_anim.txt new file mode 100644 index 0000000..ff37580 --- /dev/null +++ b/res/lucas_anim.txt | |||
@@ -0,0 +1,18 @@ | |||
1 | ../res/lucas.png | ||
2 | 17,26 | ||
3 | still[down]: 1 | ||
4 | still[left]: 4 | ||
5 | still[down_left]: 7 | ||
6 | still[down_right]: 10 | ||
7 | still[up]: 13 | ||
8 | still[right]: 16 | ||
9 | still[up_left]: 19 | ||
10 | still[up_right]: 22 | ||
11 | walk[down]: 0,1,2 | ||
12 | walk[left]: 3,4,5 | ||
13 | walk[down_left]: 6,7,8 | ||
14 | walk[down_right]: 9,10,11 | ||
15 | walk[up]: 12,13,14 | ||
16 | walk[right]: 15,16,17 | ||
17 | walk[up_left]: 18,19,20 | ||
18 | walk[up_right]: 21,22,23 \ No newline at end of file | ||
diff --git a/src/direction.h b/src/direction.h new file mode 100644 index 0000000..0679a00 --- /dev/null +++ b/src/direction.h | |||
@@ -0,0 +1,30 @@ | |||
1 | #ifndef DIRECTION_H_AB66A90E | ||
2 | #define DIRECTION_H_AB66A90E | ||
3 | |||
4 | #include <string> | ||
5 | #include <stdexcept> | ||
6 | |||
7 | enum class Direction { | ||
8 | up, | ||
9 | up_right, | ||
10 | right, | ||
11 | down_right, | ||
12 | down, | ||
13 | down_left, | ||
14 | left, | ||
15 | up_left | ||
16 | }; | ||
17 | |||
18 | inline Direction directionFromString(std::string_view str) { | ||
19 | if (str == "up") return Direction::up; | ||
20 | if (str == "up_right") return Direction::up_right; | ||
21 | if (str == "right") return Direction::right; | ||
22 | if (str == "down_right") return Direction::down_right; | ||
23 | if (str == "down") return Direction::down; | ||
24 | if (str == "down_left") return Direction::down_left; | ||
25 | if (str == "left") return Direction::left; | ||
26 | if (str == "up_left") return Direction::up_left; | ||
27 | throw std::invalid_argument("Invalid direction: " + std::string(str)); | ||
28 | } | ||
29 | |||
30 | #endif /* end of include guard: DIRECTION_H_AB66A90E */ | ||
diff --git a/src/game.h b/src/game.h index abb70ce..a8626fa 100644 --- a/src/game.h +++ b/src/game.h | |||
@@ -40,6 +40,20 @@ public: | |||
40 | 40 | ||
41 | void moveSprite(int id, vec2i newLoc); | 41 | void moveSprite(int id, vec2i newLoc); |
42 | 42 | ||
43 | void setSpriteWalking(int id, bool walking) { | ||
44 | sprites_[id].setWalking(walking); | ||
45 | } | ||
46 | |||
47 | void setSpriteDirection(int id, Direction dir) { | ||
48 | sprites_[id].setDirection(dir); | ||
49 | } | ||
50 | |||
51 | void tickSpriteAnim() { | ||
52 | for (Sprite& sprite : sprites_) { | ||
53 | sprite.tickAnim(); | ||
54 | } | ||
55 | } | ||
56 | |||
43 | private: | 57 | private: |
44 | 58 | ||
45 | std::vector<Sprite> sprites_; | 59 | std::vector<Sprite> sprites_; |
diff --git a/src/main.cpp b/src/main.cpp index 5a4373b..1d3d58e 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
@@ -7,18 +7,23 @@ void loop(Renderer& renderer) { | |||
7 | Game game; | 7 | Game game; |
8 | Input keystate; | 8 | Input keystate; |
9 | 9 | ||
10 | int kumaSprite = game.addSprite(Sprite("../res/kumatora.png", renderer, 17, 31)); | 10 | //int kumaSprite = game.addSprite(Sprite("../res/kumatora.png", renderer, 17, 31)); |
11 | int lucasSprite = game.addSprite(Sprite("../res/lucas.png", renderer, 17, 27)); | 11 | int lucasSprite = game.addSprite(Sprite("../res/lucas_anim.txt", renderer)); |
12 | int lucasSprite2 = game.addSprite(Sprite("../res/lucas_anim.txt", renderer)); | ||
12 | 13 | ||
13 | Party party; | 14 | Party party; |
14 | party.addMember(game, lucasSprite); | 15 | party.addMember(game, lucasSprite); |
15 | party.addMember(game, kumaSprite); | 16 | party.addMember(game, lucasSprite2); |
17 | //party.addMember(game, kumaSprite); | ||
16 | 18 | ||
17 | renderer.render(game); | 19 | renderer.render(game); |
18 | 20 | ||
19 | size_t inputDt = 50; | 21 | size_t inputDt = 50; |
20 | size_t inputAcc = 0; | 22 | size_t inputAcc = 0; |
21 | 23 | ||
24 | size_t animDt = 1000/5;//30fps * 1000 t/s; | ||
25 | size_t animAcc = 0; | ||
26 | |||
22 | size_t lastTime = SDL_GetTicks(); | 27 | size_t lastTime = SDL_GetTicks(); |
23 | 28 | ||
24 | for (;;) { | 29 | for (;;) { |
@@ -46,6 +51,13 @@ void loop(Renderer& renderer) { | |||
46 | party.move(game, keystate); | 51 | party.move(game, keystate); |
47 | } | 52 | } |
48 | 53 | ||
54 | animAcc += frameTime; | ||
55 | while (animAcc > animDt) { | ||
56 | animAcc -= animDt; | ||
57 | |||
58 | game.tickSpriteAnim(); | ||
59 | } | ||
60 | |||
49 | renderer.render(game); | 61 | renderer.render(game); |
50 | } | 62 | } |
51 | } | 63 | } |
diff --git a/src/party.cpp b/src/party.cpp index 1ff4bb4..19b9557 100644 --- a/src/party.cpp +++ b/src/party.cpp | |||
@@ -12,6 +12,7 @@ void Party::addMember(Game& game, int spriteId) { | |||
12 | 12 | ||
13 | for (int i = 0; i < PARTY_FRAME_DELAY * index; i++) { | 13 | for (int i = 0; i < PARTY_FRAME_DELAY * index; i++) { |
14 | newMember.nextPosition.push_back(sprite.loc()); | 14 | newMember.nextPosition.push_back(sprite.loc()); |
15 | newMember.nextDirection.push_back(sprite.getDirection()); | ||
15 | } | 16 | } |
16 | } | 17 | } |
17 | 18 | ||
@@ -25,35 +26,67 @@ void Party::move(Game& game, const Input& keystate) { | |||
25 | 26 | ||
26 | const Sprite& p1 = game.getSprite(members_[0].spriteId); | 27 | const Sprite& p1 = game.getSprite(members_[0].spriteId); |
27 | vec2i pLoc = p1.loc(); | 28 | vec2i pLoc = p1.loc(); |
29 | Direction dir = Direction::left; | ||
28 | 30 | ||
29 | if (keystate.up) | 31 | if (keystate.up) |
30 | { | 32 | { |
31 | pLoc.y() -= MOVEMENT_SPEED; | 33 | pLoc.y() -= MOVEMENT_SPEED; |
34 | dir = Direction::up; | ||
32 | } | 35 | } |
33 | 36 | ||
34 | if (keystate.down) | 37 | if (keystate.down) |
35 | { | 38 | { |
36 | pLoc.y() += MOVEMENT_SPEED; | 39 | pLoc.y() += MOVEMENT_SPEED; |
40 | dir = Direction::down; | ||
37 | } | 41 | } |
38 | 42 | ||
39 | if (keystate.left) | 43 | if (keystate.left) |
40 | { | 44 | { |
41 | pLoc.x() -= MOVEMENT_SPEED; | 45 | pLoc.x() -= MOVEMENT_SPEED; |
46 | |||
47 | if (dir == Direction::up) { | ||
48 | dir = Direction::up_left; | ||
49 | } else if (dir == Direction::down) { | ||
50 | dir = Direction::down_left; | ||
51 | } else { | ||
52 | dir = Direction::left; | ||
53 | } | ||
42 | } | 54 | } |
43 | 55 | ||
44 | if (keystate.right) | 56 | if (keystate.right) |
45 | { | 57 | { |
46 | pLoc.x() += MOVEMENT_SPEED; | 58 | pLoc.x() += MOVEMENT_SPEED; |
59 | |||
60 | if (dir == Direction::up) { | ||
61 | dir = Direction::up_right; | ||
62 | } else if (dir == Direction::down) { | ||
63 | dir = Direction::down_right; | ||
64 | } else { | ||
65 | dir = Direction::right; | ||
66 | } | ||
47 | } | 67 | } |
48 | 68 | ||
49 | if (keystate.up || keystate.down || keystate.left || keystate.right) { | 69 | if (keystate.up || keystate.down || keystate.left || keystate.right) { |
70 | for (int i = 0; i < members_.size(); i++) { | ||
71 | game.setSpriteWalking(members_[i].spriteId, true); | ||
72 | } | ||
73 | |||
50 | game.moveSprite(members_[0].spriteId, pLoc); | 74 | game.moveSprite(members_[0].spriteId, pLoc); |
75 | game.setSpriteDirection(members_[0].spriteId, dir); | ||
51 | 76 | ||
52 | for (int i = 1; i < members_.size(); i++) { | 77 | for (int i = 1; i < members_.size(); i++) { |
53 | const Sprite& pNext = game.getSprite(members_[i].spriteId); | 78 | const Sprite& pNext = game.getSprite(members_[i].spriteId); |
54 | members_[i].nextPosition.push_back(pLoc); | 79 | members_[i].nextPosition.push_back(pLoc); |
55 | game.moveSprite(members_[i].spriteId, members_[i].nextPosition.front()); | 80 | game.moveSprite(members_[i].spriteId, members_[i].nextPosition.front()); |
56 | members_[i].nextPosition.pop_front(); | 81 | members_[i].nextPosition.pop_front(); |
82 | |||
83 | members_[i].nextDirection.push_back(dir); | ||
84 | game.setSpriteDirection(members_[i].spriteId, members_[i].nextDirection.front()); | ||
85 | members_[i].nextDirection.pop_front(); | ||
86 | } | ||
87 | } else { | ||
88 | for (int i = 0; i < members_.size(); i++) { | ||
89 | game.setSpriteWalking(members_[i].spriteId, false); | ||
57 | } | 90 | } |
58 | } | 91 | } |
59 | } \ No newline at end of file | 92 | } \ No newline at end of file |
diff --git a/src/party.h b/src/party.h index 2a6ffc9..9b0aa89 100644 --- a/src/party.h +++ b/src/party.h | |||
@@ -17,6 +17,7 @@ private: | |||
17 | struct PartyMember { | 17 | struct PartyMember { |
18 | int spriteId; | 18 | int spriteId; |
19 | std::deque<vec2i> nextPosition; | 19 | std::deque<vec2i> nextPosition; |
20 | std::deque<Direction> nextDirection; | ||
20 | }; | 21 | }; |
21 | 22 | ||
22 | std::vector<PartyMember> members_; | 23 | std::vector<PartyMember> members_; |
diff --git a/src/renderer.cpp b/src/renderer.cpp index 8053de0..77f0a0c 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp | |||
@@ -49,8 +49,9 @@ void Renderer::render(Game& game) { | |||
49 | SDL_RenderClear(ren_.get()); | 49 | SDL_RenderClear(ren_.get()); |
50 | 50 | ||
51 | for (const Sprite& sprite : game.getSpritesByY() | game.spriteView()) { | 51 | for (const Sprite& sprite : game.getSpritesByY() | game.spriteView()) { |
52 | SDL_Rect dest { sprite.loc().x(), sprite.loc().y(), sprite.size().w(), sprite.size().h() }; | 52 | SDL_Rect src { sprite.getFrame() * sprite.size().w(), 0, sprite.size().w(), sprite.size().h() }; |
53 | SDL_RenderCopy(ren_.get(), textures_.at(sprite.getTextureId()).get(), nullptr, &dest); | 53 | SDL_Rect dest { sprite.loc().x(), sprite.loc().y(), sprite.size().w() * 4, sprite.size().h() * 4 }; |
54 | SDL_RenderCopy(ren_.get(), textures_.at(sprite.getTextureId()).get(), &src, &dest); | ||
54 | } | 55 | } |
55 | 56 | ||
56 | SDL_SetRenderTarget(ren_.get(), nullptr); | 57 | SDL_SetRenderTarget(ren_.get(), nullptr); |
diff --git a/src/sprite.cpp b/src/sprite.cpp index c8c4656..cc196ae 100644 --- a/src/sprite.cpp +++ b/src/sprite.cpp | |||
@@ -1,7 +1,80 @@ | |||
1 | #include "sprite.h" | 1 | #include "sprite.h" |
2 | #include <SDL_image.h> | 2 | #include <SDL_image.h> |
3 | #include <fstream> | ||
4 | #include <list> | ||
5 | #include <regex> | ||
6 | #include "util.h" | ||
3 | 7 | ||
4 | Sprite::Sprite(std::string_view filename, Renderer& renderer, int width, int height) { | 8 | Sprite::Sprite(std::string_view filename, Renderer& renderer) { |
5 | textureId_ = renderer.loadImageFromFile(filename); | 9 | std::ifstream datafile(filename.data()); |
6 | size_ = { width*4, height*4 }; | 10 | if (!datafile.is_open()) { |
11 | throw std::invalid_argument(std::string("Could not find sprite datafile: ") + std::string(filename)); | ||
12 | } | ||
13 | |||
14 | char ch; | ||
15 | |||
16 | std::string imagename; | ||
17 | datafile >> imagename; | ||
18 | textureId_ = renderer.loadImageFromFile(imagename); | ||
19 | |||
20 | datafile >> size_.w(); | ||
21 | datafile >> ch; //, | ||
22 | datafile >> size_.h(); | ||
23 | |||
24 | std::string animLine; | ||
25 | std::getline(datafile, animLine); // blank | ||
26 | while (std::getline(datafile, animLine)) { | ||
27 | std::regex re(R"(([a-z]+)\[([a-z_]+)\]: ([0-9,]+))"); | ||
28 | std::smatch m; | ||
29 | std::regex_match(animLine, m, re); | ||
30 | |||
31 | std::vector<int> frames; | ||
32 | auto framestrs = splitStr<std::list<std::string>>(m[3], ","); | ||
33 | for (const std::string& f : framestrs) { | ||
34 | frames.push_back(std::stoi(f)); | ||
35 | } | ||
36 | |||
37 | int animId = animations_.size(); | ||
38 | animations_.push_back(std::move(frames)); | ||
39 | |||
40 | Direction dir = directionFromString(std::string(m[2])); | ||
41 | |||
42 | if (m[1] == "still") { | ||
43 | stillAnims_[dir] = animId; | ||
44 | } else { | ||
45 | walkingAnims_[dir] = animId; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | updateAnimation(); | ||
50 | } | ||
51 | |||
52 | void Sprite::setDirection(Direction dir) { | ||
53 | if (curDir_ != dir) { | ||
54 | curDir_ = dir; | ||
55 | updateAnimation(); | ||
56 | } | ||
57 | } | ||
58 | |||
59 | void Sprite::setWalking(bool walking) { | ||
60 | if (isWalking_ != walking) { | ||
61 | isWalking_ = walking; | ||
62 | updateAnimation(); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | void Sprite::updateAnimation() { | ||
67 | if (isWalking_) { | ||
68 | curAnim_ = walkingAnims_[curDir_]; | ||
69 | } else { | ||
70 | curAnim_ = stillAnims_[curDir_]; | ||
71 | } | ||
72 | curFrame_ = 0; | ||
73 | } | ||
74 | |||
75 | void Sprite::tickAnim() { | ||
76 | curFrame_++; | ||
77 | if (curFrame_ >= animations_[curAnim_].size()) { | ||
78 | curFrame_ = 0; | ||
79 | } | ||
7 | } \ No newline at end of file | 80 | } \ No newline at end of file |
diff --git a/src/sprite.h b/src/sprite.h index 1f917d9..5e8003b 100644 --- a/src/sprite.h +++ b/src/sprite.h | |||
@@ -1,14 +1,17 @@ | |||
1 | #ifndef SPRITE_H_70503825 | 1 | #ifndef SPRITE_H_70503825 |
2 | #define SPRITE_H_70503825 | 2 | #define SPRITE_H_70503825 |
3 | 3 | ||
4 | #include <map> | ||
4 | #include <string_view> | 5 | #include <string_view> |
6 | #include <vector> | ||
7 | #include "direction.h" | ||
5 | #include "renderer.h" | 8 | #include "renderer.h" |
6 | #include "vector.h" | 9 | #include "vector.h" |
7 | 10 | ||
8 | class Sprite { | 11 | class Sprite { |
9 | public: | 12 | public: |
10 | 13 | ||
11 | Sprite(std::string_view filename, Renderer& renderer, int width, int height); | 14 | Sprite(std::string_view filename, Renderer& renderer); |
12 | 15 | ||
13 | int getTextureId() const { | 16 | int getTextureId() const { |
14 | return textureId_; | 17 | return textureId_; |
@@ -22,11 +25,30 @@ public: | |||
22 | 25 | ||
23 | vec2i& size() { return size_; } | 26 | vec2i& size() { return size_; } |
24 | 27 | ||
28 | int getFrame() const { return animations_[curAnim_][curFrame_]; } | ||
29 | |||
30 | void setDirection(Direction dir); | ||
31 | |||
32 | Direction getDirection() const { return curDir_; } | ||
33 | |||
34 | void setWalking(bool walking); | ||
35 | |||
36 | void tickAnim(); | ||
37 | |||
25 | private: | 38 | private: |
26 | 39 | ||
40 | void updateAnimation(); | ||
41 | |||
27 | int textureId_; | 42 | int textureId_; |
28 | vec2i loc_ { 0, 0 }; | 43 | vec2i loc_ { 0, 0 }; |
29 | vec2i size_; | 44 | vec2i size_; |
45 | Direction curDir_ = Direction::down; | ||
46 | bool isWalking_ = false; | ||
47 | int curAnim_ = 0; | ||
48 | int curFrame_ = 0; | ||
49 | std::vector<std::vector<int>> animations_; | ||
50 | std::map<Direction, int> stillAnims_; | ||
51 | std::map<Direction, int> walkingAnims_; | ||
30 | }; | 52 | }; |
31 | 53 | ||
32 | #endif /* end of include guard: SPRITE_H_70503825 */ | 54 | #endif /* end of include guard: SPRITE_H_70503825 */ |
diff --git a/src/util.h b/src/util.h new file mode 100644 index 0000000..8cdad3d --- /dev/null +++ b/src/util.h | |||
@@ -0,0 +1,39 @@ | |||
1 | #ifndef UTIL_H_4AC35025 | ||
2 | #define UTIL_H_4AC35025 | ||
3 | |||
4 | #include <string> | ||
5 | #include <iterator> | ||
6 | |||
7 | template <class OutputIterator> | ||
8 | void splitStr( | ||
9 | std::string input, | ||
10 | std::string delimiter, | ||
11 | OutputIterator out) { | ||
12 | while (!input.empty()) { | ||
13 | int divider = input.find(delimiter); | ||
14 | if (divider == std::string::npos) { | ||
15 | *out = input; | ||
16 | out++; | ||
17 | |||
18 | input = ""; | ||
19 | } else { | ||
20 | *out = input.substr(0, divider); | ||
21 | out++; | ||
22 | |||
23 | input = input.substr(divider+delimiter.length()); | ||
24 | } | ||
25 | } | ||
26 | } | ||
27 | |||
28 | template <class Container> | ||
29 | Container splitStr( | ||
30 | std::string input, | ||
31 | std::string delimiter) { | ||
32 | Container result; | ||
33 | |||
34 | splitStr(input, delimiter, std::back_inserter(result)); | ||
35 | |||
36 | return result; | ||
37 | } | ||
38 | |||
39 | #endif /* end of include guard: UTIL_H_4AC35025 */ | ||