Allegro

Pages: 1234
Checking mouse position is much easier. Allegro stores them in mouse_x and mouse_y. The current wheel position is stored in mouse_z. All of these are plain old normal ints and can be treated like any other variable you've declared (no funny '&'s or anything like that needed).


This is what is said. So it seem i can use it as a variable with no problems.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
BITMAP* buffer;
int cursor_x = 20;
int cursor_y = 20;
int radius = 30;
int g;
double distance(double x , double y){
       double Z = sqrt((x*x) + (y*y));
       return Z;
       }
struct Circle{
       int x, y, radius;
       };
       std::vector<Circle> scene;
       int selected = -1;

int getMouseInfo(){
   if(mouse_b & 1){
                  cursor_x = mouse_x;
                  cursor_y = mouse_y;
                  Circle c;
            c.x = cursor_x;
            c.y = cursor_y;
            c.radius = radius;
            scene.push_back(c);                   
      return 1;
                 }
      if(mouse_b & 2){
                 cursor_x = mouse_x;
                 cursor_y = mouse_y;
                 selected = -1;
     for(int i = 0; i < scene.size(); i++){  
           if (distance(cursor_x-scene[i].x, cursor_y-scene[i].y) <= scene[i].radius){
                                              g = selected;
                                              } 
                                              } 
       return 1;
            }
  return 0;
}
void updateScreen(){
 
    show_mouse(NULL);
    
          for(int i = 0; i < scene.size(); i++){                                                                                                                                         
            circlefill ( buffer, scene[i].x, scene[i].y, scene[i].radius, makecol( 0, 0, 255));
            
            if(g == selected){
          rect(buffer, scene[i].x - scene[i].radius - 10, scene[i].y - scene[i].radius - 10,
           scene[i].x + scene[i].radius + 10, scene[i].y + scene[i].radius + 10, makecol(0,0,255));
           }
     draw_sprite( screen, buffer, 0, 0); 
     
     }
}


Ok this code goes like this whne i run it. First left click draws a circle, and ervery consecutive left click also draws a circle, but when i right click it selects every circle that has been drawn and all new circles that i draw come with the selection square around them.
What is the purpose of 'g'? You set it to selected and then you check if it's equal to selected. That's all you do with it. What should be instead? Also, there is something wrong with line 33.
i see. i got it working now. ty. xD now the next step would be deselect. so that if i click somewhere lese the square disappears. i quess that can be achived if it clears the screen and redraws the circles. or. the square goes directly to screen, but the sircles go to buffer, se we jsut have to reload the buffer. I dont know if my idea is correct.
When you press somewhere else now, what does it do? Line 30 was meant to handle deselecting.. The frames are constantly redrawn, so you don't need to take care of that yourself. If selected is -1 (or any other impossible value), i == selected will never return true and the square will never be drawn.
if i click anywhere else, the frame stays, it doesent disappear.
That's weird. Even if no circle was clicked, you'll reach line 36 and getMouseInfo() will return 1 which should cause a redraw. Unless you changed something in your newest code, or I'm misinterpreting something..
You could add a forced redraw in getMouseInfo() with if(selected == -1) updateScreen(); just before returning from the mouse_b & 2 part. Though it's an ugly thing to do..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
int cursor_x = 20;
int cursor_y = 20;
int radius = 30;
double distance(double x , double y){
       double Z = sqrt((x*x) + (y*y));
       return Z;
       }
struct Circle{
       int x, y, radius;
       };
       std::vector<Circle> scene;
       int selected = -1;

int getMouseInfo(){
   if(mouse_b & 1){
                  cursor_x = mouse_x;
                  cursor_y = mouse_y;
                  Circle c;
            c.x = cursor_x;
            c.y = cursor_y;
            c.radius = radius;
            scene.push_back(c);                   
      return 1;
                 }
      if(mouse_b & 2){
                 cursor_x = mouse_x;
                 cursor_y = mouse_y;
                 selected = -1;
     for(int i = 0; i < scene.size(); i++){  
           if (distance(cursor_x-scene[i].x, cursor_y-scene[i].y) <= scene[i].radius){
                                              selected = i;
                                              } 
                                              } 
       return 1;
            }
  return 0;
}
void updateScreen(){
 
    show_mouse(NULL);
    
          for(int i = 0; i < scene.size(); i++){                                                                                                                                         
            circlefill ( buffer, scene[i].x, scene[i].y, scene[i].radius, makecol( 0, 0, 255));
            
            if(i == selected){
          rect(buffer, scene[i].x - scene[i].radius - 10, scene[i].y - scene[i].radius - 10,
           scene[i].x + scene[i].radius + 10, scene[i].y + scene[i].radius + 10, makecol(0,0,255));
           }
     draw_sprite( screen, buffer, 0, 0); 
     
     }
}
Do you have the console allocated? You need to do some debugging.

Add std::cout << "mouse click 2\n"; after line 25.

Add std::cout << "selected = " << selected << '\n'; before line 34.

Add std::cout << "redrawing...\n"; on line 39.

Add std::cout << "selected i = " << selected << '\n'; after line 45.

Post whatever output you get after selecting and clicking the same button on nothing.

By the way, you really need to fix that formatting.
ok if i click on the black screen where are no object ja get selected = -1, redrawing..... If i draw an object and select it then selected = the number of the object. And if then i click on black screen again first selected = -1 and the second selected = the number of object i selected.
I think this can be fixed if i but selected = -1 under if(mouse_b & 1)

Although i dont know how to allocate console in allegro, but i made it to display the messages in the corner of the screen.

If by formatting you meen teh wery wide scree, then i dont know what happened thati t turned thiway in the beginning.
Last edited on
I don't know which mouse button you're clicking when, but you try your idea..

It really doesn't matter how you get the output, as long as you get it.

By formatting, I meant that if you followed a set of rules, you could make your code more readable. Choose one: http://en.wikipedia.org/wiki/Indent_style
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
char *str = "mouse click 2";
char *str3= "redrawing...";

double distance(double x , double y){
       double Z = sqrt((x*x) + (y*y));
       return Z;
       }
       
struct Circle{
       int x, y, radius;
       };
       std::vector<Circle> scene;
       int selected = -1;

int getMouseInfo(){
   if(mouse_b & 1){
            cursor_x = mouse_x;
            cursor_y = mouse_y;
            
            Circle c;
            c.x = cursor_x;
            c.y = cursor_y;
            c.radius = radius;
            scene.push_back(c);    
                           
            return 1;
                 }
                 
   if(mouse_b & 2){
            textprintf(buffer, font, 0, 40, makecol(255, 255, 255), "%s", str);
            cursor_x = mouse_x;
            cursor_y = mouse_y;
            selected = -1;
            
     for(int i = 0; i < scene.size(); i++){  
            if (distance(cursor_x-scene[i].x, cursor_y-scene[i].y) 
            <= scene[i].radius){
                         selected = i;
                                } 
                       } 
            textprintf(buffer, font, 0, 10, makecol(255, 255,255), "selected = %i", selected);                       
            return 1;
            }
  return 0;
}
void updateScreen(){
            textprintf(buffer, font, 0, 50, makecol(255, 255, 255), "%s", str3);
            show_mouse(NULL);
    
            for(int i = 0; i < scene.size(); i++){                                                                                                                                         
                 circlefill ( buffer, scene[i].x, scene[i].y, scene[i].radius,
                 makecol( 0, 0, 255));
            
                 if(i == selected){
                     textprintf(buffer, font, 0, 20, makecol(255, 255,255), "selected = %i", selected);
                     rect(buffer, scene[i].x - scene[i].radius - 10, scene[i].y 
                     - scene[i].radius - 10, scene[i].x + scene[i].radius + 10,
                      scene[i].y + scene[i].radius + 10, makecol(0,0,255));
                     }
           draw_sprite( screen, buffer, 0, 0); 
            }
}

Is this the better format???
Last edited on
I understand that on line 30 it shows that right click was made.
on line 41 it shows what object i cliced on.
on line 47 it tells the beginngin of redrawing function.
but line 55 shows what?

I think i figured out what is the problem. all the circles ar drawn into the buffer and then on the screen to avoid flickering. but the selection rectangle is also draw into buffer and then on the screen. So probably the rectangle is memoryzed in the buffer. So i tryed to draw it straight to the screen, but then came a problem, the rectangle is drawn and then buffer draws over it. I think i need to make the rectangle drawn later than the circle buffer, but only when right click is made.
Last edited on
Line 55 would show is selected magically changed since line 41.

What you need to do is clear the buffer on every frame. Actually, having a buffer at all is weird. Double buffering is something that your library should take care of. I don't know, maybe allegro doesn't.. Any way, you could solve it as you like right now, but when your circles start moving, it would be a lot of pain to manage them.

Good formatting is
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
char *str = "mouse click 2";
char *str3= "redrawing...";

double distance(double x , double y) {
   double Z = sqrt((x*x) + (y*y));
   return Z;
}
       
struct Circle {
   int x, y, radius;
};
std::vector<Circle> scene;
int selected = -1;

int getMouseInfo() {
   if(mouse_b & 1) {
      cursor_x = mouse_x;
      cursor_y = mouse_y;
            
      Circle c;
      c.x = cursor_x;
      c.y = cursor_y;
      c.radius = radius;
      scene.push_back(c);    
                          
      return 1;
   }
                 
   if(mouse_b & 2) {
      textprintf(buffer, font, 0, 40, makecol(255, 255, 255), "%s", str);
      cursor_x = mouse_x;
      cursor_y = mouse_y;
      selected = -1;
           
      for (int i = 0; i < scene.size(); i++) {  
         if (distance(cursor_x-scene[i].x, cursor_y-scene[i].y) <= scene[i].radius) {
            selected = i;
         } 
      } 
      textprintf(buffer, font, 0, 10, makecol(255, 255,255), "selected = %i", selected);
      return 1;
   }
   return 0;
}

void updateScreen() {
   textprintf(buffer, font, 0, 50, makecol(255, 255, 255), "%s", str3);
   show_mouse(NULL);
   
   for (int i = 0; i < scene.size(); i++) {
      circlefill ( buffer, scene[i].x, scene[i].y, scene[i].radius,
      makecol( 0, 0, 255));
            
      if (i == selected) {
         textprintf(buffer, font, 0, 20, makecol(255, 255,255), "selected = %i", selected);
         rect(buffer, scene[i].x - scene[i].radius - 10,
                      scene[i].y - scene[i].radius - 10,
                      scene[i].x + scene[i].radius + 10,
                      scene[i].y + scene[i].radius + 10,
                      makecol(0,0,255));
      }
      draw_sprite( screen, buffer, 0, 0); 
   }
}
Or something like that.
Last edited on
Here is how buffering works:
If you just draw everything to the screen, you will notice that you get a lot of flicker. This is because you are drawing directly to the screen, which is updated by the operating system at an unknown rate! Buffering gets rid of flicker because it minimizes direct drawing to the screen. If you draw each component onto the 'buffer', and then the complete screen sized buffer to the screen: flicker is eliminated since you draw everything at once in one pass. It's that simple. You will also notice, in the unbuffered mode, that the ball will zoom across the screen (if you have a relatively fast computer). Even in buffered mode, things can move pretty fast (or slow - again depending on the speed of your computer). This problem is fixed using timers, which will be explained in the next lesson, so don't worry about this for now.

I took this directly from the double buffering tutorial. So it seem that allegro tiself doeset take care of that. But was my soultion correct or do you have something better in mind that could be helpful???
You'll have to try it. I think that screen is still not being cleared, so what is drawn on it stays on it, but maybe allegro does that much for you.. The question is whether empty space in buffer is black of transparent. If it's black, it will work, but still, clearing it would be simpler.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void updateScreen() {
   clear(buffer);
   textprintf(buffer, font, 0, 50, makecol(255, 255, 255), "%s", str3);
   show_mouse(NULL);
   
   for (int i = 0; i < scene.size(); i++) {
      circlefill ( buffer, scene[i].x, scene[i].y, scene[i].radius,
      makecol( 0, 0, 255));
            
      if (i == selected) {
         textprintf(buffer, font, 0, 20, makecol(255, 255,255), "selected = %i", selected);
         rect(buffer, scene[i].x - scene[i].radius - 10,
                      scene[i].y - scene[i].radius - 10,
                      scene[i].x + scene[i].radius + 10,
                      scene[i].y + scene[i].radius + 10,
                      makecol(0,0,255));
      }
      draw_sprite( screen, buffer, 0, 0); 
   }
}

This works, but it causes a lot of flicering, eatch new click kauses all the other circles to flicker.
Last edited on
Why is draw_sprite inside the loop. Isn't the plan to first draw everything into the buffer and only then draw the whole buffer on the screen. Now you're may as well not use any buffer at all. I think when you move line 18 after 19, the problem will go away.
i see, yes tha worked. it probaby isnt a problem. but selected = 38 and next circle selected = 200+.
It is a problem. As you're not can't tell whether the mouse was just clicked or held down, you're creating tons of circles instead of just one per click.

One solution is to remember previous mouse states:
Have global variables bool old_mouse1 = false, old_mouse2 = false;
Now, in getMouseInfo(), have
1
2
3
4
5
6
7
8
bool new_mouse1 = mouse_b & 1;
if (new_mouse1 != old_mouse1) {//something changed
   old_mouse1 = new_mouse1;//remember it for the next time
   if (new_mouse1) {
      //handle your mouse, like you already do
   }
}
//then do the same for the second button 


Another solution is to switch to a more comfortable library. Try http://www.sfml-dev.org/
Ok bool worked. does sfml support BLoodshed Dev-C++?? i do have Visual Studio c++ but for somereason i dont like it that mutch.
Pages: 1234