Untitled
unknown
plain_text
2 years ago
20 kB
15
Indexable
// node.h
#pragma once
#include "../States/GameState/GameState.h"
#include "../Entity/Entity.h"
struct sNode
{
sNode* parent;
GameState* gameState;
Directions ignoreDirection = Directions::None;
sf::Vector2i pos;
int gCost = 0;
int hCost = 0;
int fCost() { return (gCost + hCost); }
bool visited = false;
bool walkable = true;
sNode(sf::Vector2i pos, GameState* gameState) { this->pos = pos; this->gameState = gameState; }
void SetParent(sNode p)
{
parent = new sNode(p);
}
~sNode()
{
//delete parent
}
std::vector<sNode> GetNeighbours()
{
std::vector<sNode> neighbours;
if (ignoreDirection != Left) {
sNode left = CreateNode(sf::Vector2i(pos.x - 1, pos.y));
if (left.pos != sf::Vector2i(-100, -100)) neighbours.push_back(left);
}
if (ignoreDirection != Right) {
sNode right = CreateNode(sf::Vector2i(pos.x + 1, pos.y));
if (right.pos != sf::Vector2i(-100, -100)) neighbours.push_back(right);
}
if (ignoreDirection != Up) {
sNode up = CreateNode(sf::Vector2i(pos.x, pos.y - 1));
if (up.pos != sf::Vector2i(-100, -100)) neighbours.push_back(up);
}
if (ignoreDirection != Down) {
sNode down = CreateNode(sf::Vector2i(pos.x, pos.y + 1));
if (down.pos != sf::Vector2i(-100, -100)) neighbours.push_back(down);
}
return neighbours;
}
sNode CreateNode(sf::Vector2i pos)
{
sTile* tile = &gameState->tileArray[pos.x][pos.y];
sNode node = sNode(pos, gameState);
if (tile != NULL) {
if (pos.x < 0 || pos.y < 0 || pos.x >= NumberOfTilesX || pos.y >= NumberOfTilesY)
return sNode(sf::Vector2i(-100, -100), gameState);
if (tile->DoesTileHaveOnlyType(sTile::Wall))
node.walkable = false;
else
node.walkable = true;
return node;
}
return sNode(sf::Vector2i(-100, -100), gameState);
}
};
// Pathfinding.h
#pragma once
#include "../Common.h"
#include "../Entity/Entity.h"
class GameState;
std::vector<sf::Vector2i> FindPath(sf::Vector2i startNode, sf::Vector2i endNode, Directions currentDir, GameState* gameState);
#include "Pathfinding.h"
#include "Node.h"
#include "../Entity/Entity.h"
bool IsNodeInsideList(sNode& n, std::vector<sNode>& list)
{
for (sNode node : list)
{
if (node.pos == n.pos)
return true;
}
return false;
}
void DeleteNodeOnList(sNode& n, std::vector<sNode>& list)
{
for (int i = 0; i < list.size(); i++)
{
if (list[i].pos == n.pos) {
list.erase(list.begin() + i);
break;
}
}
}
int GetDistance(sNode& a, sNode& b)
{
int disX = a.pos.x - b.pos.x;
int disY = a.pos.y - b.pos.y;
if(disX < 0)
disX *= -1;
if(disY < 0)
disY *= -1;
int totalDis = disX + disY;
return totalDis;
}
std::vector<sf::Vector2i> FindPath(sf::Vector2i startNodePos, sf::Vector2i endNodePos, Directions currentDir, GameState* gameState)
{
std::vector<sNode> openList;
std::vector<sNode> closedList;
sNode startNode = sNode(startNodePos, gameState);
sNode endNode = sNode(endNodePos, gameState);
startNode.ignoreDirection = GetOppositeDirection(currentDir);
openList.push_back(startNode);
bool foundPath = false;
sNode currentNode = openList[0];
while(!openList.empty())
{
currentNode = openList[0];
int i = 0;
for(; i < openList.size(); i++)
{
if (openList[i].fCost() < currentNode.fCost() || (openList[i].fCost() == currentNode.fCost() && openList[i].hCost < currentNode.hCost))
{
currentNode = openList[i];
}
}
DeleteNodeOnList(currentNode, openList);
closedList.push_back(currentNode);
if (currentNode.pos == endNodePos)
{
foundPath = true;
break;
}
std::vector<sNode> neighbours = currentNode.GetNeighbours();
for (sNode neighbour : neighbours)
{
if (!neighbour.walkable || IsNodeInsideList(neighbour, closedList))
continue;
int newMovementCostToNeighbour = currentNode.gCost + GetDistance(currentNode, neighbour);
if(newMovementCostToNeighbour < neighbour.gCost || !IsNodeInsideList(neighbour, openList))
{
neighbour.gCost = newMovementCostToNeighbour;
neighbour.hCost = GetDistance(neighbour, endNode);
neighbour.SetParent(currentNode);
if (!IsNodeInsideList(neighbour, openList))
openList.push_back(neighbour);
}
}
}
if (foundPath)
{
std::vector<sf::Vector2i> pathPositionsList;
while (currentNode.pos != startNode.pos)
{
pathPositionsList.push_back(currentNode.pos);
currentNode = *currentNode.parent;
}
std::reverse(pathPositionsList.begin(), pathPositionsList.end());
return pathPositionsList;
}
else
return std::vector<sf::Vector2i>();
}
// state.h
#pragma once
#include "SFML/Graphics.hpp"
#include "../Common.h"
class GameManager;
class State
{
protected:
sf::RenderWindow* window;
std::stack<State*>* states;
bool quit;
GameManager* gameManager;
public:
State(sf::RenderWindow* window, std::stack<State*>* states, GameManager* gameManager);
virtual void Update(const float& deltaTime) = 0;
virtual void Draw() = 0;
const bool& GetQuit() const;
void EndState();
};
// state.cpp
#include "State.h"
State::State(sf::RenderWindow* window, std::stack<State*>* states, GameManager* gameManager)
{
this->window = window;
this->states = states;
this->gameManager = gameManager;
this->quit = false;
}
const bool& State::GetQuit() const
{
return this->quit;
}
void State::EndState()
{
this->quit = true;
}
// gamestate.h
#pragma once
#include "../State.h"
#include "../../Tile.h"
#include "../../Entity/Snack/Snack.h"
#include "../../Audio/AudioManager.h"
class Enemy;
class Pacman;
#define NumberOfTilesX 28
#define NumberOfTilesY 31
class GameState : public State
{
public:
Pacman* pacman;
Enemy* enemys[4];
sTile tileArray[NumberOfTilesX][NumberOfTilesY];
std::vector<Snack*> SnackList;
sf::Sprite mapSprite;
sf::Texture mapTexture;
sf::Sprite readyTextSprite;
sf::Texture readyTextTexture;
sf::Sprite gameOverTextSprite;
sf::Texture gameOverTextTexture;
AudioManager audioManager;
int score = 0;
float tileWidth = 800 / (float)NumberOfTilesX;
float tileHeight = 800 / (float)NumberOfTilesY;
bool isPacmanDead = false;
bool powerSnackActive = false;
GameState(sf::RenderWindow* window, std::stack<State*>* states, GameManager* gameManager);
~GameState();
void Update(const float& deltaTime);
void Draw();
void OnPacmanDeath();
int FindSnackID(sf::Vector2i snackPos);
void DeleteSnack(sf::Vector2i snackPos);
void ScareEnemys();
void FreezeGame(Entities entityThatWontFreeze);
void UnfreezeGame();
void StopPowerSnackSound();
Enemy* FindEnemyByPosition(sf::Vector2i pos);
private:
int lifes = 3;
bool isFreezed = false;
bool gameHasStarted = false;
Entities entityThatWontFreeze = Entities::NotDefined;
sf::Font font;
sf::Text scoreText;
sf::Text lifesText;
void Restart();
void LoadTextures();
void CreateMapCollidersAndSnacks();
void EmptyTileArray();
void CreatePacmanAndEnemys();
void CreateUI();
void UpdateUI();
void DeleteSnacks();
};
// gamestate.cpp
#include "GameState.h"
#include <iostream>
#include "../../Entity/Pacman/Pacman.h"
#include "../../Entity/Enemy/Enemy.h"
#include "../../Entity/Enemy/Blinky.h"
#include "../../Entity/Enemy/Pinky.h"
#include "../../Entity/Enemy/Inky.h"
#include "../../Entity/Enemy/Clyde.h"
#include "../../Debugger/Debug.h"
#include "SFML/Audio.hpp"
#include "../../Audio/AudioAssets.h"
#include "../../Entity/Snack/Snack.h"
#include "../MainMenuState/MainMenuState.h"
//test
#include <sstream>
GameState::GameState(sf::RenderWindow* window, std::stack<State*>* states, GameManager* gameManager)
: State(window, states, gameManager)
{
CreateMapCollidersAndSnacks();
CreatePacmanAndEnemys();
CreateUI();
isFreezed = true;
audioManager.PlaySound(Sounds::GameStart, false, VOLUME);
LoadTextures();
}
GameState::~GameState()
{
delete pacman;
for (auto const& x : enemys)
delete x;
delete window;
DeleteSnacks();
}
void GameState::OnPacmanDeath()
{
isPacmanDead = true;
FreezeGame(Entities::Pacman);
audioManager.StopSound();
audioManager.PlaySound(Sounds::Death, false, VOLUME);
}
void GameState::Restart()
{
audioManager.StopSound();
if(isPacmanDead)
lifes--;
else
{
DeleteSnacks();
EmptyTileArray();
CreateMapCollidersAndSnacks();
}
for (auto const& x : enemys)
delete x;
delete pacman;
isFreezed = true;
entityThatWontFreeze = Entities::NotDefined;
gameHasStarted = false;
isPacmanDead = false;
CreatePacmanAndEnemys();
audioManager.PlaySound(Sounds::GameStart, false, VOLUME);
}
void GameState::Update(const float& deltaTime)
{
//Logic
//if initial music has played, start the game
if (!audioManager.IsPlayingAudio(Sounds::GameStart) && !gameHasStarted)
{
isFreezed = false;
gameHasStarted = true;
audioManager.PlaySound(Sounds::Siren, true, VOLUME_SIREN);
}
//updating entities that are not freezed
if(isFreezed == false || entityThatWontFreeze == Entities::Pacman)
pacman->Update(deltaTime);
for (auto const& x : enemys)
{
if (isFreezed == false || entityThatWontFreeze == x->entityType || x->state == EnemyState::Eaten_Retreating)
{
if (x != NULL)
x->Update(deltaTime);
}
}
for (auto const& x : SnackList)
{
x->Update(deltaTime);
}
//if pacman is dead, wait death music to stop before restarting the game
if (isPacmanDead && !audioManager.IsPlayingAudio(Sounds::Death))
{
if (lifes == 0)
states->push(new MainMenuState(window, states, gameManager));
else
{
Restart();
}
}
//render
UpdateUI();
Draw();
}
void GameState::Draw()
{
window->clear();
window->draw(mapSprite);
if(isPacmanDead) window->draw(gameOverTextSprite);
if(!gameHasStarted) window->draw(readyTextSprite);
for (auto const& x : SnackList)
x->Draw(*window);
pacman->Draw(*window);
//draw walls colliders
//for (int i = 0; i < NumberOfTilesX; i++)
//{
// for (int j = 0 ; j < NumberOfTilesY; j++)
// {
// if(tileArray[i][j].DoesTileHaveType(sTile::TileType::Wall))
// DrawCube(*window, sf::Vector2i(i, j), this);
// }
//}
for (auto const& x : enemys)
{
if (x != NULL)
x->Draw(*window);
}
window->draw(lifesText);
window->draw(scoreText);
window->display();
}
void GameState::LoadTextures()
{
if (mapTexture.loadFromFile("Resources/PacManSprites.png", sf::IntRect(0, 0, 226, 248)))
{
mapTexture.setSmooth(false);
mapSprite.setTexture(mapTexture);
mapSprite.setScale((window->getView().getSize().x) / (mapSprite.getLocalBounds().width * gameManager->aspectRatio), (window->getView().getSize().y - 100) / mapSprite.getLocalBounds().height);
mapSprite.move(0, 1);
}
else
{
std::cout << "texture not loaded correctly" << std::endl;
}
if (gameOverTextTexture.loadFromFile("Resources/ready-gameover.png", sf::IntRect(0, 0, 175, 22)))
{
gameOverTextTexture.setSmooth(false);
gameOverTextSprite.setTexture(gameOverTextTexture);
gameOverTextSprite.move(310, 438);
}
else
{
std::cout << "texture not loaded correctly" << std::endl;
}
if (readyTextTexture.loadFromFile("Resources/ready-gameover.png", sf::IntRect(178, 0, 279, 22)))
{
readyTextTexture.setSmooth(false);
readyTextSprite.setTexture(readyTextTexture);
readyTextSprite.move(350, 438);
}
else
{
std::cout << "texture not loaded correctly" << std::endl;
}
}
void GameState::CreateMapCollidersAndSnacks()
{
int mapDesign[NumberOfTilesY][NumberOfTilesX] = {
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1},
{1,3,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,3,1},
{1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1},
{1,0,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,0,1},
{1,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,1},
{1,1,1,1,1,1,0,1,1,1,1,1,5,1,1,5,1,1,1,1,1,0,1,1,1,1,1,1},
{1,1,1,1,1,1,0,1,1,1,1,1,5,1,1,5,1,1,1,1,1,0,1,1,1,1,1,1},
{1,1,1,1,1,1,0,1,1,5,5,5,5,5,5,5,5,5,5,1,1,0,1,1,1,1,1,1},
{1,1,1,1,1,1,0,1,1,5,1,1,1,2,2,1,1,1,5,1,1,0,1,1,1,1,1,1},
{1,1,1,1,1,1,0,1,1,5,1,2,2,2,2,2,2,1,5,1,1,0,1,1,1,1,1,1},
{0,0,0,0,0,0,0,5,5,5,1,2,2,2,2,2,2,1,5,5,5,0,0,0,0,0,0,0},
{1,1,1,1,1,1,0,1,1,5,1,2,2,2,2,2,2,1,5,1,1,0,1,1,1,1,1,1},
{1,1,1,1,1,1,0,1,1,5,1,1,1,1,1,1,1,1,5,1,1,0,1,1,1,1,1,1},
{1,1,1,1,1,1,0,1,1,5,5,5,5,5,5,5,5,5,5,1,1,0,1,1,1,1,1,1},
{1,1,1,1,1,1,0,1,1,5,1,1,1,1,1,1,1,1,5,1,1,0,1,1,1,1,1,1},
{1,1,1,1,1,1,0,1,1,5,1,1,1,1,1,1,1,1,5,1,1,0,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1},
{1,0,1,1,1,1,0,1,1,1,1,1,0,1,1,0,1,1,1,1,1,0,1,1,1,1,0,1},
{1,3,0,0,1,1,0,0,0,0,0,0,0,5,5,0,0,0,0,0,0,0,1,1,0,0,3,1},
{1,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1},
{1,1,1,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,0,1,1,0,1,1,0,1,1,1},
{1,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,0,0,0,1},
{1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1},
{1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1},
{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}
};
for (int y = 0; y < NumberOfTilesY; y++)
{
for (int x = 0; x < NumberOfTilesX; x++)
{
if (mapDesign[y][x] == 0) // small snack
{
tileArray[x][y].isEmpty = false;
tileArray[x][y].tileTypes.push_back(sTile::Snack);
Snack* s = new Snack(Snack::SmallSnack, sf::Vector2i(x, y), this);
SnackList.push_back(s);
}
else if (mapDesign[y][x] == 1) // wall collider
{
tileArray[x][y].isEmpty = false;
tileArray[x][y].tileTypes.push_back(sTile::Wall);
}
else if (mapDesign[y][x] == 2) // ghost house
{
tileArray[x][y].isEmpty = false;
tileArray[x][y].tileTypes.push_back(sTile::GhostHouse);
}
else if (mapDesign[y][x] == 3) // big snack
{
tileArray[x][y].isEmpty = false;
tileArray[x][y].tileTypes.push_back(sTile::Snack);
Snack* s = new Snack(Snack::BigSnack, sf::Vector2i(x, y), this);
SnackList.push_back(s);
}
else if (mapDesign[y][x] == 5) // empty
{
}
}
}
}
void GameState::EmptyTileArray()
{
for (int y = 0; y < NumberOfTilesY; y++)
{
for (int x = 0; x < NumberOfTilesX; x++)
{
tileArray[x][y].isEmpty = true;
tileArray[x][y].tileTypes.clear();
}
}
}
void GameState::CreatePacmanAndEnemys()
{
pacman = new Pacman(13, 23, this);
enemys[0] = new Blinky(sf::Vector2i(13, 12), this);
enemys[1] = new Pinky(sf::Vector2i(11, 14), this);
enemys[2] = new Inky(sf::Vector2i(13, 14), this);
enemys[3] = new Clyde(sf::Vector2i(15, 14), this);
}
void GameState::CreateUI()
{
font.loadFromFile("Fonts/Dosis-Light.ttf");
//creating score text
this->scoreText.setFont(this->font);
this->scoreText.setFillColor(sf::Color::White);
this->scoreText.setCharacterSize(36);
this->scoreText.setPosition(10, 800);
//creating lives text
this->lifesText.setFont(this->font);
this->lifesText.setFillColor(sf::Color::White);
this->lifesText.setCharacterSize(36);
this->lifesText.setPosition(10, 850);
UpdateUI();
}
void GameState::UpdateUI()
{
this->scoreText.setString("Score : " + std::to_string(score));
this->lifesText.setString("Lifes : " + std::to_string(lifes));
}
void GameState::FreezeGame(Entities entityThatWontFreeze)
{
isFreezed = true;
this->entityThatWontFreeze = entityThatWontFreeze;
}
void GameState::UnfreezeGame()
{
isFreezed = false;
this->entityThatWontFreeze = Entities::NotDefined;
}
int GameState::FindSnackID(sf::Vector2i snackPos)
{
for (int i = 0; i < SnackList.size(); i++)
{
if (SnackList[i]->gridPos == snackPos)
{
return i;
}
}
return -1;
}
void GameState::DeleteSnack(sf::Vector2i snackPos)
{
int id = FindSnackID(snackPos);
if (id != -1)
{
delete SnackList[id];
SnackList.erase(SnackList.begin() + id);
if (SnackList.size() == 0)
Restart();
}
}
void GameState::DeleteSnacks()
{
for (auto const& x : SnackList)
delete x;
SnackList.clear();
}
void GameState::ScareEnemys()
{
for (Enemy* e : enemys)
if (e != NULL) e->Scare();
audioManager.StopSound(Sounds::Siren);
audioManager.PlaySound(Sounds::PowerSnack, true, VOLUME);
powerSnackActive = true;
}
void GameState::StopPowerSnackSound()
{
audioManager.StopSound(Sounds::PowerSnack);
audioManager.PlaySound(Sounds::Siren, true, VOLUME_SIREN);
powerSnackActive = false;
}
Enemy* GameState::FindEnemyByPosition(sf::Vector2i pos)
{
for (Enemy* e : enemys)
{
if (e == NULL) continue;
if (e->gridPos == pos)
return e;
}
return NULL;
}
// mainmemustate.h
#pragma once
#include "../State.h"
#include "../../UI/Button.h"
class MainMenuState : public State
{
public:
MainMenuState(sf::RenderWindow* window, std::stack<State*>* states, GameManager* gameManager);
~MainMenuState();
void Update(const float& deltaTime);
void Draw();
private:
//sf::Font font;
std::map<std::string, Button*> buttons;
sf::Sprite mapSprite;
sf::Texture mapTexture;
};
#include "MainMenuState.h"
#include "../../GameManager.h"
#include "../GameState/GameState.h"
MainMenuState::MainMenuState(sf::RenderWindow* window, std::stack<State*>* states, GameManager* gameManager)
: State(window, states, gameManager)
{
this->buttons["GAME_STATE"] = new Button(
window->getView().getCenter().x - 100, 480.f,
200.f, 53.f,
"New Game", 50,
sf::Color(130, 130, 130, 255), sf::Color(250, 250, 250, 250), sf::Color(20, 20, 20, 50)
);
if (mapTexture.loadFromFile("Resources/pac-man-logo.png"))
{
mapTexture.setSmooth(false);
mapSprite.setTexture(mapTexture);
mapSprite.setScale(0.1f, 0.1f);
mapSprite.setPosition(window->getView().getCenter().x - (mapSprite.getGlobalBounds().width / 2), 20);
}
}
MainMenuState::~MainMenuState()
{
auto it = this->buttons.begin();
for (it = this->buttons.begin(); it != this->buttons.end(); ++it)
{
delete it->second;
}
}
void MainMenuState::Update(const float& deltaTime)
{
for (auto& it : this->buttons)
{
it.second->update(this->window->mapPixelToCoords(sf::Mouse::getPosition(*this->window)));
}
//New game
if (this->buttons["GAME_STATE"]->isPressed())
{
this->states->push(new GameState(window, states, gameManager));
}
Draw();
}
void MainMenuState::Draw()
{
window->clear();
window->draw(mapSprite);
for (auto& it : this->buttons)
{
it.second->render(window);
}
window->display();
}
// gameoverstate
#pragma once
#include "../State.h"
class GameOverState : public State
{
};
#include "GameOverState.h"
Editor is loading...