summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--res/lucas.pngbin5334 -> 10009 bytes
-rw-r--r--res/lucas_anim.txt18
-rw-r--r--src/direction.h14
-rw-r--r--src/main.cpp4
-rw-r--r--src/party.cpp165
-rw-r--r--src/party.h20
-rw-r--r--src/vector.h4
7 files changed, 175 insertions, 50 deletions
diff --git a/res/lucas.png b/res/lucas.png index 4ac7157..c059f96 100644 --- a/res/lucas.png +++ b/res/lucas.png
Binary files differ
diff --git a/res/lucas_anim.txt b/res/lucas_anim.txt index ff37580..19b1d67 100644 --- a/res/lucas_anim.txt +++ b/res/lucas_anim.txt
@@ -15,4 +15,20 @@ walk[down_right]: 9,10,11
15walk[up]: 12,13,14 15walk[up]: 12,13,14
16walk[right]: 15,16,17 16walk[right]: 15,16,17
17walk[up_left]: 18,19,20 17walk[up_left]: 18,19,20
18walk[up_right]: 21,22,23 \ No newline at end of file 18walk[up_right]: 21,22,23
19crouch[down]: 24
20crouch[down_left]: 25
21crouch[left]: 26
22crouch[up_left]: 27
23crouch[up]: 28
24crouch[up_right]: 29
25crouch[right]: 30
26crouch[down_right]: 31
27run[down]: 32,33,34,35
28run[right]: 36,37,38,39
29run[down_right]: 40,41,42,43
30run[up_right]: 44,45,46,47
31run[up]: 48,49,50,51
32run[left]: 52,53,54,55
33run[up_left]: 56,57,58,59
34run[down_left]: 60,61,62,63 \ No newline at end of file
diff --git a/src/direction.h b/src/direction.h index 0679a00..ebc0e46 100644 --- a/src/direction.h +++ b/src/direction.h
@@ -3,6 +3,7 @@
3 3
4#include <string> 4#include <string>
5#include <stdexcept> 5#include <stdexcept>
6#include "vector.h"
6 7
7enum class Direction { 8enum class Direction {
8 up, 9 up,
@@ -27,4 +28,17 @@ inline Direction directionFromString(std::string_view str) {
27 throw std::invalid_argument("Invalid direction: " + std::string(str)); 28 throw std::invalid_argument("Invalid direction: " + std::string(str));
28} 29}
29 30
31inline vec2i unitVecInDirection(Direction dir) {
32 switch (dir) {
33 case Direction::up: return { 0, -1 };
34 case Direction::up_right: return { 1, -1 };
35 case Direction::right: return { 1, 0 };
36 case Direction::down_right: return { 1, 1 };
37 case Direction::down: return { 0, 1 };
38 case Direction::down_left: return { -1, 1 };
39 case Direction::left: return { -1, 0 };
40 case Direction::up_left: return { -1, -1 };
41 }
42}
43
30#endif /* end of include guard: DIRECTION_H_AB66A90E */ 44#endif /* end of include guard: DIRECTION_H_AB66A90E */
diff --git a/src/main.cpp b/src/main.cpp index 9d889f2..f9db18d 100644 --- a/src/main.cpp +++ b/src/main.cpp
@@ -33,6 +33,10 @@ void loop(Renderer& renderer) {
33 while (SDL_PollEvent(&e)) { 33 while (SDL_PollEvent(&e)) {
34 if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)) { 34 if (e.type == SDL_QUIT || (e.type == SDL_KEYDOWN && e.key.keysym.sym == SDLK_ESCAPE)) {
35 return; 35 return;
36 } else if (e.type == SDL_KEYDOWN && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) {
37 party.beginCrouch(game);
38 } else if (e.type == SDL_KEYUP && (e.key.keysym.sym == SDLK_LSHIFT || e.key.keysym.sym == SDLK_RSHIFT)) {
39 party.endCrouch(game);
36 } 40 }
37 } 41 }
38 42
diff --git a/src/party.cpp b/src/party.cpp index 28492a9..2af252f 100644 --- a/src/party.cpp +++ b/src/party.cpp
@@ -10,10 +10,7 @@ void Party::addMember(Game& game, int spriteId) {
10 if (index > 0) { 10 if (index > 0) {
11 const Sprite& sprite = game.getSprite(spriteId); 11 const Sprite& sprite = game.getSprite(spriteId);
12 12
13 for (int i = 0; i < PARTY_FRAME_DELAY * index; i++) { 13 newMember.movement = std::deque<Movement>(PARTY_FRAME_DELAY * index, {.pos = sprite.loc(), .dir = sprite.getDirection()});
14 newMember.nextPosition.push_back(sprite.loc());
15 newMember.nextDirection.push_back(sprite.getDirection());
16 }
17 } 14 }
18 15
19 members_.push_back(std::move(newMember)); 16 members_.push_back(std::move(newMember));
@@ -26,65 +23,139 @@ void Party::move(Game& game, const Input& keystate) {
26 return; 23 return;
27 } 24 }
28 25
29 const Sprite& p1 = game.getSprite(members_[0].spriteId);
30 vec2i pLoc = p1.loc();
31 Direction dir = Direction::left; 26 Direction dir = Direction::left;
32 27
33 if (keystate.up) 28 if (!keystate.up && !keystate.down && !keystate.left && !keystate.right) {
34 { 29 if (state_ == State::Running) {
35 pLoc.y() -= MOVEMENT_SPEED; 30 dir = lastDir_;
36 dir = Direction::up; 31 } else {
37 } else if (keystate.down) 32 if (state_ == State::Normal) {
38 { 33 for (int i = 0; i < members_.size(); i++) {
39 pLoc.y() += MOVEMENT_SPEED; 34 game.setSpriteState(members_[i].spriteId, "still");
40 dir = Direction::down; 35 }
41 } 36 }
42 37
43 if (keystate.left) 38 return;
44 { 39 }
45 pLoc.x() -= MOVEMENT_SPEED; 40 } else {
41 if (keystate.up)
42 {
43 dir = Direction::up;
44 } else if (keystate.down)
45 {
46 dir = Direction::down;
47 }
46 48
47 if (dir == Direction::up) { 49 if (keystate.left)
48 dir = Direction::up_left; 50 {
49 } else if (dir == Direction::down) { 51 if (dir == Direction::up) {
50 dir = Direction::down_left; 52 dir = Direction::up_left;
51 } else { 53 } else if (dir == Direction::down) {
52 dir = Direction::left; 54 dir = Direction::down_left;
55 } else {
56 dir = Direction::left;
57 }
58 } else if (keystate.right)
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 }
53 } 67 }
54 } else if (keystate.right) 68 }
55 { 69
56 pLoc.x() += MOVEMENT_SPEED; 70 lastDir_ = dir;
57 71
58 if (dir == Direction::up) { 72 const Sprite& p1 = game.getSprite(members_[0].spriteId);
59 dir = Direction::up_right; 73 vec2i pLoc = p1.loc();
60 } else if (dir == Direction::down) { 74
61 dir = Direction::down_right; 75 if (state_ == State::Crouching) {
62 } else { 76 for (int i = 0; i < members_.size(); i++) {
63 dir = Direction::right; 77 game.setSpriteDirection(members_[i].spriteId, dir);
64 } 78 }
79
80 return;
81 } else {
82 game.setSpriteDirection(members_[0].spriteId, dir);
65 } 83 }
66 84
67 if (keystate.up || keystate.down || keystate.left || keystate.right) { 85 int speed = MOVEMENT_SPEED;
86 if (state_ == State::Running) {
87 speed *= 2;
88 } else {
68 for (int i = 0; i < members_.size(); i++) { 89 for (int i = 0; i < members_.size(); i++) {
69 game.setSpriteState(members_[i].spriteId, "walk"); 90 game.setSpriteState(members_[i].spriteId, "walk");
70 } 91 }
92 }
71 93
72 game.moveSprite(members_[0].spriteId, pLoc); 94 pLoc += (unitVecInDirection(dir) * speed);
73 game.setSpriteDirection(members_[0].spriteId, dir); 95
96 game.moveSprite(members_[0].spriteId, pLoc);
74 97
98 for (int i = 1; i < members_.size(); i++) {
99 const Sprite& pNext = game.getSprite(members_[i].spriteId);
100 const Movement& posdir = members_[i].movement.front();
101 game.moveSprite(members_[i].spriteId, posdir.pos);
102 game.setSpriteDirection(members_[i].spriteId, posdir.dir);
103
104 members_[i].movement.pop_front();
105 members_[i].movement.push_back({.pos = pLoc, .dir = dir});
106 }
107}
108
109void Party::beginCrouch(Game& game) {
110 if (state_ == State::Running) {
111 state_ = State::Normal;
112
113 // Double the movement buffer for the followers.
75 for (int i = 1; i < members_.size(); i++) { 114 for (int i = 1; i < members_.size(); i++) {
76 const Sprite& pNext = game.getSprite(members_[i].spriteId); 115 std::deque<Movement> newMove;
77 members_[i].nextPosition.push_back(pLoc); 116 vec2i lastPos = game.getSprite(members_[i].spriteId).loc();
78 game.moveSprite(members_[i].spriteId, members_[i].nextPosition.front()); 117
79 members_[i].nextPosition.pop_front(); 118 while (!members_[i].movement.empty()) {
80 119 Movement m1 = members_[i].movement.front();
81 members_[i].nextDirection.push_back(dir); 120 Movement m2 = m1;
82 game.setSpriteDirection(members_[i].spriteId, members_[i].nextDirection.front()); 121 m1.pos = (m1.pos + lastPos) / 2;
83 members_[i].nextDirection.pop_front(); 122 lastPos = m2.pos;
123
124 newMove.push_back(m1);
125 newMove.push_back(m2);
126 members_[i].movement.pop_front();
127 }
128
129 members_[i].movement = std::move(newMove);
84 } 130 }
85 } else { 131 } else {
132 state_ = State::Crouching;
133
86 for (int i = 0; i < members_.size(); i++) { 134 for (int i = 0; i < members_.size(); i++) {
87 game.setSpriteState(members_[i].spriteId, "still"); 135 game.setSpriteState(members_[i].spriteId, "crouch");
88 } 136 }
89 } 137 }
90} \ No newline at end of file 138}
139
140void Party::endCrouch(Game& game) {
141 if (state_ == State::Crouching) {
142 state_ = State::Running;
143
144 for (int i = 0; i < members_.size(); i++) {
145 game.setSpriteState(members_[i].spriteId, "run");
146
147 // Halve the movement buffer for the followers.
148 if (i > 0) {
149 std::deque<Movement> newMove;
150
151 while (!members_[i].movement.empty()) {
152 newMove.push_back(members_[i].movement.front());
153 members_[i].movement.pop_front();
154 members_[i].movement.pop_front();
155 }
156
157 members_[i].movement = std::move(newMove);
158 }
159 }
160 }
161}
diff --git a/src/party.h b/src/party.h index 9b0aa89..06f8639 100644 --- a/src/party.h +++ b/src/party.h
@@ -12,15 +12,31 @@ public:
12 12
13 void move(Game& game, const Input& keystate); 13 void move(Game& game, const Input& keystate);
14 14
15 void beginCrouch(Game& game);
16
17 void endCrouch(Game& game);
18
15private: 19private:
16 20
21 enum class State {
22 Normal,
23 Crouching,
24 Running
25 };
26
27 struct Movement {
28 vec2i pos;
29 Direction dir;
30 };
31
17 struct PartyMember { 32 struct PartyMember {
18 int spriteId; 33 int spriteId;
19 std::deque<vec2i> nextPosition; 34 std::deque<Movement> movement;
20 std::deque<Direction> nextDirection;
21 }; 35 };
22 36
23 std::vector<PartyMember> members_; 37 std::vector<PartyMember> members_;
38 State state_ = State::Normal;
39 Direction lastDir_;
24}; 40};
25 41
26#endif /* end of include guard: PARTY_H_826F91BA */ 42#endif /* end of include guard: PARTY_H_826F91BA */
diff --git a/src/vector.h b/src/vector.h index 9973ea6..bf38bb2 100644 --- a/src/vector.h +++ b/src/vector.h
@@ -80,6 +80,10 @@ public:
80 return vec2(x() * s, y() * s); 80 return vec2(x() * s, y() * s);
81 } 81 }
82 82
83 vec2 operator/(T s) const {
84 return vec2(x() / s, y() / s);
85 }
86
83 vec2& operator*=(T s) { 87 vec2& operator*=(T s) {
84 x() *= s; 88 x() *= s;
85 y() *= s; 89 y() *= s;