Untitled
plain_text
a month ago
20 kB
7
Indexable
Never
// 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"