I am going back to developing a breakout game using opengl and c++ and soil to print the png sprites. however I am unsure of how to implement the collision between the ball and the bricks. I was thinking about using a vector or a list. I am unsure how to start the collision detection routines.
breakout in opengl and c++
Vector or list is not good IMO, because you need to search for the bricks spatially, you can just put them in a regular grid instead (e.g. represented by 2D array).
Collision detection may need to to be continuous, becaseu in a good Breakout game balls can go really fast, so they might tunnel through brick corners and missing collisions. ('DXBall2' is the best breakout clone i'm aware of.)
Personally i did it like this:

- From timestep and ball velocity calculate the distance the ball has to travel.
- Trace a ray of that length through the grid. At intersections with solid cells reflect the ray and shorten remaining length accordongly (red line). And ofc. make bricks disappear.
- For rendering, render the bricks (dark blue) smaller than a full grid cell (light blue), by the size of the ball radius.
It's a trick to keep it simple which only works if size of ball is constant and you are happy with resulting proportions of visuals.
If you want small and big balls, or bricks at arbitrary size, a more detailed algorithm respecting the ball radius / actual brick size becomes necessary.
Collision with paddle should give player the option to adjust angle of the balls direction, depending on where the ball hits the paddle, IMO.
well joe thanks for the graphic
well joe I have read your post but I am still confused on how to store bricks in an 2d array, here is my ball movement code.
float bricks[3][8];
void Timer(int v)
{
if (x >= 145.0f || x <= -135.0f)
{
xstep = -xstep;
}
if (y >= 100.0f || y <= -100.0f)
{
ystep = -ystep;
}
x += xstep;
y += ystep;
glutPostRedisplay();
glutTimerFunc(50, Timer, 0);
}
Using some tutorial surely is no bad idea, because a breakout game is much harder than the questions you ask usually here in the forum.
pbivens67 said:
I am still confused on how to store bricks in an 2d array,
The tutorial a linked above uses a vector, but it's size is kept constant, with zeros representing empty space. That's fine and the same i have meant with ‘array’. The ‘bad’ way would be to to have a struct with position for each brick, and deleting bricks from the dynamic vector if hit by the ball, and also needing to iterate all bricks each time we want to know if there is a brick at position (x,y). Just to make that clear.
To create and access a board of bricks, it would be convenient to use an array of char:
char *board =
"9999999999999999"
"9000000000000009"
"9001111111111009"
"9002222222222009"
"9000000000000009"
"9999999999999999"
;This example creates a board of size 16 x 6 (the compiler should joint multiple lines to just one long string, but not 100% sure this works as expected).
If we want to look up the brick at position (x:3, y:2) we calculate the index into the 1D array accordingly:
char brick = board[x + y*16];
Notice i have put a ‘9’ on the boundary of the board.
If we make 9 an undestructable brick, we do not need extra code to handle the boundary at all, like your code example (the tutorial also missed missed to do this).
But for rendering we likely want to clip that boundary and render only the inner 14 x 4 region of the board.
The tutorial seemingly does no continuous collision detection (skimmed over it just quickly), so it can only handle slowly moving balls. That's bad because Breakout becomes boring if you need to long wait periods because the slow ball became trapped into some area where it won't come back to the paddle quickly.
The tutorial also calculates exact circle - aabox collision, which is not needed because we do not want to handle ball-box corner cases, as this would cause unpredictable ball movement. So at this point the tutorial is more complicated than needed, IMO. In this case, introduced ‘inaccuracy’ from approximating the collision representation with just ‘ray vs. horizontal and vertical lines, ignoring ball radius but extruding bricks instead’ is exactly what we want for gameplay.
But somehow i doubt you would find a better tutorial, and if my proposal sounds more confusing than meaningful, i'd go with it.
@JoeJ no need to advise the newbie to use arrays over vector, IMO. They'll just end up with even more pitfalls than they already had…
@JoeJ Baby steps. Don't throw him in the deep.
Also:
Several of the issues that can still occur:
- If the ball goes too fast, it may skip over an object entirely within a single frame, not detecting any collisions.
These chapters are however aimed to teach the readers the basics of several aspects of graphics and game-development. For this reason, this collision scheme serves its purpose; its understandable and works quite well in normal scenarios.
SuperVGA said:
@JoeJ no need to advise the newbie to use arrays over vector, IMO. They'll just end up with even more pitfalls than they already had…
Yeah. I tried to explain why it does not even matter. Reason i used the char array myself is i can create a demo board so quickly. Tutorial spends a whole site on loading level form file, which does not help to get started either.
Actually i'd use std::vector
And i have just learned we can initialize this easily too:
vector<uint64_t> board{ 0,1,2,3 };
m_waddams said:
@JoeJ Baby steps. Don't throw him in the deep. Also: Several of the issues that can still occur: If the ball goes too fast, it may skip over an object entirely within a single frame, not detecting any collisions. These chapters are however aimed to teach the readers the basics of several aspects of graphics and game-development. For this reason, this collision scheme serves its purpose; its understandable and works quite well in normal scenarios.
I know. But the ‘proper’ solution has the same complexity in the end. Ray is more complex than a point, but intersection math is much simpler.
so should I use an vector or array?
pbivens67 said:
so should I use an vector or array?
In C++, you should prefer a vector over a C-style array all the time.
Whether you end up finding valid exceptions to this eventually, is a different matter.
Vector is your go-to collection for handling of stuff in a sequence. It has its drawbacks, as its not specialised to any particular use.
It's just a solid all-rounder. Here, Stroustrup explains some of the benefits of using a std::vector compared to a C-style array.
If you're up and running with the array example from @joej already, just keep using it. It's still an implementation detail, and if it's static, its even less important which one you're using.
pbivens67 said:
so should I use an vector or array?
You can use what you prefer. Does not really matter.
Some years ago, using STL was considered a no-go for games because performance. Maybe you remember this time and have doubts.
std::vector has dynamic size, and adding elements can cause a reallocation of more memory. Such reallocation takes a very long time and can ruin performance of realtime applications. Thus i prefer to use arrays (or std::array) if i do not need dynamic size.
In our case, using std::vector to represent the breakout board, reallocation only happens at the beginning of a new level, not during gameplay. So no problem and you can use it. Advantage is there is no need to allocate and free up memory. Which is very good to have because it's easy to forget freeing up memory otherwise, leading to memory leaks.
My advise previously made ‘use array over vector’ was made under a different assumption:
Many people would represent their breakout level like this:
struct Brick
{
int x, y, color;
};
std::vector<Brick> bricks;
//...
bricks.push_back( Brick({3,5,7}) ); // add brick at position (3,5) with color 7
This is bad. It seems convenient to push bricks into the board vector, setting position for each, not caring about empty space.
But we get performance problems at runtime:
To find a brick at a certain position we need to iterate ALL bricks each time. So our collision test become O(N).
Deleting (or adding) a brick during gameplay changes the size of the vector, and may cause reallocations.
Both is terribly slow and should be avoided. And we do that by representing the whole level with a ‘regular grid’:
constexpr int width = 16;
constexpr int height = 10;
std::vector<int> board(width * height, 0); // set whole grid to zero
//...
board[3 + 5 * width] = 7; // set brick at position (3,5) to color 7This is good. We can lookup which brick is at a certain position without a need of iterating all bricks. Cost is O(1) and ideal.
Adding / removing bricks does not change size of our board, so no reallocation ever happens.
To index our grid, we use simple indexing math known from arrays (index = x + y * width), and that's why i said ‘use array over vector’.
Following this, there is no difference then between using vector or array during runtime.
Vector uses an array (pointer to allocated memory of board size) internally too, so both methods give us the same performance.
If there are any questions left, ask for it. But also explain WHY you ask!
So we can make proper assumptions on what you already understood or what maybe not, to optimize both your learning and our teaching.
SuperVGA said:
In C++, you should prefer a vector over a C-style array all the time.
I can't second this advise, even if targeted at beginners.
I have seen people implementing their vec3 or matrix4x4 classes using std::vector
So, i think it's better to tell the whole truth to beginners. Even if they don't get it all at the moment, they memorize ‘there is a catch, need to keep that in mind, coming back to it later…’. Likely this helps to prevent such bad practices from coming up.
I would rephrase your advise to ‘In C++, you should prefer std::array over a C-style array all the time.’, which is fine to me : )
JoeJ said:
SuperVGA said:
In C++, you should prefer a vector over a C-style array all the time.I can't second this advise, even if targeted at beginners.
You have realistic scenarios where you'll recommend a beginner to use a C-style array over a std::vector, when they're trying to learn C++?
JoeJ said:
I have seen people implementing their vec3 or matrix4x4 classes using std::vector
pretty often. Terrible! Would you hire somebody doing this?
My advice to beginners implementing their vec3 or matrix4x4 classes would obviously be to not use array or vector at all.
You can try to argue against any tool by coming up with an example where it's used in an inefficient way, it's just not much of an argument.
So no, I probably wouldn't hire someone like that. I wouldn't hire anyone constructing a vague argument like that, either.
JoeJ said:
So, i think it's better to tell the whole truth to beginners.
It's tough with truth. They're given an arsenal of ways to shoot themselves in the foot, the first thing they should do is to at least let go of the C way to do that.
JoeJ said:
I would rephrase your advise to ‘In C++, you should prefer std::array over a C-style array all the time.’, which is fine to me : )
The overhead of using a vector in a typical beginner scenario is so little, and they have all the stuff available to them, that they'll be needing a few lessons in. Sure a std::array works for this case, and you can give that advise. Mine is and will be different, though.
SuperVGA said:
My advice to beginners implementing their vec3 or matrix4x4 classes would obviously be to not use array or vector at all. You can try to argue against any tool by coming up with an example where it's used in an inefficient way, it's just not much of an argument. So no, I probably wouldn't hire someone like that. I wouldn't hire anyone constructing a vague argument like that, either.
But there are no vague argument here at all:
struct vec3 { float v[3]; } is fast, and allows to index by dimension
struct vec3 { float x,y,z; } is fast, semantically meaningful, but lacks option to index. So i don't see why it is the obvious solution for you? (assuming that's what you mean with neither using array nor vector)
We can make a union to combine advantages without compromising anything. (discussions about unions aside)
struct vec3 { std::vector
Those my arguments are totally solid and relevant in any practical context. It's not a matter of personal opinion or preferences. It's just unfair to assert i would construct ‘vague’ arguments, honestly.
SuperVGA said:
It's tough with truth. They're given an arsenal of ways to shoot themselves in the foot, the first thing they should do is to at least let go of the C way to do that.
This is a matter of personal opinion. I accept yours, and i'm no teacher anyways.
JoeJ said:
SuperVGA said:
My advice to beginners implementing their vec3 or matrix4x4 classes would obviously be to not use array or vector at all. You can try to argue against any tool by coming up with an example where it's used in an inefficient way, it's just not much of an argument. So no, I probably wouldn't hire someone like that. I wouldn't hire anyone constructing a vague argument like that, either.But there are no vague argument here at all:
struct vec3 { float v[3]; } is fast, and allows to index by dimension
struct vec3 { float x,y,z; } is fast, semantically meaningful, but lacks option to index. So i don't see why it is the obvious solution for you? (assuming that's what you mean with neither using array nor vector)
We can make a union to combine advantages without compromising anything. (discussions about unions aside)
struct vec3 { std::vector
v; } requires allocation and wastes memory for pointers and counters which are not needed. Those my arguments are totally solid and relevant in any practical context. It's not a matter of personal opinion or preferences. It's just unfair to assert i would construct ‘vague’ arguments, honestly.
I think it is vague, not in general, but in this context. You can whip out any advanced scenario that doesn't apply to pbviens, or any other newcomer to the language, and have them using advanced features from the get-go. That's not what we're trying to do here, I think.
Aside from that, your point is entirely valid, and while I might fiddle with some [] overloads first, I'm not disputing that it has merit to use char[] for some other thought scenario.
I'm just saying it's very far-fetched in deed to use it as an argument that a beginner should use C-style arrays. I worded that wrongly, and of course your argument wasn't absolutely vague in entirety.
We're good - let's not pollute this thread with our discussion any longer.
SuperVGA said:
I think it is vague, not in general, but in this context. You can whip out any advanced scenario that doesn't apply to pbviens, or any other newcomer to the language, and have them using advanced features from the get-go. That's not what we're trying to do here, I think.
I assume a different context than you do. AFAIK, Phil hangs out here for a very long time. Too long to be treated as a total beginner, maybe even long enough to assume his background was C first, then adopt some C++ slowly (like i did). I don't think his primary goals are to learn the programming language, but to learn good solutions for given problems.
However, that's all assumptions, causing pollution as we got here. It's on Phil to provide better context by asking more specifically. Though, that's not as easy for everybody.
well I am going to use a vector
I have a tip for anyone who wants to make breakout games and needs a simple algorithm for randomly generating levels that are symmetrical:
- Split your X-Tiles so you have a left side and a right side
- For each line:
- Dice out a number using half of the maximum number of X-Tiles for a line (works better when it's even a number)
- Dice out a starting offset in the same range, but minus one → Ensure that your starting offset + number of tiles does not exceed the maximum available tiles
- Generate the tiles from the offset to the number of tiles you want (For left increment, for right decrement) → Or better, use a unit scalar as a 1D direction
- Done
Of course, this algorithm can be improved slightly:
- Different max X-tiles for each line
- Introduce a similar concept for Y
- Have three parts instead of left/right side (center)
A simple code example (can translate to C if needed):
function setRandomLevel() {
var lvl = level;
var halfWidth = (brickCols - 1) / 2;
var x, y;
for (y = brickRows - 1; y > 0; y--) {
var randomHalfWidth = Math.random() * halfWidth;
for (x = 0; x < brickCols; x++) {
lvl[y * brickCols + x] = 0;
}
var xstart = Math.random() > 0.5 ? Math.min(halfWidth, Math.round(halfWidth - randomHalfWidth)) : 0;
for (x = xstart; x < randomHalfWidth; x++) {
lvl[y * brickCols + x] = 1;
lvl[(y + 1) * brickCols + (-x - 1)] = lvl[y * brickCols + x];
}
if (Math.random() > 0.5) {
lvl[y * brickCols + halfWidth] = 1;
}
}
}This produces very interesting results (Yes this is automatically generated and not placed by hand!)
Nice! Looks like an iconic Space Invaders sprite : )
At 0:36 this video shows a ball - corner collision, result is physically correct but unpredictable for the player and he misses the ball. (Just to illustrate what i meant with that.)
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.