Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: TETRIS Clone  (Read 3190 times)

0 Members and 1 Guest are viewing this topic.

Kyoukan97

  • Newbie
  • *
  • Posts: 6
    • View Profile
TETRIS Clone
« on: July 31, 2015, 05:03:35 pm »
Hi ^.^
I am new to this forum and i currently working on my first game , Tetris *yay*

I just wanted to share my Tetromino class and get some opinions on how i can improve it :) ( i tried messing around with C++11 a bit )
This is the header file :
#ifndef TETROMINO_HPP
#define TETROMINO_HPP

#include <array>

#include <SFML\Graphics.hpp>

enum typeTetrominoID { IBrick, JBrick, LBrick, OBrick, SBrick, TBrick, ZBrick };

struct TetrominoCodes
{
        using TetrominoCode = std::array < std::array<sf::Uint32, 4>, 2 >;

        TetrominoCode I;
        TetrominoCode J;
        TetrominoCode L;
        TetrominoCode O;
        TetrominoCode S;
        TetrominoCode T;
        TetrominoCode Z;

        TetrominoCodes()
                : I(TetrominoCode{ { { 1, 1, 1, 1 }, { 0, 0, 0, 0 } } }),
                  J(TetrominoCode{ { { 1, 0, 0, 0 }, { 1, 1, 1, 0 } } }),
                  L(TetrominoCode{ { { 0, 0, 1, 0 }, { 1, 1, 1, 0 } } }),
                  O(TetrominoCode{ { { 1, 1, 0, 0 }, { 1, 1, 0, 0 } } }),
                  S(TetrominoCode{ { { 0, 1, 1, 0 }, { 1, 1, 0, 0 } } }),
                  T(TetrominoCode{ { { 0, 1, 0, 0 }, { 1, 1, 1, 0 } } }),
                  Z(TetrominoCode{ { { 1, 1, 0, 0 }, { 0, 1, 1, 0 } } })
        {};
};

struct TetrominoColors
{
        using TetrominoColor = sf::Color;

        TetrominoColor I = TetrominoColor(152, 245, 255);
        TetrominoColor J = TetrominoColor(0, 0, 255);
        TetrominoColor L = TetrominoColor(255, 165, 79);
        TetrominoColor O = TetrominoColor(255, 255, 0);
        TetrominoColor S = TetrominoColor(0, 255, 0);
        TetrominoColor T = TetrominoColor(160, 32, 240);
        TetrominoColor Z = TetrominoColor(255, 0, 0);
};

class Tetromino : public sf::Drawable, public sf::Transformable
{
private:
        typeTetrominoID   m_typeID;

        sf::Texture     m_texture;
        sf::Vector2u    m_brickSize;
        sf::VertexArray m_vertices;

        void create(TetrominoCodes::TetrominoCode code, TetrominoColors::TetrominoColor color);

        virtual void draw(sf::RenderTarget& renderTarget, sf::RenderStates renderStates) const;

public:
        Tetromino();
        Tetromino(typeTetrominoID typeID);

        void updateFixed(void);
        void updateVariable(sf::Time dt);
};

#endif // TETROMINO_HPP
 

And this is the .cpp file :
#include <iostream>

#include <SFML\Graphics.hpp>

#include "Tetromino.hpp"

Tetromino::Tetromino()
{}

Tetromino::Tetromino(typeTetrominoID typeID)
        : m_typeID(typeID), m_brickSize(sf::Vector2u(16, 16))
{
        TetrominoCodes  tetrominoCodes;
        TetrominoColors tetrominoColors;

        std::cout << "m_typeID: " << m_typeID << std::endl;

        switch (m_typeID)
        {
        case IBrick:
                create(tetrominoCodes.I, tetrominoColors.I); break;
        case JBrick:
                create(tetrominoCodes.J, tetrominoColors.J); break;
        case LBrick:
                create(tetrominoCodes.L, tetrominoColors.L); break;
        case OBrick:
                create(tetrominoCodes.O, tetrominoColors.O); break;
        case SBrick:
                create(tetrominoCodes.S, tetrominoColors.S); break;
        case TBrick:
                create(tetrominoCodes.T, tetrominoColors.T); break;
        case ZBrick:
                create(tetrominoCodes.Z, tetrominoColors.Z); break;
        }
}

void Tetromino::updateFixed(void)
{
        sf::Vector2f pos = this->getPosition();
        pos.y += m_brickSize.y;

        this->setPosition(pos);
}

void Tetromino::updateVariable(sf::Time dt)
{}

void Tetromino::create(TetrominoCodes::TetrominoCode code, TetrominoColors::TetrominoColor color)
{
        m_vertices.setPrimitiveType(sf::Quads);
        m_vertices.resize(16);

        std::array<std::array<sf::Vertex, 4>, 4> quads;

        sf::Uint16 vertexCounter = 0;

        for (sf::Uint16 i = 0; i < 2; i++)
        {
                for (sf::Uint16 j = 0; j < 4; j++)
                {
                        std::cout << "code[" << i << "][" << j << "]: " << code[i][j] << std::endl;

                        if (code[i][j] == 1)
                        {
                                quads[vertexCounter][0].color = color;
                                quads[vertexCounter][1].color = color;
                                quads[vertexCounter][2].color = color;
                                quads[vertexCounter][3].color = color;

                                quads[vertexCounter][0].position = sf::Vector2f(i * m_brickSize.x, j* m_brickSize.y);
                                quads[vertexCounter][1].position = sf::Vector2f((i + 1) * m_brickSize.x, j * m_brickSize.y);
                                quads[vertexCounter][2].position = sf::Vector2f((i + 1) * m_brickSize.x, (j + 1) * m_brickSize.y);
                                quads[vertexCounter][3].position = sf::Vector2f(i * m_brickSize.x, (j + 1) * m_brickSize.y);

                                for (auto i : quads[vertexCounter])
                                {
                                        m_vertices.append(i);

                                        std::cout << "position: " << i.position.x << ", " << i.position.y << std::endl;
                                }
                                vertexCounter++;
                        }
                }
        }
}

void Tetromino::draw(sf::RenderTarget& renderTarget, sf::RenderStates renderStates) const
{
        renderStates.transform *= getTransform();
        renderStates.texture = &m_texture;

        renderTarget.draw(m_vertices, renderStates);
}
 

P.s my english isn't always on point ... so yea  :D

SeriousITGuy

  • Full Member
  • ***
  • Posts: 123
  • Still learning...
    • View Profile
Re: TETRIS Clone
« Reply #1 on: August 07, 2015, 01:31:36 pm »
Actually it looks well structured and you use a good naming scheme, I like that. Code itself looks clear and to the point.

One thing about your Tetromino class though, why do you declare a standard constructor if it does nothing? Do you use it? Because it seems you only plan to use the overloaded ctor, just do not declare and define standard ctor it's unnecessary. You could also write public class members first and private afterwards, makes the class more readable because you see the class API in the first few rows.

The memory structure of TetrominoCode looks a bit strange to me (std::array<std::array<sf::Uint32, 4>, 2>) maybe there is something better for what you want to achieve, most of times std::vector is the easiest solution, but without context it is just an educated guess.

And if you plan to "mess around" with C++11, have a look at enum class instead of enum ;)

Otherwise keep on, it's a good starting point.

Kyoukan97

  • Newbie
  • *
  • Posts: 6
    • View Profile
Re: TETRIS Clone
« Reply #2 on: August 10, 2015, 10:17:56 pm »
I finally had some time to work on my project and I started from scratch, because i didn't like my layout ;D
Here how far i got, using some of your suggestions  :) ( kind of messy at the moment :D ):
#include <iostream>
#include <memory>
#include <vector>

#include <SFML\Graphics.hpp>

enum class TetrominoType : sf::Uint16 { IBrick, JBrick, LBrick, OBrick, SBrick, TBrick, ZBrick };

struct TetrominoCode
{
        using tCode = std::vector<std::vector < sf::Uint16 >>;

        tCode I = tCode{ { 1, 1, 1, 1 }, { 0, 0, 0, 0 } };
        tCode J = tCode{ { 1, 0, 0, 0 }, { 1, 1, 1, 0 } };
        tCode L = tCode{ { 0, 0, 1, 0 }, { 1, 1, 1, 0 } };
        tCode O = tCode{ { 1, 1, 0, 0 }, { 1, 1, 0, 0 } };
        tCode S = tCode{ { 0, 1, 1, 0 }, { 1, 1, 0, 0 } };
        tCode T = tCode{ { 0, 1, 0, 0 }, { 1, 1, 1, 0 } };
        tCode Z = tCode{ { 1, 1, 0, 0 }, { 0, 1, 1, 0 } };
};

struct TetrominoColor
{
        using tColor = sf::Color;

        tColor I = tColor(152, 245, 255);
        tColor J = tColor(0, 0, 255);
        tColor L = tColor(255, 165, 79);
        tColor O = tColor(255, 255, 0);
        tColor S = tColor(0, 255, 0);
        tColor T = tColor(160, 32, 240);
        tColor Z = tColor(255, 0, 0);
};

struct Tetromino
{
        Tetromino(TetrominoType type, sf::Vector2f size = sf::Vector2f(16.f, 16.f))
        {
                for (sf::Uint16 i = 0; i < 4; i++) m_squares.emplace_back(std::unique_ptr<sf::RectangleShape>(new sf::RectangleShape(size)));

                TetrominoCode  tetrominoCode;
                TetrominoColor tetrominoColor;

                switch (type)
                {
                case TetrominoType::IBrick:
                        create(tetrominoCode.I, tetrominoColor.I); break;
                case TetrominoType::JBrick:
                        create(tetrominoCode.J, tetrominoColor.J); break;
                case TetrominoType::LBrick:
                        create(tetrominoCode.L, tetrominoColor.L); break;
                case TetrominoType::OBrick:
                        create(tetrominoCode.O, tetrominoColor.O); break;
                case TetrominoType::SBrick:
                        create(tetrominoCode.S, tetrominoColor.S); break;
                case TetrominoType::TBrick:
                        create(tetrominoCode.T, tetrominoColor.T); break;
                case TetrominoType::ZBrick:
                        create(tetrominoCode.Z, tetrominoColor.Z); break;
                }
        }

        void create(TetrominoCode::tCode code, TetrominoColor::tColor color)
        {
                for (auto& i : m_squares) i->setFillColor(color);

                sf::Uint16 counter = 0;

                for (sf::Uint16 row = 0; row < 2; row++)
                        for (sf::Uint16 column = 0; column < 4; column++)
                        {
                                if (code[row][column] == 1)
                                {
                                        m_squares[counter]->setPosition(m_squares[counter]->getSize().x * column, m_squares[counter]->getSize().y * row);
                                        counter++;
                                }
                        }
       
        }

        void draw(sf::RenderWindow* window)
        {
                for (auto& i : m_squares) { window->draw(*i); };
        }

        std::vector<std::unique_ptr<sf::RectangleShape>> m_squares;
};

int main()
{
        sf::RenderWindow window(sf::VideoMode(800, 600), "TETRIS");

        Tetromino iBrick(TetrominoType::IBrick);

        while (window.isOpen())
        {
                sf::Event ev;
                while (window.pollEvent(ev))
                {
                        if (ev.type == sf::Event::Closed)
                                window.close();
                }
                window.clear();
                iBrick.draw(&window);
                window.display();
        }

        return EXIT_SUCCESS;
}