Breakout
ultratar

I want to know how to make a very basic breakout game....
How would you make the blocks disappear when the ball hits it?
Or, even better, can someone post their code for a simple one so I can learn from it?

LennyLen

Here, here, and here are three breakout games from the depot that all have source code.

ultratar

Thank you... but the code and stuff is kinda complex and difficult to understand... are there any more simpler or easy-to-understand ones?:D

LennyLen
Quote:

are there any more simpler or easy-to-understand ones?

I doubt it, those weren't that complicated really. Perhaps you should try something simpler first.

Kris Asick

Having worked on a breakout clone in 3D before, I know the logic in making one can be stifling. Here are some tips to help you out:

• Ball physics hitting blocks are easy. You check to see which side of the block you hit then simply reverse the X or Y speed of the ball by multiplying by -1.

• Ball physics hitting the paddle are not so easy. There are a variety of ways to go about it but the most accepted method is that the paddle is sort of like a compass. One side is the largest angle left you can hit the ball, the other is the largest angle right, and then where the ball hits you just interpret between those angles. You can calculate the X and Y speeds of the ball by taking the angle and speed you want and using sin() and cos().

• Making blocks disappear is simple enough. Just make a grid of blocks. Each block has a state, either on or off. When on, the ball can hit the block. When off, the ball passes right through. You can use that state to determine what to draw as well.

• Anything else, such as non-fixed block sizes, powerups, etc. will add huge amounts of complexity. Start simple, then build off of that.

The 3D version I was making was complicated by having to make the ball roll in 3D, along with having a smart camera that viewed the playfield optimally. I never completed it, but it's still on my system if I ever want to try. Making it in 3D was what really jumped the production time of it and why I had to stop.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

ultratar

Thank you! You've just made it seem so much simpler to do!

Okay... I need a bit of help.

My friend finished this much code (for our project)... but it's glitchy!
She asked me to fix it up but I don't know what to do. I checked the code a few times and I just don't get why it's not working properly.

The startNew function doesn't work.
And the passage of the ball is VERY repetitive... but we used srand() function. Why isn't it going in random directions?

 1 #include 2 #include 3 #include 4 5 int bar_x = 10; 6 int bar_y = 460; 7 int tempx = 10; 8 int tempy = 460; 9 int ball_x = 100; 10 int ball_y = 100; 11 int ball_tempx = 100; 12 int ball_tempy = 100; 13 int dir = 1; 14 15 time_t secs; 16 17 BITMAP* buffer; 18 BITMAP* bar; 19 BITMAP* ball; 20 21 void ballBounce(){ 22 23 ball_tempx = ball_x; 24 ball_tempy = ball_y; 25 26 if (dir == 1 && ball_x > 10 && ball_y > 10){ 27 if( ball_y == 11 || ball_x == 11){ 28 dir = rand()% 2 + 3; 29 } 30 else{ 31 --ball_x; 32 --ball_y; 33 } 34 } 35 36 else if (dir == 2 && ball_x > 10 && ball_y + 10 < 460){ 37 if (ball_x >= bar_x && ball_x <= bar_x + 100 && ball_y + 10 == bar_y){ 38 dir = rand()% 3 + 1; 39 } 40 else if (ball_x - 10 == 1){ 41 dir = rand()% 2 + 3; 42 } 43 else{ 44 --ball_x; 45 ++ball_y; 46 } 47 } 48 49 else if (dir == 3 && ball_x < 630 && ball_y > 10){ 50 if (ball_x == 629 || ball_y == 11){ 51 dir = rand()% 2 + 1; 52 } 53 else{ 54 ++ball_x; 55 --ball_y; 56 } 57 } 58 59 else if (dir == 4 && ball_x < 630 && ball_y < 460){ 60 if (ball_x >= bar_x && ball_x <= bar_x + 100 && ball_y + 10 == bar_y){ 61 dir = rand()% 3 + 1; 62 } 63 else if (ball_x == 629){ 64 dir = rand()% 2 + 1; 65 } 66 else{ 67 ++ball_x; 68 ++ball_y; 69 } 70 } 71 72 else{ 73 if (dir == 1 || dir == 3) 74 ++dir; 75 else if (dir == 2 || dir == 4) 76 --dir; 77 } 78 79 acquire_screen(); 80 circlefill ( buffer, ball_tempx, ball_tempy, 10, makecol(255,255,255)); 81 circlefill ( buffer, ball_x, ball_y, 10, makecol(200, 10, 10)); 82 draw_sprite( screen, buffer, 0, 0); 83 release_screen(); 84 85 rest(3); 86 } 87 88 void moveBar(){ 89 tempx = bar_x; 90 tempy = bar_y; 91 92 clear_to_color( buffer, makecol(255,255,255)); 93 bar = load_bitmap("bar.bmp", NULL); 94 95 if (key[KEY_RIGHT]&& bar_x != 540) 96 ++bar_x; 97 98 else if (key[KEY_LEFT]&& bar_x !=0) 99 --bar_x; 100 101 acquire_screen(); 102 draw_sprite( buffer, bar, bar_x, bar_y); 103 draw_sprite( screen, buffer, 0, 0); 104 release_screen(); 105 106 rest(0); 107 } 108 109 void setGame(){ 110 acquire_screen(); 111 circlefill(buffer, ball_x, ball_y, 10, makecol (200, 10, 10)); 112 release_screen(); 113 114 time(&secs); 115 srand( (unsigned int)secs); 116 dir = rand() % 4 + 1; 117 } 118 119 void startNew(){ 120 clear_keybuf(); 121 readkey(); 122 clear_to_color( buffer, makecol( 255, 255, 255)); 123 int ball_x = 100; 124 int ball_y = 100; 125 int bar_x = 100; 126 int bar_y = 100; 127 } 128 129 void checkWin(){ 130 if (ball_y + 10 > bar_y){ 131 textout_ex( screen, font, "You Lose!", 320, 240, makecol( 255, 0, 0), makecol( 255, 255, 255)); 132 startNew(); 133 } 134 } 135 136 int main(){ 137 138 allegro_init(); 139 install_keyboard(); 140 set_color_depth(16); 141 set_gfx_mode( GFX_AUTODETECT, 640, 480, 0, 0); 142 143 buffer = create_bitmap(640, 480); 144 145 setGame(); 146 147 while (!key[KEY_ESC]){ 148 moveBar(); 149 ballBounce(); 150 checkWin(); 151 } 152 153 return 0; 154 } 155 END_OF_MAIN();

James Stanley
Quote:

by multiplying by -1

You could, but you could also do:

xspeed = -xspeed

I assume that would be quicker, but I don't know

Kris Asick

James Stanley: I think compiler optimization probably converts multiplying by -1 to exactly that, since that is faster. It was just easier to explain the way I did.

ultratar:

Here are some suggestions:

• You should only draw your buffer to the screen once each frame. Not after every object you draw.

• When you draw a buffer to the screen it is much better to use blit() than draw_sprite().

• So long as you only make one draw to the screen per frame you can remove your acquire_screen() and release_screen() commands.

• There is no reason to keep track of "dir". It's an overcomplicated solution to the problem of knowing which side the ball has hit a block on, and is prone to errors. The better way is to check hits on 8 points of the ball, one point for each 45 degree angle from the centre. When a point registers a hit, you simply reflect those axises. It's made even simpler since you can combine each opposite check with each other. (For instance, if you hit the bottom or top of a block you still reflect the y speed by converting to its negative, or multiplying by -1.)

• Having a fixed speed will get boring fast due to the limited ways you can move the ball this way. What you should do instead is make your speed and ball coordinates a floating point value and use decimal values for movement, such as 0.1 or 0.0583. This way you can incorporate more angles and get more interesting movement.

--- Kris Asick (Gemini)
--- http://www.pixelships.com

LennyLen
Quote:

I checked the code a few times and I just don't get why it's not working properly.

The organisation is a bit chaotic, which really doesn't help. Try restructuring the game loop. Here's a pseudocode suggestion:

```while (!done) {
if (key[KEY_LEFT])

if (key[KEY_RIGHT])

if (key[KEY_ESC])
done = 1;

move_ball();

update_screen();
}
```

This keeps your logic seperate from your drawing routines, which will help once you add timers to control the speed of the game.

Some other suggestions:

• Don't reload the bar image every time you want to draw it. just load it in your initialization routines.

</li>