How to make balls coming from the top?
vilafranca

Hey buddies, I have the following program that I made [college homework]

1#include <stdio.h>
2#include <stdlib.h>
3#include <allegro.h>
4 
5#define RESOLUCAO_X 800
6#define RESOLUCAO_Y 600
7#define COR 16
8#define RAIO 15
9 
10int inicia(void);
11void abertura(void);
12void principal(void);
13void finaliza(void);
14 
15int main (void)
16{
17 
18 if (!inicia())
19 {
20 finaliza();
21 exit(-1);
22 }
23 
24 principal();
25 
26 finaliza();
27 exit(0);
28 
29}
30 
31 END_OF_MAIN();
32 
33int inicia (void)
34{
35 allegro_init();
36 
37 install_keyboard();
38 install_mouse();
39 
40 set_color_depth(COR);
41 set_gfx_mode(GFX_AUTODETECT, RESOLUCAO_X, RESOLUCAO_Y, 0, 0);
42 
43 if (set_gfx_mode(GFX_AUTODETECT, RESOLUCAO_X, RESOLUCAO_Y, 0, 0) < 0)
44 {
45 puts("Erro no modo gráfico!");
46 return (FALSE);
47 }
48 
49 return (TRUE);
50 
51}
52 
53void principal (void)
54{
55 int i;
56 
57 abertura();
58 
59 BITMAP *buffer;
60 buffer = create_bitmap(RESOLUCAO_X, RESOLUCAO_Y);
61 
62 while (!(key[KEY_ESC]))
63 {
64 for(i=0; !(key[KEY_ESC]); i=i+1)
65 {
66 circlefill(buffer, i, i, RAIO+8, makecol(200,0,10));
67 circlefill(buffer, mouse_x, mouse_y, RAIO, makecol(0,120,160));
68 textprintf_right_ex(buffer, font, 515, 10, makecol(255,255,255), 0, "Posicao X: %3.0d Posicao Y: %3.0d", mouse_x, mouse_y);
69 draw_sprite(screen, buffer, 0,0);
70 clear(buffer);
71 if ((mouse_x == i) && (mouse_y == i))
72 {
73 finaliza();
74 exit(-1);
75 }
76 }
77 }
78}
79 
80void finaliza (void)
81{
82 while(!keypressed());
83 allegro_exit();
84}
85 
86void abertura (void)
87{
88 textprintf_centre_ex(screen, font, RESOLUCAO_X/2, 250, makecol(255,255,255), 0, "Aperte uma tecla para INICIAR");
89 textprintf_centre_ex(screen, font, RESOLUCAO_X/2, 350, makecol(255,255,255), 0, "OBJETIVO: Acerte a bola AZUL em qualquer uma das bolas VERMELHAS");
90 while(!keypressed());
91}

*** My doubt is in the "Void Principal" part of the program! [take a look, please]
They want us to have a blue ball moved by the mouse cursor [ok, i did that]... and at the same time they want red balls coming from the TOP of the screen [ONE by ONE] going to different directions! The program will finish when we hit the blue ball in one of the red balls... that's when my doubt starts! I created a FOR command for the red ball... but this For command never stops, so, the next red ball never comes! I'd like a help of you to make the next balls come from the top of the screen... and if u also could take a look at what I did in the IF command I opened to make the program finishes when the red ball is hit by the blue one! I think it's not right at all! Please, help me!!!

Thank u so much!!! :-[

Paul whoknows

Use code tags [CODE][/CODE](tags must be in lower case). Also, it would be nice if you translate your variables and functions names to English.

vilafranca

Hey Paul, thanks for your help!
But I'm very new to allegro, so I don't understand this tags =/

Could u explain that to me, or someone else?!
:-[

Mark Oates

in the text box where you reply to posts, click the help button. It'll show you there a tag for source code. You should edit your first post and use the code tags. It makes it easier to read :)

vilafranca

Ok, I edited it :P

Now, could u help meeeeee?! :-/

Paul whoknows

Remove the while (!(key[KEY_ESC]) in principal(). Does that work?

CGamesPlay
1void principal (void)
2{
3 int i;
4 
5 abertura();
6 
7 BITMAP *buffer;
8 buffer = create_bitmap(RESOLUCAO_X, RESOLUCAO_Y);
9 
10 while (!(key[KEY_ESC]))
11 {
12 for(i=0; !(key[KEY_ESC]); i=i+1)
13 {
14 circlefill(buffer, i, i, RAIO+8, makecol(200,0,10));
15 circlefill(buffer, mouse_x, mouse_y, RAIO, makecol(0,120,160));
16 textprintf_right_ex(buffer, font, 515, 10, makecol(255,255,255), 0, "Posicao X: %3.0d Posicao Y: %3.0d", mouse_x, mouse_y);
17 draw_sprite(screen, buffer, 0,0);
18 clear(buffer);
19 if ((mouse_x == i) && (mouse_y == i))
20 {
21 finaliza();
22 exit(-1);
23 }
24 }
25 }
26}

This is the code in question. It is called your "main loop". If you look at what's happening, it's not at all what you need to be happening.

The while part is good. You want your code to run until the escape key is pressed. In other words, while the escape key is not pressed. That's fine. Inside the loop, You need to separate your code into logic and drawing.

First, make a list of what you need to keep track of. In this case, it's the ball's position. Store these variables outside of the loop:

// ...
int ball_x, ball_y;
while(!(key[KEY_ESC]))
{
    // Logic:
    // Drawing:
}

Then, in the logic section, move the ball by changing ball_x and ball_y. Also check if the player has moved the mouse over the ball in this section. And finally, in the drawing section, draw the player's ball using mouse_x and mouse_y and draw the ball using the stored ball_x and ball_y.

I hope that all makes sense. Don't worry if the ball zooms off-screen faster than you can hover over it. You'll need to get into timers to fix that issue.

vilafranca

Actually, there's no error when I compile the program!
The only problem is... since I made this FOR command for the red ball moves on the screen

    for(i=0; !(key[KEY_ESC]); i=i+1)
    {
      circlefill(buffer, i, i, RAIO+8, makecol(200,0,10));
      circlefill(buffer, mouse_x, mouse_y, RAIO, makecol(0,120,160));
      textprintf_right_ex(buffer, font, 515, 10, makecol(255,255,255), 0,  "Posicao X: %3.0d  Posicao Y: %3.0d", mouse_x, mouse_y);
      draw_sprite(screen, buffer, 0,0);
      clear(buffer);
      if ((mouse_x == i) && (mouse_y == i))
      {
        finaliza();
        exit(-1);
      }
    }

When the red ball disappears of the screen, it must appear a new one! But this for command seems never stop, so, when i create another for command for another red ball, it doesn't work, cos the 1st FOR is still running... so the next ball never comes... that's the problem! what do i do? is there a way to do these balls coming one by one without using FOR?!

Paul whoknows

Try this:

1int i = 0;
2while (!(key[KEY_ESC]))
3 {
4 i++;
5 if(i > 640) i = 0;
6 if ((mouse_x == i) && (mouse_y == i))
7 {
8 finaliza();
9 exit(-1);
10 }
11 clear(buffer);
12 circlefill(buffer, i, i, RAIO+8, makecol(200,0,10));
13 circlefill(buffer, mouse_x, mouse_y, RAIO, makecol(0,120,160));
14 textprintf_right_ex(buffer, font, 515, 10, makecol(255,255,255), 0, "Posicao X: %3.0d Posicao Y: %3.0d", mouse_x, mouse_y);
15 draw_sprite(screen, buffer, 0,0);
16
17 }

However, this:

if ((mouse_x == i) && (mouse_y == i))
    {
      finaliza();
      exit(-1);
    }

won't work as a collision detection.

vilafranca

Doesn't work Paul!
Actually, there's no error... but this code just makes the same ball coming always in the same direction... and the right thing should be the ball coming in a direction... when it disappears of the screen, another ball comes in another direction... and it goes till we hit one of them with the blue ball [which is the mouse cursor]

My gosh, I have no IDEA how to do that...

:'( :'(

Paul whoknows
Quote:

but this code just makes the same ball coming always in the same direction

Yes of course, what did you expect? I posted that just to 'stop' your neverending for(). If you want balls in different directions you should use vectors, something like this:

double theta = angle;
x =  x_start_position + cos(theta) * distance;
y =  y_start_position + sin(theta) * distance;
distance++;

vilafranca

Hey buddies, I fixed some part of the program!
Now, the next red ball is coming... I made something to finish the FOR command, so it can stop now for the following red ball appears on the screen! :D

The matter now is... the program must finish when the blue ball [mouse cursor] hits the red ball! I made this instruction for it:

if ((mouse_x == i) && (mouse_y == j))
      {
        finaliza(); /* calls the end of the program */
        exit(-1);
      }

But this command will only work if the mouse cursor hits EXACTLY the center of the red ball (coordinates i,j), which is not pretty good! the best thing to do is to finish the program if the blue ball hits ANY part of the red ball, not exactly the center, cos it makes more difficult to hit it!

Any help to fix it, please?! ;D

Paul whoknows

Put a bounding box in each ball, do the collision detection between both boxes using this function:

x1,y1             
   +----+
   |RED |
   |BALL|
   +----+x2,y2
xx1,yy1             
   +----+
   |BLUE|
   |BALL|
   +----+xx2,yy2

inline bool collide(int x1, int y1, int x2, int y2, int xx1, int yy1, int xx2, int yy2)
{
     if (x2 <= xx1) return false;
     else if (x1 >= xx2) return false;
     else if (y2 <= yy1) return false;
     else if (y1 >= yy2) return false;
     else return true;
}

miran

@paul: That's just stupid. Why would you use bounding box collision detection for detecting collisions between circles? Use circle/circle collision detection for that instead:

1. calculate distance between the centre of red ball and blue ball
2. if the calculated distance is smaller than the sum of the balls' radii, there was a collision

float x1, y1, r1;
float x2, y2, r2,

float dx = x2 - x1;
float dy = y2 - y1;

float d = dx*dx + dy*dy;

if (d <= (r1+r2)*(r1+r2)) {
   // collision!
}

@vilafranca: Do EXACTLY what CGamesPlay tells you to do and get completely and totally rid of your for loop!

Paul whoknows
Quote:

That's just stupid. Why would you use bounding box collision detection for detecting collisions between circles?

Box collision is easier to understand than circle/cirlcle collision, that's why I showed him the b. box collision function. Also, I think he does not need so much precision in his program.
However, Miran's code is the best way to solve this problem, obviously.

miran
Quote:

Box collision is easier to understand than circle/cirlcle collision, that's why I showed him the b. box collision function. Also, I think he does not need so much precision in his program.

Uhm, maybe that's just me, but circle-circle collision is the simplest, easiest, most basic type of collision test there is.

Johan Halmén

No, it's me too. Even when you go into bouncing reaction, the circle-circle thing is not very difficult. You can define a line from one circle to the other (middle points), you can find out the collision point on this line, you can define the tangential line through this point. Now you have an imaginary wall that both circles collide against. And so on.

Paul whoknows
Quote:

Uhm, maybe that's just me, but circle-circle collision is the simplest, easiest, most basic type of collision test there is.

Damn! you got me.>:( I just wanted to draw some ASCII boxes! are you happy now? :P

Johan Halmén

Yes.

CGamesPlay
Quote:

Try this:

Hmm, give a man a fish, teach a man to fish...

Tobias Dammers
Quote:

Hmm, give a man a fish, teach a man to fish...

My thought exactly.
Break the problem down into sub-problems until you reach something you can't divide any further. If you can solve it, do so. If you can't, come back here.

Here are a few things to google / forum-search:
- main loop
- collision detection
- separate logic and drawing
and more generally:
- game programming

Set up a main loop. This should do logic and drawing.
Logic needs to:
- update player position
- update ball position
- check if ball hits player -> end game
- check if ball is outside screen -> reset ball coordinates and speed
Drawing is just drawing.

Paul whoknows
Quote:

Quote:

Try this:

Hmm, give a man a fish, teach a man to fish...

A fish is better than nothing. Also, learning to fish takes some time, meanwhile, he needs something to eat.

CGamesPlay
Quote:

Hey buddies, I have the following program that I made [college homework]

...

Tobias Dammers

That reads: OMG WTF PLZ DO MY HOMEWORK 4 ME LOLZ

vilafranca

No Tobias, I didn't ask anyone to DO my homework... I just asked for HELP!
That's different, ok? >:(

Anyway, I wanna thank everyone who came here to gimme a help!
I made some changes and now the program's workin' perfectly!

Thank u guys... 8-)

CGamesPlay

You could post the code here, so we can comment on it and let you know if we see anything wrong with it (bad practices, wastes of resources, memory leaks, etc).

spellcaster

Don't take the folks around here too seriously.
They are not used to people actually coding something instead of just posting here and discussing how somebody should code ;)

LennyLen
Quote:

They are not used to people actually coding something instead of just posting here and discussing how somebody should code

That, and there have been quite a few requests by people to do their programming assignments in the last few months.

Thread #591659. Printed from Allegro.cc