Hello Gamedev.net,
I recently finished making a breakout clone with C++ and sfml and would love to get some feedback on my rather long code. For my future projects I would like to possibly write better quality code than what I have here so would appreciate it if any of the pros would take the time to review it. I'd like to know the areas where I can improve and also anything that I am doing totally the wrong way.
I would also like some feedback on the game play, you can download the executable from here https://www.dropbox.com/s/t0vkmw6qk13r552/Eent%20Tord%20setup.rar
Here is the code:
Eent Tord.cpp
// Eent Tord.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
int main(int argc, _TCHAR* argv[])
{
srand((unsigned int)time(0)); // Seed the random number generator
Game game; // Initialize the game object and create a window
game.run();
return 0;
}
stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
// TODO: reference additional headers your program requires here
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include <memory>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cmath>
#include <vector>
#include <fstream>
#include <sstream>
#include "Random.h"
#include "Game_Object.h"
#include "Paddle.h"
#include "Brick.h"
#include "Ball.h"
#include "Image_Manager.h"
#include "Input_Manager.h"
#include "Level_Manager.h"
#include "Game.h"
#define SCREENWIDTH 832
#define SCREENHEIGHT 600
#define PADDLEYPOS 550.0f
#define MAXPADDLESPEED 400.0f
Game.h
#pragma once
class Game
{
public:
Game(void);
~Game(void);
void run();
void setTextures();
void update();
void drawAll();
bool isExiting();
void loseLife();
int livesLeft();
bool isLevelWon();
enum GAMESTATE { uninitialized, title, about, running, paused, gamelost, gamewon, exiting };
sf::RenderWindow m_Window;
sf::Event m_Event;
std::vector<std::unique_ptr<Brick>> m_Bricks;
private:
sf::VideoMode m_VMode;
GAMESTATE m_GameState;
Image_Manager m_imgMgr;
Input_Manager m_inpMgr;
Level_Manager m_lvlMgr;
sf::Clock m_Clock;
Paddle m_Paddle;
Ball m_Ball;
sf::Sprite m_Background;
sf::Sprite m_Quit;
sf::Sprite m_About;
sf::Sprite m_NewGame;
sf::Sprite m_GameOver;
sf::Sprite m_GameWon;
sf::Sprite m_Paused;
sf::Text m_AboutText;
sf::Text m_LivesText;
sf::Font m_Font;
};
Game.cpp
#include "stdafx.h"
Game::Game(void)
{
// Initialize the game object.
m_VMode.width = SCREENWIDTH;
m_VMode.height = SCREENHEIGHT;
m_VMode.bitsPerPixel = 32;
m_Window.create(m_VMode, "Eent Tord (Breakout/Arkanoid clone)", sf::Style::Titlebar); // Actually creates the window.
m_GameState = uninitialized;
m_Font.loadFromFile("C:/Windows/Fonts/arial.ttf");
m_AboutText.setFont(m_Font);
m_AboutText.setCharacterSize(16);
m_LivesText.setFont(m_Font);
m_LivesText.setCharacterSize(16);
m_imgMgr.loadAssets(); // Loads all the image files into memory.
m_Paddle.resetLives();
}
Game::~Game(void)
{
}
void Game::setTextures()
{
static GAMESTATE background = uninitialized;
switch (m_GameState)
{
case title:
if (background != title)
{
m_Background.setTexture(m_imgMgr.getTitle());
m_Quit.setTexture(m_imgMgr.getQuit());
m_About.setTexture(m_imgMgr.getAbout());
m_NewGame.setTexture(m_imgMgr.getNewGame());
m_GameOver.setTexture(m_imgMgr.getLost());
m_GameWon.setTexture(m_imgMgr.getWon());
m_Paused.setTexture(m_imgMgr.getPaused());
m_Paddle.getSprite().setTexture(m_imgMgr.getPaddle());
m_Ball.getSprite().setTexture(m_imgMgr.getBall());
}
background = title;
break;
case about:
{
background = about;
m_AboutText.setString("Left and right keys for movement, escape to pause, and space to launch the ball! Avoid hitting the red bricks!");
}
break;
case running:
if (background != running && background != paused)
{
m_Paddle.initialize();
m_Ball.initialize();
m_Clock.restart();
m_Paddle.resetLives();
if (!m_Bricks.empty())
{
m_Bricks.clear();
m_lvlMgr.setupLevel(m_Bricks, m_imgMgr);
}
else
m_lvlMgr.setupLevel(m_Bricks, m_imgMgr);
}
background = running;
break;
default:
break;
}
}
void Game::update()
{
switch (m_GameState)
{
case title:
m_Quit.setPosition(675.0f, 540.0f);
m_About.setPosition(675.0f, 500.0f);
m_NewGame.setPosition(670.0f, 460.0f);
break;
case about:
break;
case running:
{
std::stringstream printLives;
printLives << "Lives left = ";
printLives << m_Paddle.livesLeft();
m_LivesText.setString(printLives.str());
m_Paddle.update(m_Clock);
m_Ball.update(m_Clock, m_Paddle, m_Bricks);
}
break;
case gamelost:
m_GameOver.setPosition(350.0f, 250.0f);
break;
case gamewon:
m_GameWon.setPosition(350.0f, 250.0f);
break;
case paused:
m_Paused.setPosition(350.0f, 250.0f);
default:
break;
}
}
void Game::drawAll()
{
switch (m_GameState)
{
case title:
m_Window.draw(m_Background);
m_Window.draw(m_Quit);
m_Window.draw(m_About);
m_Window.draw(m_NewGame);
break;
case about:
{
m_Window.draw(m_AboutText);
}
break;
case running:
{
m_Window.draw(m_LivesText);
m_Window.draw(m_Paddle.getSprite());
m_Window.draw(m_Ball.getSprite());
for (auto iter = m_Bricks.begin(); iter != m_Bricks.end(); ++iter)
{
if ((*iter)->isAlive())
{
m_Window.draw((*iter)->getSprite());
}
}
}
break;
case gamelost:
{
m_Window.draw(m_LivesText);
m_Window.draw(m_Paddle.getSprite());
m_Window.draw(m_Ball.getSprite());
for (auto iter = m_Bricks.begin(); iter != m_Bricks.end(); ++iter)
{
if ((*iter)->isAlive())
{
m_Window.draw((*iter)->getSprite());
}
}
m_Window.draw(m_GameOver);
}
break;
case gamewon:
{
m_Window.draw(m_LivesText);
m_Window.draw(m_Paddle.getSprite());
m_Window.draw(m_Ball.getSprite());
for (auto iter = m_Bricks.begin(); iter != m_Bricks.end(); ++iter)
{
if ((*iter)->isAlive())
{
m_Window.draw((*iter)->getSprite());
}
}
m_Window.draw(m_GameWon);
}
break;
case paused:
{
m_Window.draw(m_LivesText);
m_Window.draw(m_Paddle.getSprite());
m_Window.draw(m_Ball.getSprite());
for (auto iter = m_Bricks.begin(); iter != m_Bricks.end(); ++iter)
{
if ((*iter)->isAlive())
{
m_Window.draw((*iter)->getSprite());
}
}
m_Window.draw(m_Paused);
}
break;
default:
break;
}
}
bool Game::isLevelWon()
{
bool isWon = false;
int aliveBricks = 0;
for (auto iter = m_Bricks.begin(); iter != m_Bricks.end(); iter++)
{
if ((*iter)->getType() == "blue" && (*iter)->isAlive() == true)
{
aliveBricks++;
}
}
if(aliveBricks > 0)
return false;
else
return true;
}
void Game::run()
{
//m_Window.setFramerateLimit(60);
m_GameState = title;
while (!isExiting()) // This is the main game loop responsible for handling events, updating game logic and drawing assets.
{
m_Window.pollEvent(m_Event);
static Input_Manager::titleResult tresult;
static Input_Manager::aboutResult aresult;
static Input_Manager::gameResult gresult;
static Input_Manager::gamelostResult lresult;
static Input_Manager::gamewonResult wresult;
static Input_Manager::pauseResult presult;
switch (m_GameState)
{
case title:
tresult = m_inpMgr.titleEvents(m_Event); // Accesses the titleEvents function in input manager class and returns a result.
if (tresult == Input_Manager::exit) // Based on the result the game state changes appropriately.
m_GameState = exiting;
else if (tresult == Input_Manager::about)
m_GameState = about;
else if (tresult == Input_Manager::newGame)
m_GameState = running;
else
break;
break;
case about:
aresult = m_inpMgr.aboutEvents(m_Event); // Accesses the aboutEvents function in input manager class and returns a result.
if (aresult == Input_Manager::back) // Based on the result the game state changes appropriately.
m_GameState = title;
else
break;
break;
case running:
gresult = m_inpMgr.gameEvents(m_Event, m_Paddle, m_Ball); // Accesses the gameEvents function in input manager class and returns a result.
if (gresult == Input_Manager::prev) // Based on the result the game state changes appropriately.
m_GameState = title;
else if (gresult == Input_Manager::paused)
m_GameState = paused;
else if (gresult == Input_Manager::idle && m_Paddle.livesLeft() > 0 && isLevelWon() == false);
else if (gresult == Input_Manager::idle && m_Paddle.livesLeft() > 0 && isLevelWon() == true)
m_GameState = gamewon;
else if (gresult == Input_Manager::idle && m_Paddle.livesLeft() < 0)
m_GameState = gamelost;
else
break;
break;
case gamelost:
lresult = m_inpMgr.lostEvents(m_Event);
if (lresult == Input_Manager::nada);
else if (lresult == Input_Manager::mainMenu)
m_GameState = title;
break;
case gamewon:
wresult = m_inpMgr.wonEvents(m_Event);
if (wresult == Input_Manager::idling);
else if (wresult == Input_Manager::menu)
m_GameState = title;
break;
case paused:
presult = m_inpMgr.pauseEvents(m_Event);
if (presult == Input_Manager::doNothing);
else if (presult == Input_Manager::theMainMenu)
m_GameState = title;
else if (presult == Input_Manager::resume)
m_GameState = running;
break;
default:
break;
}
setTextures(); // Sets all the textures according to game states.
update(); // Updates the position of all the items on screen
m_Clock.restart(); // Reset the clock
m_Window.clear(); // Clear the window to black color
drawAll(); // Draws all the sprite members to the renderTarget.
m_Window.display(); // Finally display the window.
sf::sleep(sf::milliseconds(2));
}
m_Window.close();
}
bool Game::isExiting()
{
if (m_GameState == exiting)
return true;
else
return false;
}
Random.h
#pragma once
int Random(int a, int b);
Random.cpp
#include "stdafx.h"
#include "Random.h"
// Returns a random number in [low, high].
int Random(int low, int high)
{
return low + rand() % ((high + 1) - low);
}
Game_Object.h
#pragma once
class Game_Object
{
public:
Game_Object(void);
~Game_Object(void);
virtual void initialize();
void setTexture(sf::Texture &texture);
sf::Sprite& getSprite();
sf::Vector2f getCenter();
protected:
sf::Sprite m_Sprite;
};
Game_Object.cpp
#include "StdAfx.h"
#include "Game_Object.h"
Game_Object::Game_Object(void)
{
}
Game_Object::~Game_Object(void)
{
}
void Game_Object::setTexture(sf::Texture &texture)
{
m_Sprite.setTexture(texture);
}
sf::Sprite& Game_Object::getSprite()
{
return m_Sprite;
}
void Game_Object::initialize()
{
}
sf::Vector2f Game_Object::getCenter()
{
return sf::Vector2f(m_Sprite.getGlobalBounds().left + m_Sprite.getGlobalBounds().width / 2, m_Sprite.getGlobalBounds().top + m_Sprite.getGlobalBounds().height / 2);
}
Paddle.h
#pragma once
class Paddle : public Game_Object
{
public:
Paddle(void);
~Paddle(void);
void initialize();
void update(sf::Clock& clock);
void resetLives();
void loseLife();
int livesLeft();
float m_Speed;
private:
int m_Lives;
};
Paddle.cpp
#include "StdAfx.h"
#include "Paddle.h"
Paddle::Paddle(void) : m_Speed(0.0f)
{
}
Paddle::~Paddle(void)
{
}
void Paddle::initialize()
{
m_Sprite.setPosition((SCREENWIDTH / 2) - (m_Sprite.getLocalBounds().width / 2), PADDLEYPOS);
m_Speed = 0.0f;
}
void Paddle::resetLives()
{
m_Lives = 5;
}
void Paddle::loseLife()
{
m_Lives -= 1;
/*if ( m_Lives < 0 )
m_Lives = 0;*/
}
int Paddle::livesLeft()
{
return m_Lives;
}
void Paddle::update(sf::Clock& clock)
{
m_Sprite.move(m_Speed * clock.getElapsedTime().asSeconds(), 0.0f);
if (m_Sprite.getPosition().x < 0.0f) // If the sprite goes past the bounds of the window
m_Sprite.setPosition(sf::Vector2f(0.0f, PADDLEYPOS)); // the position is reset to keep it inside the window
else if (m_Sprite.getPosition().x + m_Sprite.getLocalBounds().width > (float)SCREENWIDTH)
m_Sprite.setPosition(sf::Vector2f((float)SCREENWIDTH - m_Sprite.getLocalBounds().width , PADDLEYPOS));
}
Brick.h
#pragma once
#include "game_object.h"
class Brick : public Game_Object
{
public:
Brick(void);
Brick(sf::Texture& texture, std::string type);
~Brick(void);
void initialize();
void setPos(sf::Vector2f pos);
bool isAlive();
void kill();
std::string getType();
private:
bool alive;
std::string m_Type;
};
Brick.cpp
#include "StdAfx.h"
#include "Brick.h"
Brick::Brick(void) : alive(true), m_Type("")
{
}
Brick::Brick(sf::Texture& texture, std::string type)
{
m_Sprite.setTexture(texture);
m_Type = type;
alive = true;
}
Brick::~Brick(void)
{
}
void Brick::initialize()
{
}
std::string Brick::getType()
{
return m_Type;
}
void Brick::setPos(sf::Vector2f pos)
{
m_Sprite.setPosition(pos);
}
bool Brick::isAlive()
{
if (alive)
return true;
else
return false;
}
void Brick::kill()
{
alive = false;
}
Ball.h
#pragma once
class Ball : public Game_Object
{
public:
Ball(void);
~Ball(void);
void update(sf::Clock& clock, Paddle& paddle, std::vector<std::unique_ptr<Brick>>& bricks);
void initialize();
void normalizeDirectionVec();
void updatePosition(sf::Clock& clock);
bool lineIntersects(sf::Vector2f p1, sf::Vector2f p2, sf::Vector2f p3, sf::Vector2f p4);
void handleCollisions(Paddle& paddle, std::vector<std::unique_ptr<Brick>>& bricks);
bool isBallMoving;
sf::Vector2f m_Position;
sf::Vector2f m_Direction;
private:
float m_Speed;
sf::Vector2f m_LastPosition;
};
Ball.cpp
#include "StdAfx.h"
#include "Ball.h"
Ball::Ball(void) : isBallMoving(false), m_Speed(MAXPADDLESPEED)
{
}
Ball::~Ball(void)
{
}
void Ball::initialize()
{
if(isBallMoving)
isBallMoving = false;
m_Direction.x = 0.0f;
m_Direction.y = 0.0f;
int x = Random(-1, 1); // Generates a random number between -1 and 1 so that the direction of the ball is randomly chosen
m_Direction.x = static_cast<float>(x); // between three possible directions.
m_Direction.y = 1.0f;
normalizeDirectionVec();
m_Position.x = (SCREENWIDTH / 2) - (m_Sprite.getLocalBounds().width / 2);
m_Position.y = PADDLEYPOS - 300.0f;
m_Sprite.setPosition(m_Position);
}
void Ball::normalizeDirectionVec()
{
float len = sqrtf(m_Direction.x * m_Direction.x + m_Direction.y * m_Direction.y); // Get the length of the vector
m_Direction.x /= len;
m_Direction.y /= len;
}
void Ball::update(sf::Clock& clock, Paddle& paddle, std::vector<std::unique_ptr<Brick>>& bricks)
{
if (isBallMoving)
{
updatePosition(clock);
if (m_Sprite.getPosition().x + m_Sprite.getLocalBounds().width > static_cast<float>(SCREENWIDTH))
{
m_Sprite.setPosition(static_cast<float>(SCREENWIDTH) - m_Sprite.getLocalBounds().width, m_Sprite.getPosition().y);
m_Direction.x = m_Direction.x * (-1);
}
else if (m_Sprite.getPosition().x < 0.0f)
{
m_Sprite.setPosition(0.0f , m_Sprite.getPosition().y);
m_Direction.x = m_Direction.x * (-1);
}
else if (m_Sprite.getPosition().y < 0.0f)
{
m_Sprite.setPosition(m_Sprite.getPosition().x, 0.0f);
m_Direction.y *= (-1);
}
else if (m_Sprite.getPosition().y + m_Sprite.getLocalBounds().height > static_cast<float>(SCREENHEIGHT))
{
initialize();
paddle.initialize();
paddle.loseLife();
}
else
handleCollisions(paddle, bricks);
}
}
void Ball::updatePosition(sf::Clock& clock)
{
m_Sprite.move(m_Direction.x * m_Speed * clock.getElapsedTime().asSeconds(), m_Direction.y * m_Speed * clock.getElapsedTime().asSeconds());
}
bool Ball::lineIntersects(sf::Vector2f p1, sf::Vector2f p2, sf::Vector2f p3, sf::Vector2f p4)
{
float ua = (p4.x - p3.x) * (p1.y - p3.y) - (p4.y - p3.y) * (p1.x - p3.x);
float ub = (p2.x - p1.x) * (p1.y - p3.y) - (p2.y - p1.y) * (p1.x - p3.x);
float de = (p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y);
bool intersects = false;
if (fabsf(de) >= 0.00001f)
{
ua /= de;
ub /= de;
if (ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f)
intersects = true;
}
return intersects;
}
void Ball::handleCollisions(Paddle& paddle, std::vector<std::unique_ptr<Brick>>& bricks)
{
if (m_Sprite.getGlobalBounds().top > static_cast<float>(SCREENHEIGHT) / 2.0f) // Check the position of the ball and only check for collisions with the appropriate object
{
if (m_Direction.y > 0.0f && paddle.getSprite().getGlobalBounds().intersects(this->getSprite().getGlobalBounds()))
{
m_Direction.y *= (-1);
m_Sprite.setPosition(m_Sprite.getPosition().x, paddle.getSprite().getGlobalBounds().top - m_Sprite.getLocalBounds().height);
m_Direction.x = (getCenter().x - paddle.getCenter().x) / (paddle.getSprite().getGlobalBounds().width / 2); // Changes the direction
// of the ball depending upon where the ball hits the paddle.
normalizeDirectionVec();
}
}
else
{
sf::Vector2f centerTop(this->getSprite().getGlobalBounds().width / 2.0f, 0.0f);
sf::Vector2f centerLeft(0.0f, this->getSprite().getGlobalBounds().height / 2.0f);
sf::Vector2f centerRight(this->getSprite().getGlobalBounds().width, this->getSprite().getGlobalBounds().height / 2.0f);
sf::Vector2f centerBottom(this->getSprite().getGlobalBounds().width / 2.0f, this->getSprite().getGlobalBounds().height);
sf::Vector2f newDirection(m_Direction.x, m_Direction.y);
bool hit = false;
bool hitRed = false;
for (auto iter = bricks.begin(); iter != bricks.end(); ++iter)
{
if (!hit)
{
if ((*iter)->getSprite().getGlobalBounds().intersects(this->getSprite().getGlobalBounds()))
{
if ((*iter)->isAlive())
{
bool changed = false;
sf::Vector2f topLeft((*iter)->getSprite().getGlobalBounds().left, (*iter)->getSprite().getGlobalBounds().top);
sf::Vector2f topRight((*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width, (*iter)->getSprite().getGlobalBounds().top);
sf::Vector2f bottomLeft((*iter)->getSprite().getGlobalBounds().left, (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height);
sf::Vector2f bottomRight((*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width, (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height);
if (m_Direction.x > 0.0f && lineIntersects(m_LastPosition + centerRight, this->getSprite().getPosition() + centerRight, topLeft, bottomLeft))
{
newDirection.x *= -1.0f;
std::cout << "left" << std::endl;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
}
else if (m_Direction.x < 0.0f && lineIntersects(m_LastPosition + centerLeft, this->getSprite().getPosition() + centerLeft, topRight, bottomRight))
{
newDirection.x *= -1.0f;
std::cout << "right" << std::endl;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
}
if (m_Direction.y > 0.0f && lineIntersects(m_LastPosition + centerBottom, this->getSprite().getPosition() + centerBottom, topLeft, topRight))
{
newDirection.y *= -1.0f;
std::cout << "top" << std::endl;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
}
else if (m_Direction.y < 0.0f && lineIntersects(m_LastPosition + centerTop, this->getSprite().getPosition() + centerTop, bottomLeft, bottomRight))
{
newDirection.y *= -1.0f;
std::cout << "bottom" << std::endl;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
}
// Hit a corner
if (!changed)
{
if (m_Direction.x > 0.0f && m_Direction.y < 0.0f)
{
if (this->getSprite().getPosition().x < (*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width / 2.0f && this->getSprite().getPosition().y > (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height / 2.0f)
{
newDirection.x *= -1.0f;
newDirection.y *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
else if (this->getSprite().getPosition().x > (*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width / 2.0f && this->getSprite().getPosition().y > (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height / 2.0f)
{
newDirection.y *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
else
{
newDirection.x *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
}
else if (m_Direction.x < 0.0f && m_Direction.y < 0.0f)
{
if (this->getSprite().getPosition().x > (*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width / 2.0f && this->getSprite().getPosition().y > (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height / 2.0f)
{
newDirection.x *= -1.0f;
newDirection.y *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
else if (this->getSprite().getPosition().x < (*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width / 2.0f && this->getSprite().getPosition().y > (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height / 2.0f)
{
newDirection.y *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
else
{
newDirection.x *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
hitRed = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
}
else if (m_Direction.x > 0.0f && m_Direction.y > 0.0f)
{
if (this->getSprite().getPosition().x < (*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width / 2.0f && this->getSprite().getPosition().y < (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height / 2.0f)
{
newDirection.x *= -1.0f;
newDirection.y *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
else if (this->getSprite().getPosition().x > (*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width / 2.0f && this->getSprite().getPosition().y < (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height / 2.0f)
{
newDirection.y *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
else
{
newDirection.x *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
}
else
{
if (this->getSprite().getPosition().x > (*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width / 2.0f && this->getSprite().getPosition().y < (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height / 2.0f)
{
newDirection.x *= -1.0f;
newDirection.y *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
else if (this->getSprite().getPosition().x < (*iter)->getSprite().getGlobalBounds().left + (*iter)->getSprite().getGlobalBounds().width / 2.0f && this->getSprite().getPosition().y < (*iter)->getSprite().getGlobalBounds().top + (*iter)->getSprite().getGlobalBounds().height / 2.0f)
{
newDirection.y *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
else
{
newDirection.x *= -1.0f;
if ((*iter)->getType() == "blue")
{
(*iter)->kill();
changed = true;
hit = true;
break;
}
else if ((*iter)->getType() == "red")
{
initialize();
paddle.initialize();
paddle.loseLife();
hitRed = true;
break;
}
std::cout << "corner" << std::endl;
}
}
}
}
}
}
}
if(!hitRed)
m_Direction = newDirection;
m_LastPosition = this->getSprite().getPosition();
}
}
Image_Manager.h
#pragma once
class Image_Manager
{
public:
Image_Manager(void);
~Image_Manager(void);
void loadAssets();
sf::Texture& getTitle();
sf::Texture& getQuit();
sf::Texture& getAbout();
sf::Texture& getNewGame();
sf::Texture& getPaddle();
sf::Texture& getBall();
sf::Texture& getBlue();
sf::Texture& getRed();
sf::Texture& getLost();
sf::Texture& getWon();
sf::Texture& getPaused();
private:
sf::Texture m_Title;
sf::Image m_Image_Quit;
sf::Texture m_Texture_Quit;
sf::Image m_Image_About;
sf::Texture m_Texture_About;
sf::Image m_Image_NewGame;
sf::Texture m_Texture_NewGame;
sf::Texture m_GameLost;
sf::Texture m_GameWon;
sf::Texture m_PauseMenu;
sf::Texture m_Texture_Paddle;
sf::Image m_Image_Ball;
sf::Texture m_Texture_Ball;
sf::Texture m_Texture_Blue;
sf::Texture m_Texture_Red;
};
Image_Manager.cpp
#include "stdafx.h"
Image_Manager::Image_Manager(void)
{
}
Image_Manager::~Image_Manager(void)
{
}
void Image_Manager::loadAssets()
{
m_Title.loadFromFile("images/title_background.png");
m_Image_Quit.loadFromFile("images/quit.png");
m_Image_Quit.createMaskFromColor(sf::Color::White);
m_Texture_Quit.loadFromImage(m_Image_Quit);
m_Image_About.loadFromFile("images/About.png");
m_Image_About.createMaskFromColor(sf::Color::White);
m_Texture_About.loadFromImage(m_Image_About);
m_Image_NewGame.loadFromFile("images/new_game.png");
m_Image_NewGame.createMaskFromColor(sf::Color::White);
m_Texture_NewGame.loadFromImage(m_Image_NewGame);
m_GameLost.loadFromFile("images/game_over.png");
m_GameWon.loadFromFile("images/you_win.png");
m_PauseMenu.loadFromFile("images/pause_menu.png");
m_Texture_Paddle.loadFromFile("images/paddle.png");
m_Image_Ball.loadFromFile("images/ball.png");
m_Image_Ball.createMaskFromColor(sf::Color::White);
m_Texture_Ball.loadFromImage(m_Image_Ball);
m_Texture_Blue.loadFromFile("images/blue.png");
m_Texture_Red.loadFromFile("images/red.png");
}
sf::Texture& Image_Manager::getTitle()
{
return m_Title;
}
sf::Texture& Image_Manager::getQuit()
{
return m_Texture_Quit;
}
sf::Texture& Image_Manager::getAbout()
{
return m_Texture_About;
}
sf::Texture& Image_Manager::getNewGame()
{
return m_Texture_NewGame;
}
sf::Texture& Image_Manager::getLost()
{
return m_GameLost;
}
sf::Texture& Image_Manager::getWon()
{
return m_GameWon;
}
sf::Texture& Image_Manager::getPaused()
{
return this->m_PauseMenu;
}
sf::Texture& Image_Manager::getPaddle()
{
return m_Texture_Paddle;
}
sf::Texture& Image_Manager::getBall()
{
return m_Texture_Ball;
}
sf::Texture& Image_Manager::getBlue()
{
return m_Texture_Blue;
}
sf::Texture& Image_Manager::getRed()
{
return m_Texture_Red;
}
Input_Manager.h
#pragma once
class Input_Manager
{
public:
Input_Manager(void);
~Input_Manager(void);
enum titleResult { newGame, about, exit, nothing };
enum aboutResult { noAction, back };
enum gameResult { idle, prev, paused };
enum gamelostResult { mainMenu, nada };
enum gamewonResult { menu, idling };
enum pauseResult { theMainMenu, resume, doNothing };
titleResult titleEvents(sf::Event &Event);
aboutResult aboutEvents(sf::Event &Event);
gamelostResult lostEvents(sf::Event &Event);
gamewonResult wonEvents(sf::Event &Event);
pauseResult pauseEvents(sf::Event &Event);
gameResult gameEvents(sf::Event &Event, Paddle& paddle, Ball& ball);
};
Input_Manager.cpp
#include "StdAfx.h"
Input_Manager::Input_Manager(void)
{
}
Input_Manager::~Input_Manager(void)
{
}
Input_Manager::titleResult Input_Manager::titleEvents(sf::Event &Event)
{
switch(Event.type)
{
case sf::Event::Closed:
return exit;
break;
case sf::Event::KeyPressed:
switch(Event.key.code)
{
case sf::Keyboard::Escape:
return exit;
break;
default:
return nothing;
break;
}
case sf::Event::MouseButtonPressed:
if (Event.mouseButton.button == sf::Mouse::Left) // If mouse click is inside the Quit button
{ // The application will exit.
if(Event.mouseButton.x > 675.0f
&& Event.mouseButton.x < 675.0f + 54.0f
&& Event.mouseButton.y > 540.0f
&& Event.mouseButton.y < 540.0f + 16.0f)
return exit;
else if (Event.mouseButton.x > 675.0f
&& Event.mouseButton.x < 675.0f + 64.0f // If mouse click is inside the about button
&& Event.mouseButton.y > 500.0f // The application will display the about screen.
&& Event.mouseButton.y < 500.0f + 22.0f)
return about;
else if (Event.mouseButton.x > 670.0f // If mouse click is inside the new game button
&& Event.mouseButton.x < 675.0f + 108.0f // The application will display the game screen.
&& Event.mouseButton.y > 460.0f
&& Event.mouseButton.y < 460.0f + 32.0f)
return newGame;
else
return nothing;
}
else
return nothing;
break;
default:
return nothing;
break;
}
return nothing;
}
Input_Manager::aboutResult Input_Manager::aboutEvents(sf::Event& Event)
{
switch(Event.type)
{
case sf::Event::Closed:
return back;
break;
case sf::Event::KeyPressed:
switch(Event.key.code)
{
case sf::Keyboard::Escape:
return back;
break;
default:
return noAction;
break;
}
case sf::Event::MouseButtonPressed:
if (Event.mouseButton.button == sf::Mouse::Left)
{
if(Event.mouseButton.x > 0.0f // Clicking the mouse button anywhere inside the
&& Event.mouseButton.x < (float)SCREENWIDTH // window will take it back to the title screen.
&& Event.mouseButton.y > 0.0f
&& Event.mouseButton.y < (float)SCREENHEIGHT)
return back;
else
return noAction;
}
default:
return noAction;
break;
}
return noAction;
}
Input_Manager::gameResult Input_Manager::gameEvents(sf::Event& Event, Paddle& paddle, Ball& ball)
{
switch(Event.type)
{
case sf::Event::Closed:
return prev;
break;
case sf::Event::KeyPressed:
switch(Event.key.code)
{
case sf::Keyboard::Escape:
return paused;
break;
case sf::Keyboard::Left:
if (ball.isBallMoving)
{
paddle.m_Speed -= 40.0f;
if (paddle.m_Speed < -MAXPADDLESPEED)
paddle.m_Speed = -MAXPADDLESPEED;
}
return idle;
break;
case sf::Keyboard::Right:
if (ball.isBallMoving)
{
paddle.m_Speed += 40.0f;
if (paddle.m_Speed > MAXPADDLESPEED)
paddle.m_Speed = MAXPADDLESPEED;
}
return idle;
break;
case sf::Keyboard::Space:
if(!ball.isBallMoving)
ball.isBallMoving = true;
return idle;
break;
default:
return idle;
break;
}
case sf::Event::KeyReleased:
switch(Event.key.code)
{
case sf::Keyboard::Left:
paddle.m_Speed = 0.0f;
return idle;
break;
case sf::Keyboard::Right:
paddle.m_Speed = 0.0f;
return idle;
break;
default:
return idle;
break;
}
default:
return idle;
break;
}
return idle;
}
Input_Manager::gamelostResult Input_Manager::lostEvents(sf::Event &Event)
{
switch (Event.type)
{
case sf::Event::MouseButtonPressed:
if (Event.mouseButton.button == sf::Mouse::Left)
{
if (Event.mouseButton.x >= 380.0f &&
Event.mouseButton.x <= 460.0f &&
Event.mouseButton.y >= 385.0f &&
Event.mouseButton.y <= 400.0f)
return mainMenu;
}
break;
default:
break;
}
return nada;
}
Input_Manager::gamewonResult Input_Manager::wonEvents(sf::Event &Event)
{
switch (Event.type)
{
case sf::Event::MouseButtonPressed:
if (Event.mouseButton.button == sf::Mouse::Left)
{
if (Event.mouseButton.x >= 380.0f &&
Event.mouseButton.x <= 460.0f &&
Event.mouseButton.y >= 375.0f &&
Event.mouseButton.y <= 385.0f)
return menu;
}
break;
default:
break;
}
return idling;
}
Input_Manager::pauseResult Input_Manager::pauseEvents(sf::Event &Event)
{
switch (Event.type)
{
case sf::Event::MouseButtonPressed:
if (Event.mouseButton.button == sf::Mouse::Left)
{
if (Event.mouseButton.x >= 385.0f &&
Event.mouseButton.x <= 445.0f &&
Event.mouseButton.y >= 260.0f &&
Event.mouseButton.y <= 280.0f)
return resume;
else if (Event.mouseButton.x >= 370.0f &&
Event.mouseButton.x <= 440.0f &&
Event.mouseButton.y >= 375.0f &&
Event.mouseButton.y <= 390.0f)
return theMainMenu;
}
break;
case sf::Event::KeyPressed:
switch (Event.key.code)
{
case sf::Keyboard::Escape:
return resume;
}
default:
break;
}
return doNothing;
}
Level_Manager.h
#pragma once
class Level_Manager
{
public:
Level_Manager(void);
~Level_Manager(void);
void setLevel(int level);
void setupLevel(std::vector<std::unique_ptr<Brick>>& bricks, Image_Manager& m_imgMgr);
int getCurrentLevel();
int getNumberOfLevels();
void addBrick(int num);
private:
int m_Current_Level;
std::vector<int> m_brickType;
};
Level_Manger.cpp
#include "StdAfx.h"
#include "Level_Manager.h"
Level_Manager::Level_Manager(void) : m_Current_Level(1)
{
}
Level_Manager::~Level_Manager(void)
{
}
void Level_Manager::setLevel(int level)
{
m_Current_Level = level;
}
void Level_Manager::setupLevel(std::vector<std::unique_ptr<Brick>>& bricks, Image_Manager& m_imgMgr)
{
m_brickType.clear();
const int MAXBRICKS = 65;
float xPos = 0.0f, yPos = 50.0f;
const float HOFFSET = 64.0f;
const float VOFFSET = 20.0f;
const int BRICKROW = 13;
int count = 0;
std::ifstream inFile("levels/Walls.txt");
if (inFile)
{
int numLevel = 0, level = 0, type = 0;
std::string garbage = "";
inFile >> garbage >> numLevel;
inFile >> garbage >> level;
for ( int i = 0; i < MAXBRICKS; ++i )
{
inFile >> type;
m_brickType.push_back(type);
}
for (auto iter = m_brickType.begin(); iter != m_brickType.end(); ++iter)
{
std::string type = "";
if ( *iter == 1 )
{
type = "blue";
bricks.push_back(std::unique_ptr<Brick>(new Brick(m_imgMgr.getBlue(), type)));
}
else if ( *iter == 2)
{
type = "red";
bricks.push_back(std::unique_ptr<Brick>(new Brick(m_imgMgr.getRed(), type)));
}
}
for (auto iter = bricks.begin(); iter != bricks.end(); iter++)
{
(*iter)->setPos(sf::Vector2f(xPos, yPos));
xPos += HOFFSET;
count++;
if ( count % BRICKROW == 0 )
{
xPos = 0.0f;
yPos += VOFFSET;
}
}
}
else
std::cout << "Could not open file!" << std::endl;
}
int Level_Manager::getCurrentLevel()
{
return m_Current_Level;
}
int Level_Manager::getNumberOfLevels()
{
return 1; // To be updated later!!!!
}
void Level_Manager::addBrick(int num)
{
m_brickType.push_back(num);
}