Browse Source

Menus ang game states

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

+ 10
- 10
TODO.md View File

@@ -1,15 +1,15 @@
1 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 13
  - [ ] Add obstacles to prevent flying across the screen
14 14
    - [ ] Edits by customer
15 15
    - [ ] QA engineers

+ 0
- 0
bin/.gitkeep View File


+ 35
- 10
include/debuggers.h View File

@@ -10,16 +10,26 @@
10 10
 #include "programmer.h"
11 11
 
12 12
 #include <chrono>
13
+#include <list>
13 14
 #include <map>
14 15
 #include <random>
15 16
 #include <string>
16 17
 #include <vector>
17 18
 
18 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 29
 class Debuggers : public olc::PixelGameEngine {
20 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 34
     std::map<BonusType, uint32_t> bonusesCatched;
25 35
 
@@ -29,13 +39,16 @@ private:
29 39
 
30 40
     uint8_t linesOfCode = 5;
31 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 47
     std::mt19937 generator;
35 48
 
36 49
 public:
37 50
     Debuggers()
38
-        : generator(rd())
51
+        : generator(std::chrono::system_clock::now().time_since_epoch().count())
39 52
     {
40 53
         sAppName = "Debuggers";
41 54
     }
@@ -44,21 +57,33 @@ public:
44 57
     bool OnUserCreate() override;
45 58
     bool OnUserUpdate(float fElapsedTime) override;
46 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 63
     template <typename T>
50 64
     T GetRandom(T from = 0, T to = 1);
51 65
 
52 66
 private:
67
+    void ResetGame();
68
+    void SwitchState(GameState newState);
69
+    void DrawMenu();
70
+
71
+    void SpawnPlayer();
53 72
     void SpawnProgrammer();
54 73
     void SpawnBug();
55 74
     void SpawnBonus();
56 75
     Bug* CreateBug();
57 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 85
 public:
61
-    std::vector<Bug*> bugs;
86
+    std::list<Bug*> bugs;
62 87
 
63 88
     olc::ResourcePack pack;
64 89
 
@@ -71,9 +96,9 @@ public:
71 96
     int bugFallSample;
72 97
     int bugCatchSample;
73 98
 
74
-    const int gravity = 30;
99
+    const int gravity = 25;
75 100
 #ifdef _DEBUG
76
-    bool debug = true;
101
+    bool debug = false;
77 102
 #endif
78 103
 };
79 104
 }

+ 5
- 0
include/programmer.h View File

@@ -23,6 +23,11 @@ public:
23 23
     bool IsOnGround() { return onGround; }
24 24
     uint8_t GetSkin() { return tile.x; }
25 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,6 +33,43 @@ namespace olc {
33 33
         NO_FILE = -1,
34 34
     };
35 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 75
 #endif

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

@@ -235,44 +235,6 @@
235 235
 
236 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 238
 	struct HWButton
277 239
 	{
278 240
 		bool bPressed = false;	// Set once during the frame the event occurs

+ 85
- 123
src/debuggers.cpp View File

@@ -34,7 +34,6 @@ int Debuggers::GetRandom<int>(int from, int to)
34 34
 
35 35
 bool Debuggers::OnUserCreate()
36 36
 {
37
-    SetPixelMode(olc::Pixel::MASK);
38 37
     std::srand(std::time(0));
39 38
 
40 39
     if (!olc::SOUND::InitialiseAudio()) {
@@ -110,124 +109,26 @@ bool Debuggers::OnUserCreate()
110 109
     std::string line;
111 110
     while (std::getline(is, line)) {
112 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 117
     // Free Memory
119 118
     pack.ClearPack();
120 119
 
121 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 125
     return true;
127 126
 }
128 127
 
129 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 130
 #ifdef _DEBUG
224 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 132
         if (GetKey(olc::B).bPressed) {
232 133
             SpawnBug();
233 134
         }
@@ -242,33 +143,88 @@ bool Debuggers::OnUserUpdate(float fElapsedTime)
242 143
         debug = !debug;
243 144
     }
244 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 230
 void Debuggers::SpawnBug()
@@ -283,6 +239,12 @@ void Debuggers::SpawnBonus()
283 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 248
 void Debuggers::SpawnProgrammer()
287 249
 {
288 250
     auto programmer = new Programmer(this);

+ 195
- 0
src/debuggers_states.cpp View File

@@ -0,0 +1,195 @@
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,7 +14,7 @@ Entity::Entity(Debuggers* game, olc::Sprite* s)
14 14
 void Entity::Update(float dt)
15 15
 {
16 16
     pos += vel * dt;
17
-    pos.y += game->gravity * dt;
17
+    vel.y += game->gravity * dt;
18 18
 
19 19
     rotation += rotationSpeed * dt;
20 20
 
@@ -37,7 +37,9 @@ void Entity::Draw()
37 37
         game->DrawRect(pos.x - size.x / 2, pos.y - size.y / 2, size.x, size.y, DEBUG_COLOR);
38 38
     }
39 39
 #endif
40
+    game->SetPixelMode(olc::Pixel::MASK);
40 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 45
 bool Entity::IsActive()
@@ -48,7 +50,7 @@ bool Entity::IsInScreen()
48 50
 {
49 51
     return pos.x > -size.x / 2 && pos.y > -size.y
50 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 56
 bool Entity::IsAlive()

+ 22
- 7
src/programmer.cpp View File

@@ -18,7 +18,7 @@ void Programmer::Think()
18 18
 {
19 19
     Bug* closest = nullptr;
20 20
     float dist = 1e100;
21
-    for (auto bug : game->bugs) {
21
+    for (auto& bug : game->bugs) {
22 22
         float d = bug->Dist(this);
23 23
         if (d < dist && bug->IsInScreen() && bug->IsAlive()) {
24 24
             dist = d;
@@ -27,11 +27,19 @@ void Programmer::Think()
27 27
     }
28 28
 
29 29
     if (closest != nullptr) {
30
+#ifdef _DEBUG
31
+        target.x = closest->GetX();
32
+        target.y = closest->GetY();
33
+#endif
30 34
         doJump = closest->GetY() < pos.y;
31 35
         moveDown = closest->GetY() > pos.y;
32 36
         walkLeft = closest->GetX() < pos.x;
33 37
         walkRight = closest->GetX() > pos.x;
34 38
     } else {
39
+#ifdef _DEBUG
40
+        target.x = 0;
41
+        target.y = 0;
42
+#endif
35 43
         doJump = false;
36 44
         walkLeft = false;
37 45
         walkRight = false;
@@ -81,13 +89,15 @@ void Programmer::Update(float dt)
81 89
     if (pos.x > game->ScreenWidth() - size.x / 2) {
82 90
         vel.x *= -0.3;
83 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 96
     if (pos.x < size.x / 2) {
88 97
         vel.x *= -0.3;
89 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 103
     auto groundLevel = game->GameScreenHeight() - size.y / 2 - 1;
@@ -102,7 +112,7 @@ void Programmer::Update(float dt)
102 112
     }
103 113
 
104 114
     bool newOnGround = pos.y >= groundLevel;
105
-    if (newOnGround && !onGround) {
115
+    if (newOnGround && !onGround && game->GetState() == STATE_GAME) {
106 116
         olc::SOUND::PlaySample(game->playerFallSample);
107 117
     }
108 118
     onGround = newOnGround;
@@ -127,15 +137,20 @@ void Programmer::Update(float dt)
127 137
 
128 138
 void Programmer::Draw()
129 139
 {
140
+    game->SetPixelMode(olc::Pixel::MASK);
130 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 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 148
 #ifdef _DEBUG
137 149
     if (game->debug) {
138 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 155
 #endif
141 156
 }

Loading…
Cancel
Save