ソースを参照

Modern random numbers generator, deduplicate some code, Bonus class

Pabloader 4年前
コミット
b4ebec6437
13個のファイルの変更205行の追加82行の削除
  1. 3
    1
      .vscode/c_cpp_properties.json
  2. 13
    0
      include/bonus.h
  3. 0
    10
      include/bug.h
  4. 23
    4
      include/debuggers.h
  5. 21
    4
      include/entity.h
  6. 2
    4
      include/programmer.h
  7. 0
    0
      res/bonuses.png
  8. 16
    0
      src/bonus.cpp
  9. 3
    40
      src/bug.cpp
  10. 63
    2
      src/debuggers.cpp
  11. 41
    3
      src/entity.cpp
  12. 4
    1
      src/player.cpp
  13. 16
    13
      src/programmer.cpp

+ 3
- 1
.vscode/c_cpp_properties.json ファイルの表示

@@ -27,7 +27,9 @@
27 27
             "includePath": [
28 28
                 "${workspaceFolder}/**"
29 29
             ],
30
-            "defines": [],
30
+            "defines": [
31
+                "_DEBUG"
32
+            ],
31 33
             "compilerPath": "/usr/bin/gcc",
32 34
             "cStandard": "c11",
33 35
             "cppStandard": "c++17",

+ 13
- 0
include/bonus.h ファイルの表示

@@ -0,0 +1,13 @@
1
+#ifndef BONUS_H
2
+#define BONUS_H
3
+
4
+#include "entity.h"
5
+
6
+namespace pabloader {
7
+class Bonus : public Entity {
8
+public:
9
+    Bonus(Debuggers* game);
10
+};
11
+}
12
+
13
+#endif

+ 0
- 10
include/bug.h ファイルの表示

@@ -7,16 +7,6 @@ namespace pabloader {
7 7
 class Bug : public Entity {
8 8
 public:
9 9
     Bug(Debuggers* game);
10
-    void Update(float dt) override;
11
-    void Draw() override;
12
-    bool IsActive();
13
-    void ResetPosition();
14
-    void Kill();
15
-
16
-private:
17
-    int kind = 0;
18
-    float rotation = 0;
19
-    int8_t rotationSpeed;
20 10
 };
21 11
 }
22 12
 

+ 23
- 4
include/debuggers.h ファイルの表示

@@ -1,27 +1,36 @@
1 1
 #ifndef DEBUGGERS_H
2 2
 #define DEBUGGERS_H
3 3
 
4
-#include "bug.h"
5 4
 #include "olcPGEX_Sound.h"
6 5
 #include "olcPixelGameEngine.h"
7
-#include "programmer.h"
6
+
7
+#include "bonus.h"
8
+#include "bug.h"
8 9
 #include "player.h"
9
-#include <vector>
10
+#include "programmer.h"
11
+
10 12
 #include <string>
13
+#include <vector>
14
+#include <random>
15
+#include <chrono>
11 16
 
12 17
 namespace pabloader {
13 18
 class Debuggers : public olc::PixelGameEngine {
14 19
 private:
15 20
     std::vector<Programmer*> programmers;
21
+    std::vector<Bonus*> bonuses;
22
+
16 23
     uint32_t bugsCatched = 0;
17 24
     uint32_t bugsMissed = 0;
18 25
 
19 26
     uint8_t linesOfCode = 5;
20 27
     uint16_t totalLines;
21 28
     std::vector<std::string> sourceCode;
29
+    std::random_device rd;
30
+    std::mt19937 generator;
22 31
 
23 32
 public:
24
-    Debuggers()
33
+    Debuggers(): generator(rd())
25 34
     {
26 35
         sAppName = "Debuggers";
27 36
     }
@@ -32,22 +41,32 @@ public:
32 41
     bool OnUserDestroy() override;
33 42
     int GameScreenHeight() { return ScreenHeight() - linesOfCode * 10; };
34 43
 
44
+    template <typename T>
45
+    T GetRandom(T from = 0, T to = 1);
46
+
35 47
 private:
36 48
     void SpawnProgrammer();
37 49
     void SpawnBug();
50
+    void SpawnBonus();
38 51
     Bug* CreateBug();
52
+    Bonus* CreateBonus();
39 53
     bool GameOver();
40 54
 
41 55
 public:
42 56
     std::vector<Bug*> bugs;
43 57
 
44 58
     olc::ResourcePack pack;
59
+
45 60
     olc::Sprite playerSprite;
46 61
     olc::Sprite enemiesSprite;
62
+    olc::Sprite bonusesSprite;
47 63
     olc::Sprite backgroundSprite;
64
+
48 65
     int playerFallSample;
49 66
     int bugFallSample;
50 67
     int bugCatchSample;
68
+
69
+    const int gravity = 30;
51 70
 };
52 71
 }
53 72
 

+ 21
- 4
include/entity.h ファイルの表示

@@ -11,23 +11,40 @@ class Debuggers;
11 11
 class Entity {
12 12
 protected:
13 13
     Debuggers* game;
14
+    olc::Sprite* sprite;
14 15
     olc::GFX2D::Transform2D transform;
15 16
     float x, y;
16
-    float xv, yv;
17
+    float xv = 0, yv = 0;
17 18
     int w, h;
18 19
 
20
+    uint8_t tileX = 0;
21
+    uint8_t tileY = 0;
22
+
23
+    uint8_t tileCols = 4;
24
+    uint8_t tileRows = 4;
25
+
26
+    float rotation = 0;
27
+    float rotationSpeed = 0;
28
+#ifdef _DEBUG
29
+    olc::Pixel DEBUG_COLOR;
30
+#endif
31
+
19 32
 public:
20
-    Entity(Debuggers* game_);
33
+    Entity(Debuggers* game, olc::Sprite* s);
21 34
     virtual ~Entity(){};
22 35
 
23
-    virtual void Update(float dt) = 0;
24
-    virtual void Draw() = 0;
36
+    virtual void Update(float dt);
37
+    virtual void Draw();
25 38
 
26 39
     float GetX() { return x; }
27 40
     float GetY() { return y; }
28 41
 
29 42
     bool Collides(Entity* entity);
30 43
     float Dist(Entity* entity) { return std::hypot(x - entity->x, y - entity->y); }
44
+
45
+    virtual bool IsActive();
46
+    virtual void ResetPosition();
47
+    virtual void Kill();
31 48
 };
32 49
 }
33 50
 

+ 2
- 4
include/programmer.h ファイルの表示

@@ -8,9 +8,7 @@ namespace pabloader {
8 8
 
9 9
 class Programmer : public Entity {
10 10
 protected:
11
-    uint8_t tile = 0;
12 11
     uint32_t tileCounter = 0;
13
-    uint8_t skin = 0;
14 12
     bool onGround = false;
15 13
     bool doJump = false;
16 14
     bool walkLeft = false;
@@ -23,8 +21,8 @@ public:
23 21
     virtual void Update(float dt) override;
24 22
     virtual void Draw() override;
25 23
     bool IsOnGround() { return onGround; }
26
-    uint8_t GetSkin() { return skin; }
27
-    void UpgradeLevel() { skin = std::min(skin + 1, 2); }
24
+    uint8_t GetSkin() { return tileX; }
25
+    void UpgradeLevel() { tileX = std::min(tileX + 1, tileCols - 1); }
28 26
 };
29 27
 }
30 28
 

res/sprites.png → res/bonuses.png ファイルの表示


+ 16
- 0
src/bonus.cpp ファイルの表示

@@ -0,0 +1,16 @@
1
+#include "bug.h"
2
+#include "debuggers.h"
3
+#include <iostream>
4
+#include <random>
5
+
6
+namespace pabloader {
7
+Bonus::Bonus(Debuggers* game)
8
+    : Entity(game, &game->bonusesSprite)
9
+{
10
+    tileCols = 1;
11
+    tileRows = 1;
12
+#ifdef _DEBUG
13
+    DEBUG_COLOR = olc::YELLOW;
14
+#endif
15
+}
16
+}

+ 3
- 40
src/bug.cpp ファイルの表示

@@ -5,48 +5,11 @@
5 5
 
6 6
 namespace pabloader {
7 7
 Bug::Bug(Debuggers* game)
8
-    : Entity(game)
9
-{
10
-    w = game->enemiesSprite.width / 4;
11
-    h = game->enemiesSprite.height / 4;
12
-}
13
-
14
-void Bug::Update(float dt)
15
-{
16
-    y += yv * dt;
17
-    yv += 30 * dt;
18
-
19
-    rotation += 3.14 / 8 * rotationSpeed * dt;
20
-
21
-    transform.Reset();
22
-    transform.Rotate(rotation);
23
-    transform.Translate(x, y);
24
-}
25
-
26
-void Bug::Draw()
8
+    : Entity(game, &game->enemiesSprite)
27 9
 {
10
+    tileCols = 1;
28 11
 #ifdef _DEBUG
29
-    game->DrawRect(x - w / 2, y - h / 2, w, h, olc::RED);
12
+    DEBUG_COLOR = olc::RED;
30 13
 #endif
31
-    olc::GFX2D::DrawPartialSprite(&game->enemiesSprite, 0, kind * h, w, h, transform, true);
32
-}
33
-
34
-bool Bug::IsActive()
35
-{
36
-    return y - h / 2 < game->GameScreenHeight();
37
-}
38
-
39
-void Bug::ResetPosition()
40
-{
41
-    y = -20 - std::rand() % game->ScreenHeight();
42
-    x = w + std::rand() % (game->ScreenWidth() - w * 2);
43
-    yv = 0;
44
-    kind = std::rand() % 4;
45
-    rotationSpeed = -8 + rand()%17;
46
-}
47
-
48
-void Bug::Kill()
49
-{
50
-    y = game->GameScreenHeight() + 100;
51 14
 }
52 15
 }

+ 63
- 2
src/debuggers.cpp ファイルの表示

@@ -63,6 +63,14 @@ bool Debuggers::OnUserCreate()
63 63
         return false;
64 64
     }
65 65
 
66
+    // Load bonuses
67
+
68
+    fileName = "res/bonuses.pgs";
69
+    if (!bonusesSprite.LoadFromPGESprFile(fileName, &pack)) {
70
+        std::cerr << "[Load bonuses] File " << fileName << " is not found" << std::endl;
71
+        return false;
72
+    }
73
+
66 74
     // Load background
67 75
 
68 76
     fileName = "res/bg.pgs";
@@ -131,6 +139,19 @@ bool Debuggers::OnUserUpdate(float fElapsedTime)
131 139
         }
132 140
     }
133 141
 
142
+    Programmer* player = programmers.at(0);
143
+
144
+    for (auto& bonus : bonuses) {
145
+        if (bonus->IsActive()) {
146
+            bonus->Update(fElapsedTime);
147
+            bonus->Draw();
148
+            if (player->Collides(bonus)) {
149
+                // TODO add to inventory
150
+                bonus->Kill();
151
+            }
152
+        }
153
+    }
154
+
134 155
     linesOfCode = (sourceCode.size() * 4 / totalLines) + 1;
135 156
 
136 157
     for (auto it = programmers.rbegin(); it != programmers.rend(); it++) {
@@ -140,8 +161,6 @@ bool Debuggers::OnUserUpdate(float fElapsedTime)
140 161
         programmer->Draw();
141 162
     }
142 163
 
143
-    Programmer* player = programmers.at(0);
144
-
145 164
     if (bugsSize == 0 && player->IsOnGround()) {
146 165
         SpawnBug();
147 166
     }
@@ -155,9 +174,14 @@ bool Debuggers::OnUserUpdate(float fElapsedTime)
155 174
 
156 175
 #ifdef _DEBUG
157 176
     DrawString(1, 37, "Bugs: " + std::to_string(bugs.size()));
177
+    DrawString(1, 46, "Progs: " + std::to_string(programmers.size()));
178
+    DrawString(1, 55, "Bonuses: " + std::to_string(bonuses.size()));
158 179
     if (GetKey(olc::B).bPressed) {
159 180
         SpawnBug();
160 181
     }
182
+    if (GetKey(olc::N).bPressed) {
183
+        SpawnBonus();
184
+    }
161 185
     if (GetKey(olc::P).bPressed) {
162 186
         SpawnProgrammer();
163 187
     }
@@ -197,6 +221,12 @@ void Debuggers::SpawnBug()
197 221
     bug->ResetPosition();
198 222
 }
199 223
 
224
+void Debuggers::SpawnBonus()
225
+{
226
+    auto bonus = CreateBonus();
227
+    bonus->ResetPosition();
228
+}
229
+
200 230
 void Debuggers::SpawnProgrammer()
201 231
 {
202 232
     auto programmer = new Programmer(this);
@@ -214,9 +244,40 @@ Bug* Debuggers::CreateBug()
214 244
     return bug;
215 245
 }
216 246
 
247
+Bonus* Debuggers::CreateBonus()
248
+{
249
+    for (auto bonus : bonuses) {
250
+        if (!bonus->IsActive())
251
+            return bonus;
252
+    }
253
+    auto bonus = new Bonus(this);
254
+    bonuses.push_back(bonus);
255
+    return bonus;
256
+}
257
+
217 258
 bool Debuggers::OnUserDestroy()
218 259
 {
219 260
     olc::SOUND::DestroyAudio();
220 261
     return true;
221 262
 }
263
+
264
+template <>
265
+float Debuggers::GetRandom<float>(float from, float to)
266
+{
267
+    if (from > to) {
268
+        std::swap(from, to);
269
+    }
270
+    std::uniform_real_distribution<double> dist(from, to);
271
+    return dist(generator);
272
+}
273
+
274
+template <>
275
+int Debuggers::GetRandom<int>(int from, int to)
276
+{
277
+    if (from > to) {
278
+        std::swap(from, to);
279
+    }
280
+    std::uniform_int_distribution<int> dist(from, to - 1);
281
+    return dist(generator);
282
+}
222 283
 }

+ 41
- 3
src/entity.cpp ファイルの表示

@@ -1,13 +1,24 @@
1 1
 #include "entity.h"
2
+#include "debuggers.h"
2 3
 
3 4
 namespace pabloader {
4
-Entity::Entity(Debuggers* game)
5
+Entity::Entity(Debuggers* game, olc::Sprite* s): sprite(s), w(s->width / 4), h(s->height / 4)
5 6
 {
6
-    xv = 0;
7
-    yv = 0;
8 7
     Entity::game = game;
9 8
 }
10 9
 
10
+void Entity::Update(float dt)
11
+{
12
+    y += yv * dt;
13
+    yv += game->gravity * dt;
14
+
15
+    rotation += rotationSpeed * dt;
16
+
17
+    transform.Reset();
18
+    transform.Rotate(rotation);
19
+    transform.Translate(x, y);
20
+}
21
+
11 22
 bool Entity::Collides(Entity* entity)
12 23
 {
13 24
     bool collidesX = (x - w / 2 < entity->x + entity->w / 2) && (entity->x - entity->w / 2 < x + w / 2);
@@ -15,4 +26,31 @@ bool Entity::Collides(Entity* entity)
15 26
     return collidesX && collidesY;
16 27
 }
17 28
 
29
+void Entity::Draw()
30
+{
31
+#ifdef _DEBUG
32
+    game->DrawRect(x - w / 2, y - h / 2, w, h, DEBUG_COLOR);
33
+#endif
34
+    olc::GFX2D::DrawPartialSprite(sprite, tileX * w, tileY * h, w, h, transform, true);
35
+}
36
+
37
+bool Entity::IsActive()
38
+{
39
+    return y - h / 2 < game->GameScreenHeight();
40
+}
41
+
42
+void Entity::ResetPosition()
43
+{
44
+    y = game->GetRandom(-20, -game->ScreenHeight());
45
+    x = game->GetRandom(w, game->ScreenWidth() - w);
46
+    yv = 0;
47
+    tileX = game->GetRandom<int>(0, tileCols);
48
+    tileY = game->GetRandom<int>(0, tileRows);
49
+    rotationSpeed = game->GetRandom(-3.14f, 3.14f);
50
+}
51
+
52
+void Entity::Kill()
53
+{
54
+    y = game->ScreenHeight() + 100;
55
+}
18 56
 }

+ 4
- 1
src/player.cpp ファイルの表示

@@ -7,6 +7,9 @@ namespace pabloader {
7 7
 Player::Player(Debuggers* game)
8 8
     : Programmer(game)
9 9
 {
10
+#ifdef _DEBUG
11
+    DEBUG_COLOR = olc::BLUE;
12
+#endif
10 13
 }
11 14
 
12 15
 void Player::Think()
@@ -20,7 +23,7 @@ void Player::Think()
20 23
     // game->DrawString(1, 28, std::to_string(xv) + " " + std::to_string(yv));
21 24
 
22 25
     if (game->GetKey(olc::J).bPressed) {
23
-        skin = (skin + 1) % 4;
26
+        tileX = (tileX + 1) % tileCols;
24 27
     }
25 28
 #endif
26 29
 }

+ 16
- 13
src/programmer.cpp ファイルの表示

@@ -5,12 +5,15 @@
5 5
 
6 6
 namespace pabloader {
7 7
 Programmer::Programmer(Debuggers* game)
8
-    : Entity(game)
8
+    : Entity(game, &game->playerSprite)
9 9
 {
10
-    w = game->playerSprite.width / 4;
11
-    h = game->playerSprite.height / 4;
12 10
     x = (game->ScreenWidth() - w) / 2;
13 11
     y = h / 2;
12
+    tileCols = 3;
13
+
14
+#ifdef _DEBUG
15
+    DEBUG_COLOR = olc::GREEN;
16
+#endif
14 17
 }
15 18
 
16 19
 void Programmer::Think()
@@ -46,7 +49,7 @@ void Programmer::Update(float dt)
46 49
     xv *= 1 - 0.2 * dt;
47 50
 
48 51
     if (!onGround) {
49
-        yv += (70 + skin * 30) * dt;
52
+        yv += (70 + tileX * 30) * dt;
50 53
         yv *= 1 - 0.05 * dt;
51 54
     } else {
52 55
         xv *= 1 - dt;
@@ -57,23 +60,23 @@ void Programmer::Update(float dt)
57 60
     bool userInput = false;
58 61
 
59 62
     if (doJump && onGround) {
60
-        yv = -100 - 50 * skin;
63
+        yv = -100 - 50 * tileX;
61 64
         userInput = true;
62 65
     }
63 66
 
64 67
     if (walkLeft) {
65
-        xv -= (150 + skin * 50) * dt;
68
+        xv -= (150 + tileX * 50) * dt;
66 69
         userInput = true;
67 70
     }
68 71
 
69 72
     if (walkRight) {
70
-        xv += (150 + skin * 50) * dt;
73
+        xv += (150 + tileX * 50) * dt;
71 74
         userInput = true;
72 75
     }
73 76
 
74 77
     if (moveDown) {
75 78
         if (!onGround) {
76
-            yv += (150 + skin * 50) * dt;
79
+            yv += (150 + tileX * 50) * dt;
77 80
         }
78 81
         userInput = true;
79 82
     }
@@ -106,10 +109,10 @@ void Programmer::Update(float dt)
106 109
     onGround = newOnGround;
107 110
 
108 111
     if (onGround) {
109
-        tile = 2;
112
+        tileY = 2;
110 113
         tileCounter = static_cast<uint32_t>(0.1 / dt);
111 114
     } else if (tileCounter <= 0) {
112
-        tile = 0;
115
+        tileY = 0;
113 116
     } else {
114 117
         tileCounter--;
115 118
     }
@@ -127,12 +130,12 @@ void Programmer::Draw()
127 130
 {
128 131
     int xOff = xv < 0 ? -1 : 0;
129 132
     if (std::abs(xv) < 1) {
130
-        olc::GFX2D::DrawPartialSprite(&game->playerSprite, skin * w + xOff, h + tile * h, w - xOff, h, transform, true);
133
+        olc::GFX2D::DrawPartialSprite(&game->playerSprite, tileX * w + xOff, h + tileY * h, w - xOff, h, transform, true);
131 134
     } else {
132
-        olc::GFX2D::DrawPartialSprite(&game->playerSprite, skin * w + xOff, 0 + tile * h, w - xOff, h, transform, true);
135
+        olc::GFX2D::DrawPartialSprite(&game->playerSprite, tileX * w + xOff, 0 + tileY * h, w - xOff, h, transform, true);
133 136
     }
134 137
 #ifdef _DEBUG
135
-    game->DrawRect(x - w / 2, y - h / 2, w, h, olc::GREEN);
138
+    game->DrawRect(x - w / 2, y - h / 2, w, h, DEBUG_COLOR);
136 139
 #endif
137 140
 }
138 141
 }

読み込み中…
キャンセル
保存