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");
}
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]);
}
}
}
}
}
- 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;
}
// 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];
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);
}
}
}
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;
+ }
+}