Untitled

mail@pastecode.io avatarunknown
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"