Merge pull request #30 from mod-cpp/corentin/fruits
Basic fruits support
This commit is contained in:
commit
0923351045
7 changed files with 118 additions and 2 deletions
|
@ -44,6 +44,8 @@ void Canvas::update(const GameState & gameState) {
|
|||
renderScore(gameState.score.points);
|
||||
renderLives(gameState.score.lives);
|
||||
|
||||
renderFruits(gameState.fruit, gameState.score.eatenFruits);
|
||||
|
||||
renderPacMan(gameState.pacMan);
|
||||
|
||||
render();
|
||||
|
@ -99,6 +101,23 @@ void Canvas::renderPacMan(const PacMan & pac_man) {
|
|||
renderSprite(pacmanSprite, pos);
|
||||
}
|
||||
|
||||
void Canvas::renderFruits(const Fruits & fruit, int eatenFruits) {
|
||||
Sprite sprite = getSprite(fruit.currentSprite());
|
||||
if (fruit.isVisible()) {
|
||||
const auto & pos = fruit.position();
|
||||
renderSprite(sprite, pos);
|
||||
}
|
||||
const auto x = static_cast<size_t>(LEFT_MARGIN + TARGET_MAZE_WIDTH + LEFT_MARGIN);
|
||||
const auto y = static_cast<size_t>((TARGET_MAZE_HEIGHT / 3.0) * 2);
|
||||
|
||||
for (auto i = 0; i < eatenFruits + 1; i++) {
|
||||
auto sprite_position = float(i) * SPRITE_WIDTH * 1.5f;
|
||||
sf::Vector2f pos{ x + sprite_position, y };
|
||||
sprite.setPosition(pos.x, pos.y);
|
||||
window.draw(sprite);
|
||||
}
|
||||
}
|
||||
|
||||
void Canvas::renderGhost(const Ghost & ghost) {
|
||||
Sprite sprite = getSprite(ghost.currentSprite());
|
||||
const auto & pos = ghost.position();
|
||||
|
|
53
lib/Fruits.cpp
Normal file
53
lib/Fruits.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include "Fruits.hpp"
|
||||
#include "GameState.hpp"
|
||||
|
||||
namespace pacman {
|
||||
|
||||
void Fruits::update(std::chrono::milliseconds time_delta, const GameState & gameState) {
|
||||
if(visible) {
|
||||
time_visible += time_delta;
|
||||
}
|
||||
|
||||
if(time_visible > std::chrono::seconds(9)) {
|
||||
hide();
|
||||
}
|
||||
|
||||
// Two times the same fruit for each level, after 70 and 170 pellets eaten
|
||||
else if ((index == 0 && gameState.score.eatenPellets >= 70)
|
||||
|| (index == 1 && gameState.score.eatenPellets >= 170)) {
|
||||
visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
GridPosition Fruits::currentSprite() const {
|
||||
// That's the cherry
|
||||
return {3, 8};
|
||||
}
|
||||
|
||||
Position Fruits::position() const {
|
||||
// under the pen
|
||||
return {13.5, 17};
|
||||
}
|
||||
|
||||
bool Fruits::isVisible() const {
|
||||
return visible;
|
||||
}
|
||||
|
||||
int Fruits::value() const {
|
||||
// The cherry is worth 100
|
||||
return 100;
|
||||
}
|
||||
|
||||
int Fruits::eat() {
|
||||
hide();
|
||||
return value();
|
||||
}
|
||||
|
||||
void Fruits::hide() {
|
||||
index++;
|
||||
time_visible = std::chrono::seconds{0};
|
||||
visible = false;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -21,6 +21,7 @@ void GameState::step(std::chrono::milliseconds delta) {
|
|||
pinky.update(delta, *this); // ghosts know what they want, which is usually pacman's location
|
||||
inky.update(delta, *this);
|
||||
clyde.update(delta, *this);
|
||||
fruit.update(delta, *this);
|
||||
|
||||
checkCollision(blinky);
|
||||
checkCollision(pinky);
|
||||
|
@ -28,12 +29,14 @@ void GameState::step(std::chrono::milliseconds delta) {
|
|||
checkCollision(clyde);
|
||||
|
||||
eatPellets();
|
||||
eatFruit();
|
||||
}
|
||||
|
||||
void GameState::checkCollision(Ghost & ghost) {
|
||||
if (isPacManDying() || ghost.isEyes())
|
||||
return;
|
||||
|
||||
// TODO: hitboxes based collision
|
||||
if (ghost.positionInGrid() != pacMan.positionInGrid())
|
||||
return;
|
||||
|
||||
|
@ -76,6 +79,17 @@ void GameState::eatPellets() {
|
|||
}
|
||||
}
|
||||
|
||||
void GameState::eatFruit() {
|
||||
const auto pos = pacMan.positionInGrid();
|
||||
const auto fruitpos = positionToGridPosition(fruit.position());
|
||||
|
||||
// TODO: hitboxes based collision
|
||||
if(fruit.isVisible() && pos == fruitpos) {
|
||||
score.points += fruit.eat();
|
||||
score.eatenFruits++;
|
||||
}
|
||||
}
|
||||
|
||||
void GameState::killPacMan() {
|
||||
pacMan.die();
|
||||
score.lives--;
|
||||
|
@ -86,4 +100,4 @@ bool GameState::isPacManDying() const {
|
|||
return timeSinceDeath.count() != 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,11 +37,12 @@ private:
|
|||
void renderGhost(const Ghost & ghost);
|
||||
void renderPellets(const Pellets & pellets);
|
||||
void renderSuperPellets(const SuperPellets & superPellets);
|
||||
void renderSprite(Sprite sprite, Position pos);
|
||||
void renderFruits(const Fruits& fruit, int eatenFruits);
|
||||
|
||||
void renderScore(int score);
|
||||
void renderLives(int lives);
|
||||
|
||||
void renderSprite(Sprite sprite, Position pos);
|
||||
static Rect viewDimensions();
|
||||
static sf::Texture loadTexture(std::string_view path);
|
||||
static sf::Font loadFont(std::string_view path);
|
||||
|
|
25
lib/include/Fruits.hpp
Normal file
25
lib/include/Fruits.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#pragma once
|
||||
#include "Position.hpp"
|
||||
#include <chrono>
|
||||
|
||||
namespace pacman {
|
||||
|
||||
struct GameState;
|
||||
|
||||
class Fruits {
|
||||
public:
|
||||
void update(std::chrono::milliseconds time_delta, const GameState & gameState);
|
||||
GridPosition currentSprite() const;
|
||||
Position position() const;
|
||||
bool isVisible() const;
|
||||
int value() const;
|
||||
int eat();
|
||||
|
||||
private:
|
||||
void hide();
|
||||
bool visible = false;
|
||||
int index = 0;
|
||||
std::chrono::milliseconds time_visible{ 0 };
|
||||
};
|
||||
|
||||
} // namespace pacman
|
|
@ -9,6 +9,7 @@
|
|||
#include "Pinky.hpp"
|
||||
#include "Score.hpp"
|
||||
#include "SuperPellets.hpp"
|
||||
#include "Fruits.hpp"
|
||||
#include "InputState.hpp"
|
||||
|
||||
namespace pacman {
|
||||
|
@ -25,6 +26,7 @@ struct GameState {
|
|||
InputState inputState;
|
||||
Pellets pellets;
|
||||
SuperPellets superPellets;
|
||||
Fruits fruit;
|
||||
|
||||
Score score;
|
||||
std::chrono::milliseconds timeSinceDeath{};
|
||||
|
@ -32,6 +34,7 @@ struct GameState {
|
|||
void checkCollision(Ghost & ghost);
|
||||
void handleDeathAnimation(std::chrono::milliseconds delta);
|
||||
void eatPellets();
|
||||
void eatFruit();
|
||||
void killPacMan();
|
||||
bool isPacManDying() const;
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@ struct Score {
|
|||
int lives = DEFAULT_LIVES;
|
||||
int points = 0;
|
||||
int eatenPellets = 0;
|
||||
int eatenFruits = 0;
|
||||
};
|
||||
|
||||
} // namespace pacman
|
||||
|
|
Loading…
Reference in a new issue