breakout in opengl and c++

Started by
55 comments, last by pbivens67 2 years, 10 months ago

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.

Advertisement

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:

  1. From timestep and ball velocity calculate the distance the ball has to travel.
  2. 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.
  3. 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);
}

Maybe it's easier to follow along with a tutorial like this one.

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<uint64_t>. Native machine type and enough bits to handle various states and some timer for animation.
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.

This topic is closed to new replies.

Advertisement