summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--res/lucas.pngbin1663 -> 5334 bytes
-rw-r--r--res/lucas_anim.txt18
-rw-r--r--src/direction.h30
-rw-r--r--src/game.h14
-rw-r--r--src/main.cpp18
-rw-r--r--src/party.cpp33
-rw-r--r--src/party.h1
-rw-r--r--src/renderer.cpp5
-rw-r--r--src/sprite.cpp79
-rw-r--r--src/sprite.h24
-rw-r--r--src/util.h39
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
217,26
3still[down]: 1
4still[left]: 4
5still[down_left]: 7
6still[down_right]: 10
7still[up]: 13
8still[right]: 16
9still[up_left]: 19
10still[up_right]: 22
11walk[down]: 0,1,2
12walk[left]: 3,4,5
13walk[down_left]: 6,7,8
14walk[down_right]: 9,10,11
15walk[up]: 12,13,14
16walk[right]: 15,16,17
17walk[up_left]: 18,19,20
18walk[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
7enum class Direction {
8 up,
9 up_right,
10 right,
11 down_right,
12 down,
13 down_left,
14 left,
15 up_left
16};
17
18inline 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
43private: 57private:
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
4Sprite::Sprite(std::string_view filename, Renderer& renderer, int width, int height) { 8Sprite::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
52void Sprite::setDirection(Direction dir) {
53 if (curDir_ != dir) {
54 curDir_ = dir;
55 updateAnimation();
56 }
57}
58
59void Sprite::setWalking(bool walking) {
60 if (isWalking_ != walking) {
61 isWalking_ = walking;
62 updateAnimation();
63 }
64}
65
66void Sprite::updateAnimation() {
67 if (isWalking_) {
68 curAnim_ = walkingAnims_[curDir_];
69 } else {
70 curAnim_ = stillAnims_[curDir_];
71 }
72 curFrame_ = 0;
73}
74
75void 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
8class Sprite { 11class Sprite {
9public: 12public:
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
25private: 38private:
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
7template <class OutputIterator>
8void 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
28template <class Container>
29Container 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 */