SFML 2.0 Lots of objects

Pages: 12
i have been thinking about making a breakout clone and i don't know how to make all those bricks easily (in other words the way i would do it is i would make a bunch of sf::sprites and draw them separately) and i don't know how to do it faster (and without using so much memory)
Last edited on
I usually just make a vector of whatever objects I'm drawing. You don't have to use an sf::Sprite in this case, you could use sf::RectangleShape. Then do something like this to draw everything:
1
2
3
4
for(unsigned Pos = 0; Pos < BlockVector.size(); ++Pos)
{
      MyRenderWindow.draw(BlockVector[Pos].Block);
}


You're writing a game, memory is only something you should worry about if you run out of it. But until then don't let yourself make excuses that stop you from writing this game.
Last edited on
memory wasn't really my problem. my issue was that it would take me forever just to make a game like breakout :(
closed account (N36fSL3A)
Well you should read tutorials on breakout mechanics, and basic physics. If you use a nice OOP design something like this shouldn't take more than a few weeks (at most a month) to complete.
my issue was that it would take me forever just to make a game like breakout :(


Why do you think that? Your first game is always going to take the longest, but that's just because you need to fill in a few holes in what you know. I wrote a Conway's Game of Life program in C++ using SFML 2.0 or 2.1 and it was less then 500 Lines of code. Here is how I made the grid:
1
2
3
4
5
6
7
8
9
10
for(int y = 0; y < Limit; ++y)
    {
        for(int x = 0; x < Limit; ++x)
        {
            int X = TileSize + (TileSize * x) % (Limit * TileSize);
            int Y = TileSize + y * TileSize;

            TileArray[x][y].Place(sf::Vector2f(X, Y));
        }
    }

My member function "Place()" just takes the coordinates and sets the tile to that position. This is literally all it is:
1
2
3
4
5
6
7
bool TILE::Place(sf::Vector2f pos)
    {
        Pos = pos;
        tile.setPosition(Pos);

        return true;
    }



You can see how easily something like this scales, so don't go thinking you have to hard code the position of every block you want to break. Heck make things interesting and randomize them if you want to.
ok i am fine with the grid now (i used an array) but now my ball is registering collision regardless of whether or not it actually is colliding

Collision function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
bool Collision(sf::RectangleShape paddle, sf::RectangleShape ball)
{
    float pbottom = paddle.getPosition().y + paddle.getSize().y, pleft = paddle.getPosition().x,
    pright = paddle.getPosition().x + paddle.getSize().x, ptop = paddle.getPosition().y;

    float bbottom = ball.getPosition().y, bleft = ball.getPosition().x - (ball.getSize().x),
    bright = ball.getPosition().x, btop = ball.getPosition().y - (ball.getSize().y);

    if (pright < bleft || pleft > bright || ptop > bbottom || pbottom < btop)
            {
                return false;
            }
            return true;
}




Where it is called:
1
2
3
4
5
6
7
8
for (unsigned i = 0; i < 500; i++)
        {
            if (Collision(bricks[i], ball_box) && bricks[i].getFillColor() == sf::Color::Transparent);
            {
                bricks[i].setFillColor(sf::Color::Transparent);
                ball.setRotation(rand() & 360);
            }
        }


Please don't tell me how to improve my code unless it fixes the issue
closed account (D80DSL3A)
Remove the ; at the end of line 3 in 2nd snippet.
Cronnoc wrote:
Please don't tell me how to improve my code unless it fixes the issue

Everything you are doing looks fine, but that is part of getting help. You will be critiqued and always have more effective ways pointed out to you. Though, putting that could result in a limited amount of help because not wanting to know ways to improve sends a possible bad image of not wanting to learn.
its not that i don't want to learn its that i want to learn for myself and not be told what to do
Cronnoc wrote:
its not that i don't want to learn its that i want to learn for myself and not be told what to do

That is perfectly fine. Just be aware that even that has a possible downfall. You could get set in your ways and stick to ways that aren't effective unless someone points it out. Like I said though, so far everything is looking good.
Last edited on by closed account z6A9GNh0
ok here is my full code (it isn't finished). please help me figure out what is wrong:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
#include <SFML/Graphics.hpp>
#include <cstdlib>
#include <ctime>

const double PI = 3.14159265;

bool Collision(sf::RectangleShape paddle, sf::RectangleShape ball)
{
    float pbottom = paddle.getPosition().y + paddle.getSize().y, pleft = paddle.getPosition().x,
    pright = paddle.getPosition().x + paddle.getSize().x, ptop = paddle.getPosition().y;

    float bbottom = ball.getPosition().y, bleft = ball.getPosition().x - (ball.getSize().x),
    bright = ball.getPosition().x, btop = ball.getPosition().y - (ball.getSize().y);

    if (pright < bleft || pleft > bright || ptop > bbottom || pbottom < btop)
            {
                return false;
            }
            return true;
}


int main()
{
    srand(time(0));
    sf::RenderWindow window(sf::VideoMode (800,600), "Breakout");

    sf::RectangleShape bricks[500];

    sf::RectangleShape paddle(sf::Vector2f(60, 10)), ball_box(sf::Vector2f(16, 16));
    paddle.setFillColor(sf::Color::Blue);
    paddle.setPosition((window.getSize().x / 2) - (paddle.getSize().x / 2), window.getSize().y - (30 + paddle.getSize().y));

    sf::CircleShape ball(8.f);
    ball.setFillColor(sf::Color::Red);
    ball.setPosition(paddle.getPosition().x, paddle.getPosition().y - 30);
    ball.setRotation(-90);
    ball_box.setPosition(ball.getPosition());


    float ball_speed = 0.01, ball_time = 1, ball_distance = ball_speed*ball_time, ball_spd = ball_distance;

    for (unsigned i = 0; i < 500; i++)
    {
        bricks[i].setFillColor(sf::Color((rand() % 256), (rand() % 256), (rand() % 256)));
        bricks[i].setSize(sf::Vector2f(32, 12));
        if (i == 0)
        {
            bricks[i].setPosition(0, 0);
        }
        else if (i < 50)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, 0);
        }
        else if (i==50)
        {
            bricks[i].setPosition(0, 0+bricks[i].getSize().y);
        }
        else if (i > 50 && i < 100)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, bricks[i-1].getPosition().y);
        }
        else if (i==100)
        {
            bricks[i].setPosition(0, 12+bricks[i].getSize().y);
        }
        else if (i > 100 && i < 150)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, bricks[i-1].getPosition().y);
        }
        else if (i==150)
        {
            bricks[i].setPosition(0, 24+bricks[i].getSize().y);
        }
        else if (i > 150 && i < 200)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, bricks[i-1].getPosition().y);
        }

        else if (i==200)
        {
            bricks[i].setPosition(0, 36+bricks[i].getSize().y);
        }
        else if (i > 200 && i < 250)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, bricks[i-1].getPosition().y);
        }
        else if (i==250)
        {
            bricks[i].setPosition(0, 48+bricks[i].getSize().y);
        }
        else if (i > 250 && i < 300)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, bricks[i-1].getPosition().y);
        }
        else if (i==300)
        {
            bricks[i].setPosition(0, 60+bricks[i].getSize().y);
        }
        else if (i > 300 && i < 350)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, bricks[i-1].getPosition().y);
        }
        else if (i==350)
        {
            bricks[i].setPosition(0, 72+bricks[i].getSize().y);
        }
        else if (i > 350 && i < 400)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, bricks[i-1].getPosition().y);
        }
        else if (i==400)
        {
            bricks[i].setPosition(0, 84+bricks[i].getSize().y);
        }
        else if (i > 400 && i < 450)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, bricks[i-1].getPosition().y);
        }
        else if (i==450)
        {
            bricks[i].setPosition(0, 96+bricks[i].getSize().y);
        }
        else if (i > 450 && i < 500)
        {
            bricks[i].setPosition(bricks[i-1].getPosition().x + bricks[i].getSize().x, bricks[i-1].getPosition().y);
        }

    }

    while(window.isOpen())
    {
        sf::Event Event;
        while(window.pollEvent(Event))
        {
            switch (Event.type)
            {
                case sf::Event::Closed:
                window.close();
                break;
            }
        }

        ball_box.setPosition(ball.getPosition());

        if (sf::Mouse::getPosition(window).x > 0 && sf::Mouse::getPosition(window).x < (window.getSize().x - paddle.getSize().x))
            paddle.setPosition(sf::Mouse::getPosition(window).x, paddle.getPosition().y);

        if (Collision(paddle, ball_box))
        {
            ball.setRotation(rand() % 360);
        }

        for (unsigned i = 0; i < 500; i++)
        {
            if (Collision(bricks[i], ball_box) && bricks[i].getFillColor() == sf::Color::Transparent);
            {
                bricks[i].setFillColor(sf::Color::Transparent);
                ball.setRotation(rand() & 360);
            }
        }

        ball.move(ball_spd*cos(ball.getRotation()*PI/180.0f ), ball_spd*sin(ball.getRotation()*PI/180.0f));

        window.clear();
        for (unsigned i = 0; i < 500; i++)
        {
            window.draw(bricks[i]);
        }
        window.draw(paddle);
        window.draw(ball);
        window.display();
    }
}
Have a good look at line 156. Should that line end with a semi-colon?

VC++ ouputs a convenient warning:
main.cpp(157): warning C4390: ';' : empty controlled statement found; is this the intent?
THANK YOU. i can't believe i missed that
closed account (D80DSL3A)
You also missed being told about it yesterday.
Cronnoc wrote:
i can't believe i missed that

Neither can I since fun2code pointed that out yesterday :P. Looking good though:).
lol i didn't even see that post
i got the bricks for breakout working but what about a game like tetris. you don't know how many you will need so how would you do that?
i got the bricks for breakout working but what about a game like tetris.

If by "i got the bricks working" you mean, "I drew some rectangles and a moving circle on the screen" I would agree, but those bricks (and the program logic) are definitely not "working" for breakout.

I would attempt to get the game actually working before jumping to the next one.
Last edited on
@Cronnoc
I agree with cire on this one. I like this article: http://www.gamedev.net/page/resources/_/technical/game-programming/your-first-step-to-game-development-starts-here-r2976

I think his list is a great list of beginner games.
Pong = Simple: input, physics, collision detection, sound; scoring
Worm = Placement of random powerups, handling of screen boundaries, worm data structure
Breakout = Lessons of pong, powerups, maps (brick arrangements)
Missile Command = targeting; simple enemy ai, movement, and sound
Space Invaders = simple movement for player and enemy, very similar to breakout with the exception that the enemy constantly moves downward, simple sound
Asteroids = asteroids (enemies) and player can move in all directions, asteroids appear and move randomly, simple sound
Tetris = block design, clearing the lines, scoring, simple animation
Pac Man = simple animation, input, collision detection, maps (level design), ai
Ikari Warriors = top down view, enemy ai, powerups, scoring, collision detection, maps (level design), input, sound, boss ai
Super Mario Bros = lessons of Ikari Warriors (except with side-view instead of top-down view), acceleration, jumping, platforms

The list shows games in terms of difficulty from least to greatest as far as programming them goes. There are games that others may suggest but these 10 games will definitely round out what you need to know in 2D game development. If you can make and complete these games, then games like Sonic, Metroid, or even Zelda become that much easier. Those games are just variations or extensions of what you have already learned.
i have been following something like that but i will have a look
Pages: 12