Basic fruits support
Of course, there is no support for levels yet!
This commit is contained in:
parent
c95fddc481
commit
c495dd9c37
7 changed files with 118 additions and 2 deletions
|
@ -44,6 +44,8 @@ void Canvas::update(const GameState & gameState) {
|
||||||
renderScore(gameState.score.points);
|
renderScore(gameState.score.points);
|
||||||
renderLives(gameState.score.lives);
|
renderLives(gameState.score.lives);
|
||||||
|
|
||||||
|
renderFruits(gameState.fruit, gameState.score.eatenFruits);
|
||||||
|
|
||||||
renderPacMan(gameState.pacMan);
|
renderPacMan(gameState.pacMan);
|
||||||
|
|
||||||
render();
|
render();
|
||||||
|
@ -99,6 +101,23 @@ void Canvas::renderPacMan(const PacMan & pac_man) {
|
||||||
renderSprite(pacmanSprite, pos);
|
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 size_t x = (LEFT_MARGIN + TARGET_MAZE_WIDTH + LEFT_MARGIN);
|
||||||
|
const size_t y = (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) {
|
void Canvas::renderGhost(const Ghost & ghost) {
|
||||||
Sprite sprite = getSprite(ghost.currentSprite());
|
Sprite sprite = getSprite(ghost.currentSprite());
|
||||||
const auto & pos = ghost.position();
|
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
|
pinky.update(delta, *this); // ghosts know what they want, which is usually pacman's location
|
||||||
inky.update(delta, *this);
|
inky.update(delta, *this);
|
||||||
clyde.update(delta, *this);
|
clyde.update(delta, *this);
|
||||||
|
fruit.update(delta, *this);
|
||||||
|
|
||||||
checkCollision(blinky);
|
checkCollision(blinky);
|
||||||
checkCollision(pinky);
|
checkCollision(pinky);
|
||||||
|
@ -28,12 +29,14 @@ void GameState::step(std::chrono::milliseconds delta) {
|
||||||
checkCollision(clyde);
|
checkCollision(clyde);
|
||||||
|
|
||||||
eatPellets();
|
eatPellets();
|
||||||
|
eatFruit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameState::checkCollision(Ghost & ghost) {
|
void GameState::checkCollision(Ghost & ghost) {
|
||||||
if (isPacManDying() || ghost.isEyes())
|
if (isPacManDying() || ghost.isEyes())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// TODO: hitboxes based collision
|
||||||
if (ghost.positionInGrid() != pacMan.positionInGrid())
|
if (ghost.positionInGrid() != pacMan.positionInGrid())
|
||||||
return;
|
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() {
|
void GameState::killPacMan() {
|
||||||
pacMan.die();
|
pacMan.die();
|
||||||
score.lives--;
|
score.lives--;
|
||||||
|
@ -86,4 +100,4 @@ bool GameState::isPacManDying() const {
|
||||||
return timeSinceDeath.count() != 0;
|
return timeSinceDeath.count() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,11 +37,12 @@ private:
|
||||||
void renderGhost(const Ghost & ghost);
|
void renderGhost(const Ghost & ghost);
|
||||||
void renderPellets(const Pellets & pellets);
|
void renderPellets(const Pellets & pellets);
|
||||||
void renderSuperPellets(const SuperPellets & superPellets);
|
void renderSuperPellets(const SuperPellets & superPellets);
|
||||||
void renderSprite(Sprite sprite, Position pos);
|
void renderFruits(const Fruits& fruit, int eatenFruits);
|
||||||
|
|
||||||
void renderScore(int score);
|
void renderScore(int score);
|
||||||
void renderLives(int lives);
|
void renderLives(int lives);
|
||||||
|
|
||||||
|
void renderSprite(Sprite sprite, Position pos);
|
||||||
static Rect viewDimensions();
|
static Rect viewDimensions();
|
||||||
static sf::Texture loadTexture(std::string_view path);
|
static sf::Texture loadTexture(std::string_view path);
|
||||||
static sf::Font loadFont(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 <chrono>
|
||||||
|
#include "Position.hpp"
|
||||||
|
|
||||||
|
namespace pacman {
|
||||||
|
|
||||||
|
class 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 "Pinky.hpp"
|
||||||
#include "Score.hpp"
|
#include "Score.hpp"
|
||||||
#include "SuperPellets.hpp"
|
#include "SuperPellets.hpp"
|
||||||
|
#include "Fruits.hpp"
|
||||||
#include "InputState.hpp"
|
#include "InputState.hpp"
|
||||||
|
|
||||||
namespace pacman {
|
namespace pacman {
|
||||||
|
@ -25,6 +26,7 @@ struct GameState {
|
||||||
InputState inputState;
|
InputState inputState;
|
||||||
Pellets pellets;
|
Pellets pellets;
|
||||||
SuperPellets superPellets;
|
SuperPellets superPellets;
|
||||||
|
Fruits fruit;
|
||||||
|
|
||||||
Score score;
|
Score score;
|
||||||
std::chrono::milliseconds timeSinceDeath{};
|
std::chrono::milliseconds timeSinceDeath{};
|
||||||
|
@ -32,6 +34,7 @@ struct GameState {
|
||||||
void checkCollision(Ghost & ghost);
|
void checkCollision(Ghost & ghost);
|
||||||
void handleDeathAnimation(std::chrono::milliseconds delta);
|
void handleDeathAnimation(std::chrono::milliseconds delta);
|
||||||
void eatPellets();
|
void eatPellets();
|
||||||
|
void eatFruit();
|
||||||
void killPacMan();
|
void killPacMan();
|
||||||
bool isPacManDying() const;
|
bool isPacManDying() const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,6 +7,7 @@ struct Score {
|
||||||
int lives = DEFAULT_LIVES;
|
int lives = DEFAULT_LIVES;
|
||||||
int points = 0;
|
int points = 0;
|
||||||
int eatenPellets = 0;
|
int eatenPellets = 0;
|
||||||
|
int eatenFruits = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace pacman
|
} // namespace pacman
|
||||||
|
|
Loading…
Reference in a new issue