[Open Layer] Creating a GUI
Balinor

I'm working with Open Layer on an RPG. So, I want to integrate a GUI into my game but I don't exactly know how to do that.

Are there libraries that I could use or do I have to code everything by myself? Is it possible to use the GUI functions of Allegro?

Vanneto

I was thinking the exact same thing. I want to create a simple GUI for a game im making. Just a basic menu, start button, maybe some options and a quit button. But I dont know how to do it!

So im hoping someone will reply to this thread! :)

Paul Rowan

I've had the same problem, but I solved it by using something similar to collision detection in a game. If you want any type of button, you will know the size of it say 64 wide x 32 deep. You also know where you're going to display it on the screen say 100,100. You can track where the x and y is of the mouse pointer on screen (you have to install the mouse first) and you can also check for the mouse button being clicked.

So using the numbers above, the top left co-ords of the button on the screen are 100,100 and the bottom right co-ords of the button on screen are 163,131 (screen x: 100 + button width 64 - 1 [cos the button starts at 100 not 101] , screen y: 100 + button height 32 - 1 [for same reason]).

So if the mouse buttom is clicked and mouse x>=100 and mouse x<=163 and mouse y>=100 and mouse y<=131 then the button on screen has been clicked and you can use that info to do what you want.

If you want more than one button on screen at once, just keep a track of what the button co-ords are to initiate the correct function.

:)

If you want a full code example let me know ;D

Vanneto

A code example would be nice. Anyway sounds pretty simple. Now... But when youre thinking how to do its a diffrent story! Ill try this! Thanks!

tobing

I'm using guichan as a UI library together with OpenLayer, works fine, if you manage to setup all libraries you need. That means allegro, allegrogl, lpng (optional) and lzip (used only for lpng).

Paul Rowan

Hi, as promised here is my full code listing for my GUI. It's very basic and there may be other ways to do it better, but it worked for me :)

1#include <allegro.h>
2 
3#define RED makecol(255,0,0)
4#define GREEN makecol(0,255,0)
5#define BLUE makecol(0,0,255)
6#define WHITE makecol(255,255,255)
7#define BLACK makecol(0,0,0)
8 
9//number of buttons on GUI interface
10#define BUTTONS 2
11 
12//function prototypes
13void create_buttons(void);
14int check_click(int mousex,int mousey);
15 
16//set up an array of button bitmaps - use a loop to display them
17BITMAP *buttons[BUTTONS];
18 
19//set up an array for x,y cor-ords of each button on screen
20//can loop through them when mouse button is clicked to see
21//which button or not is clicked
22int but_xy[BUTTONS*2];
23 
24//variables to keep track of mouse info
25int mousex,mousey,mousebut;
26 
27int main()
28{
29 allegro_init();
30 set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640, 480, 0, 0);
31 text_mode(-1);
32 install_keyboard();
33 install_mouse();
34 install_timer();
35 show_mouse(screen);
36
37 int x,but;
38
39 create_buttons();
40 
41//loop to display buttons on screen at proper co-ords
42 for(x=0;x<BUTTONS;x++)
43 {
44 blit(buttons[x],screen,0,0,but_xy[x*2],but_xy[x*2+1],buttons[x]->w,buttons[x]->h);
45 }
46 
47 while(! key[KEY_ESC])
48 {
49 textprintf(screen,font,1,1,WHITE,"%s","Press ESC KEY to Exit");
50//keeping track of mouse info
51 mousex=mouse_x;
52 mousey=mouse_y;
53 mousebut=(mouse_b&1); // this only checks left mouse button
54
55//if left mouse button is clicked the mouse x,y co-ords are checked against
56//button co-ords on screen held in array
57 if(mousebut==1)
58 {
59 but=check_click(mousex,mousey);
60 rectfill(screen,1,11,500,21,BLACK);
61//the button number clicked on will be returned and can be used in the switch statement
62//to do the required thing it is designed to do in your game
63 switch(but)
64 {
65 case 0:
66 textprintf(screen,font,1,11,RED,"Result of last mouse click: %s","Play Button Clicked");
67 break;
68 case 1:
69 textprintf(screen,font,1,11,BLUE,"Result of last mouse click: %s","Quit Button Clicked");
70 break;
71 default:
72 textprintf(screen,font,1,11,WHITE,"Result of last mouse click: %s","No Button Clicked");
73 break;
74 }
75 }
76 }
77 
78 allegro_exit();
79 return 0;
80}
81END_OF_MAIN();
82 
83 
84//creating bitmaps in memory, you can load your own nice looking buttons instead
85void create_buttons(void)
86{
87 int x;
88
89//set up all x,y co-ords of all buttons to display on screen here
90
91//x,y co-ord of button 0
92 but_xy[0]=100;
93 but_xy[1]=100;
94 
95//x,y co-ord of button 1
96 but_xy[2]=150;
97 but_xy[3]=200;
98
99//creating bitmaps in memory here, you can load them instead
100 buttons[0]=create_bitmap(64,32);
101 clear_to_color(buttons[0],RED);
102 buttons[1]=create_bitmap(40,40);
103 clear_to_color(buttons[1],BLUE);
104 textprintf(buttons[0],font,14,12,WHITE,"%s","PLAY");
105 textprintf(buttons[1],font,5,17,WHITE,"%s","QUIT");
106}
107 
108//checking if mouse pointer is over a button on screen when clicked
109int check_click(int mousex,int mousey)
110{
111 int x;
112 int x1,y1,x2,y2;
113 int b=-1; // this is used to record which button number is clicked - if none returns -1
114
115//looping through all buttons on screen and checking if mouse pointer is inside button
116 for(x=0;x<BUTTONS;x++)
117 {
118 x1=but_xy[x*2]; //top left corner of button on screen - x
119 y1=but_xy[x*2+1]; // top left corner of button on screen - y
120 x2=x1+buttons[x]->w-1; // bottom right corner of button on screen - x
121 y2=y1+buttons[x]->h-1; // bottom right corner of button on screen - y
122 
123// if mouse pointer is inside button co-ords the button number is stored in b
124 if(mousex>=x1 && mousex<=x2 && mousey>=y1 && mousey<=y2) b=x;
125 }
126//either returns a button number or -1 for no button clicked
127 return (b);
128}

Let me know if this helps or I'd be interested if you find an easier/better way cos I'm quite new to all this and still learning :)

Balinor

Thanks for your answers. Thanks for your code, Paul Rowan. That's the way I had done it before as I wrote a game with another library than Open Layer / Allegro. I think I will do it like that.

Vanneto

Here is a class I made for the purpouse. Makes the process easier

1#ifndef _BUTTON_H_
2#define _BUTTON_H_
3/**
4* Class for drawing button on the screen and using actions from it
5**/
6 
7class Button {
8 public:
9 Button()
10 {
11 button_image = NULL;
12 }
13 ~Button()
14 {
15 button_image = NULL;
16 }
17 
18 void set_bitmap(BITMAP *bitmap_b)
19 {
20 button_image = bitmap_b;
21 }
22 void set_coords(int x, int y)
23 {
24 button_x = x;
25 button_y = y;
26 }
27 void draw_button(BITMAP *to) const
28 {
29 blit(button_image, to, 0, 0, button_x, button_y, button_image->w,
30 button_image->h);
31 }
32 
33 int button_clicked()
34 {
35 // Mouse must be clicked
36 if(mouse_b & 1)
37 {
38 int real_x, real_y;
39 real_x = button_x + button_image->w - 1;
40 real_y = button_y + button_image->h - 1;
41 
42 if(mouse_x>=button_x && mouse_x<=real_x && mouse_y>=button_y
43 && mouse_y <=real_y)
44 {
45 // CLICKED
46 return 1;
47 }
48 }
49 }
50 
51 private:
52 int button_x,button_y;
53 BITMAP *button_image;
54};
55 
56 
57#endif

spellcaster

@Vanneto:
Just a small comment: Normally a button fires only if somebody presses and releases the mouse inside the boundaries of the button. Links work the same way.

Besides working like the user expects it, it also solves the problem that the click might be registered on the next page as well, if the page changes before the button was released.

Vanneto

And how do I know if it was released? I will change the class appropriately.

Thanks!

spellcaster

Well, that's the point where it gets more complicated.
Let's say you have a function like this:

1// you will want to place these vars inside a class
2GUIItem lastItem = NULL;
3int lastMouseButtonState= 0;
4 
5void handleGUI() {
6 int x= mouse_x;
7 int y= mouse_y;
8 int buttons = mouse_b;
9 GUIItem item = findGUIItem(x, y);
10 
11 if (item == null) {
12 // mouse is not inside an item.
13 if (lastItem != NULL) {
14 lastItem ->handleMouseOut();
15 }
16 }
17 if (buttons != lastMouseButtonState) {
18 if (lastItem != NULL && lastItem != item) {
19 lastItem->handleMouseButton(buttons);
20 }
21 if (item != NULL) {
22 item->handleMouseButton(buttons);
23 }
24
25 lastMouseButtonState = buttons;
26 }
27 lastItem = item;
28}

If you want even more flexibility, you could add the concept of a grabbed item, receiving all related events until it declares itself as no longer interested.

This way your button can grab the events as soon as the mouse button goes down inside his boundaries. It should release the grab as soon as the mouse button is no longer pressed.

The code above was written on the fly and will probably contain errors. I hope the example will be good enough to visualize the idea, though.

Thread #591458. Printed from Allegro.cc