Browse Source

Menus ang game states

Pabloader 5 years ago
parent
commit
63529f4849
11 changed files with 396 additions and 193 deletions
  1. 3
    3
      Makefile
  2. 10
    10
      TODO.md
  3. 0
    0
      bin/.gitkeep
  4. 35
    10
      include/debuggers.h
  5. 5
    0
      include/programmer.h
  6. 37
    0
      pge/include/olcPGE_Common.h
  7. 0
    38
      pge/include/olcPixelGameEngine.h
  8. 85
    123
      src/debuggers.cpp
  9. 195
    0
      src/debuggers_states.cpp
  10. 4
    2
      src/entity.cpp
  11. 22
    7
      src/programmer.cpp

+ 3
- 3
Makefile View File

3
 INCLUDES=-Iinclude -Ipge/include
3
 INCLUDES=-Iinclude -Ipge/include
4
 ifeq ($(OS),Windows_NT)
4
 ifeq ($(OS),Windows_NT)
5
 	LIBRARIES=-luser32 -lgdi32 -lopengl32 -lgdiplus -lwinmm
5
 	LIBRARIES=-luser32 -lgdi32 -lopengl32 -lgdiplus -lwinmm
6
-	EXECUTABLE=debuggers.exe
6
+	EXECUTABLE=bin/debuggers.exe
7
 	PACKER=packer/packer.exe
7
 	PACKER=packer/packer.exe
8
 ifneq ($(DEBUG),1)
8
 ifneq ($(DEBUG),1)
9
 	LDFLAGS+=--machine=windows
9
 	LDFLAGS+=--machine=windows
13
 	MAKE=mingw32-make
13
 	MAKE=mingw32-make
14
 else
14
 else
15
 	LIBRARIES=-lX11 -lGL -lpthread -lpng -lasound
15
 	LIBRARIES=-lX11 -lGL -lpthread -lpng -lasound
16
-	EXECUTABLE=debuggers
16
+	EXECUTABLE=bin/debuggers
17
 	PACKER=packer/packer
17
 	PACKER=packer/packer
18
 	CC=gcc
18
 	CC=gcc
19
 	CPP=g++
19
 	CPP=g++
30
 SPRITES=$(IMAGES:.png=.pgs)
30
 SPRITES=$(IMAGES:.png=.pgs)
31
 RESOURCES=$(SPRITES) $(wildcard res/*.wav) src/programmer.cpp
31
 RESOURCES=$(SPRITES) $(wildcard res/*.wav) src/programmer.cpp
32
 
32
 
33
-PACK=debuggers.pgp
33
+PACK=bin/debuggers.pgp
34
 
34
 
35
 all: $(SOURCES) $(PACK) $(EXECUTABLE)
35
 all: $(SOURCES) $(PACK) $(EXECUTABLE)
36
 
36
 

+ 10
- 10
TODO.md View File

1
  # TODO
1
  # TODO
2
- - [ ] Main menu
3
- - [ ] Pause (ESC) menu
4
- - [ ] Play as bug gamemode
2
+ - [X] Main menu
3
+ - [X] Pause (ESC) menu
4
+ - [ ] Help screen
5
 
5
 
6
- - [ ] Bugs only catchable by 2 programmers
7
- - [ ] Bugs only catchable with debugger
8
- - [ ] Bugs only catchable with unit tests
9
- - [ ] Bugs immune to debugger
10
- - [ ] Bugs immune to unit tests
11
- - [ ] Not bug - a feature
12
- - [ ] Reduce programmers spawn rate (maybe cubic function?)
6
+ - [ ] ? Bugs only catchable by 2 programmers
7
+ - [ ] ? Bugs only catchable with debugger
8
+ - [ ] ? Bugs only catchable with unit tests
9
+ - [ ] ? Bugs immune to debugger
10
+ - [ ] ? Bugs immune to unit tests
11
+ - [ ] ? Not bug - a feature
12
+ - [X] Reduce programmers spawn rate (maybe cubic function?)
13
  - [ ] Add obstacles to prevent flying across the screen
13
  - [ ] Add obstacles to prevent flying across the screen
14
    - [ ] Edits by customer
14
    - [ ] Edits by customer
15
    - [ ] QA engineers
15
    - [ ] QA engineers

+ 0
- 0
bin/.gitkeep View File


+ 35
- 10
include/debuggers.h View File

10
 #include "programmer.h"
10
 #include "programmer.h"
11
 
11
 
12
 #include <chrono>
12
 #include <chrono>
13
+#include <list>
13
 #include <map>
14
 #include <map>
14
 #include <random>
15
 #include <random>
15
 #include <string>
16
 #include <string>
16
 #include <vector>
17
 #include <vector>
17
 
18
 
18
 namespace pabloader {
19
 namespace pabloader {
20
+enum GameState {
21
+    STATE_MAIN_MENU,
22
+    STATE_GAME,
23
+    STATE_PAUSE_MENU,
24
+    STATE_GAME_OVER,
25
+    STATE_HELP,
26
+    STATE_QUIT
27
+};
28
+
19
 class Debuggers : public olc::PixelGameEngine {
29
 class Debuggers : public olc::PixelGameEngine {
20
 private:
30
 private:
21
-    std::vector<Programmer*> programmers;
22
-    std::vector<Bonus*> bonuses;
31
+    std::list<Programmer*> programmers;
32
+    std::list<Bonus*> bonuses;
23
 
33
 
24
     std::map<BonusType, uint32_t> bonusesCatched;
34
     std::map<BonusType, uint32_t> bonusesCatched;
25
 
35
 
29
 
39
 
30
     uint8_t linesOfCode = 5;
40
     uint8_t linesOfCode = 5;
31
     uint16_t totalLines;
41
     uint16_t totalLines;
32
-    std::vector<std::string> sourceCode;
33
-    std::random_device rd;
42
+    std::list<std::string> originalSourceCode;
43
+    std::list<std::string> sourceCode;
44
+
45
+    GameState state = STATE_MAIN_MENU;
46
+
34
     std::mt19937 generator;
47
     std::mt19937 generator;
35
 
48
 
36
 public:
49
 public:
37
     Debuggers()
50
     Debuggers()
38
-        : generator(rd())
51
+        : generator(std::chrono::system_clock::now().time_since_epoch().count())
39
     {
52
     {
40
         sAppName = "Debuggers";
53
         sAppName = "Debuggers";
41
     }
54
     }
44
     bool OnUserCreate() override;
57
     bool OnUserCreate() override;
45
     bool OnUserUpdate(float fElapsedTime) override;
58
     bool OnUserUpdate(float fElapsedTime) override;
46
     bool OnUserDestroy() override;
59
     bool OnUserDestroy() override;
47
-    int GameScreenHeight() { return ScreenHeight() - linesOfCode * 10; };
60
+    int GameScreenHeight() { return ScreenHeight() - linesOfCode * 10; }
61
+    GameState GetState() { return state; }
48
 
62
 
49
     template <typename T>
63
     template <typename T>
50
     T GetRandom(T from = 0, T to = 1);
64
     T GetRandom(T from = 0, T to = 1);
51
 
65
 
52
 private:
66
 private:
67
+    void ResetGame();
68
+    void SwitchState(GameState newState);
69
+    void DrawMenu();
70
+
71
+    void SpawnPlayer();
53
     void SpawnProgrammer();
72
     void SpawnProgrammer();
54
     void SpawnBug();
73
     void SpawnBug();
55
     void SpawnBonus();
74
     void SpawnBonus();
56
     Bug* CreateBug();
75
     Bug* CreateBug();
57
     Bonus* CreateBonus();
76
     Bonus* CreateBonus();
58
-    bool GameOver();
77
+
78
+private: // Gamemodes
79
+    bool MainMenu(float dt);
80
+    bool GamePlay(float dt);
81
+    bool PauseMenu(float dt);
82
+    bool GameOver(float dt);
83
+    bool HelpMenu(float dt);
59
 
84
 
60
 public:
85
 public:
61
-    std::vector<Bug*> bugs;
86
+    std::list<Bug*> bugs;
62
 
87
 
63
     olc::ResourcePack pack;
88
     olc::ResourcePack pack;
64
 
89
 
71
     int bugFallSample;
96
     int bugFallSample;
72
     int bugCatchSample;
97
     int bugCatchSample;
73
 
98
 
74
-    const int gravity = 30;
99
+    const int gravity = 25;
75
 #ifdef _DEBUG
100
 #ifdef _DEBUG
76
-    bool debug = true;
101
+    bool debug = false;
77
 #endif
102
 #endif
78
 };
103
 };
79
 }
104
 }

+ 5
- 0
include/programmer.h View File

23
     bool IsOnGround() { return onGround; }
23
     bool IsOnGround() { return onGround; }
24
     uint8_t GetSkin() { return tile.x; }
24
     uint8_t GetSkin() { return tile.x; }
25
     void UpgradeLevel() { tile.x = std::min(tile.x + 1, tileDim.x - 1); }
25
     void UpgradeLevel() { tile.x = std::min(tile.x + 1, tileDim.x - 1); }
26
+
27
+private:
28
+#ifdef _DEBUG
29
+    olc::vf2d target;
30
+#endif
26
 };
31
 };
27
 }
32
 }
28
 
33
 

+ 37
- 0
pge/include/olcPGE_Common.h View File

33
         NO_FILE = -1,
33
         NO_FILE = -1,
34
     };
34
     };
35
     std::wstring ConvertS2W(std::string s);
35
     std::wstring ConvertS2W(std::string s);
36
+
37
+    
38
+	template <class T>
39
+	struct v2d_generic
40
+	{
41
+		T x = 0;
42
+		T y = 0;
43
+
44
+		inline v2d_generic() : x(0), y(0)                        {                                                      }
45
+		inline v2d_generic(T _x, T _y) : x(_x), y(_y)            {                                                      }
46
+		inline v2d_generic(const v2d_generic& v) : x(v.x), y(v.y){                                                      }
47
+		inline T mag()                                           { return sqrt(x * x + y * y);                          }
48
+		inline v2d_generic  norm()                               { T r = 1 / mag(); return v2d_generic(x*r, y*r);       }
49
+		inline v2d_generic  perp()                               { return v2d_generic(-y, x);                           }
50
+		inline T dot(const v2d_generic& rhs)                     { return this->x * rhs.x + this->y * rhs.y;            }
51
+		inline T cross(const v2d_generic& rhs)                   { return this->x * rhs.y - this->y * rhs.x;            }
52
+		inline v2d_generic  operator +  (const v2d_generic& rhs) const { return v2d_generic(this->x + rhs.x, this->y + rhs.y);}
53
+		inline v2d_generic  operator -  (const v2d_generic& rhs) const { return v2d_generic(this->x - rhs.x, this->y - rhs.y);}
54
+		inline v2d_generic  operator *  (const T& rhs)           const { return v2d_generic(this->x * rhs, this->y * rhs);    }
55
+		inline v2d_generic  operator /  (const T& rhs)           const { return v2d_generic(this->x / rhs, this->y / rhs);    }
56
+		inline v2d_generic& operator += (const v2d_generic& rhs) { this->x += rhs.x; this->y += rhs.y; return *this;    }
57
+		inline v2d_generic& operator -= (const v2d_generic& rhs) { this->x -= rhs.x; this->y -= rhs.y; return *this;    }
58
+		inline v2d_generic& operator *= (const T& rhs)           { this->x *= rhs; this->y *= rhs; return *this;        }
59
+		inline v2d_generic& operator /= (const T& rhs)           { this->x /= rhs; this->y /= rhs; return *this;        }
60
+		inline T& operator [] (std::size_t i)                    { return *((T*)this + i);	   /* <-- D'oh :( */        }
61
+	};
62
+
63
+	template<class T> inline v2d_generic<T> operator * (const float& lhs, const v2d_generic<T>& rhs) { return v2d_generic<T>(lhs * rhs.x, lhs * rhs.y); }
64
+	template<class T> inline v2d_generic<T> operator * (const double& lhs, const v2d_generic<T>& rhs){ return v2d_generic<T>(lhs * rhs.x, lhs * rhs.y); }
65
+	template<class T> inline v2d_generic<T> operator * (const int& lhs, const v2d_generic<T>& rhs)   { return v2d_generic<T>(lhs * rhs.x, lhs * rhs.y); }
66
+	template<class T> inline v2d_generic<T> operator / (const float& lhs, const v2d_generic<T>& rhs) { return v2d_generic<T>(lhs / rhs.x, lhs / rhs.y); }
67
+	template<class T> inline v2d_generic<T> operator / (const double& lhs, const v2d_generic<T>& rhs){ return v2d_generic<T>(lhs / rhs.x, lhs / rhs.y); }
68
+	template<class T> inline v2d_generic<T> operator / (const int& lhs, const v2d_generic<T>& rhs)   { return v2d_generic<T>(lhs / rhs.x, lhs / rhs.y); }
69
+
70
+	typedef v2d_generic<int> vi2d;
71
+	typedef v2d_generic<float> vf2d;
72
+	typedef v2d_generic<double> vd2d;
36
 }
73
 }
37
 
74
 
38
 #endif
75
 #endif

+ 0
- 38
pge/include/olcPixelGameEngine.h View File

235
 
235
 
236
 namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
236
 namespace olc // All OneLoneCoder stuff will now exist in the "olc" namespace
237
 {
237
 {
238
-	template <class T>
239
-	struct v2d_generic
240
-	{
241
-		T x = 0;
242
-		T y = 0;
243
-
244
-		inline v2d_generic() : x(0), y(0)                        {                                                      }
245
-		inline v2d_generic(T _x, T _y) : x(_x), y(_y)            {                                                      }
246
-		inline v2d_generic(const v2d_generic& v) : x(v.x), y(v.y){                                                      }
247
-		inline T mag()                                           { return sqrt(x * x + y * y);                          }
248
-		inline v2d_generic  norm()                               { T r = 1 / mag(); return v2d_generic(x*r, y*r);       }
249
-		inline v2d_generic  perp()                               { return v2d_generic(-y, x);                           }
250
-		inline T dot(const v2d_generic& rhs)                     { return this->x * rhs.x + this->y * rhs.y;            }
251
-		inline T cross(const v2d_generic& rhs)                   { return this->x * rhs.y - this->y * rhs.x;            }
252
-		inline v2d_generic  operator +  (const v2d_generic& rhs) const { return v2d_generic(this->x + rhs.x, this->y + rhs.y);}
253
-		inline v2d_generic  operator -  (const v2d_generic& rhs) const { return v2d_generic(this->x - rhs.x, this->y - rhs.y);}
254
-		inline v2d_generic  operator *  (const T& rhs)           const { return v2d_generic(this->x * rhs, this->y * rhs);    }
255
-		inline v2d_generic  operator /  (const T& rhs)           const { return v2d_generic(this->x / rhs, this->y / rhs);    }
256
-		inline v2d_generic& operator += (const v2d_generic& rhs) { this->x += rhs.x; this->y += rhs.y; return *this;    }
257
-		inline v2d_generic& operator -= (const v2d_generic& rhs) { this->x -= rhs.x; this->y -= rhs.y; return *this;    }
258
-		inline v2d_generic& operator *= (const T& rhs)           { this->x *= rhs; this->y *= rhs; return *this;        }
259
-		inline v2d_generic& operator /= (const T& rhs)           { this->x /= rhs; this->y /= rhs; return *this;        }
260
-		inline T& operator [] (std::size_t i)                    { return *((T*)this + i);	   /* <-- D'oh :( */        }
261
-	};
262
-
263
-	template<class T> inline v2d_generic<T> operator * (const float& lhs, const v2d_generic<T>& rhs) { return v2d_generic<T>(lhs * rhs.x, lhs * rhs.y); }
264
-	template<class T> inline v2d_generic<T> operator * (const double& lhs, const v2d_generic<T>& rhs){ return v2d_generic<T>(lhs * rhs.x, lhs * rhs.y); }
265
-	template<class T> inline v2d_generic<T> operator * (const int& lhs, const v2d_generic<T>& rhs)   { return v2d_generic<T>(lhs * rhs.x, lhs * rhs.y); }
266
-	template<class T> inline v2d_generic<T> operator / (const float& lhs, const v2d_generic<T>& rhs) { return v2d_generic<T>(lhs / rhs.x, lhs / rhs.y); }
267
-	template<class T> inline v2d_generic<T> operator / (const double& lhs, const v2d_generic<T>& rhs){ return v2d_generic<T>(lhs / rhs.x, lhs / rhs.y); }
268
-	template<class T> inline v2d_generic<T> operator / (const int& lhs, const v2d_generic<T>& rhs)   { return v2d_generic<T>(lhs / rhs.x, lhs / rhs.y); }
269
-
270
-	typedef v2d_generic<int> vi2d;
271
-	typedef v2d_generic<float> vf2d;
272
-	typedef v2d_generic<double> vd2d;
273
-
274
-	//=============================================================
275
-
276
 	struct HWButton
238
 	struct HWButton
277
 	{
239
 	{
278
 		bool bPressed = false;	// Set once during the frame the event occurs
240
 		bool bPressed = false;	// Set once during the frame the event occurs

+ 85
- 123
src/debuggers.cpp View File

34
 
34
 
35
 bool Debuggers::OnUserCreate()
35
 bool Debuggers::OnUserCreate()
36
 {
36
 {
37
-    SetPixelMode(olc::Pixel::MASK);
38
     std::srand(std::time(0));
37
     std::srand(std::time(0));
39
 
38
 
40
     if (!olc::SOUND::InitialiseAudio()) {
39
     if (!olc::SOUND::InitialiseAudio()) {
110
     std::string line;
109
     std::string line;
111
     while (std::getline(is, line)) {
110
     while (std::getline(is, line)) {
112
         if (!rtrim(line).empty())
111
         if (!rtrim(line).empty())
113
-            sourceCode.push_back(line);
112
+            originalSourceCode.push_back(line);
114
     }
113
     }
115
 
114
 
116
-    totalLines = sourceCode.size();
115
+    totalLines = originalSourceCode.size();
117
 
116
 
118
     // Free Memory
117
     // Free Memory
119
     pack.ClearPack();
118
     pack.ClearPack();
120
 
119
 
121
     // Creating entities
120
     // Creating entities
122
 
121
 
123
-    auto player = new Player(this);
124
-    programmers.push_back(player);
122
+    ResetGame();
123
+    SwitchState(STATE_MAIN_MENU);
125
 
124
 
126
     return true;
125
     return true;
127
 }
126
 }
128
 
127
 
129
 bool Debuggers::OnUserUpdate(float fElapsedTime)
128
 bool Debuggers::OnUserUpdate(float fElapsedTime)
130
 {
129
 {
131
-    if (!IsFocused())
132
-        return true;
133
-
134
-    if (sourceCode.size() == 0) {
135
-        return GameOver();
136
-    }
137
-
138
-    DrawSprite(0, 0, &backgroundSprite);
139
-
140
-    uint32_t bugsSize = bugs.size();
141
-    auto aliveBugs = std::count_if(bugs.begin(), bugs.end(), [](Bug* bug) { return bug->IsActive() && bug->IsAlive(); });
142
-
143
-    Programmer* player = programmers.at(0);
144
-
145
-    for (auto bug : bugs) {
146
-        if (bug->IsActive()) {
147
-            bug->Update(fElapsedTime);
148
-            bug->Draw();
149
-            for (auto& programmer : programmers) {
150
-                if (programmer->Collides(bug)) {
151
-                    bugsCatched++;
152
-                    if (programmer == player) {
153
-                        bugsCatchedByPlayer++;
154
-                    }
155
-                    bug->Kill();
156
-                    olc::SOUND::PlaySample(bugCatchSample);
157
-                    SpawnBug();
158
-                }
159
-            }
160
-        } else if (bug->IsAlive()) {
161
-            bugsMissed++;
162
-            sourceCode.erase(sourceCode.begin());
163
-
164
-            SpawnBug();
165
-            olc::SOUND::PlaySample(bugFallSample);
166
-        }
167
-    }
168
-
169
-    for (auto& bonus : bonuses) {
170
-        if (bonus->IsActive()) {
171
-            bonus->Update(fElapsedTime);
172
-            bonus->Draw();
173
-            if (player->Collides(bonus)) {
174
-                auto type = bonus->GetType();
175
-                if (type == BONUS_DOCUMENTATION) {
176
-                    if (aliveBugs > 1) {
177
-                        for (auto& bug : bugs) {
178
-                            if (bug->IsAlive() && bug->IsActive()) {
179
-                                bug->Kill();
180
-                                break;
181
-                            }
182
-                        }
183
-                    }
184
-                } else {
185
-                    bonusesCatched[type]++;
186
-                }
187
-                bonus->Kill();
188
-                // TODO play pickup sound
189
-            }
190
-        } else {
191
-            bonus->Kill();
192
-        }
193
-    }
194
-
195
-    linesOfCode = (sourceCode.size() * 4 / totalLines) + 1;
196
-
197
-    for (auto it = programmers.rbegin(); it != programmers.rend(); it++) {
198
-        auto& programmer = *it;
199
-        programmer->Think();
200
-        programmer->Update(fElapsedTime);
201
-        programmer->Draw();
202
-    }
203
-
204
-    if (bugsSize == 0 && player->IsOnGround()) {
205
-        SpawnBug();
206
-    }
207
-
208
-    auto programmersSize = programmers.size();
209
-    if (bugsCatchedByPlayer >= 15 * programmersSize * programmersSize && player->GetSkin() < programmersSize) {
210
-        player->UpgradeLevel();
211
-        SpawnBug();
212
-        SpawnProgrammer();
213
-    }
214
-
215
-    if (bugsCatched > 10 * bugsSize) {
216
-        SpawnBug();
217
-    }
218
-
219
-    if (GetRandom<float>() < 0.01 * fElapsedTime) {
220
-        SpawnBonus();
221
-    }
222
-
223
 #ifdef _DEBUG
130
 #ifdef _DEBUG
224
     if (debug) {
131
     if (debug) {
225
-        DrawString(1, 37, "Bg: " + std::to_string(bugs.size()) + " Ab: " + std::to_string(aliveBugs));
226
-        DrawString(1, 46, "Ps: " + std::to_string(programmers.size()) + " Bn: " + std::to_string(bonuses.size()));
227
-        DrawString(1, 55, "Cp: " + std::to_string(bugsCatchedByPlayer));
228
-        DrawString(1, 64, "DBG: " + std::to_string(bonusesCatched[BONUS_DEBUGGER]));
229
-        DrawString(1, 73, "UTS: " + std::to_string(bonusesCatched[BONUS_UNIT_TEST]));
230
-
231
         if (GetKey(olc::B).bPressed) {
132
         if (GetKey(olc::B).bPressed) {
232
             SpawnBug();
133
             SpawnBug();
233
         }
134
         }
242
         debug = !debug;
143
         debug = !debug;
243
     }
144
     }
244
 #endif
145
 #endif
245
-    DrawString(1, 1, "A,S,D - move; SPACE - jump", olc::CYAN);
246
-    DrawString(1, 10, "Don't let the bugs destroy your code!", olc::YELLOW);
247
-    DrawString(1, 19, "Bugs catched: " + std::to_string(bugsCatched));
248
-    DrawString(1, 28, "Bugs missed: " + std::to_string(bugsMissed));
249
-
250
-    int y = GameScreenHeight();
251
-    FillRect(0, y - 1, ScreenWidth(), ScreenHeight() - y + 1, olc::VERY_DARK_GREY);
252
-
253
-    for (auto& line : sourceCode) {
254
-        DrawString(1, y, line);
255
-        y += 10;
256
-        if (y >= ScreenHeight())
257
-            break;
146
+    switch (state) {
147
+    case STATE_GAME:
148
+    case STATE_MAIN_MENU:
149
+        return GamePlay(fElapsedTime);
150
+    case STATE_PAUSE_MENU:
151
+        return PauseMenu(fElapsedTime);
152
+    case STATE_GAME_OVER:
153
+        return GameOver(fElapsedTime);
154
+    default:
155
+        return false;
258
     }
156
     }
157
+}
259
 
158
 
260
-    return true;
159
+void Debuggers::DrawMenu()
160
+{
161
+    SetPixelMode(olc::Pixel::ALPHA);
162
+    FillRect(0, 0, ScreenWidth(), ScreenHeight(), { 0, 0, 0, 160 });
163
+    SetPixelMode(olc::Pixel::NORMAL);
164
+
165
+    DrawString(ScreenWidth() / 2 - 144, 32, "DEBUGGERS", olc::YELLOW, 4);
166
+    DrawString(ScreenWidth() - 128, 64, "by Pabloader");
167
+    DrawString(ScreenWidth() - 17 * 8 - 2, ScreenHeight() - 10, "OLC Code Jam 2019");
168
+
169
+    std::string resumeText = state == STATE_PAUSE_MENU ? "continue" : "start";
170
+
171
+    DrawString(ScreenWidth() / 2 - 144, 100, "SPACE to " + resumeText + " game");
172
+    DrawString(ScreenWidth() / 2 - 144, 116, "H to view help");
173
+    DrawString(ScreenWidth() / 2 - 144, 132, "X to quit");
174
+
175
+    if (GetKey(olc::SPACE).bPressed || (GetKey(olc::ESCAPE).bPressed && state == STATE_PAUSE_MENU)) {
176
+        SwitchState(STATE_GAME);
177
+    }
178
+
179
+    if (GetKey(olc::H).bPressed) {
180
+        SwitchState(STATE_HELP);
181
+    }
182
+
183
+    if (GetKey(olc::X).bPressed) {
184
+        SwitchState(STATE_QUIT);
185
+    }
186
+}
187
+
188
+void Debuggers::SwitchState(GameState newState)
189
+{
190
+    switch (newState) {
191
+    case STATE_GAME:
192
+        if (state == STATE_MAIN_MENU || state == STATE_GAME_OVER) {
193
+            ResetGame();
194
+            SpawnPlayer();
195
+        }
196
+        break;
197
+    case STATE_MAIN_MENU:
198
+        ResetGame();
199
+        SpawnProgrammer();
200
+        break;
201
+    default:
202
+        break;
203
+    }
204
+
205
+    state = newState;
261
 }
206
 }
262
 
207
 
263
-bool Debuggers::GameOver()
208
+void Debuggers::ResetGame()
264
 {
209
 {
265
-    DrawSprite(0, 0, &backgroundSprite);
266
-    DrawString(ScreenWidth() / 2 - 143, ScreenHeight() / 2 - 15, "GAME OVER", olc::BLACK, 4);
267
-    DrawString(ScreenWidth() / 2 - 144, ScreenHeight() / 2 - 16, "GAME OVER", olc::RED, 4);
210
+    for (auto& i : programmers) {
211
+        delete i;
212
+    }
213
+    programmers.clear();
268
 
214
 
269
-    DrawString(ScreenWidth() / 2 - 144, ScreenHeight() / 2 + 16, "Bugs catched: " + std::to_string(bugsCatched), olc::CYAN, 2);
215
+    for (auto& i : bugs) {
216
+        i->Kill();
217
+    }
270
 
218
 
271
-    return true;
219
+    for (auto& i : bonuses) {
220
+        i->Kill();
221
+    }
222
+
223
+    bonusesCatched.clear();
224
+    bugsCatched = 0;
225
+    bugsCatchedByPlayer = 0;
226
+    bugsMissed = 0;
227
+    sourceCode = originalSourceCode;
272
 }
228
 }
273
 
229
 
274
 void Debuggers::SpawnBug()
230
 void Debuggers::SpawnBug()
283
     bonus->ResetPosition();
239
     bonus->ResetPosition();
284
 }
240
 }
285
 
241
 
242
+void Debuggers::SpawnPlayer()
243
+{
244
+    auto programmer = new Player(this);
245
+    programmers.push_front(programmer);
246
+}
247
+
286
 void Debuggers::SpawnProgrammer()
248
 void Debuggers::SpawnProgrammer()
287
 {
249
 {
288
     auto programmer = new Programmer(this);
250
     auto programmer = new Programmer(this);

+ 195
- 0
src/debuggers_states.cpp View File

1
+#include "debuggers.h"
2
+#include <algorithm>
3
+#include <cmath>
4
+#include <ctime>
5
+#include <iostream>
6
+#include <random>
7
+
8
+namespace pabloader {
9
+
10
+bool Debuggers::GamePlay(float fElapsedTime)
11
+{
12
+    if (state == STATE_GAME) {
13
+        if (!IsFocused() || GetKey(olc::ESCAPE).bPressed) {
14
+            SwitchState(STATE_PAUSE_MENU);
15
+            return true;
16
+        }
17
+
18
+        if (sourceCode.size() == 0) {
19
+            SwitchState(STATE_GAME_OVER);
20
+            return true;
21
+        }
22
+    }
23
+
24
+    DrawSprite(0, 0, &backgroundSprite);
25
+
26
+    uint32_t bugsSize = bugs.size();
27
+    auto aliveBugs = std::count_if(bugs.begin(), bugs.end(), [](Bug* bug) { return bug->IsActive() && bug->IsAlive(); });
28
+
29
+    Programmer* player = programmers.front();
30
+
31
+    for (auto& bug : bugs) {
32
+        if (bug->IsActive()) {
33
+            bug->Update(fElapsedTime);
34
+            bug->Draw();
35
+            for (auto& programmer : programmers) {
36
+                if (programmer->Collides(bug)) {
37
+                    bugsCatched++;
38
+                    if (programmer == player) {
39
+                        bugsCatchedByPlayer++;
40
+                    }
41
+                    bug->Kill();
42
+                    if (state == STATE_GAME)
43
+                        olc::SOUND::PlaySample(bugCatchSample);
44
+                    SpawnBug();
45
+                }
46
+            }
47
+        } else if (bug->IsAlive()) {
48
+            bugsMissed++;
49
+            SpawnBug();
50
+            if (state == STATE_GAME) {
51
+                sourceCode.erase(sourceCode.begin());
52
+                olc::SOUND::PlaySample(bugFallSample);
53
+            }
54
+        }
55
+    }
56
+
57
+    for (auto& bonus : bonuses) {
58
+        if (bonus->IsActive()) {
59
+            bonus->Update(fElapsedTime);
60
+            bonus->Draw();
61
+            if (player->Collides(bonus)) {
62
+                auto type = bonus->GetType();
63
+                if (type == BONUS_DOCUMENTATION) {
64
+                    if (aliveBugs > 1) {
65
+                        for (auto& bug : bugs) {
66
+                            if (bug->IsAlive() && bug->IsActive()) {
67
+                                bug->Kill();
68
+                                break;
69
+                            }
70
+                        }
71
+                    }
72
+                } else {
73
+                    bonusesCatched[type]++;
74
+                }
75
+                bonus->Kill();
76
+                // TODO play pickup sound
77
+            }
78
+        } else {
79
+            bonus->Kill();
80
+        }
81
+    }
82
+
83
+    linesOfCode = (sourceCode.size() * 4 / totalLines) + 1;
84
+
85
+    for (auto it = programmers.rbegin(); it != programmers.rend(); it++) {
86
+        auto& programmer = *it;
87
+        programmer->Think();
88
+        programmer->Update(fElapsedTime);
89
+        programmer->Draw();
90
+    }
91
+
92
+    if (aliveBugs == 0 && player->IsOnGround()) {
93
+        SpawnBug();
94
+    }
95
+
96
+    auto programmersSize = programmers.size();
97
+    if (bugsCatchedByPlayer >= 15 * programmersSize * programmersSize * programmersSize && player->GetSkin() < programmersSize) {
98
+        player->UpgradeLevel();
99
+        SpawnBug();
100
+        SpawnProgrammer();
101
+    }
102
+
103
+    if (bugsCatched > 10 * bugsSize) {
104
+        SpawnBug();
105
+    }
106
+
107
+    if (GetRandom<float>() < 0.01 * fElapsedTime) {
108
+        SpawnBonus();
109
+    }
110
+
111
+#ifdef _DEBUG
112
+    if (debug) {
113
+        DrawString(1, 37, "Bg: " + std::to_string(bugs.size()) + " Ab: " + std::to_string(aliveBugs));
114
+        DrawString(1, 46, "Ps: " + std::to_string(programmers.size()) + " Bn: " + std::to_string(bonuses.size()));
115
+        DrawString(1, 55, "Cp: " + std::to_string(bugsCatchedByPlayer));
116
+        DrawString(1, 64, "DBG: " + std::to_string(bonusesCatched[BONUS_DEBUGGER]));
117
+        DrawString(1, 73, "UTS: " + std::to_string(bonusesCatched[BONUS_UNIT_TEST]));
118
+    }
119
+#endif
120
+    if (state == STATE_GAME) {
121
+        DrawString(1, 1, "A,S,D - move; SPACE - jump", olc::CYAN);
122
+        DrawString(1, 10, "Don't let the bugs destroy your code!", olc::YELLOW);
123
+        DrawString(1, 19, "Bugs catched: " + std::to_string(bugsCatched));
124
+        DrawString(1, 28, "Bugs missed: " + std::to_string(bugsMissed));
125
+    }
126
+
127
+    int y = GameScreenHeight();
128
+    FillRect(0, y - 1, ScreenWidth(), ScreenHeight() - y + 1, olc::VERY_DARK_GREY);
129
+
130
+    for (auto& line : sourceCode) {
131
+        DrawString(1, y, line);
132
+        y += 10;
133
+        if (y >= ScreenHeight())
134
+            break;
135
+    }
136
+
137
+    if (state == STATE_MAIN_MENU) {
138
+        DrawMenu();
139
+    }
140
+
141
+    return true;
142
+}
143
+
144
+bool Debuggers::PauseMenu(float fElapsedTime)
145
+{
146
+    DrawSprite(0, 0, &backgroundSprite);
147
+
148
+    for (auto& bug : bugs) {
149
+        if (bug->IsActive() && bug->IsAlive()) {
150
+            bug->Draw();
151
+        }
152
+    }
153
+
154
+    for (auto& bonus : bonuses) {
155
+        if (bonus->IsActive()) {
156
+            bonus->Draw();
157
+        }
158
+    }
159
+
160
+    for (auto it = programmers.rbegin(); it != programmers.rend(); it++) {
161
+        auto& programmer = *it;
162
+        programmer->Draw();
163
+    }
164
+
165
+    int y = GameScreenHeight();
166
+    FillRect(0, y - 1, ScreenWidth(), ScreenHeight() - y + 1, olc::VERY_DARK_GREY);
167
+
168
+    for (auto& line : sourceCode) {
169
+        DrawString(1, y, line);
170
+        y += 10;
171
+        if (y >= ScreenHeight())
172
+            break;
173
+    }
174
+
175
+    DrawMenu();
176
+
177
+    return true;
178
+}
179
+
180
+bool Debuggers::GameOver(float dt)
181
+{
182
+    DrawSprite(0, 0, &backgroundSprite);
183
+    DrawString(ScreenWidth() / 2 - 143, ScreenHeight() / 2 - 15, "GAME OVER", olc::BLACK, 4);
184
+    DrawString(ScreenWidth() / 2 - 144, ScreenHeight() / 2 - 16, "GAME OVER", olc::RED, 4);
185
+
186
+    DrawString(ScreenWidth() / 2 - 144, ScreenHeight() / 2 + 16, "Bugs catched: " + std::to_string(bugsCatched), olc::CYAN, 2);
187
+    DrawString(ScreenWidth() / 2 - 144, ScreenHeight() / 2 + 34, "Press SPACE to continue");
188
+
189
+    if (GetKey(olc::SPACE).bPressed) {
190
+        SwitchState(STATE_MAIN_MENU);
191
+    }
192
+
193
+    return true;
194
+}
195
+}

+ 4
- 2
src/entity.cpp View File

14
 void Entity::Update(float dt)
14
 void Entity::Update(float dt)
15
 {
15
 {
16
     pos += vel * dt;
16
     pos += vel * dt;
17
-    pos.y += game->gravity * dt;
17
+    vel.y += game->gravity * dt;
18
 
18
 
19
     rotation += rotationSpeed * dt;
19
     rotation += rotationSpeed * dt;
20
 
20
 
37
         game->DrawRect(pos.x - size.x / 2, pos.y - size.y / 2, size.x, size.y, DEBUG_COLOR);
37
         game->DrawRect(pos.x - size.x / 2, pos.y - size.y / 2, size.x, size.y, DEBUG_COLOR);
38
     }
38
     }
39
 #endif
39
 #endif
40
+    game->SetPixelMode(olc::Pixel::MASK);
40
     olc::GFX2D::DrawPartialSprite(sprite, tile.x * size.x, tile.y * size.y, size.x, size.y, transform, true);
41
     olc::GFX2D::DrawPartialSprite(sprite, tile.x * size.x, tile.y * size.y, size.x, size.y, transform, true);
42
+    game->SetPixelMode(olc::Pixel::NORMAL);
41
 }
43
 }
42
 
44
 
43
 bool Entity::IsActive()
45
 bool Entity::IsActive()
48
 {
50
 {
49
     return pos.x > -size.x / 2 && pos.y > -size.y
51
     return pos.x > -size.x / 2 && pos.y > -size.y
50
         && pos.x < game->ScreenWidth() + size.x / 2
52
         && pos.x < game->ScreenWidth() + size.x / 2
51
-        && pos.x < game->ScreenHeight() + size.y / 2;
53
+        && pos.y < game->ScreenHeight() + size.y / 2;
52
 }
54
 }
53
 
55
 
54
 bool Entity::IsAlive()
56
 bool Entity::IsAlive()

+ 22
- 7
src/programmer.cpp View File

18
 {
18
 {
19
     Bug* closest = nullptr;
19
     Bug* closest = nullptr;
20
     float dist = 1e100;
20
     float dist = 1e100;
21
-    for (auto bug : game->bugs) {
21
+    for (auto& bug : game->bugs) {
22
         float d = bug->Dist(this);
22
         float d = bug->Dist(this);
23
         if (d < dist && bug->IsInScreen() && bug->IsAlive()) {
23
         if (d < dist && bug->IsInScreen() && bug->IsAlive()) {
24
             dist = d;
24
             dist = d;
27
     }
27
     }
28
 
28
 
29
     if (closest != nullptr) {
29
     if (closest != nullptr) {
30
+#ifdef _DEBUG
31
+        target.x = closest->GetX();
32
+        target.y = closest->GetY();
33
+#endif
30
         doJump = closest->GetY() < pos.y;
34
         doJump = closest->GetY() < pos.y;
31
         moveDown = closest->GetY() > pos.y;
35
         moveDown = closest->GetY() > pos.y;
32
         walkLeft = closest->GetX() < pos.x;
36
         walkLeft = closest->GetX() < pos.x;
33
         walkRight = closest->GetX() > pos.x;
37
         walkRight = closest->GetX() > pos.x;
34
     } else {
38
     } else {
39
+#ifdef _DEBUG
40
+        target.x = 0;
41
+        target.y = 0;
42
+#endif
35
         doJump = false;
43
         doJump = false;
36
         walkLeft = false;
44
         walkLeft = false;
37
         walkRight = false;
45
         walkRight = false;
81
     if (pos.x > game->ScreenWidth() - size.x / 2) {
89
     if (pos.x > game->ScreenWidth() - size.x / 2) {
82
         vel.x *= -0.3;
90
         vel.x *= -0.3;
83
         pos.x = game->ScreenWidth() - size.x / 2;
91
         pos.x = game->ScreenWidth() - size.x / 2;
84
-        olc::SOUND::PlaySample(game->playerFallSample);
92
+        if (game->GetState() == STATE_GAME)
93
+            olc::SOUND::PlaySample(game->playerFallSample);
85
     }
94
     }
86
 
95
 
87
     if (pos.x < size.x / 2) {
96
     if (pos.x < size.x / 2) {
88
         vel.x *= -0.3;
97
         vel.x *= -0.3;
89
         pos.x = size.x / 2;
98
         pos.x = size.x / 2;
90
-        olc::SOUND::PlaySample(game->playerFallSample);
99
+        if (game->GetState() == STATE_GAME)
100
+            olc::SOUND::PlaySample(game->playerFallSample);
91
     }
101
     }
92
 
102
 
93
     auto groundLevel = game->GameScreenHeight() - size.y / 2 - 1;
103
     auto groundLevel = game->GameScreenHeight() - size.y / 2 - 1;
102
     }
112
     }
103
 
113
 
104
     bool newOnGround = pos.y >= groundLevel;
114
     bool newOnGround = pos.y >= groundLevel;
105
-    if (newOnGround && !onGround) {
115
+    if (newOnGround && !onGround && game->GetState() == STATE_GAME) {
106
         olc::SOUND::PlaySample(game->playerFallSample);
116
         olc::SOUND::PlaySample(game->playerFallSample);
107
     }
117
     }
108
     onGround = newOnGround;
118
     onGround = newOnGround;
127
 
137
 
128
 void Programmer::Draw()
138
 void Programmer::Draw()
129
 {
139
 {
140
+    game->SetPixelMode(olc::Pixel::MASK);
130
     int xOff = walkLeft ? -1 : 0;
141
     int xOff = walkLeft ? -1 : 0;
131
-    if (std::abs(vel.x) < 1) {
132
-        olc::GFX2D::DrawPartialSprite(&game->playerSprite, tile.x * size.x + xOff, size.y + tile.y * size.y, size.x - xOff, size.y, transform, true);
133
-    } else {
142
+    if (walkLeft || walkRight) {
134
         olc::GFX2D::DrawPartialSprite(&game->playerSprite, tile.x * size.x + xOff, 0 + tile.y * size.y, size.x - xOff, size.y, transform, true);
143
         olc::GFX2D::DrawPartialSprite(&game->playerSprite, tile.x * size.x + xOff, 0 + tile.y * size.y, size.x - xOff, size.y, transform, true);
144
+    } else {
145
+        olc::GFX2D::DrawPartialSprite(&game->playerSprite, tile.x * size.x + xOff, size.y + tile.y * size.y, size.x - xOff, size.y, transform, true);
135
     }
146
     }
147
+    game->SetPixelMode(olc::Pixel::NORMAL);
136
 #ifdef _DEBUG
148
 #ifdef _DEBUG
137
     if (game->debug) {
149
     if (game->debug) {
138
         game->DrawRect(pos.x - size.x / 2, pos.y - size.y / 2, size.x, size.y, DEBUG_COLOR);
150
         game->DrawRect(pos.x - size.x / 2, pos.y - size.y / 2, size.x, size.y, DEBUG_COLOR);
151
+        if (target.x != 0 || target.y != 0) {
152
+            game->DrawLine(pos.x, pos.y, target.x, target.y, DEBUG_COLOR);
153
+        }
139
     }
154
     }
140
 #endif
155
 #endif
141
 }
156
 }

Loading…
Cancel
Save