Не могу нарисовать sf :: RectangleShape s хранится в векторе (клон Тетриса) - PullRequest
0 голосов
/ 12 марта 2020

Я пытаюсь сохранить sf::RectangleShape в std::vector, а затем нарисовать каждый из них в sf::RenderWindow.

Одиночный прямоугольник представляет 1x1 тетромино, и я хотел бы сохранить его в вектор каждый раз, когда он достигает нижней части окна. Затем я хотел бы сбросить положение текущего тетромино в положение по умолчанию.

Я думаю, что я даже не могу правильно его сохранить. Каждый раз, когда тетромино достигает дна, оно выдает мне следующее сообщение об ошибке:

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

Тетромино. 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);

1 Ответ

0 голосов
/ 12 марта 2020

В методе drawStack () вы пытаетесь выполнить итерацию в обратном направлении.

  1. Для вас есть обратный итератор.
  2. при расчете индекса у вас есть одна ошибка, которая работает только с пустым вектором (именно для предотвращения этих ошибок вы должны использовать итератор!)

Вы можете хочу прочитать об итераторах в C ++ , вот небольшой пример . В соответствии с вашим кодом он будет выглядеть (обратите внимание, что вам также нужен getStack () -метод в Tetromino.hpp, возвращающий ссылку вектора):

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