0

I am creating a classic breakout game in C++ using SFML library. So far I have a movable paddle and ball implemented.

Currently, my goal is to create a layout of bricks. So far I have it so that a single brick is displayed. However, I want to make it so that I can draw a layout of bricks in text file using a letter (For example using letter 'B'), read that text file's brick layout and draw that layout in game.

I am not sure how to do this so any help would be great!

Here is my code so far (Note that I did not include for Paddle and Ball as I thought it was not needed for this problem):

GameObject.h

#pragma once
#include <SFML/Graphics.hpp>

class GameObject
{
protected:
    sf::Vector2f position;
    float speed;
    sf::RenderWindow& m_window;

public:
    GameObject(float startX, float startY, sf::RenderWindow& window);
    virtual ~GameObject() {};
    virtual void Draw() = 0;
    virtual void Update() = 0;
}; 

GameObject.cpp

#include "GameObject.h"

GameObject::GameObject(float startX, float startY, sf::RenderWindow& window)
    : position{ startX, startY }
    , speed{ 0.5f }
    , m_window{ window }
{
}

Brick.h

#pragma once
#include "GameObject.h"

class Brick : public GameObject
{
private:
    sf::RectangleShape brickShape;
    static constexpr int shapeWidth = 50;
    static constexpr int shapeHeight = 20;
    int color;
    int strength;

public:
    Brick(float startX, float startY, sf::RenderWindow& window);
    sf::FloatRect getPosition();
    sf::RectangleShape getShape();
    int getStrength();
    void setStrength(int strengthValue);
    void Draw() override;
    void Update() override;
};

Brick.cpp

#include "Brick.h"

Brick::Brick(float startX, float startY, sf::RenderWindow& window)
    : GameObject{ startX, startY, window }
{
    brickShape.setSize(sf::Vector2f(shapeWidth, shapeHeight));
    brickShape.setPosition(position);
    
    color = (rand() % 2) + 1;
    if (color == 1)
    {
        brickShape.setFillColor(sf::Color::Yellow);
        strength = 1;
    }
    else
    {
        brickShape.setFillColor(sf::Color(255, 165, 0));
        strength = 2;
    }
}

sf::FloatRect Brick::getPosition()
{
    return brickShape.getGlobalBounds();
}

sf::RectangleShape Brick::getShape()
{
    return brickShape;
}

int Brick::getStrength()
{
    return strength;
}

void Brick::setStrength(int strengthValue)
{
    strength = strengthValue;
}

void Brick::Draw()
{
    m_window.draw(brickShape);
}

void Brick::Update()
{

}

Game.h

#pragma once
#include <SFML/Graphics.hpp>

#include "Paddle.h"
#include "Ball.h"
#include "Brick.h"

#include <algorithm>
#include <fstream>
#include <iostream>

class Game
{
private:
    sf::RenderWindow& m_window;
    std::unique_ptr<Paddle> player;
    std::unique_ptr<Ball> ball;
    std::unique_ptr<Brick> brick;
    std::vector<std::unique_ptr<Brick>>bricks;

    int bricksCountX;
    int bricksCountY;

public:
    const unsigned int m_windowWidth;
    const unsigned int m_windowHeight;

public:
    Game(sf::RenderWindow& window, const unsigned int& windowWidth, const unsigned int& windowHeight);
    float RandomFloat(float a, float b);
    void ReadFile();
    void HandleCollision();
    void HandleInput();
    void Draw();
    void Update();
    void Run();
};

Game.cpp

#include "Game.h"

Game::Game(sf::RenderWindow& window, const unsigned int& windowWidth, const unsigned int& windowHeight)
    : m_window{ window }
    , m_windowWidth{ windowWidth }
    , m_windowHeight{ windowHeight }
{
    player = std::make_unique<Paddle>(m_windowWidth/2, m_windowHeight - 70, m_window);
    ball = std::make_unique<Ball>(m_windowWidth / 2, m_windowHeight / 2, m_window);

    ReadFile();

    for (int i = 0; i < bricksCountX; i++)
        for (int j = 0; j < bricksCountY; j++)
            bricks.emplace_back(std::make_unique<Brick>((i + 1.5) * ((long long)brick->getShape().getSize().x + 3) + 22,
                (j + 5) * (brick->getShape().getSize().y + 3), m_window));
}

float Game::RandomFloat(float a, float b)
{
    return ((b - a) * ((float)rand() / RAND_MAX)) + a;
}

void Game::ReadFile()
{
    // Create a text string, which is used to output the text file
    std::string bricksText;
    int numOfLines = 0;

    // Read from the text file
    std::ifstream MyReadFile("Bricks Layout.txt");

    // Use a while loop together with the getline() function to read the file line by line
    while (std::getline(MyReadFile, bricksText))
    {
        ++numOfLines;

        // Output the text from the file
        

        bricksCountX = bricksText.length();

        std::cout << bricksCountX;
    }

    bricksCountY = numOfLines;

    // Close the file
    MyReadFile.close();
}

void Game::HandleCollision()
{
    if (ball->getShape().getPosition().x - ball->getRadius() < 0.0f)
    {
        ball->reboundLeft();
    }
    else if (ball->getShape().getPosition().x + ball->getRadius() > m_windowWidth)
    {
        ball->reboundRight();
    }
    else if (ball->getShape().getPosition().y - ball->getRadius() < 0.0f)
    {
        ball->reboundTop();
    }
    else if (ball->getShape().getPosition().y + ball->getRadius() > m_windowHeight)
    {
        ball->ballAngle = ball->ballAngle * -1;
    }
    else if (ball->getPosition().intersects(player->getPosition()))
    {
        ball->reboundPaddle(*player);
    }
    for (unsigned int i = 0; i < bricks.size(); i++)
    {
        if (ball->getPosition().intersects(bricks[i]->getPosition()))
        {
            if (bricks[i]->getStrength() == 1)
            {
                ball->reboundBrick(*bricks[i]);
                bricks.erase(std::remove(bricks.begin(), bricks.end(), bricks[i]), bricks.end());
            }
            else
            {
                ball->reboundBrick(*bricks[i]);
                bricks[i]->setStrength(1);
            }
        }
    }
}

void Game::HandleInput()
{
    player->HandleInput();
}

void Game::Draw()
{
    player->Draw();
    ball->Draw();
    for (unsigned int i = 0; i < bricks.size(); i++)
    {
        bricks[i]->Draw();
    }
}

void Game::Update()
{
    player->Update();
    ball->Update();
    brick->Update();
}

void Game::Run()
{
    //Game Loop
    while (m_window.isOpen())
    {
        sf::Event event;
        while (m_window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed || sf::Keyboard::isKeyPressed(sf::Keyboard::Escape))
                m_window.close();
        }

        m_window.clear();

        Draw();
        HandleInput();
        HandleCollision();
        Update();

        m_window.display();
    }
}
AaySquare
  • 123
  • 10
  • create list (it is STL, bruh) of objects of `Bricks` class, and to all classes, that inherits `GameObject` class add field `name`(for example, Brick class will have `string name = "brick`"). By `for` loop check collision and names of objects. To draw bricks use array. – luk_chesnok_xren Nov 07 '20 at 18:25
  • if you want to write bricks in other file, use `` – luk_chesnok_xren Nov 07 '20 at 18:34
  • So I have updated my code. In the `Game` class, you will see I am now drawing the bricks using vector array. Also I tried reading text file and drawing the layout of bricks but it is not working properly just yet. As an example, if I put in my text file: `BBB BBB` , It draws the layout just fine, but if I put: `BBB BB` It draws like this: `BB BB` Sorry, Hope you understand what I am trying to say here. – AaySquare Nov 07 '20 at 21:53
  • for understanding, first it is better to implement an array of layers in the game file itself (in Game.cpp) – luk_chesnok_xren Nov 08 '20 at 06:20
  • also, try to create bricks with different lengths, I want say you not to use only one letter, use B and P, for example – luk_chesnok_xren Nov 08 '20 at 06:23

0 Answers0