]> git.seodisparate.com - LD52/commitdiff
WIP work on game
authorStephen Seo <seo.disparate@gmail.com>
Sat, 7 Jan 2023 07:01:46 +0000 (16:01 +0900)
committerStephen Seo <seo.disparate@gmail.com>
Sat, 7 Jan 2023 07:01:46 +0000 (16:01 +0900)
Game is almost done. The core functionality is working. May need tweaking and
sfx.

src/constants.h
src/game.cc
src/game.h
src/helpers.cc
src/helpers.h

index 086443922b22c8ac392414ce4395d9d9085beda7..39ec957c99574f2ab113c77ea9a05a527c83a651 100644 (file)
@@ -22,11 +22,11 @@ constexpr int APPLE_COORDS[4] = {513, 0, 250, 251};
 constexpr int BROCCOLI_COORDS[4] = {767, 2, 268, 153};
 constexpr int BANANA_COORDS[4] = {525, 254, 189, 355};
 
-constexpr float CORN_EYE_OFFSET[2] = {-10, 0};
+constexpr float CORN_EYE_OFFSET[2] = {-0.01F, 0};
 constexpr float GRAPES_EYE_OFFSET[2] = {0, 0};
 constexpr float APPLE_EYE_OFFSET[2] = {0, 0};
 constexpr float BROCCOLI_EYE_OFFSET[2] = {0, 0};
-constexpr float BANANA_EYE_OFFSET[2] = {40, 0};
+constexpr float BANANA_EYE_OFFSET[2] = {0.2F, 0};
 
 constexpr float EYE_WIDTH_RATIO = 0.3F;
 
@@ -44,8 +44,14 @@ constexpr float MIN_BLINK_TIME = 1.0F;
 constexpr float MAX_BLINK_TIME = 20.0F;
 constexpr float BLINK_DURATION = 0.7F;
 
-constexpr float CUT_TIMER_RATE = 1.0F;
+constexpr float CUT_RATE = 0.7F;
 
-constexpr float CUT_TIMER_RATE_INC_AMT = 0.03F;
+constexpr float CUT_TIMER_RATE_INC_AMT = 0.1F;
+
+constexpr float SPLIT_DX = 60.0F;
+constexpr float SPLIT_DY = 100.0F;
+constexpr float SPLIT_DA = 80.0F;
+
+constexpr float POST_CUT_TIME = 1.7F;
 
 #endif
index dd038271ffb6e4bbf8824f8f1a2fefe87bb17006..df07ab1aed4e22749783858558ffc9abf9413d37 100644 (file)
@@ -11,8 +11,9 @@
 Game::Game()
     : re(std::random_device{}()), dist(0, FOOD_COUNT - 1), score(0),
       areaSizeRatio(1.0F), currentFood(dist(re)), blinkTimer(10.0F),
-      cutTimer(0.0F), cutTimerRateInc(1.0F) {
+      cutTimer(0.0F), cutTimerRateInc(1.0F), postCutTimer(0.0F) {
   flags.set(0);
+  flags.set(3);
 
   spriteSheet = LoadTexture("resources/produceStuff.png");
 }
@@ -35,8 +36,8 @@ void Game::update_impl() {
       for (unsigned long long i = score; i > 0; i /= 10) {
         temp.push_back((i % 10) + '0');
       }
-      for (auto c : temp) {
-        scoreString.push_back(c);
+      for (int i = temp.size(); i-- > 0;) {
+        scoreString.push_back(temp[i]);
       }
     }
   }
@@ -52,136 +53,180 @@ void Game::update_impl() {
     }
   }
 
-  cutTimer += dt * CUT_TIMER_RATE * cutTimerRateInc;
-  if (cutTimer > 1.0F) {
-    cutTimer -= 1.0F;
-  }
-}
-
-void Game::draw_impl() {
+  if (flags.test(3)) {
+    flags.reset(3);
+    switch (currentFood) {
+    case (unsigned int)FoodType::FT_APPLE:
+      ratio = (float)APPLE_COORDS[2] / (float)APPLE_COORDS[3];
+      break;
+    case (unsigned int)FoodType::FT_BANANA:
+      ratio = (float)BANANA_COORDS[2] / (float)BANANA_COORDS[3];
+      break;
+    case (unsigned int)FoodType::FT_BROCCOLI:
+      ratio = (float)BROCCOLI_COORDS[2] / (float)BROCCOLI_COORDS[3];
+      break;
+    case (unsigned int)FoodType::FT_CORN:
+      ratio = (float)CORN_COORDS[2] / (float)CORN_COORDS[3];
+      break;
+    case (unsigned int)FoodType::FT_GRAPES:
+      ratio = (float)GRAPES_COORDS[2] / (float)GRAPES_COORDS[3];
+      break;
+    default:
+      ratio = 1.0F;
+      break;
+    }
 
-  BeginDrawing();
-  ClearBackground(RAYWHITE);
+    if (ratio < 1.0F) {
+      height = MAX_FOOD_WH;
+      width = height * ratio;
+    } else {
+      width = MAX_FOOD_WH;
+      height = width / ratio;
+    }
 
-  float ratio;
-  float width;
-  float height;
-  float offsetX;
-  float offsetY;
-
-  switch (currentFood) {
-  case (unsigned int)FoodType::FT_APPLE:
-    ratio = (float)APPLE_COORDS[2] / (float)APPLE_COORDS[3];
-    break;
-  case (unsigned int)FoodType::FT_BANANA:
-    ratio = (float)BANANA_COORDS[2] / (float)BANANA_COORDS[3];
-    break;
-  case (unsigned int)FoodType::FT_BROCCOLI:
-    ratio = (float)BROCCOLI_COORDS[2] / (float)BROCCOLI_COORDS[3];
-    break;
-  case (unsigned int)FoodType::FT_CORN:
-    ratio = (float)CORN_COORDS[2] / (float)CORN_COORDS[3];
-    break;
-  case (unsigned int)FoodType::FT_GRAPES:
-    ratio = (float)GRAPES_COORDS[2] / (float)GRAPES_COORDS[3];
-    break;
-  default:
-    ratio = 1.0F;
-    break;
+    if (width > GetScreenWidth() && height <= GetScreenHeight()) {
+      if (ratio < 1.0F) {
+        height = GetScreenWidth() / ratio;
+        width = height * ratio;
+      } else {
+        width = GetScreenWidth();
+        height = width / ratio;
+      }
+    } else if (width <= GetScreenWidth() && height > GetScreenHeight()) {
+      if (ratio < 1.0F) {
+        height = GetScreenHeight();
+        width = height * ratio;
+      } else {
+        width = GetScreenHeight() * ratio;
+        height = width / ratio;
+      }
+    }
+    offsetX = (GetScreenWidth() - width) / 2.0F;
+    offsetY = (GetScreenHeight() - height) / 2.0F;
   }
 
-  if (ratio < 1.0F) {
-    height = MAX_FOOD_WH;
-    width = height * ratio;
-  } else {
-    width = MAX_FOOD_WH;
-    height = width / ratio;
+  if (!flags.test(4)) {
+    cutTimer += dt * CUT_RATE * cutTimerRateInc;
+    if (cutTimer > 1.0F) {
+      cutTimer -= 1.0F;
+    }
   }
 
-  if (width > GetScreenWidth() && height <= GetScreenHeight()) {
-    if (ratio < 1.0F) {
-      height = GetScreenWidth() / ratio;
-      width = height * ratio;
+  cutPos = cutTimer * height + offsetY - height / 3.0F;
+
+  if (!flags.test(4) && IsMouseButtonPressed(0)) {
+    flags.set(4);
+    if (cutPos >= offsetY && cutPos <= offsetY + height / 3.0F) {
+      // in correct range
+      flags.set(2);
+      ++score;
+      flags.set(0);
+    } else if (cutPos > offsetY + height / 3.0F) {
+      // past range
+      flags.set(5);
+      postCutTimer = POST_CUT_TIME;
     } else {
-      width = GetScreenWidth();
-      height = width / ratio;
+      // before range
+      postCutTimer = POST_CUT_TIME;
     }
-  } else if (width <= GetScreenWidth() && height > GetScreenHeight()) {
-    if (ratio < 1.0F) {
-      height = GetScreenHeight();
-      width = height * ratio;
-    } else {
-      width = GetScreenHeight() * ratio;
-      height = width / ratio;
+
+    if (flags.test(4) && (flags.test(2) || flags.test(5)) && !flags.test(6)) {
+      flags.set(6);
+      relativeCutRatio = (cutPos - offsetY) / height;
+      splitX = offsetX;
+      splitY = offsetY;
+      splitAngle = 0.0F;
+      splitDX = std::uniform_real_distribution<float>(-SPLIT_DX, SPLIT_DX)(re);
+      splitDY = std::uniform_real_distribution<float>(-SPLIT_DY, SPLIT_DY)(re);
+      splitDAngle =
+          std::uniform_real_distribution<float>(-SPLIT_DA, SPLIT_DA)(re);
+      postCutTimer = POST_CUT_TIME;
+      cutTimerRateInc += CUT_TIMER_RATE_INC_AMT;
+    }
+  }
+
+  if (flags.test(6)) {
+    splitX += splitDX * dt;
+    splitY += splitDY * dt;
+    splitAngle += splitDAngle * dt;
+  }
+  if (postCutTimer > 0.0F) {
+    postCutTimer -= dt;
+    if (postCutTimer <= 0.0F) {
+      reset(!flags.test(2));
     }
   }
-  offsetX = (GetScreenWidth() - width) / 2.0F;
-  offsetY = (GetScreenHeight() - height) / 2.0F;
+}
+
+void Game::draw_impl() {
+  BeginDrawing();
+  ClearBackground(RAYWHITE);
 
-  switch (currentFood) {
-  case (unsigned int)FoodType::FT_APPLE:
+  int coords[4];
+  Helpers::get_fruit_coords(coords, (FoodType)currentFood);
+
+  if (flags.test(6)) {
+    // bottom portion
     DrawTexturePro(
         spriteSheet,
-        {APPLE_COORDS[0], APPLE_COORDS[1], APPLE_COORDS[2], APPLE_COORDS[3]},
-        {offsetX, offsetY, width, height}, {0.0F, 0.0F}, 0.0F, WHITE);
-    break;
-  case (unsigned int)FoodType::FT_BANANA:
-    DrawTexturePro(spriteSheet,
-                   {BANANA_COORDS[0], BANANA_COORDS[1], BANANA_COORDS[2],
-                    BANANA_COORDS[3]},
-                   {offsetX, offsetY, width, height}, {0.0F, 0.0F}, 0.0F,
-                   WHITE);
-    break;
-  case (unsigned int)FoodType::FT_BROCCOLI:
-    DrawTexturePro(spriteSheet,
-                   {BROCCOLI_COORDS[0], BROCCOLI_COORDS[1], BROCCOLI_COORDS[2],
-                    BROCCOLI_COORDS[3]},
-                   {offsetX, offsetY, width, height}, {0.0F, 0.0F}, 0.0F,
-                   WHITE);
-    break;
-  case (unsigned int)FoodType::FT_CORN:
+        {(float)coords[0], (float)coords[1] + coords[3] * relativeCutRatio,
+         (float)coords[2], (float)coords[3] * (1.0F - relativeCutRatio)},
+        {offsetX, offsetY + height * relativeCutRatio, width,
+         height * (1.0F - relativeCutRatio)},
+        {0.0F, 0.0F}, 0.0F, WHITE);
+    // top portion
     DrawTexturePro(
         spriteSheet,
-        {CORN_COORDS[0], CORN_COORDS[1], CORN_COORDS[2], CORN_COORDS[3]},
-        {offsetX, offsetY, width, height}, {0.0F, 0.0F}, 0.0F, WHITE);
-    break;
-  case (unsigned int)FoodType::FT_GRAPES:
+        {(float)coords[0], (float)coords[1], (float)coords[2],
+         (float)coords[3] * relativeCutRatio},
+        {splitX + width / 2.0F, splitY + (height * relativeCutRatio / 2.0F),
+         width, height * relativeCutRatio},
+        {width / 2.0F, height * relativeCutRatio / 2.0F}, splitAngle, WHITE);
+  } else {
     DrawTexturePro(spriteSheet,
-                   {GRAPES_COORDS[0], GRAPES_COORDS[1], GRAPES_COORDS[2],
-                    GRAPES_COORDS[3]},
+                   {(float)coords[0], (float)coords[1], (float)coords[2],
+                    (float)coords[3]},
                    {offsetX, offsetY, width, height}, {0.0F, 0.0F}, 0.0F,
                    WHITE);
-    break;
-  default:
-    break;
   }
 
   DrawRectangle(0, offsetY, GetScreenWidth(), height / 3.0F,
                 {255, 255, 255, 127});
 
-  float cutPos = cutTimer * height;
-
-  DrawLine(0, cutPos + offsetY - height / 3.0F, GetScreenWidth(),
-           cutPos + offsetY - height / 3.0F, BLACK);
+  DrawLine(0, cutPos, GetScreenWidth(), cutPos, BLACK);
 
   Helpers::draw_eyes_full(offsetX + width / 2.0F, offsetY + height / 2.0F,
-                          width, EYE_RADIUS, (FoodType)currentFood,
+                          width, height, EYE_RADIUS, (FoodType)currentFood,
                           flags.test(1));
 
   if (flags.test(2)) {
-    Helpers::draw_happy_mouth(offsetX + width / 2.0F, offsetY + height / 2.0F,
-                              MOUTH_RADIUS);
+    Helpers::draw_happy_mouth(offsetX + width / 2.0F,
+                              offsetY + height / 2.0F * 1.1F, width,
+                              MOUTH_RADIUS, (FoodType)currentFood);
   }
 
   DrawText(scoreString.c_str(), 2, 2, 32, BLACK);
   EndDrawing();
 }
 
-void Game::reset() {
+void Game::reset(bool wasGameOver) {
   flags.set(0);
-  score = 0;
+  flags.reset(1);
+  flags.reset(2);
+  flags.set(3);
+  flags.reset(4);
+  flags.reset(5);
+  flags.reset(6);
+  if (wasGameOver) {
+    score = 0;
+    cutTimerRateInc = 1.0F;
+  }
   areaSizeRatio = 1.0F;
-  currentFood = dist(re);
+  unsigned int prevFood = currentFood;
+  while (prevFood == currentFood) {
+    currentFood = dist(re);
+  }
   blinkTimer = 10.0F;
-  cutTimer = 0.0F;
+  cutTimer = std::uniform_real_distribution<float>(0.0F, 1.0F)(re);
+  postCutTimer = 0.0F;
 }
index 12eb9d64d310da8982380e88201c6717b13362f9..539426a3e28eee29edbb1ae5768cb063e7bd0540 100644 (file)
@@ -18,7 +18,7 @@ private:
   void update_impl();
   void draw_impl();
 
-  void reset();
+  void reset(bool wasGameOver);
 
   std::default_random_engine re;
   std::uniform_int_distribution<unsigned int> dist;
@@ -29,6 +29,10 @@ private:
    * 0 - score dirty
    * 1 - is blinking
    * 2 - happy
+   * 3 - fruit dirty
+   * 4 - cut has happened
+   * 5 - sad
+   * 6 - relativeCutPos is set
    */
   std::bitset<32> flags;
   float areaSizeRatio;
@@ -37,6 +41,20 @@ private:
   float blinkTimer;
   float cutTimer;
   float cutTimerRateInc;
+  float ratio;
+  float width;
+  float height;
+  float offsetX;
+  float offsetY;
+  float cutPos;
+  float relativeCutRatio;
+  float splitX;
+  float splitY;
+  float splitAngle;
+  float splitDX;
+  float splitDY;
+  float splitDAngle;
+  float postCutTimer;
 };
 
 #endif
index c0743554257da77fcc8ed4e90c79666344b5479e..e8513805e31db8b1295e9b5d0d413350ccccf66e 100644 (file)
@@ -9,26 +9,7 @@
 // local includes
 #include "constants.h"
 
-void Helpers::draw_eye(float x, float y, float radius) {
-  DrawCircle(x + 0.5F, y + 0.5F, radius, BLACK);
-  DrawCircleSector({x, y}, radius / 1.5F, 180.0F, 270.0F, 32, WHITE);
-}
-
-void Helpers::draw_blinking_eye(float x, float y, float radius) {
-  DrawLineEx({x - radius, y}, {x + radius, y}, BLINKING_EYE_SIZE, BLACK);
-}
-
-void Helpers::draw_open_mouth(float x, float y, float radius) {
-  DrawCircle(x, y, radius, BLACK);
-}
-
-void Helpers::draw_happy_mouth(float x, float y, float radius) {
-  DrawCircleSector({x, y}, radius, -90.0F, 90.0F, 32, BLACK);
-}
-
-void Helpers::draw_eyes_full(float x, float y, float width, float radius,
-                             FoodType foodType, bool isBlinking) {
-  float offsets[2];
+void internal_get_offsets(float offsets[2], FoodType foodType) {
   switch (foodType) {
   case FoodType::FT_CORN:
     offsets[0] = CORN_EYE_OFFSET[0];
@@ -55,17 +36,47 @@ void Helpers::draw_eyes_full(float x, float y, float width, float radius,
     offsets[1] = 0.0F;
     break;
   }
+}
+
+void Helpers::draw_eye(float x, float y, float radius) {
+  DrawCircle(x + 0.5F, y + 0.5F, radius, BLACK);
+  DrawCircleSector({x, y}, radius / 1.5F, 180.0F, 270.0F, 32, WHITE);
+}
+
+void Helpers::draw_blinking_eye(float x, float y, float radius) {
+  DrawLineEx({x - radius, y}, {x + radius, y}, BLINKING_EYE_SIZE, BLACK);
+}
+
+void Helpers::draw_open_mouth(float x, float y, float radius) {
+  DrawCircle(x, y, radius, BLACK);
+}
+
+void Helpers::draw_happy_mouth(float x, float y, float width, float radius,
+                               FoodType foodType) {
+  float offsets[2];
+  internal_get_offsets(offsets, foodType);
+
+  DrawCircleSector({x + offsets[0] * width, y}, radius, -90.0F, 90.0F, 32,
+                   BLACK);
+}
+
+void Helpers::draw_eyes_full(float x, float y, float width, float height,
+                             float radius, FoodType foodType, bool isBlinking) {
+  float offsets[2];
+  internal_get_offsets(offsets, foodType);
 
   const float eye_width = width * EYE_WIDTH_RATIO;
 
   if (isBlinking) {
-    draw_blinking_eye(x - eye_width / 2.0F + offsets[0], y + offsets[1],
-                      radius);
-    draw_blinking_eye(x + eye_width / 2.0F + offsets[0], y + offsets[1],
-                      radius);
+    draw_blinking_eye(x - eye_width / 2.0F + offsets[0] * width,
+                      y + offsets[1] * height, radius);
+    draw_blinking_eye(x + eye_width / 2.0F + offsets[0] * width,
+                      y + offsets[1] * height, radius);
   } else {
-    draw_eye(x - eye_width / 2.0F + offsets[0], y + offsets[1], radius);
-    draw_eye(x + eye_width / 2.0F + offsets[0], y + offsets[1], radius);
+    draw_eye(x - eye_width / 2.0F + offsets[0] * width, y + offsets[1] * height,
+             radius);
+    draw_eye(x + eye_width / 2.0F + offsets[0] * width, y + offsets[1] * height,
+             radius);
   }
 }
 
@@ -84,3 +95,44 @@ float Helpers::get_cut_pos(float timer, FoodType foodType) {
   }
   return 0.0F;
 }
+
+void Helpers::get_fruit_coords(int coords[4], FoodType foodType) {
+  switch (foodType) {
+  case FoodType::FT_CORN:
+    coords[0] = CORN_COORDS[0];
+    coords[1] = CORN_COORDS[1];
+    coords[2] = CORN_COORDS[2];
+    coords[3] = CORN_COORDS[3];
+    break;
+  case FoodType::FT_GRAPES:
+    coords[0] = GRAPES_COORDS[0];
+    coords[1] = GRAPES_COORDS[1];
+    coords[2] = GRAPES_COORDS[2];
+    coords[3] = GRAPES_COORDS[3];
+    break;
+  case FoodType::FT_APPLE:
+    coords[0] = APPLE_COORDS[0];
+    coords[1] = APPLE_COORDS[1];
+    coords[2] = APPLE_COORDS[2];
+    coords[3] = APPLE_COORDS[3];
+    break;
+  case FoodType::FT_BROCCOLI:
+    coords[0] = BROCCOLI_COORDS[0];
+    coords[1] = BROCCOLI_COORDS[1];
+    coords[2] = BROCCOLI_COORDS[2];
+    coords[3] = BROCCOLI_COORDS[3];
+    break;
+  case FoodType::FT_BANANA:
+    coords[0] = BANANA_COORDS[0];
+    coords[1] = BANANA_COORDS[1];
+    coords[2] = BANANA_COORDS[2];
+    coords[3] = BANANA_COORDS[3];
+    break;
+  default:
+    coords[0] = 0;
+    coords[1] = 0;
+    coords[2] = 0;
+    coords[3] = 0;
+    break;
+  }
+}
index 7944ca503eb77e1891afda5b55ff2081739e7329..02082942b9031ec69cbf8b552a0d3bae44acd807 100644 (file)
@@ -8,13 +8,16 @@ namespace Helpers {
 extern void draw_eye(float x, float y, float radius);
 extern void draw_blinking_eye(float x, float y, float radius);
 extern void draw_open_mouth(float x, float y, float radius);
-extern void draw_happy_mouth(float x, float y, float radius);
+extern void draw_happy_mouth(float x, float y, float width, float radius,
+                             FoodType foodType);
 
-extern void draw_eyes_full(float x, float y, float width, float radius,
-                           FoodType foodType, bool isBlinking);
+extern void draw_eyes_full(float x, float y, float width, float height,
+                           float radius, FoodType foodType, bool isBlinking);
 
 extern float get_cut_pos(float timer, FoodType foodType);
 
+extern void get_fruit_coords(int coords[4], FoodType foodType);
+
 } // namespace Helpers
 
 #endif