GUI Basics? (AGUI)

I am back again, I guess I am trying to do way too much than my current knowledge is letting me but I am learning so much so here goes.

I am coding a little side scrolling shooter game while I am learning allegro/C++/Programming in general. I've managed to get a lot accomplished thanks to the people in this forum and in the internet in general but I have run into a new issue. I wanted to try and make a clickable button, but I quickly learned that that isn't as simple as it sounds. So I dove into the world of GUI's and all that and am a tad overwhelmed, mostly because I haven't found anything that is beginner friendly. I downloaded and installed AGUI (I think successfully but I don't know how to operate it. So I have a few questions:

1. Is working with GUI's too advanced for me now? Should I just draw a box to the screen and use collision-like detection to find out if the area has been clicked or being hovered over?

2. Is AGUI a good lib to start learning about GUI's?

3. I actually can't get AGUI's example to run and it is giving me an error on line 157 saying the vector is out of range. However I haven't modified the source code at all so I am wondering if I missed something installing the library or if the example has a bug?

1/* _____ 2 * /\ _ \ __ 3 * \ \ _\ \ __ __ __ /_\ 4 * \ \ __ \ /'_ `\ /\ /\ \/\ \ 5 * \ \ /\ \ /\ _\ \\ \ _\ \\ \ \ 6 * \ _\ _\\ ____ \\ ____/ \ _\ 7 * /_//_/ /____\ \/___/ /_/ 8 * /____/ 9 * _/__/ 10 * 11 * Copyright (c) 2011 Joshua Larouche 12 * 13 * 14 * License: (BSD) 15 * Redistribution and use in source and binary forms, with or without 16 * modification, are permitted provided that the following conditions 17 * are met: 18 * 1. Redistributions of source code must retain the above copyright 19 * notice, this list of conditions and the following disclaimer. 20 * 2. Redistributions in binary form must reproduce the above copyright 21 * notice, this list of conditions and the following disclaimer in 22 * the documentation and/or other materials provided with the 23 * distribution. 24 * 3. Neither the name of Agui nor the names of its contributors may 25 * be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 34 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 35 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 37 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 38 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 */ 40 41#include <Agui/Agui.hpp> 42#include <Agui/Backends/Allegro5/Allegro5.hpp> 43 44#include <Agui/Widgets/Button/Button.hpp> 45#include <Agui/Widgets/CheckBox/CheckBox.hpp> 46#include <Agui/Widgets/DropDown/DropDown.hpp> 47#include <Agui/Widgets/TextField/TextField.hpp> 48#include <Agui/Widgets/Frame/Frame.hpp> 49#include <Agui/Widgets/RadioButton/RadioButton.hpp> 50#include <Agui/Widgets/RadioButton/RadioButtonGroup.hpp> 51#include <Agui/Widgets/Slider/Slider.hpp> 52#include <Agui/Widgets/TextBox/ExtendedTextBox.hpp> 53#include <Agui/Widgets/Tab/TabbedPane.hpp> 54#include <Agui/Widgets/ListBox/ListBox.hpp> 55#include <Agui/Widgets/ScrollPane/ScrollPane.hpp> 56#include <Agui/FlowLayout.hpp> 57 58#include <allegro5/allegro_native_dialog.h> 59#include <stdlib.h> 60#include <vector> 61#include <ctime> 62#include <iostream> 63 64 65#define FRAME_RATE 60 66 67//Globals 68ALLEGRO_DISPLAY *display = NULL; 69ALLEGRO_TIMER *timer = NULL; 70ALLEGRO_EVENT event; 71ALLEGRO_EVENT_QUEUE *queue = NULL; 72bool done = false; 73agui::Gui *gui = NULL; 74agui::Allegro5Input* inputHandler = NULL; 75agui::Allegro5Graphics* graphicsHandler = NULL; 76 77agui::Font *defaultFont = NULL; 78 79 80class SimpleActionListener : public agui::ActionListener 81{ 82public: 83 virtual void actionPerformed(const agui::ActionEvent &evt) 84 { 85 agui::Slider* slider = dynamic_cast<agui::Slider*>(evt.getSource()); 86 if(slider) 87 { 88 slider->setBackColor(agui::Color(slider->getValue(),slider->getValue(),slider->getValue())); 89 return; 90 91 } 92 al_show_native_message_box(al_get_current_display(), 93 "Agui Action Listener", 94 "", 95 "An Action Event has occured!", 96 NULL,NULL); 97 } 98}; 99 100 101 102class WidgetCreator { 103private: 104 SimpleActionListener simpleAL; 105 agui::FlowLayout flow; 106 agui::Button button; 107 agui::CheckBox checkBox; 108 agui::DropDown dropDown; 109 agui::TextField textField; 110 agui::Frame frame; 111 agui::Gui* mGui; 112 agui::RadioButton rButton[3]; 113 agui::RadioButtonGroup rGroup; 114 agui::Slider slider; 115 agui::ExtendedTextBox exTextBox; 116 agui::TabbedPane tabbedPane; 117 agui::Tab tab[3]; 118 agui::ListBox listBox; 119 agui::ScrollPane scrollPane; 120 agui::Button scrollButtons[15]; 121 122public: 123 WidgetCreator(agui::Gui *guiInstance) 124{ 125 mGui = guiInstance; 126 mGui->add(&flow); 127 flow.add(&button); 128 button.setSize(80,40); 129 button.setText("Push Me"); 130 button.addActionListener(&simpleAL); 131 132 flow.add(&checkBox); 133 checkBox.setAutosizing(true); 134 checkBox.setText("Show me a message box"); 135 checkBox.setCheckBoxAlignment(agui::ALIGN_MIDDLE_LEFT); 136 checkBox.addActionListener(&simpleAL); 137 138 flow.add(&dropDown); 139 dropDown.setText("Select Item"); 140 dropDown.setSize(120,30); 141 dropDown.addItem("Apples"); 142 dropDown.addItem("Oranges"); 143 dropDown.addItem("Grapes"); 144 dropDown.addItem("Peaches"); 145 dropDown.addActionListener(&simpleAL); 146 147 flow.add(&textField); 148 textField.setText("Press Enter!"); 149 textField.resizeToContents(); 150 textField.addActionListener(&simpleAL); 151 152 gui->add(&frame); 153 frame.setSize(220,120); 154 frame.setLocation(60,60); 155 frame.setText("Example Frame"); 156 std::stringstream ss; 157 for(int i = 0; i < 3; ++i) 158 { 159 ss.str(""); 160 ss.clear(); 161 ss << "Sample Radio Button "; 162 ss << i; 163 164 rGroup.add(&rButton[i]); 165 rButton[i].setAutosizing(true); 166 rButton[i].setText(ss.str()); 167 frame.add(&rButton[i]); 168 rButton[i].setLocation(0,30 * i); 169 rButton[i].addActionListener(&simpleAL); 170 } 171 172 flow.add(&slider); 173 slider.setSize(100,36); 174 slider.setMaxValue(255); 175 slider.setMarkerSize(agui::Dimension(10,30)); 176 slider.addActionListener(&simpleAL); 177 178 exTextBox.setWordWrap(true); 179 exTextBox.setText("Welcome \n"); 180 exTextBox.setCurrentColor(agui::Color(255,0,0)); 181 exTextBox.appendText("WARNING!!!\n\n"); 182 exTextBox.setCurrentColor(agui::Color(255,0,255)); 183 exTextBox.appendText("Viewing text in magenta is not recommended\n\n"); 184 exTextBox.setCurrentColor(agui::Color(100,0,200)); 185 exTextBox.appendText("Copyright (c) 2011 Joshua Larouche \n \ 186\ 187License: (BSD) \n \ 188Redistribution and use in source and binary forms, with or without \ 189modification, are permitted provided that the following conditions \ 190are met: \n \ 1911. Redistributions of source code must retain the above copyright \ 192notice, this list of conditions and the following disclaimer. \n \ 1932. Redistributions in binary form must reproduce the above copyright \ 194notice, this list of conditions and the following disclaimer in \ 195the documentation and/or other materials provided with the distribution. \n \ 1963. Neither the name of Agui nor the names of its contributors may \ 197be used to endorse or promote products derived from this software \ 198without specific prior written permission. \n\n \ 199"); 200 201 exTextBox.setCurrentColor(agui::Color(255,128,0)); 202exTextBox.appendText("THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \ 203\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT \ 204LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR \ 205A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT \ 206OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, \ 207SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED \ 208TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR \ 209PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF \ 210LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING \ 211NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS \ 212SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ 213"); 214 exTextBox.setSelection(84,100); 215 exTextBox.setSelectionColor(agui::Color(255,0,0)); 216 exTextBox.setSelection(0,0); 217 exTextBox.setTextAlignment(agui::ALIGN_CENTER); 218 exTextBox.setSize(600,300); 219 exTextBox.positionCaret(0,0); 220 221 tabbedPane.setSize(agui::Dimension(300,400)); 222 flow.add(&tabbedPane); 223 tab[0].setText("Text Box"); 224 tab[1].setText("List Box"); 225 tab[2].setText("Scroll Pane"); 226 tabbedPane.addTab(&tab[0],&exTextBox); 227 tabbedPane.addTab(&tab[1],&listBox); 228 tabbedPane.addTab(&tab[2],&scrollPane); 229 230 tabbedPane.setResizeTabContent(true); 231 232 for(int i = 0; i < 250; ++i) 233 { 234 ss.str(""); 235 ss.clear(); 236 ss << "Item "; 237 ss << i; 238 239 listBox.addItem(ss.str()); 240 } 241 242 listBox.setMultiselectExtended(true); 243 244 int count = 0; 245 for(int i = 0; i < 3; ++i) 246 { 247 for(int j = 0; j < 5; ++j) 248 { 249 250 ss.str(""); 251 ss.clear(); 252 ss << "Scroll Button "; 253 ss << i + 1; 254 ss << " , "; 255 ss << j + 1; 256 257 scrollPane.add(&scrollButtons[count]); 258 scrollButtons[count].setSize(200,100); 259 scrollButtons[count].setLocation(210 * i,110 * j); 260 scrollButtons[count].setText(ss.str()); 261 262 count++; 263 } 264 } 265} 266}; 267 268WidgetCreator* creator; 269 270bool initializeAllegro() { 271 //Initialize Allegro 272 if(!al_init()) 273 { 274 return false; 275 } 276 277 if(!al_init_image_addon()) 278 { 279 return false; 280 } 281 282 al_init_font_addon(); 283 284 if(!al_init_ttf_addon()) 285 { 286 return false; 287 } 288 289 if(!al_init_primitives_addon()) 290 { 291 return false; 292 } 293 if(!al_install_mouse()) 294 { 295 return false; 296 } 297 if(!al_install_keyboard()) 298 { 299 return false; 300 } 301 302 // Start a timer to regulate speed 303 timer = al_create_timer(1.0/FRAME_RATE); 304 al_start_timer(timer); 305 306 //show screen 307 308 al_set_new_display_flags(ALLEGRO_RESIZABLE); 309 310 display = al_create_display(640,480); 311 312 if(!display) 313 { 314 315 return false; 316 } 317 //show the mouse 318 al_show_mouse_cursor(display); 319 320 al_set_new_bitmap_flags(ALLEGRO_VIDEO_BITMAP); 321 322 //Window Title 323 al_set_window_title(display,"Agui - Example"); 324 325 queue = al_create_event_queue(); 326 327 return true; 328} 329 330void initializeAgui() 331{ 332 333 //Set the image loader 334 agui::Image::setImageLoader(new agui::Allegro5ImageLoader); 335 336 //Set the font loader 337 agui::Font::setFontLoader(new agui::Allegro5FontLoader); 338 339 //Instance the input handler 340 inputHandler = new agui::Allegro5Input(); 341 342 //Instance the graphics handler 343 graphicsHandler = new agui::Allegro5Graphics(); 344 345 //Allegro does not automatically premultiply alpha so let Agui do it 346 agui::Color::setPremultiplyAlpha(true); 347 348 //Instance the gui 349 gui = new agui::Gui(); 350 351 //Set the input handler 352 gui->setInput(inputHandler); 353 354 //Set the graphics handler 355 gui->setGraphics(graphicsHandler); 356 357 defaultFont = agui::Font::load("data/DejaVuSans.ttf",16); 358 359 //Setting a global font is required and failure to do so will crash. 360 agui::Widget::setGlobalFont(defaultFont); 361 362 363} 364 365void addWidgets() 366{ 367 creator = new WidgetCreator(gui); 368} 369void cleanUp() 370{ 371 gui->getTop()->clear(); 372 delete creator; 373 creator = NULL; 374 delete gui; 375 gui = NULL; 376 delete inputHandler; 377 delete graphicsHandler; 378 inputHandler = NULL; 379 graphicsHandler = NULL; 380 381 delete defaultFont; 382 defaultFont = NULL; 383} 384 void render() 385 { 386 al_clear_to_color(al_map_rgb(240,240,240)); 387 388 //render the widgets 389 gui->render(); 390 391 al_flip_display(); 392 393 } 394 395int main(int argc, char *argv[]) 396 397{ 398 if (!initializeAllegro()) 399 { 400 return 1; 401 } 402 403 initializeAgui(); 404 addWidgets(); 405 bool needRedraw = true; 406 // Start the event queue to handle keyboard input, mouse and our timer 407 408 al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)al_get_keyboard_event_source()); 409 al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)al_get_mouse_event_source()); 410 al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)timer); 411 al_register_event_source(queue, (ALLEGRO_EVENT_SOURCE*)display); 412 413 while(!done) { 414 415 // Block until an event enters the queue 416 al_wait_for_event(queue, &event); 417 418 //Let Agui process the event 419 inputHandler->processEvent(event); 420 421 //Handle rendering and logic 422 if (needRedraw && al_event_queue_is_empty(queue)) { 423 424 gui->logic(); 425 render(); 426 427 needRedraw = false; 428 } 429 430 431 switch(event.type) { 432 433 case ALLEGRO_EVENT_TIMER: 434 if(event.timer.source == timer) 435 { 436 437 needRedraw = true; 438 } 439 440 break; 441 case ALLEGRO_EVENT_DISPLAY_RESIZE: 442 443 al_acknowledge_resize(event.display.source); 444 445 //Resize Agui 446 gui->resizeToDisplay(); 447 448 break; 449 case ALLEGRO_EVENT_DISPLAY_SWITCH_IN: 450 //Resize Agui 451 gui->resizeToDisplay(); 452 break; 453 case ALLEGRO_EVENT_DISPLAY_CLOSE: 454 return 0; 455 break; 456 } 457 } 458 459 cleanUp(); 460 461 return 0; 462}

I am sure more questions will come up as the discussion starts. Thanks in advance!



1. Guis are pretty complex. When I made Agui, I had only been programming for 1 year and only 6 months with C++. But, they are very useful. While the old collision-box method will solve your problem, you'll eventually need more.

2. I would say Agui is a good library for GUIs. But it is intended for small to large projects, and has a little bit of a learning curve. In addition, like I say to everyone, Agui is intended as a generic GUI solution that should be fit to your needs. So, for example, if you dont like how buttons look, you are responsible for making them look pretty. For an example on a pretty GUI, check out the calculators demo I made to showcase this.

In addition, there are a few principals to understand for GUIs to be useful. One of these is understanding that Widgets (ex, buttons) should be thought of as notifications systems. So, you'll need to understand that, when you click the button, Agui will dispatch an Action trigger, hence the action listeners. You'll want to familiarize yourself with listeners.

I don't want to overwhelm you with information. For now, let's try to get the example working and get a button in your project!

3. I suspect the problem you might be getting with the example is that the font absolutely needs to be in your execution directory. So, try to stick the ttf file that comes with Agui into the directory of your exe and run it straight from the folder. In Visual Studio, if you Start Debugging (F5) then the font needs to be in the solution folder (same folder as your cpp's usually).

Let me know what problems you encounter and I'll see what I can do to help!

Oh also, please make sure you use Agui 0.2.0


Well, I took some more time to play with it and I haven't found the solution to the example, however I found out that it seems to run fine in release mode. I am running Visual Studios 2010 and when I run it in debug mode it gives me a debug assertion failure because "vector iteration + off sets out of range". Regardless I don't need to worry about it because now I can get it to run through release and start studying the code.

Thanks for the other information you gave, it was very helpful. I do think I will try and learn agui because I will eventually need something to do more complex things like you said and it would be a good think to learn for future projects as well. I'll study up on this and see if I find any questions. Thanks again for releasing this for others to use, it seems very well done.

EDIT: I lied, when I scroll down to the bottom of your terms and copyright information the release version breaks. Not sure why, I should be using the 0.2.0 I did it through SVN (which was an experience) because I saw you posted how to install agui for someone else on another thread (I did look for help before I posted)


Could you post your msvc solution and binary? If I get some time tomorrow I can try to see what might be going wrong. The example used to have trouble in vs 2010, but I was sure that had been resolved.

Mark Oates

If you want to work on the shooter, then yes to:

Should I just draw a box to the screen and use collision-like detection to find out if the area has been clicked or being hovered over?

If you want to sidetrack working on the shooter, and are OK with taking time to learn more about programming in other areas, then go ahead and think about GUIs and GUI libs.

(On a side note, it's a shame that we don't have a dumb-simple GUI that plops into Allegro somewhere... or maybe we do?)


You just wanted the things in my project folder?

And I am ok stepping away from my project to learn because I am doing my project in order to learn.

As a side note, I started playing around with the example (changing code, adding new things based on documentation) and I found out that all the locations of the buttons seem to depend on the layout that you have going. I was wondering what the best one to use for a single Colosseum of buttons in the center of the screen would be, If I used a grid I would have to make a bunch of empty widgets it seems? Also is there a way to make the buttons not fill up the entire grid square? I tried set size but that didn't seem to work.



Yes, send me your project folder.

To do what you're asking, I think the FlowLayout might be what you want.

setMaxOnRow to 1.
setHorizontallyCentered to true

But, there's no setVerticallyCentered.

Really, this should be solved with a BoxLayout, but, I never made one.

You will have to manually solve for the FlowLayout's Margins to make it vertically centered.

The other option is to do the above, but,make a GridLayout with 3 rows. Put the FlowLayout in the second row and shove an empty widget for the first row.

This way, your menu always takes 1/3 of the screen without you having to calculate it.

The Layout system was added in as a last minute feature and unfortunately I have only made it as flexible as I needed. But, a BoxLayout would be a nice future addon. Either that or add setVerticallyCentered to FlowLayout.

Note, you can always directly add buttons to the gui objects itself, and manually set the position of the button with button->setLocation().

The layouts are for games that are dynamically resizable and do not used a fixed resolution.


To have them not take up the whole grid square:

Change the horizontal and vertical spacing of the grid
Change the button's margins.


Thanks for the info I think I am getting the hang of this. Also, I tried zipping the folder and putting it in this post but the upload keeps failing. Want me to send an email to ya? Or do you want to just try it yourself?


You could upload it to a place like mediafire



It turned out to be a bug. When I added color support to the extended textbox, I forgot to add code that would add the colors to the color array when calling the setText function. This would leave it in an inconsistent state and cause an array out of bounds problem.

I just fixed it in SVN. Recompile from SVN sources and let me know how it goes :)


I created a simple GUI in C which checks the mouse position against where the buttons are, it's really quite simple and for what I am doing, all I need.

This is my level editor for a pacman style game I am working on...

I just check the mouse position, if it is over one of the buttons, it changes the button graphic to one for when it is hovered over. If it is over it and the mouse button is clicked I have a button for when it is clicked, so they light up as it moves over them etc... it looks quite nice and works well. IN the events I simply flag the button that was click on or hovered over then react to that later on in my code.

It's definitely not GUI library coding! But it's all one needs for a video game.


That's a really nice looking editor. What do you use to make your graphics? I'm using MS paint atm and it doesn't look great.


GIMP is nice on Linux, but there is even a Windows version of it, which is OK.

There's also Inkscape for vector graphics.


I use a variety. For my game characters and some of my pills I actually rendered them with TruSpace 6. For my line graphics I made them by hand mostly with Tile Studio, although I could have rendered them as well, I just wasn't happy with the results and found it easier to just do them by hand. ;) I also done much of my background tiles with Tile Studio. I used Photoshop for my buttons, although I have GIMP which would work just about as well (Edit: I also like Inkscape).

Here are examples of how I did my two styles of buttons.
The top graphic is what is displayed normally. The second one down (middle) is when the mouse hovers over it (very simple to detect), then the third is when the mouse button is clicked while over the button.

I'm not much of a C++ programmer yet, this project is in pure C, but it works well for what I need. I use the following struct for the buttons...

typedef struct BUTTON {
   int x;                  // upper left corner horizontal position
   int y;                  // upper left corner vertical position
   int w;                  // width of button
   int h;                  // height of button
   int state;              // Button state: 0 up, 1 over, 2 down
   int old_state;          // store the old state to see if it changed
   bool is_switch;         // is this a switch (true) or button (false)?
   ALLEGRO_BITMAP *bmp;    // main bitmap with button images
   ALLEGRO_BITMAP *up;     // subbitmap for button up graphic (when it isn't active)
   ALLEGRO_BITMAP *over;   // subbitmap for button that is being hovered over by mouse
   ALLEGRO_BITMAP *down;   // subbitmap for button after it has been clicked

And these are the functions I use to handle them... they're fairly self explanatory. I can post more code if you wish. It's probably not the best way to do things but it works and I am fairly certain this could easily be converted to a C++ class. I may try that actually some time.

bool new_button(BUTTON *b, bool is_switch, const char *file, int x, int y);
bool check_button(BUTTON *b, ALLEGRO_MOUSE_STATE *mouse);
void draw_button(BUTTON *b);
void destroy_button(BUTTON *b);

EDIT: If you're curious, you can download the editor here. The game isn't finished yet, I always create the editor first before I make the game.
Note: Turn the mouse wheel to change the background tile.
To draw lines you simply click on the map and start "drawing" the lines, no need to place individual tiles. Left mouse draws, right mouse erases.

I have also thought about using Allegro 5 exclusively to actually draw the buttons rather than load them in. It's got some nice functions for drawing that could do the job quite nicely and probably make for a more portable GUI.


That's awesome thank you so much! I love it


Once you run the editor it creates an INI file, if you change "fullscreen=0" to "fullscreen=1" you can use it in fullscreen mode. Thanks to Matthew Leverton, it uses a function he created for stretching the screen to match your desktop resolution. Something to keep in mind for your game as well.

Hmmm... the game and the editor use the same INI file, I should probably change that. ;)

Thread #613096. Printed from