This is my third review request on this forum:
Snake
Pong
Game:
Video
Files:
https://www.dropbox.com/s/5er86wt8wpy30zi/Breakout.zip
Code:
main.cpp
[spoiler]
#include <iostream>
#include "includes.h"
void doEvents(sf::RenderWindow & window, Upgrades & ups, BallState * ballState, Bullets * bullets, Entity * pad, Entity * ball, SoundEffect & shootSound, float pad_ball_delta_x);
int main(){
srand(time(0));
sf::RenderWindow window(sf::VideoMode(SCREEN_SIZE_X, SCREEN_SIZE_Y), "Breakout");
window.setVerticalSyncEnabled(true);
Entity pad(PAD_SIZE, (sf::Vector2f)SCREEN_SIZE - sf::Vector2f(SCREEN_CENTER.x - PAD_CENTER.x, PAD_SIZE.y + 10), sf::Color::White);
Entity ball(BALL_SIZE, sf::Vector2f(pad.getPosition().x + PAD_CENTER.x - BALL_CENTER.x, pad.getPosition().y - BALL_SIZE.y), sf::Color(200, 200, 200));
float volume = 50;
SoundEffect powerupSpawnSound("sounds/powerspawn.wav", volume);
SoundEffect powerupCatchSound("sounds/powercatch.wav", volume);
SoundEffect blockHitSound("sounds/blockhit.wav", volume);
SoundEffect explodeSound("sounds/explode.wav", volume);
SoundEffect wallHitSound("sounds/wallhit.wav", volume);
SoundEffect padHitSound("sounds/padhit.wav", volume);
SoundEffect deathSound("sounds/death.wav", volume);
SoundEffect shootSound("sounds/shoot.wav", volume);
float global_veloctiy = ORIGIN_VELOCITY;
float angle = 0;
sf::Vector2f velocity(global_veloctiy, global_veloctiy * -1);
Upgrades ups;
BallState ballState = BallState::Stopped;
Bullets bullets(sf::Vector2f(5, 15), sf::Color(255, 165, 0), MAX_VELOCITY * -1);
float lives = LIVES;
size_t score = 0;
size_t blockScore = 100;
size_t deathScore = 1000;
size_t padScore = 200;
size_t upgradeScore = 1000;
size_t boundScore = 50;
// Setting up the maps
size_t curMap = 0; // Set first map
size_t map_count = 11;
std::vector<std::string> maps(map_count);
for (size_t i = 0; i < map_count; i++)
maps[i] = "maps/" + std::to_string(i + 1) + ".png";
Map map(BLOCK_SIZE, OUTLINE_THICK, maps[curMap]);
//Fixed timestep stuff
sf::Clock clock;
double skippedTime = 0;
int updates = 0;
double secondSkipped = 0;
while (window.isOpen()){
const double elapsedTime = clock.getElapsedTime().asMicroseconds() / 1000.0;
skippedTime += elapsedTime;
secondSkipped += elapsedTime;
clock.restart();
while (skippedTime >= INTERVAL){
updates++;
while (secondSkipped > SECOND){
system("cls");
std::cout << updates << "Updates, " << secondSkipped / updates << " Average interval\n\n";
std::cout << "Stats:\n";
std::cout << "Lives: " << lives << '\n';
std::cout << "Score: " << score << '\n';
std::cout << '\n';
std::cout << "Upgrades:\n";
std::cout << "shooting: " << ups.isActive(Shooting) << '\n';
std::cout << "transparent: " << ups.isActive(Transparent) << '\n';
std::cout << "large pad: " << ups.isActive(Large) << '\n';
std::cout << "small pad: " << ups.isActive(Small) << '\n';
std::cout << "ball explode: " << ups.isActive(Explode) << '\n';
std::cout << "sticky pad: " << ups.isActive(Sticky) << '\n';
std::cout << "Y vel: " << velocity.y << '\n';
std::cout << "X vel: " << velocity.x << '\n';
std::cout << '\n';
updates = 0;
secondSkipped -= SECOND;
}
//Events
doEvents(window, ups, &ballState, &bullets, &pad, &ball, shootSound, ball.getPosition().x - pad.getPosition().x);
//Update
bullets.move();
ups.move();
if (ballState == BallState::Moving){
ball.move(velocity);
}
Entity bounds((sf::Vector2f)window.getSize(), sf::Vector2f(0, 0));
if (mth::boundaryIntersect(ball, bounds, Side::Left)){
velocity.x *= NEG;
ball.setPosition(bounds.getPosition().x, ball.getPosition().y);
wallHitSound.play();
score += boundScore;
}
else if (mth::boundaryIntersect(ball, bounds, Side::Right)){
velocity.x *= NEG;
ball.setPosition(bounds.getSize().x - ball.getSize().x, ball.getPosition().y);
wallHitSound.play();
score += boundScore;
}
if (mth::boundaryIntersect(ball, bounds, Side::Top)){
velocity.y *= NEG;
ball.setPosition(ball.getPosition().x, bounds.getPosition().y);
wallHitSound.play();
score += boundScore;
}
if (mth::boundaryIntersect(ball, bounds, Side::Bottom)){
lives--;
if (lives <= 0)
window.close();
ups.clearActive();
angle = 0;
global_veloctiy = ORIGIN_VELOCITY;
ballState = BallState::Stopped;
ball.setPosition(pad.getPosition().x + PAD_CENTER.x - BALL_CENTER.x, pad.getPosition().y - BALL_SIZE.y - 1);
velocity = sf::Vector2f(global_veloctiy, global_veloctiy * -1);
deathSound.play();
score += deathScore;
}
// Check for collisions between upgrades and pad
std::vector<Entity> upgrade_entities = ups.getEntities();
for (size_t i = 0; i < upgrade_entities.size(); i++){
if (mth::doesIntersect(pad, upgrade_entities[i])){
ups.addUpgrade(i);
ups.removeAt(i);
std::cout << "sup";
ballState = BallState::Moving;
powerupCatchSound.play();
score += upgradeScore;
}
}
// Check for collisions between bullets and blocks
bool hit = false;
size_t loc_y;
size_t loc_x;
vect2dTile blocks = map.getMap();
std::vector<Entity> bullet_entities = bullets.get();
for (size_t z = 0; z < bullet_entities.size(); z++){
size_t x = bullet_entities[z].getGridPosition().x;
for (size_t y = 0; y < blocks.size(); y++){
if (blocks[y][x].strength > 0 && mth::doesIntersect(blocks[y][x].entity, bullet_entities[z])){
if (!ups.isActive(Transparent)){
bullets.removeAt(z);
}
if (rand() % 1000 <= UP_CHANCE){
ups.spawn(blocks[y][x].entity, FALL_VELOCITY, GRAVITY);
powerupSpawnSound.play();
}
map.hitAt(y, x);
if (ups.isActive(Explode)){
explodeSound.play();
map.hitAt(y + 1, x);
map.hitAt(y - 1, x);
map.hitAt(y, x + 1);
map.hitAt(y, x - 1);
score += blockScore * 4;
}
score += blockScore;
blockHitSound.play();
hit = true;
break;
}
}
if (hit)
break;
}
// Check for intersepts
blocks = map.getMap();
hit = false;
// Downwards movement intersepts
if (velocity.y > 0 && !hit){
if (mth::willIntercept(ball, pad, velocity, Side::Top)){
if (ups.isActive(Sticky)){
ballState = BallState::Stopped;
}
global_veloctiy += VELOCITY_INC;
if (global_veloctiy > MAX_VELOCITY) global_veloctiy = MAX_VELOCITY;
angle = mth::getAngleInRadians(pad.getPosition() + sf::Vector2f(pad.getSize().x / 2.0f, 20), ball.getPosition() + ball.getSize() / 2.0f);
velocity = mth::getVelocity(angle, global_veloctiy);
score += padScore;
padHitSound.play();
}
else
for (size_t i = 0; i < blocks.size(); i++){
for (size_t j = 0; j < blocks[i].size(); j++)
if (blocks[i][j].strength > 0 && mth::willIntercept(ball, blocks[i][j].entity, velocity, Side::Top)){
if (!ups.isActive(Transparent))
velocity.y *= NEG;
loc_y = i;
loc_x = j;
hit = true;
break;
}
if (hit)
break;
}
}
// Upwards movement intersepts
else if (velocity.y < 0 && !hit){
for (size_t i = 0; i < blocks.size(); i++){
for (size_t j = 0; j < blocks[i].size(); j++)
if (blocks[i][j].strength > 0 && mth::willIntercept(ball, blocks[i][j].entity, velocity, Side::Bottom)){
if (!ups.isActive(Transparent))
velocity.y *= NEG;
loc_y = i;
loc_x = j;
hit = true;
break;
}
if (hit)
break;
}
}
// Right movement intersepts
if (velocity.x > 0 && !hit){
if (mth::willIntercept(ball, pad, velocity, Side::Left)){
velocity *= NEG;
padHitSound.play();
score += padScore * 2;
}
else
for (size_t i = 0; i < blocks.size(); i++){
for (size_t j = 0; j < blocks[i].size(); j++)
if (blocks[i][j].strength > 0 && mth::willIntercept(ball, blocks[i][j].entity, velocity, Side::Left)){
if (!ups.isActive(Transparent))
velocity.x *= NEG;
loc_y = i;
loc_x = j;
hit = true;
break;
}
if (hit)
break;
}
}
// Left movement intersepts
else if (velocity.x < 0 && !hit){
if (mth::willIntercept(ball, pad, velocity, Side::Right)){
velocity *= NEG;
padHitSound.play();
score += padScore * 2;
}
else
for (size_t i = 0; i < blocks.size(); i++){
for (size_t j = 0; j < blocks[i].size(); j++)
if (blocks[i][j].strength > 0 && mth::willIntercept(ball, blocks[i][j].entity, velocity, Side::Right)){
if (!ups.isActive(Transparent))
velocity.x *= NEG;
loc_y = i;
loc_x = j;
hit = true;
break;
}
if (hit)
break;
}
}
if (hit){
if (rand() % 1000 <= UP_CHANCE){
ups.spawn(blocks[loc_y][loc_x].entity, FALL_VELOCITY, GRAVITY);
powerupSpawnSound.play();
}
map.hitAt(loc_y, loc_x);
if (ups.isActive(Explode)){
explodeSound.play();
map.hitAt(loc_y + 1, loc_x);
map.hitAt(loc_y - 1, loc_x);
map.hitAt(loc_y, loc_x + 1);
map.hitAt(loc_y, loc_x - 1);
}
blockHitSound.play();
score += blockScore;
}
std::vector<Upgrd> active_ups = ups.getActiveUpgrades();
Upgrd LorS = None_upgrd;
for (size_t i = 0; i < active_ups.size(); i++){
if (active_ups[i] == Large || active_ups[i] == Small)
LorS = active_ups[i];
}
if (LorS == Large){
pad.setSize(PAD_SIZE.x * 2.0f, PAD_SIZE_Y);
}
else if (LorS == Small){
pad.setSize(PAD_SIZE.x / 2.0f, PAD_SIZE_Y);
}
else if (LorS == None_upgrd){
pad.setSize(PAD_SIZE);
}
upgrade_entities = ups.getEntities();
for (size_t i = 0; i < upgrade_entities.size(); i++){
if (upgrade_entities[i].getPosition().y > window.getSize().y)
ups.removeAt(i);
}
bullet_entities = bullets.get();
for (size_t i = 0; i < bullet_entities.size(); i++){
if (bullet_entities[i].getPosition().y < -100)
bullets.removeAt(i);
}
if (map.isCleared()){
if (curMap < map_count - 1){
map.setMap(maps[++curMap]);
global_veloctiy = ORIGIN_VELOCITY;
velocity = sf::Vector2f(global_veloctiy, global_veloctiy * -1);
ballState = BallState::Stopped;
ball.setPosition(pad.getPosition().x + PAD_CENTER.x - BALL_CENTER.x, pad.getPosition().y - BALL_SIZE.y);
ups.clearActive();
bullets.clear();
}
else{
curMap = 0;
}
}
// Subtract INTERVAL from skippedTime
skippedTime -= INTERVAL;
}
// Render
window.clear(sf::Color(20, 20, 20));
map.draw(window);
ball.draw(window);
ups.draw(window);
pad.draw(window);
bullets.draw(window);
window.display();
}
return 0;
}
void doEvents(sf::RenderWindow & window, Upgrades & ups, BallState * ballState, Bullets * bullets, Entity * pad, Entity * ball, SoundEffect & shootSound, float pad_ball_delta_x){
sf::Event event;
while (window.pollEvent(event)){
if (event.type == sf::Event::Closed)
window.close();
else if (event.type == sf::Event::KeyPressed){
sf::Keyboard k;
if (event.key.code == k.Escape){
window.close();
}
if (event.key.code == k.Space){
*ballState = BallState::Moving;
}
if (event.key.code == k.F1){
ups.addUpgrade(Sticky);
}
if (event.key.code == k.F2){
ups.addUpgrade(Shooting);
}
if (event.key.code == k.F3){
ups.addUpgrade(Explode);
}
if (event.key.code == k.F4){
ups.addUpgrade(Transparent);
}
if (event.key.code == k.F5){
ups.addUpgrade(Large);
}
if (event.key.code == k.F6){
ups.addUpgrade(Small);
}
}
else if (event.type == sf::Event::MouseMoved){
pad->setPosition(event.mouseMove.x - pad->getSize().x / 2.0f, pad->getPosition().y);
if (*ballState == BallState::Stopped){
ball->setPosition(pad->getPosition().x + pad_ball_delta_x, pad->getPosition().y - ball->getSize().y);
}
}
else if (event.type == sf::Event::MouseButtonPressed){
if (event.mouseButton.button == sf::Mouse::Button::Left){
*ballState = BallState::Moving;
if (ups.isActive(Shooting)){
bullets->spawn(pad->getPosition() + sf::Vector2f(pad->getSize().x / 2.0f, 0));
shootSound.play();
}
}
}
}
}
[/spoiler]
includes.h
[spoiler]
#pragma once
#include <string>
#include <vector>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "globals.h"
#include "Entity.h"
#include "SoundEffect.h"
#include "Map.h"
#include "Bullet.h"
#include "Upgrade.h"
#include "mth_namespace.h"
[/spoiler]
globals.h
[spoiler]
#pragma once
#include <SFML/System/Vector2.hpp>
struct Tile;
const float BLOCK_SIZE_XY = 40.0f;
const float BALL_SIZE_XY = 20.0f;
const float PAD_SIZE_Y = 20.0f;
const float PAD_SIZE_X = PAD_SIZE_Y * 5.0f;
const float UP_SIZE_XY = 40.0f;
const int GRID_SIZE_X = 20;
const int GRID_SIZE_Y = 10;
const int SCREEN_SIZE_X = (int)BLOCK_SIZE_XY * GRID_SIZE_X;
const int SCREEN_SIZE_Y = (int)BLOCK_SIZE_XY * GRID_SIZE_Y + 200;
const float FALL_VELOCITY = -2;
const float GRAVITY = 0.04f;
const float ORIGIN_VELOCITY = 2;
const float VELOCITY_INC = 0.15f;
const float MAX_VELOCITY = 8;
const int LIVES = 3;
const int INTERVAL = 10;
const int SECOND = 1000;
const int UP_CHANCE = 50; // in 1000
const float OUTLINE_THICK = -10.0f;
const float NEG = -1.0f;
const sf::Vector2i SCREEN_SIZE(SCREEN_SIZE_X, SCREEN_SIZE_Y);
const sf::Vector2f BLOCK_SIZE(BLOCK_SIZE_XY, BLOCK_SIZE_XY);
const sf::Vector2f BALL_SIZE(BALL_SIZE_XY, BALL_SIZE_XY);
const sf::Vector2i GRID_SIZE(GRID_SIZE_X , GRID_SIZE_Y);
const sf::Vector2f SCREEN_CENTER(SCREEN_SIZE / 2);
const sf::Vector2f PAD_SIZE(PAD_SIZE_X, PAD_SIZE_Y);
const sf::Vector2f BLOCK_CENTER(BLOCK_SIZE / 2.0f);
const sf::Vector2f BALL_CENTER(BALL_SIZE / 2.0f);
const sf::Vector2f PAD_CENTER( PAD_SIZE / 2.0f);
typedef std::vector<std::vector<Tile>> vect2dTile;
enum BallState{
Moving,
Stopped
};
enum class Movement{
Up,
Down,
Left,
Right
};
enum Side{
Top,
Bottom,
Left,
Right
};
enum Upgrd{
Shooting,
Transparent,
Large,
Small,
Explode,
Sticky,
LAST_upgrd,
None_upgrd
};
[/spoiler]
mth_namespace.h
[spoiler]
#pragma once
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
class Entity;
enum Side;
namespace mth{
// A simple struct to make it easier to do stuff with lines
struct Line;
// A simple function to determine whether entity1 is within entity2
bool doesIntersect(Entity entity1, Entity entity2);
// Test if an entity is outside the entity bounds
bool boundaryIntersect(Entity entity, Entity bounds, Side side);
// Test for an intersection between two lines
bool lineIntersect(Line line, sf::Vector2f pointMoving, float diam);
// Test if two entities will intersect with the current velocity vel
bool willIntercept(const Entity & entityMoving, const Entity & entityStatic, sf::Vector2f vel, Side side);
// Get the angle between two vectors in radians
float getAngleInRadians(const sf::Vector2f & entityStaticCenter, const sf::Vector2f & entityMovingCenter);
// Calculate directional veloctiy, given radians and global velocity
sf::Vector2f getVelocity(float radians, float vel);
}
[/spoiler]
mth_namespace.cpp
[spoiler]
#include "mth_namespace.h"
#include "includes.h"
#include <iostream>
struct mth::Line{
Line(){}
Line(sf::Vector2f pointA, sf::Vector2f pointB) : A(pointA), B(pointB){}
sf::Vector2f A;
sf::Vector2f B;
};
bool mth::doesIntersect(Entity entity1, Entity entity2){
if (entity1.getPosition().x <= entity2.getPosition().x + entity2.getSize().x &&
entity1.getPosition().x + entity1.getSize().x >= entity2.getPosition().x &&
entity1.getPosition().y <= entity2.getPosition().y + entity2.getSize().y &&
entity1.getPosition().y + entity1.getSize().y >= entity2.getPosition().y)
return true;
return false;
}
bool mth::boundaryIntersect(Entity entity, Entity bounds, Side side){
if (side == Side::Top && entity.getPosition().y < bounds.getPosition().y)
return true;
else if (side == Side::Bottom && entity.getPosition().y + entity.getSize().y > bounds.getPosition().y + bounds.getSize().y)
return true;
else if (side == Side::Left && entity.getPosition().x < bounds.getPosition().x)
return true;
else if (side == Side::Right && entity.getPosition().x + entity.getSize().x > bounds.getPosition().x + bounds.getSize().x)
return true;
return false;
}
bool mth::lineIntersect(Line line, sf::Vector2f pointMoving, float diam){
if (line.A.x == line.B.x && pointMoving.x >= line.A.x - diam / 2.0f && pointMoving.x <= line.A.x + diam / 2.0f &&
pointMoving.y >= line.A.y && pointMoving.y <= line.B.y)
return true;
if (line.A.y == line.B.y && pointMoving.y >= line.A.y - diam / 2.0f && pointMoving.y <= line.A.y + diam / 2.0f &&
pointMoving.x >= line.A.x && pointMoving.x <= line.B.x)
return true;
return false;
}
bool mth::willIntercept(const Entity & entityMoving, const Entity & entityStatic, sf::Vector2f vel, Side side){
float m, b;
sf::Vector2f emCenter(entityMoving.getPosition() + (entityMoving.getSize() / 2.0f));
m = ((emCenter.y + vel.y) - emCenter.y) /
((emCenter.x + vel.x) - emCenter.x);
b = emCenter.y - m * emCenter.x;
Line line;
sf::Vector2f start(emCenter);
sf::Vector2f end;
if (side <= Bottom){
line.A = entityStatic.getPosition() + sf::Vector2f(0, entityStatic.getSize().y * side);
line.B = entityStatic.getPosition() + sf::Vector2f(entityStatic.getSize().x, entityStatic.getSize().y * side);
end = sf::Vector2f((int)((vel.y + emCenter.y - b) / m), vel.y + emCenter.y);
if (side == Top){
for (float y = 0; y <= vel.y; y += 0.1f){
if (lineIntersect(line, sf::Vector2f((int)((y + emCenter.y - b) / m), y + emCenter.y), entityMoving.getSize().y))
return true;
}
}
else if (side == Bottom){
for (float y = 0; y >= vel.y; y -= 0.1f){
if (lineIntersect(line, sf::Vector2f((int)((y + emCenter.y - b) / m), y + emCenter.y), entityMoving.getSize().y))
return true;
}
}
}
else if (side >= Left){
int tmpSide = side - Left;
line.A = entityStatic.getPosition() + sf::Vector2f(entityStatic.getSize().x * tmpSide, 0);
line.B = entityStatic.getPosition() + sf::Vector2f(entityStatic.getSize().x * tmpSide, entityStatic.getSize().y);
end = sf::Vector2f(vel.x + emCenter.x, (int)(m * (vel.x + emCenter.x) + b));
if (side == Left){
for (float x = 0; x <= vel.x; x += 0.1f){
if (lineIntersect(line, sf::Vector2f(x + emCenter.x, (int)(m * (x + emCenter.x) + b)), entityMoving.getSize().x))
return true;
}
}
else if (side == Right){
for (float x = 0; x >= vel.x; x -= 0.1f){
if (lineIntersect(line, sf::Vector2f(x + emCenter.x, (int)(m * (x + emCenter.x) + b)), entityMoving.getSize().x))
return true;
}
}
}
return false;
}
float mth::getAngleInRadians(const sf::Vector2f & entityStaticCenter, const sf::Vector2f & entityMovingCenter){
return atan2f((entityMovingCenter.y - (entityStaticCenter.y)), (entityMovingCenter.x - (entityStaticCenter.x)));
}
sf::Vector2f mth::getVelocity(float radians, float vel){
return sf::Vector2f((float)cos(radians) * (float)vel, (float)sin(radians) * (float)vel);
}
[/spoiler]
Entity.h
[spoiler]
#pragma once
#include <SFML/Graphics/RectangleShape.hpp>
#include <SFML/System/Vector2.hpp>
#include <SFML/Graphics/Color.hpp>
#include <SFML/Graphics/RenderWindow.hpp>
class Entity
{
private:
protected:
sf::RectangleShape rect;
public:
Entity(sf::Vector2f size, sf::Vector2f pos, sf::Color color = sf::Color::White);
Entity(){ }
sf::Vector2f getPosition() const;
sf::Vector2i getGridPosition() const;
sf::Vector2f getSize() const;
float getOutlineThickness() const;
void draw(sf::RenderWindow & window);
void move(const sf::Vector2f & dist);
void setPosition(float x, float y);
void setPosition(const sf::Vector2f & pos);
void setGridPosition(size_t x, size_t y);
void setSize(float x, float y);
void setSize(const sf::Vector2f & size);
void setColor(const sf::Color & color);
void setOutline(float thickness, const sf::Color & color);
void setOutlineThickness(float thickness);
void setOutlineColor(const sf::Color & color);
};
[/spoiler]
Entity.cpp
[spoiler]
#include "Entity.h"
#include "includes.h"
#include <iostream>
Entity::Entity(sf::Vector2f size, sf::Vector2f pos, sf::Color color){
setSize(size);
setPosition(pos);
setColor(color);
}
sf::Vector2f Entity::getPosition() const{
return rect.getPosition();
}
sf::Vector2i Entity::getGridPosition() const{
return sf::Vector2i(rect.getPosition().x / BLOCK_SIZE_XY, rect.getPosition().y / BLOCK_SIZE_XY);
}
sf::Vector2f Entity::getSize() const{
return rect.getSize();
}
float Entity::getOutlineThickness() const{
return rect.getOutlineThickness();
}
void Entity::draw(sf::RenderWindow & window){
window.draw(rect);
}
void Entity::move(const sf::Vector2f & dist){
rect.setPosition(rect.getPosition() + dist);
}
void Entity::setPosition(float x, float y){
rect.setPosition(x, y);
}
void Entity::setPosition(const sf::Vector2f & pos){
rect.setPosition(pos);
}
void Entity::setGridPosition(size_t x, size_t y){
setPosition(x * getSize().x, y * getSize().y);
}
void Entity::setSize(float x, float y){
rect.setSize(sf::Vector2f(x, y));
}
void Entity::setSize(const sf::Vector2f & size){
rect.setSize(size);
}
void Entity::setColor(const sf::Color & color){
rect.setFillColor(color);
}
void Entity::setOutline(float thickness, const sf::Color & color){
rect.setOutlineThickness(thickness);
rect.setOutlineColor(color);
}
void Entity::setOutlineThickness(float thickness){
rect.setOutlineThickness(thickness);
}
void Entity::setOutlineColor(const sf::Color & color){
rect.setOutlineColor(color);
}
[/spoiler]
Map.h
[spoiler]
#pragma once
#include "Entity.h"
#include "globals.h"
struct Tile{
Entity entity;
char strength = 1;
};
class Map
{
vect2dTile tileMap;
sf::Image map;
Entity model;
public:
Map(const sf::Vector2f & tileSize, float outlineThickness, std::string mapPath);
vect2dTile getMap() const;
bool isCleared() const;
void setMap(std::string mapPath);
void hitAt(size_t y, size_t x);
void draw(sf::RenderWindow & window);
};
[/spoiler]
Map.cpp
[spoiler]
#include "Map.h"
#include "includes.h"
Map::Map(const sf::Vector2f & tileSize, float outlineThickness, std::string mapPath){
model.setSize(tileSize);
model.setOutlineThickness(outlineThickness);
setMap(mapPath);
}
vect2dTile Map::getMap() const{
return tileMap;
}
bool Map::isCleared() const{
bool cleared = true;
for (size_t y = 0; y < tileMap.size(); y++){
for (size_t x = 0; x < tileMap[y].size(); x++){
if (tileMap[y][x].strength > 0)
cleared = false;
}
}
return cleared;
}
void Map::setMap(std::string mapPath){
// Load map
if (!map.loadFromFile(mapPath))
std::exit(-3);
// Initialize tile map
tileMap.resize(map.getSize().y);
for (size_t i = 0; i < tileMap.size(); i++)
tileMap[i].resize(map.getSize().x);
// Set tile map
for (size_t y = 0; y < tileMap.size(); y++){
for (size_t x = 0; x < tileMap[y].size(); x++){
if (map.getPixel(x, y) == sf::Color::Magenta)
tileMap[y][x].strength = 0;
else{
tileMap[y][x].strength = 1;
sf::Color pixCol = map.getPixel(x, y);
tileMap[y][x].entity.setSize(model.getSize());
tileMap[y][x].entity.setGridPosition(x, y);
tileMap[y][x].entity.setColor(pixCol);
tileMap[y][x].entity.setOutline(model.getOutlineThickness(), sf::Color(pixCol.r / 1.5f, pixCol.g / 1.5f, pixCol.b / 1.5f));
}
}
}
}
void Map::hitAt(size_t y, size_t x){
if (tileMap.size() > y && y >= 0 && tileMap[y].size() > x && x >= 0){
if (tileMap[y][x].strength <= 1)
tileMap[y][x].strength = 0;
else
tileMap[y][x].strength--;
}
}
void Map::draw(sf::RenderWindow & window){
for (size_t i = 0; i < tileMap.size(); i++)
for (size_t j = 0; j < tileMap[i].size(); j++){
if (tileMap[i][j].strength > 0)
tileMap[i][j].entity.draw(window);
}
}
[/spoiler]
Upgrade.h
[spoiler]
#pragma once
#include <vector>
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Vector2.hpp>
#include "globals.h"
class Entity;
class Upgrades
{
std::vector<Upgrd> active;
std::vector<Entity> entity;
std::vector<Upgrd> upgrd;
std::vector<sf::Vector2f> velocity;
float gravity;
public:
Upgrades(){
}
std::vector<Upgrd> getActiveUpgrades() const;
std::vector<Entity> getEntities() const;
void spawn(const Entity & origin, float startYVel, float gravity);
void move();
void removeAt(size_t item);
void addUpgrade(Upgrd up);
void addUpgrade(size_t upgrd_item);
bool isActive(Upgrd up) const;
void draw(sf::RenderWindow & window);
void clearActive();
};
[/spoiler]
Upgrade.cpp
[spoiler]
#include "Upgrade.h"
#include "includes.h"
std::vector<Upgrd> Upgrades::getActiveUpgrades() const{
return active;
}
std::vector<Entity> Upgrades::getEntities() const{
return entity;
}
void Upgrades::spawn(const Entity & origin, float startYVel, float gravity){
entity.push_back(origin);
Upgrd tmp = (Upgrd)(rand() % LAST_upgrd);
upgrd.push_back(tmp);
velocity.push_back(sf::Vector2f(-0.5f + rand() % 11 / 10.0f, startYVel));
this->gravity = gravity;
}
void Upgrades::move(){
for (size_t i = 0; i < entity.size(); i++){
entity[i].move(velocity[i]);
if (velocity[i].y < MAX_VELOCITY)
velocity[i].y += gravity;
else
velocity[i].y = MAX_VELOCITY;
}
}
void Upgrades::removeAt(size_t item){
entity.erase(entity.begin() + item);
upgrd.erase(upgrd.begin() + item);
velocity.erase(velocity.begin() + item);
}
void Upgrades::addUpgrade(Upgrd up){
active.push_back(up);
}
void Upgrades::addUpgrade(size_t upgrd_item){
active.push_back(upgrd[upgrd_item]);
}
bool Upgrades::isActive(Upgrd up) const{
for (size_t i = 0; i < active.size(); i++){
if (active[i] == up)
return true;
}
return false;
}
void Upgrades::draw(sf::RenderWindow & window){
for (size_t i = 0; i < entity.size(); i++){
entity[i].draw(window);
}
}
void Upgrades::clearActive(){
active.clear();
}
[/spoiler]
Bullet.h
[spoiler]
#pragma once
#include <vector>
#include "Entity.h"
#include <SFML/System/Vector2.hpp>
namespace sf{
class Color;
class RenderWindow;
};
class Bullets
{
std::vector<Entity> bullets;
Entity model;
float yVel;
public:
Bullets(const sf::Vector2f & size, const sf::Color & color, float vel);
std::vector<Entity> get() const;
void draw(sf::RenderWindow & window);
void move();
void clear();
void removeAt(size_t item);
void spawn(const sf::Vector2f & origin);
};
[/spoiler]
Bullet.cpp
[spoiler]
#include "Bullet.h"
#include "includes.h"
Bullets::Bullets(const sf::Vector2f & size, const sf::Color & color, float vel){
model.setSize(size);
model.setColor(color);
yVel = vel;
}
std::vector<Entity> Bullets::get() const{
return bullets;
}
void Bullets::draw(sf::RenderWindow & window){
for (size_t i = 0; i < bullets.size(); i++){
bullets[i].draw(window);
}
}
void Bullets::move(){
for (size_t i = 0; i < bullets.size(); i++){
bullets[i].move(sf::Vector2f(0, yVel));
}
}
void Bullets::clear(){
bullets.clear();
}
void Bullets::removeAt(size_t item){
bullets.erase(bullets.begin() + item);
}
void Bullets::spawn(const sf::Vector2f & origin){
model.setPosition(origin);
bullets.push_back(model);
}
[/spoiler]
SoundEffect.h
[spoiler]
#pragma once
#include <SFML/Audio/SoundBuffer.hpp>
#include <SFML/Audio/Sound.hpp>
class SoundEffect
{
sf::SoundBuffer buffer;
sf::Sound sound;
public:
SoundEffect(std::string filePath, float volume);
SoundEffect(std::string filePath, sf::Sound sound);
SoundEffect(){ }
float getVolume() const;
void setVolume(float volume);
void play();
void pause();
void stop();
};
[/spoiler]
SoundEffect.cpp
[spoiler]
#include "SoundEffect.h"
#include "includes.h"
SoundEffect::SoundEffect(std::string filePath, float volume){
if (!buffer.loadFromFile(filePath))
std::exit(-2);
sound.setBuffer(buffer);
sound.setVolume(volume);
}
SoundEffect::SoundEffect(std::string filePath, sf::Sound sound){
if (!buffer.loadFromFile(filePath))
std::exit(-2);
this->sound = sound;
this->sound.setBuffer(buffer);
}
float SoundEffect::getVolume() const{
return sound.getVolume();
}
void SoundEffect::setVolume(float volume){
sound.setVolume(volume);
}
void SoundEffect::play(){
sound.play();
}
void SoundEffect::pause(){
sound.pause();
}
void SoundEffect::stop(){
sound.stop();
}
[/spoiler]