无法绘制存储在向量中的 sf::RectangleShape s(俄罗斯方块克隆)

Can't draw sf::RectangleShape s stored in vector (Tetris clone)

我正在尝试将 sf::RectangleShape 存储到 std::vector 中,然后将它们中的每一个都绘制到 sf::RenderWindow 中。

单个矩形代表 1x1 tetromino,每次到达 window 底部时我都想将它存储到向量中。那我想把当前的四联骨牌的位置重新设置到默认位置。

我想我什至无法正确存储它。每次四联骨牌到达底部时,它都会给我这个错误信息:

    terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc

请在下面找到我当前的代码。我刚开始研究它,但已经卡住了。

Definitions.h

#pragma once

// Point structure
struct Point
{
    int dim_x;
    int dim_y;
};

// Field Dimensions
const int fieldRows = 10;
const int fieldColumns = 9;
const int pointSize = 50.f;

// For checkingEdges funntion within the Tetrnomino.h
enum Edge
{
    leftEdge,
    rightEdge,
    noneEdge
};

Game.h

#pragma once

#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>

#include "Definitions.h"
#include "Tetromino.h"

class Game
{
public:
    Game();
    ~Game();
    // Game starter
    void run();

    // Accessors
    bool running();
private:

    // Updating and rendering the game window
    void update();
    void render();

    // Initialization
    void initVariables();
    void initWindow();
    void initBacgroundMusic();

    // Polling
    void pollEvents();

    // Window logic stuff
    sf::RenderWindow* _window;
    sf::Event _event;
    void drawStack();

    // Bacground Music
    sf::Music _ost;

    // Tetromino + Its logic
    Tetromino _T;
    sf::Time delayTime = sf::milliseconds(300);
    sf::Clock clock;

};

Tetromino.h

#pragma once

#include <SFML/Graphics.hpp>
#include <vector>

#include "Definitions.h"

class Tetromino
{
public:
    Tetromino();
    ~Tetromino();

    // Initialization
    void initTetromino();

    // Tetromonino logic
    void moveTetromino();
    Edge checkEdges();

    // Getters & Setters
    sf::RectangleShape getTetromino();
    sf::RectangleShape getStackPart(int part);
    int getStackSize();
    void setTetromino(sf::RectangleShape &t);

private:
    // The current tetromino
    sf::RectangleShape _tetromino;
    std::vector<sf::RectangleShape> _stack;
};

Game.cpp

#include "Game.h"

//-----Consturcotrs and Destructors-----//
Game::Game()
{
    //Basic Initialization
    _T.initTetromino();
    initVariables();
}

Game::~Game()
{
    delete _window;
}

//-----Private Functions-----//
void Game::run()
{
     update();
     render();
}

bool Game::running()
{
    return _window->isOpen();
}

void Game::update()
{
    sf::Time elapsed = clock.getElapsedTime();

    pollEvents();
    if (elapsed >= delayTime)
    {
        _T.moveTetromino();
        clock.restart();
    }
}

void Game::render()
{
    _window->clear(sf::Color::White);
    _window->draw(_T.getTetromino());
    drawStack();
    _window->display();
}

void Game::initVariables()
{
    _window = nullptr;
    initWindow();
    initBacgroundMusic();
}

void Game::initWindow()
{
    _window = new sf::RenderWindow(sf::VideoMode(fieldColumns * pointSize, fieldRows * pointSize), "Tetris v0.2", sf::Style::Default);
    _window->setVerticalSyncEnabled(true);
    _window->setFramerateLimit(60);
}

void Game::initBacgroundMusic()
{
    _ost.openFromFile("../QT_SFML_Tetris/Music.ogg");
    _ost.play();
    _ost.setLoop(true);
    _ost.setVolume(50.f);
}

void Game::pollEvents()
{
    while (_window->pollEvent(_event))
    {
        if (_event.type == sf::Event::Closed) {_window->close();}
        if (_event.type == sf::Event::KeyPressed)
        {
            if (_event.key.code == sf::Keyboard::Escape){_window->close();}
            if (_event.key.code == sf::Keyboard::Left && _T.checkEdges() != leftEdge)
            {
                sf::RectangleShape t = _T.getTetromino();
                t.setPosition(t.getPosition().x - pointSize, t.getPosition().y);
                _T.setTetromino(t);
                render();
            }
            if (_event.key.code == sf::Keyboard::Right && _T.checkEdges() != rightEdge)
            {
                sf::RectangleShape t = _T.getTetromino();
                t.setPosition(t.getPosition().x + pointSize, t.getPosition().y);
                _T.setTetromino(t);
                render();
            }
            if (_event.key.code == sf::Keyboard::Down)
            {
                sf::RectangleShape t = _T.getTetromino();
                t.setPosition(t.getPosition().x, t.getPosition().y+ pointSize);
                _T.setTetromino(t);
                render();
            }
        }
    }
}

**void Game::drawStack()**
{
        for (unsigned int i = _T.getStackSize(); i > 0; --i)
        {
            _window->draw(_T.getStackPart(i));
        }
}

main.cpp

#include <Game.h>

int main()
{
    Game game;
    while (game.running())
    {
        game.run();
    }
    return 0;
}

Tetromino.cpp

#include "Tetromino.h"

//-----Consturcotrs and Destructors-----//
Tetromino::Tetromino()
{

}

Tetromino::~Tetromino()
{

}

//-----Public Functions-----//
void Tetromino::initTetromino()
{
    _tetromino.setPosition(sf::Vector2f((fieldColumns * pointSize - pointSize) / 2, 0.f));
    _tetromino.setSize(sf::Vector2f(pointSize, pointSize));
    _tetromino.setFillColor(sf::Color::Red);
}

void Tetromino::moveTetromino()
{
    _tetromino.move(0.f, pointSize);

    if (_tetromino.getPosition().y > fieldRows * pointSize - pointSize)
    {
        _stack.push_back(_tetromino);
        _tetromino.setPosition(sf::Vector2f((fieldColumns * pointSize - pointSize) / 2, 0.f));
    }
}

Edge Tetromino::checkEdges()
{
    if (_tetromino.getPosition().x == 0)
    {
        return leftEdge;
    }
    else if (_tetromino.getPosition().x == (fieldColumns * pointSize) - pointSize)
    {
        return rightEdge;
    }
    else return noneEdge;
}

sf::RectangleShape Tetromino::getTetromino()
{
    return _tetromino;
}

sf::RectangleShape Tetromino::getStackPart(int part)
{
    return _stack[part];
}

int Tetromino::getStackSize()
{
    return _stack.size();
}

void Tetromino::setTetromino(sf::RectangleShape &t)
{
    _tetromino = t;
}

我认为主要问题可能在这一行内:

        _stack.push_back(_tetromino);

在 drawStack() 方法中,您尝试向后迭代。

  1. 有一个反向迭代器为您做这件事。
  2. 你的索引计算中有一个差一错误,它只适用于空向量(正是为了防止这些错误,你应该使用迭代器!)

您可能想要了解 C++ 中的迭代器 here is a small example。 根据您的代码,它看起来像(请注意,您还需要一个 getStack()-Tetromino.hpp 中的方法,返回 reference向量):

void Game::drawStack()
{
    for (auto it = _T.getStack().rbegin(); it != _T.getStack().rend(); it++)
    {
        _window->draw(*it);
    }
}

如果你想保留索引,我这是一个修复:

    void Game::drawStack()
    {
        for (int i = _T.getStackSize()-1; i >= 0; --i)
        {
            _window->draw(_T.getStackPart(i));
        }
    }