首页 > 解决方案 > 如何使用 C++ SFML 中的数据/文本文件为 Breakout 游戏创建砖块布局?

问题描述

我正在使用 SFML 库在 C++ 中创建一个经典的突破游戏。到目前为止,我已经实现了一个可移动的桨和球。

目前,我的目标是创建砖的布局。到目前为止,我拥有它以便显示单个砖块。但是,我想这样做,以便我可以使用字母(例如使用字母“B”)在文本文件中绘制砖块布局,读取该文本文件的砖块布局并在游戏中绘制该布局。

我不知道该怎么做,所以任何帮助都会很棒!

到目前为止,这是我的代码(请注意,我没有包括 Paddle 和 Ball,因为我认为这个问题不需要它):

游戏对象.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;
}; 

游戏对象.cpp

#include "GameObject.h"

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

砖.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;
};

砖块.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()
{

}

游戏.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();
};

游戏.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();
    }
}

标签: c++videosfmlbreakout

解决方案


推荐阅读