should I re-write the whole code Chris? Is it that bad?
It's not horrible. Architecting code is a life-long endeavor and you'll constantly get better at it the more you do it.
Basically though, it's good to separate things based on their purpose.
Have an init() function, and put all the "setup" code in that function. (You can of course split that init function into sub-purposes like init allegro, loading fonts, loading bitmaps.)
Have a function related to execution of the game loop. (I just use "execute()".) Within that, you have input() (handling keyboard/joystick/etc), logic(), and draw(). In that order. You check for inputs and set relevant flags. You then run logic that affects the game (updating positions), you then draw everything.
You can decouple logic and drawing events by having them occur at different rates but it's not necessary. But notice, by keeping those functions (input, logic, and draw) separate, it would be really easy to call one more times than the other, or with delay if necessary. It's also easier to keep track of what you're doing because the only thing that happens in logic() is related to logic. The only thing that happens in draw() is related to drawing. So you'll don't have to think about things that are outside your function, and if you know you have a drawing problem, you go straight to the draw() function.
Now, then comes a problem. You're in the input function, but you want to affect something related to logic or drawing! You press a key, and you want a guy to move, or you want something special to be drawn like a message. How do you effect something outside of your function? You do it through interfaces. A specifically-defined way to access the other "aspect" of your game. If your input() function wants a character to move, you set a flag that says "move_character_left = true", and then when the logic() function gets called, it reads that value "if(move_character_left)player.x -= 10;".
The key there is, since you've "decoupled" input from logic through a defined interface (the move_character_left variable), if someone were to press the left arrow 5 times in a row before the next frame was processed, the character would only move once. Which is what you want. If logic happens 30 times a second (a typical rate), you want that character to move a maximum of YOUR_SPEED * 30 times a second. Consider the alternative: If you called the function "move left" every time the a "left arrow" event is fired, then someone could press the left key super fast (or have an outside program fake it) and move faster than expected. Also, the opposite applies. Allegro 5 only fires off an event when you press the key. If you hold the key, the event doesn't fire again! So if you want "guy/paddle/whatever" to keep moving as it is held down, you mark the flag when the key is pressed inside input(), and then unset that flag only when Allegro says the key has been unpressed.
I may be getting a bit off track and confusing, so if it is confusing, don't stress out.
Now back to what you're trying to do:
- You're trying to setup Allegro (init)
- Load resources specific to your game (the brick bitmap) (init, or a second, more specific init function)
- Read from the keyboard (input)
- Act on those keys (logic)
- Draw the result (draw)
Inside logic(), you're trying to decide whether a brick is intersecting or not.
So what you want to do, is keep track of all bricks and whether or not they have been intersected with. Then, when you get to the draw() routine, you check if "has_intersected = true" and if so, draw it another color. If not, draw the main color.
Since it appears that you want real-time colors, you will use al_draw_tinted_bitmap(). So you only need one ALLEGRO_BITMAP for the brick image, and then you draw it to the screen as many times you want with the added tint that you specify in that function. There's no need for an array of bitmaps, or multiple al_load_bitmap calls.
As amarillion and jmasterx has suggested, objects will help here. For example, you have a structure like this:
// - bricks are all the same width/height
// - There are always 100 bricks
}bricks; //array of 100 "brick_type" objects
1logic() //decide collisions here, and mark them
3 for(int i = 0; i < 100; i++)
5 if(intersect(bricks[i].x, bricks[i].y, ball.x, ball.y)
7 bricks[i].has_intersected = true;
9 bricks[i].has_intersected = false;
13draw() //draw them, based on the previous marking
15 for(int i = 0; i < 100; i++)
19 //draw with tinted color
22 //draw normal
If you want to mark whether a brick has been destroyed, you do the same thing, the same way as has_intersected. It becomes much easier to add and modify your code when things are split like this.