![]() |
|
This thread is locked; no one can reply to it.
![]() ![]() |
1
2
|
[A5] Object Oriented Programming -Confusing. |
Matias Persson
Member #15,093
May 2013
|
Hello again.. This is my code, so you can take a look at it: As you can see the code is very ugly and not even understandable, if not for all the comments. But anyways, here's my question: So what I really need help with is; |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
OOP will help you organize your code, and make autonomous objects. Ex. class Button { int x,y,w,h; ALLEGRO_BITMAP* img; bool IsMouseOver(int msx,int msy); void Draw(); }; Even something as simple as that will help you shorten your code. And it will help get rid of hard coded values, which are hard to modify. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
beoran
Member #12,636
March 2011
|
Or, you could start by learning how to walk before you try to run and learn how to use functions to structure your program. Normally you'd have a function to initializing everything, one for cleaning up on closing down, and one for the main loop. Then the main loop function calls one function for drawing and one for input handling, and one for AI. And so on as is needed. I think OOP is a bit overrated. I wouldn't study it before learning how to use all the basics of the C language. |
Chris Katko
Member #1,881
January 2002
![]() |
Matias Persson said: I guess you are all tired of my questions, Not at all. Object-oriented is just a way of organizing things, of which there are many ways. Objects are collections of data, and that data can only be accessed by that object's methods. That way, if you know you wrote the set and get functions correctly (to plan for unsafe/erroneous inputs), you know for a fact that that object will never have corrupted data inside it. Basically, it's just a standard way of structuring things to keep your data from being accessed in ways you never intended. Encapsulation. Quote: As you can see the code is very ugly and not even understandable, if not for all the comments. Not really. But you're incorrectly using elseif, instead of a switch statement or just a bunch of if statements. Look into those. You also want your code in modular functions. That means you put all your statements initializing allegro in say, a function called initialize_game(). You can also do one for handle_events(), game_logic(), and draw_a_frame(). -----sig: |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Something else OOP will do for you is get rid of globals. Both beoran and Katko are suggesting a design that will necessitate global data or dependency injection (passing everything around in a giant clusterfsck). What is really needed is a way for you to organize your data into relevant objects. In a class, all member objects are global to class methods. But they are only as accessible as you make them (private , protected , public). play_game() becomes Game::Play(). My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Thomas Fjellstrom
Member #476
June 2000
![]() |
Edgar Reynaldo said: or dependency injection (passing everything around in a giant clusterfsck). Those aren't really related. you can still group data into structs, and not be OO. But Dependency Injection is usually the way to go. -- |
Matias Persson
Member #15,093
May 2013
|
Wow, thank you for all your answers. Anyways, I am having troubles for example when creating a function to initialize everything. I will look into ways to organize my program better; Functions, Objects etc.. |
beoran
Member #12,636
March 2011
|
Edgar, how does OOP not lead to dependency injection? The data must go somewhere no matter if it's on the stack heap or in the bss. In this aspect classes are equivalent to using structs + functions. And "global" data is fine if you hide it behind a proper functional interface. Much like Allegro does. |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
OOP encourages you not to use global data and dependency injection, but rather to group your data in the most effective ways. Yes there will still be data getting passed around, because not every object can know everything it will ever need (ie. not all the data will / should be members of the class). My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
beoran
Member #12,636
March 2011
|
Well, it's true that it's better to organize data thematically, but you can do that perfectly with C structs. And with OOP and no global data, you can't avoid having a "god object" that holds the references to all long-lived data that exists in your program either directly or recursively, or a list of such objects in your main() function. In contrast, if you let your .c files hang on to their own long lived "global" data, but put a clean function API in front of it, you get much better modularity than with such a "god object" data hierarchy. Just think of, say, OpenGL. All you get are integer handles, all the global OpenGL state is in the GPU, safely abstracted away behind a function based interface. Also, C is excellent for encapsulation with integer handles, or if you use incomplete struct declarations. In the header player.h header you put typedef struct Player_ Player; and all getter and setter functions, like, say `Player * player_new(int id); void player_free(Player *); VEC2D player_get_position(Player *);`, etc. You only define the internals then in the player.c file. Player new might even return a pointer from a static array for extra speed over malloc(). Or why not even typedef int Player;, for even better encapsulation. So call me a heretic. OOP isn't a silver bullet. Before the hype, the name of the game was simply "modularity", and that is by far the more important concept. |
Chris Katko
Member #1,881
January 2002
![]() |
One more note, which will thoroughly confuse you, is that there are tons of design patterns--that is, ways to frame data. And they all have their advantages and disadvantages. But don't worry, it'll sink in over time. -----sig: |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
/* Another major feature of C (plus plus) is inheritance and polymorphism, which is obnoxious to implement in C. I hate writing my own vtable and having to swap out members based on configuration. And why oh why would I ever want to write my own vector implementation because I have to - it's C. It was a breeze to implement N-Dimensional Arrays of any type using templates and recursion. I feel like I am tying my ankle to my butt when I code in C. Having to hop around on one foot when I have two perfectly good feet. It is sad though, the state of MinGW. The C++ standard is still not implemented fully. I can't even use std::thread without using MinGW-w64. I can see why low level library implementors would use C though, for its portability. But for higher level tasks I think C++ is the way to go, and since it interfaces with C just fine you don't have to change hardly any of your code to do it. If Java wasn't entirely contained in headers and slowed down by interpreting code and if it had a better gui and layout library, I would go even further and say to use Java instead even. To get back on topic, what have you tried so far, and what are your results? How is your understanding of classes / structs? Do you know array syntax yet and see how it can help you? Basic C array handling with an example button class : 1//*/
2
3#include <stdlib.h>
4#include <assert.h>
5#include <stdio.h>
6
7#include "allegro5/allegro.h"
8#include "allegro5/allegro_primitives.h"
9#include "allegro5/allegro_font.h"
10#include "allegro5/allegro_ttf.h"
11
12
13typedef struct CBUTTON {
14 int x,y,w,h;
15} CBUTTON;
16
17
18
19void alloc_cbutton_array(CBUTTON** cbuttonp , unsigned int size);
20void realloc_cbutton_array(CBUTTON** cbuttonp , unsigned int size);
21void free_cbutton_array(CBUTTON** cbutton);
22
23void init_cbutton_array(CBUTTON* cbuttonp , unsigned int size);
24void init_cbutton(CBUTTON* cbutton , int x , int y , int w , int h);
25void draw_cbutton(CBUTTON* cbutton , ALLEGRO_COLOR c , int i , ALLEGRO_FONT* font);
26
27int is_cbutton_clicked(CBUTTON* cbutton , int msx , int msy);// returns 1 (true) for yes, 0 (false) for no
28
29
30void alloc_cbutton_array(CBUTTON** cbuttonp , unsigned int size) {
31
32 free_cbutton_array(cbuttonp);
33 *cbuttonp = (CBUTTON*)calloc(size , sizeof(CBUTTON));
34
35}
36void realloc_cbutton_array(CBUTTON** cbuttonp , unsigned int size) {
37
38 realloc((void*)*cbuttonp , size*sizeof(CBUTTON));
39
40}
41void free_cbutton_array(CBUTTON** cbuttonp) {
42
43 CBUTTON* cbutton = 0;
44
45 assert(cbuttonp);
46 cbutton = *cbuttonp;
47 free(cbutton);
48
49 *cbuttonp = 0;
50
51}
52
53
54
55void init_cbutton_array(CBUTTON* cbuttonp , unsigned int size) {
56 unsigned int i = 0;
57 for (i = 0 ; i < size ; ++i) {
58 init_cbutton(&(cbuttonp[i]),0,0,1,1);
59 }
60}
61
62
63
64void init_cbutton(CBUTTON* cbutton , int x , int y , int w , int h) {
65 cbutton->x = x;
66 cbutton->y = y;
67 cbutton->w = w;
68 cbutton->h = h;
69}
70
71
72
73void draw_cbutton(CBUTTON* cbutton , ALLEGRO_COLOR c , int i , ALLEGRO_FONT* font) {
74 al_draw_filled_rectangle(cbutton->x , cbutton->y , cbutton->x + cbutton->w , cbutton->y + cbutton->h , c);
75 al_draw_rectangle(cbutton->x , cbutton->y , cbutton->x + cbutton->w , cbutton->y + cbutton->h , al_map_rgb(255,255,255) , 2.0);
76//void al_draw_textf(const ALLEGRO_FONT *font, ALLEGRO_COLOR color,
77// float x, float y, int flags,
78// const char *format, ...)
79 al_draw_textf(font , al_map_rgb(255,255,255) , cbutton->x + cbutton->w/2.0f - al_get_font_line_height(font)/2.0f , cbutton->y + cbutton->h/2.0f , ALLEGRO_ALIGN_CENTRE , "Button #%i" , i);
80}
81
82
83
84int is_cbutton_clicked(CBUTTON* cbutton , int msx , int msy) {
85 return !( cbutton->x > msx ||
86 cbutton->y > msy ||
87 (cbutton->x + cbutton->w - 1) < msx ||
88 (cbutton->y + cbutton->h - 1) < msy);
89}
90
91
92
93
94
95int main(int argc , char** argv) {
96 CBUTTON* cbuttonarray = 0;
97 const unsigned int size1 = 10;
98 const unsigned int size2 = 11;
99 int size = size1;
100 const unsigned int SCREEN_WIDTH = 800;
101 const unsigned int SCREEN_HEIGHT = 600;
102 const float TIMER_RATE = 1.0/60.0f;
103 int quit = 0;
104 int redraw = 1;
105 int i = 0;
106
107 ALLEGRO_DISPLAY* display = 0;
108 ALLEGRO_EVENT_QUEUE* queue = 0;
109 ALLEGRO_TIMER* timer = 0;
110 ALLEGRO_FONT* font = 0;
111
112
113 alloc_cbutton_array(&cbuttonarray , size);
114
115 init_cbutton_array(cbuttonarray , size);
116
117 for (i = 0 ; i < size ; ++i) {
118 init_cbutton(&cbuttonarray[i] , i*50 , i*50 , 300 , 50);
119 }
120
121 size = size2;
122 realloc_cbutton_array(&cbuttonarray , size);
123
124 init_cbutton(&cbuttonarray[size - 1] , 0 , 0 , SCREEN_WIDTH , SCREEN_HEIGHT);// screen sized button
125
126 /// INIT ALLEGRO
127
128 if (!al_init()) {return 1;}
129
130 if (!al_install_keyboard()) {return 1;}
131
132 if (!al_install_mouse()) {return 2;}
133
134 if (!al_init_primitives_addon()) {return 3;}
135
136 if (!al_init_font_addon()) {return 3;}
137
138 if (!al_init_ttf_addon()) {return 3;}
139
140 al_set_new_display_flags(ALLEGRO_WINDOWED);
141 display = al_create_display(SCREEN_WIDTH , SCREEN_HEIGHT);
142 if (!display) {return 4;}
143
144 timer = al_create_timer(TIMER_RATE);
145 if (!timer) {return 5;}
146
147 queue = al_create_event_queue();
148 if (!queue) {return 6;}
149
150 al_register_event_source(queue , al_get_display_event_source(display));
151 al_register_event_source(queue , al_get_keyboard_event_source());
152 al_register_event_source(queue , al_get_mouse_event_source());
153 al_register_event_source(queue , al_get_timer_event_source(timer));
154
155 font = al_load_ttf_font("verdana.ttf" , -20 , 0);
156
157 /// main loop
158
159 al_start_timer(timer);
160
161 do {
162 if (redraw) {
163 for (i = size - 1 ; i >= 0 ; --i) {
164 draw_cbutton(&cbuttonarray[i] , al_map_rgb((i*255)/size , (i*255)/size , (i*255)/size) , i , font);
165 }
166 al_flip_display();
167 redraw = false;
168 }
169 do {
170 ALLEGRO_EVENT ev;
171 al_wait_for_event(queue , &ev);
172
173
174 if (ev.type == ALLEGRO_EVENT_KEY_DOWN && ev.keyboard.keycode == ALLEGRO_KEY_ESCAPE) {quit = 1;}
175 if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) {quit = 1;}
176 if (ev.type == ALLEGRO_EVENT_TIMER) {
177 redraw = true;
178 }
179 if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {
180 for (i = 0 ; i < size ; ++i) {
181 if (is_cbutton_clicked(&cbuttonarray[i] , ev.mouse.x , ev.mouse.y)) {
182 printf("Button #%i clicked.\n" , i + 1);
183 }
184 }
185 }
186 if (ev.type == ALLEGRO_EVENT_DISPLAY_FOUND) {redraw = 1;}
187
188 } while (!al_is_event_queue_empty(queue));
189 } while (!quit);
190
191
192 /// FREE RESOURCES
193
194 free_cbutton_array(&cbuttonarray);
195
196 return 0;
197}
198
199
200/*
//*/ And since I provided an example in C I think Beoran should have to provide an example in C++. Feel my pain bro. If you have any questions on what is posted here, ask away. Do your best to understand the code presented here though. Attached 7zip file of source and exe , 7-zip download site {"name":"608893","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/6\/d6e233e7ca59d3aeaa400a2ca71a9aaa.png","w":1280,"h":800,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/d\/6\/d6e233e7ca59d3aeaa400a2ca71a9aaa"} My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Neil Roy
Member #2,229
April 2002
![]() |
Note: rename "libzlib.dll" to "libz.dll" in Edgar's attached example to run it. Nice example of some fine C programming. The only thing that bugs me about it is if any of the initialization fails, and the program exits, you'll have a memory leak due to cbuttonarray not being freed. But I understand this is just an example. --- |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
I'm too lazy to do proper deallocation in C these days. I figure if something went wrong enough to quit the program you have bigger problems than a memory leak that will be cleaned up by the OS anyway. </lame_excuse> For safety it should have been this : Edgar Reynaldo said: But it looks like 'free' accepts a NULL pointer so it doesn't matter. My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Arthur Kalliokoski
Second in Command
February 2005
![]() |
NiteHackr said: The only thing that bugs me about it is if any of the initialization fails, and the program exits, you'll have a memory leak due to cbuttonarray not being freed. I thought we went over this a few days ago? Any modern OS will release memory when the program exits. It's when you're continually leaking memory, for instance in an image viewer, where the user may click on scores of pictures before exiting the program, that the leak becomes a problem. They all watch too much MSNBC... they get ideas. |
Neil Roy
Member #2,229
April 2002
![]() |
Arthur Kalliokoski said: I thought we went over this a few days ago? Any modern OS will release memory when the program exits. You're probably right. We didn't go over this, maybe someone else. But I like to handle that anyhow, to be safe. "Never assume, it makes an ass out of you and me." Edit: Just read the thread on "Memory Leak?", very interesting. I'll keep freeing it anyhow, but.. --- |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Minor fix to draw button text properly centered : Edgar Reynaldo said:
void draw_cbutton(CBUTTON* cbutton , ALLEGRO_COLOR c , int i , ALLEGRO_FONT* font) { al_draw_filled_rectangle(cbutton->x , cbutton->y , cbutton->x + cbutton->w , cbutton->y + cbutton->h , c); al_draw_rectangle(cbutton->x , cbutton->y , cbutton->x + cbutton->w , cbutton->y + cbutton->h , al_map_rgb(255,255,255) , 2.0); //void al_draw_textf(const ALLEGRO_FONT *font, ALLEGRO_COLOR color, // float x, float y, int flags, // const char *format, ...)
My Website! | EAGLE GUI Library Demos | My Deviant Art Gallery | Spiraloid Preview | A4 FontMaker | Skyline! (Missile Defense) Eagle and Allegro 5 binaries | Older Allegro 4 and 5 binaries | Allegro 5 compile guide |
Chris Katko
Member #1,881
January 2002
![]() |
Arthur Kalliokoski said: I thought we went over this a few days ago? I thought you explained that you had an error that took up memory even after your program exited, and only running a possibly obscure Linux command would the kernel process and free it. -----sig: |
Arthur Kalliokoski
Second in Command
February 2005
![]() |
Chris Katko said: I thought you explained that you had an error that took up memory even after your program exited, and only running a possibly obscure Linux command would the kernel process and free it. Shared memory. Shared memory. Repeat until you grok. They all watch too much MSNBC... they get ideas. |
beoran
Member #12,636
March 2011
|
Edgar, we'll probably have to agree to disagree there. Before I also used C++ a lot but I got burned repeatedly and suffered greatly because of C++ until finally I realized plain C + a nice scripting language like mruby (or lua or python if you prefer that) is a much better solution for me. Sorry for not taking you up on your offer for the buttons, I already implemented the Allegro haptics driver on windows for directx in C++ so I already did my part. Ugh! I do agree that C needs more libraries for data structures and algorithms but I'm slowly working on solving that problem too. I'm not in favor of templates since they exchange speed for space (how much code is generated behind your back?), but with a good x-macro you can get the same effects. And I love explicit vtables like the ones Allegro uses, they give me full control, and allowed me to write a very simple wrapper driver for the windows joystick around the directx and xinput driver. |
bamccaig
Member #7,536
July 2006
![]() |
Edgar, I think you're sort of missing the point with dependency injection. A large part of the advantage to true OO is polymorphism. That's probably the most useful feature of it. Inheritance can be useful, but is often abused. When you have truly modular, decoupled code you end up with things like (contrived example): 1/**
2 * Not necessarily bug-free, definitely contrived example...
3 */
4void PaymentProcessor::process(
5 const IDatabaseManager & db,
6 const IPaymentServiceProxy & psp,
7 const IOrder & order)
8{
9 const IPayment & payment = order.payment();
10 const IPaymentMethod & method = order.payment_method();
11 const IUserDetails & user = order.user_details();
12
13 ITransaction & txn = db.begin_transaction();
14
15 try
16 {
17 IChargeHandle charge = psp.charge(user, payment, method);
18
19 db.update_order_status(order, ORDER_STATUS_PAYED);
20
21 psp.confirm(charge);
22
23 db.commit(txn);
24 }
25 catch(std::exception & ex)
26 {
27 WHATEVER(ex);
28
29 db.rollback(txn);
30
31 throw;
32 }
33}
That is all handled through a defined set of interfaces which can be implemented however you want, as long as the API semantics defined are obeyed properly. This makes code extremely easy to test. Instead of charging your credit card every time you run the test suite, the necessary layers just pretend to contact the credit card company and really just flag enough state to fake it. You can take advantage of that for various things like testing, or for distributing the load of a complex project among many people, and allowing people to work on their isolated segments of the application while the unimplemented stuff just pretends to exist. If something isn't done yet create an acceptable mock for it and use that. In that case, you'd also want some kind of factory object to generate these instances. pp.process( factory.create_db(), factory.create_payment_service_proxy(), order); During development or testing the factory might generate a mock object for the database manager or payment service proxy, but in production it will create the real thing, initialized with real data and running real code. This makes it trivial to completely change the behavior of the program from a single place instead of having to go and change thousands of complex, unpredictably written statements (the latter of which is far more error prone and depending on how you do it, far more time consuming). Edgar Reynaldo said: For safety it should have been this: *snip* But it looks like 'free' accepts a NULL pointer so it doesn't matter.
In other words, no, it shouldn't have been that at all. -- acc.js | al4anim - Allegro 4 Animation library | Allegro 5 VS/NuGet Guide | Allegro.cc Mockup | Allegro.cc <code> Tag | Allegro 4 Timer Example (w/ Semaphores) | Allegro 5 "Winpkg" (MSVC readme) | Bambot | Blog | C++ STL Container Flowchart | Castopulence Software | Check Return Values | Derail? | Is This A Discussion? Flow Chart | Filesystem Hierarchy Standard | Clean Code Talks - Global State and Singletons | How To Use Header Files | GNU/Linux (Debian, Fedora, Gentoo) | rot (rot13, rot47, rotN) | Streaming |
Fishcake
Member #8,704
June 2007
![]() |
You should split your main function into multiple functions, and then name each of those function with a proper name that accurately describes what it does. Here's an example of splitting using your existing code (probably not compilable): 1#include <stdlib.h>
2#include "Includes.h"
3
4#define screenHeight 640
5#define screenWidth 480
6
7// The global variables
8ALLEGRO_DISPLAY *display;
9ALLEGRO_EVENT_QUEUE *event_queue;
10ALLEGRO_TIMER *timer;
11ALLEGRO_BITMAP *abg;
12ALLEGRO_BITMAP *bg;
13ALLEGRO_BITMAP *menub;
14ALLEGRO_BITMAP *login;
15ALLEGRO_BITMAP *menub2;
16ALLEGRO_BITMAP *creation;
17ALLEGRO_BITMAP *readfirst;
18ALLEGRO_SAMPLE *lsm;
19
20int init();
21int load_resources();
22void process_loop();
23void unload_resources();
24void shutdown();
25
26int main()
27{
28 if (init() == -1) return EXIT_FAILURE;
29 if (load_resources() == -1) return EXIT_FAILURE;
30
31 process_loop();
32
33 unload_resources();
34 shutdown();
35 return EXIT_FAILURE;
36}
37
38int init()
39{
40 //If Allegro 5 fails to initialize, exit.
41 if(!al_init())
42 return -1;
43
44 //Initialize display.
45 al_set_new_display_flags(ALLEGRO_WINDOWED);
46 display = al_create_display(screenHeight, screenWidth);
47 al_set_window_title(display, "EOC++");
48
49 //If display fails to initialize, exit.
50 if (!display)
51 return -1;
52
53 //Install Keyboad, Mouse & Initialize most addons.
54 al_install_keyboard();
55 al_install_mouse();
56 al_init_primitives_addon();
57 al_init_font_addon();
58 al_init_ttf_addon();
59 al_init_image_addon();
60 al_install_audio();
61 al_init_acodec_addon();
62 al_reserve_samples(1);
63
64 //Create event queue
65 event_queue = al_create_event_queue();
66
67 //Create timer that will tick once per frame.
68 timer = al_create_timer(1.0/60.0); //60 frames per second.
69
70 //register the event sources so they send events to our queue
71 al_register_event_source(event_queue, al_get_display_event_source(display)); //display/window
72 al_register_event_source(event_queue, al_get_keyboard_event_source()); //keyboard
73 al_register_event_source(event_queue, al_get_mouse_event_source()); //mouse
74 al_register_event_source(event_queue, al_get_timer_event_source(timer)); //fps timer
75
76 return 0;
77}
78
79int load_resources()
80{
81 //Initialize Bitmaps
82 abg = al_load_bitmap("resources/images/0.bmp");
83 bg = al_load_bitmap("resources/images/1.bmp");
84 menub = al_load_bitmap("resources/images/2.bmp");
85 login = al_load_bitmap("resources/images/3.bmp");
86 menub2 = al_load_bitmap("resources/images/4.bmp");
87 creation = al_load_bitmap("resources/images/5.bmp");
88 readfirst = al_load_bitmap("resources/images/6.bmp");
89
90 //Initialize MFX
91 lsm = al_load_sample("resources/mfx/mfx001.ogg");
92
93 //Initialize Fonts
94 //None yet.
95
96 return 0;
97}
98
99void unload_resources()
100{
101 al_destroy_sample(lsm);
102 al_destroy_bitmap(readfirst);
103 al_destroy_bitmap(creation);
104 al_destroy_bitmap(menub2);
105 al_destroy_bitmap(login);
106 al_destroy_bitmap(menub);
107 al_destroy_bitmap(bg);
108 al_destroy_bitmap(abg);
109}
110
111void shutdown()
112{
113 al_destroy_timer(timer);
114 al_destroy_event_queue(event_queue);
115 al_destroy_display(display);
116}
117
118void process_loop()
119{
120 bool redraw = true;
121
122 //Clicks
123 bool loginclicked = false;
124 bool accountclicked = false;
125 bool okclicked = false;
126
127 //Hovers for menu screen
128 bool hovercreate = false;
129 bool hoverplay = false;
130 bool hovercredits = false;
131 bool hoverexit = false;
132 bool hoverconnect = false;
133 bool hovercancel = false;
134 //Hovers for account creation screen
135 bool hovercreate2 = false;
136 bool hovercancel2 = false;
137 bool hoverok = false;
138
139 al_convert_mask_to_alpha(menub, al_map_rgb(0,0,0));
140 al_convert_mask_to_alpha(menub2, al_map_rgb(0,0,0));
141 al_convert_mask_to_alpha(creation, al_map_rgb(0,0,0));
142 al_clear_to_color(al_map_rgb(0,0,0));
143 al_flip_display();
144
145 //Start the timer
146 al_start_timer(timer);
147
148 /*when this variable is set to false
149 the program will quit the main loop
150 and free the allocated resources
151 before quitting */
152 while(1)
153 {
154 ALLEGRO_EVENT ev;
155 al_wait_for_event(event_queue, &ev);
156
157 if(ev.type == ALLEGRO_EVENT_TIMER)
158 {
159 al_play_sample(lsm, 1.0, 0.0,1.0,ALLEGRO_PLAYMODE_LOOP,NULL);
160 redraw = true;
161 }
162 else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
163 {
164 break;
165 }
166 else if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
167 {
168 //handle key presses
169 switch(ev.keyboard.keycode)
170 {
171 case ALLEGRO_KEY_F1:
172 {
173 }
174 break;
175 }
176 }
177 else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES)
178 {
179 ////////////////////////////////
180 //Hovers for Menu screen
181 //Hover Create Account button
182 if(ev.mouse.x > 20 && ev.mouse.x < 200 && ev.mouse.y > 300 && ev.mouse.y < 340)
183 {
184 hovercreate = true;
185 }
186 else
187 hovercreate = false;
188
189 //Hover Play button
190 if(ev.mouse.x > 20 && ev.mouse.x < 200 && ev.mouse.y > 340 && ev.mouse.y < 380)
191 {
192 hoverplay = true;
193 }
194 else
195 hoverplay = false;
196
197 //Hover Credits button
198 if(ev.mouse.x > 20 && ev.mouse.x < 200 && ev.mouse.y > 380 && ev.mouse.y < 420)
199 {
200 hovercredits = true;
201 }
202 else
203 hovercredits = false;
204
205 //Hover Exit button
206 if(ev.mouse.x > 20 && ev.mouse.x < 200 && ev.mouse.y > 420 && ev.mouse.y < 460)
207 {
208 hoverexit = true;
209 }
210 else
211 hoverexit = false;
212
213 //Hover Connect button
214 if(ev.mouse.x > 388 && ev.mouse.x < 478 && ev.mouse.y > 400 && ev.mouse.y < 427)
215 {
216 hoverconnect = true;
217 }
218 else
219 hoverconnect = false;
220
221 //Hover Cancel button
222 if(ev.mouse.x > 480 && ev.mouse.x < 570 && ev.mouse.y > 400 && ev.mouse.y < 427)
223 hovercancel = true;
224 else
225 hovercancel = false;
226 ////////////////////////////////
227
228 ////////////////////////////////
229 //Hovers for account creations screen
230 //Hover create button
231 if(ev.mouse.x > 358 && ev.mouse.x < 478 && ev.mouse.y > 420 && ev.mouse.y < 460)
232 hovercreate2 = true;
233 else
234 hovercreate2 = false;
235
236 //Hover cancel button
237 if(ev.mouse.x > 480 && ev.mouse.x < 600 && ev.mouse.y > 420 && ev.mouse.y < 460)
238 hovercancel2 = true;
239 else
240 hovercancel2 = false;
241
242 //Hover OK Button
243 if(ev.mouse.x > 297 && ev.mouse.x < 388 && ev.mouse.y > 315 && ev.mouse.y < 344)
244 hoverok = true;
245 else
246 hoverok = false;
247 }
248 else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN)
249 {
250 if(ev.mouse.button & 1)
251 {
252 ////////////////////////////////
253 //Menu buttons
254 //Create Account button
255 if(ev.mouse.x > 20 && ev.mouse.x < 200)
256 {
257 if(ev.mouse.y > 300 && ev.mouse.y < 340)
258 {
259 accountclicked = true;
260 }
261 }
262
263 //Play button
264 if(ev.mouse.x > 20 && ev.mouse.x < 200 && ev.mouse.y > 340 && ev.mouse.y < 380)
265 {
266
267 loginclicked = true;
268 }
269
270 //Credits button
271
272 //Exit button
273 if(ev.mouse.x > 20 && ev.mouse.x < 200 && ev.mouse.y > 420 && ev.mouse.y < 460)
274 {
275 break;
276 }
277
278 //Login Connect button
279
280 //Login Cancel button
281 if(ev.mouse.x > 480 && ev.mouse.x < 570 && ev.mouse.y > 400 && ev.mouse.y < 427)
282 loginclicked = false;
283 ////////////////////////////////
284
285 ////////////////////////////////
286 //Buttons in account creation screen
287 //Cancel button
288 if(ev.mouse.x > 480 && ev.mouse.x < 600 && ev.mouse.y > 420 && ev.mouse.y < 460)
289 {
290 accountclicked = false;
291 okclicked = false;
292 }
293
294 //OK Button
295 if(ev.mouse.x > 297 && ev.mouse.x < 388 && ev.mouse.y > 315 && ev.mouse.y < 344)
296 okclicked = true;
297 }
298 }
299
300 if(redraw && al_is_event_queue_empty(event_queue))
301 {
302 redraw = false;
303 al_clear_to_color(al_map_rgb(0,0,0));
304
305 if(!accountclicked)
306 {
307 //Draw BG
308 al_draw_bitmap(bg, 0, 0, 0);
309
310 //if mouse is not over create account button area, draw create account button.
311 //Else, draw hovered create account button.
312 if(!hovercreate)
313 al_draw_bitmap_region(menub, 0, 0, 180, 40, 20, 300, 0);
314 else
315 al_draw_bitmap_region(menub, 180, 0, 180, 40, 20, 300, 0);
316
317 //If mouse is not over play button area, draw play button.
318 //Else, draw hovered play button.
319 if(!hoverplay)
320 al_draw_bitmap_region(menub, 0, 40, 180, 40, 20, 340, 0);
321 else
322 al_draw_bitmap_region(menub, 180, 40, 180, 40, 20, 340, 0);
323
324 //if mouse is not over credits button area, draw credits button.
325 //Else, draw hovered credit button.
326 if(!hovercredits)
327 al_draw_bitmap_region(menub, 0, 80, 180, 40, 20, 380, 0);
328 else
329 al_draw_bitmap_region(menub, 180, 80, 180, 40, 20, 380, 0);
330
331 //if mouse is not over exit button area, draw exit button.
332 //Else, draw hovered exit button.
333 if(!hoverexit)
334 al_draw_bitmap_region(menub, 0, 120, 180, 40, 20, 420, 0);
335 else
336 al_draw_bitmap_region(menub, 180, 120, 180, 40, 20, 420, 0);
337
338 if(loginclicked)
339 {
340 al_draw_bitmap(login, 300, 300, 0);
341 if(!hoverconnect)
342 al_draw_bitmap_region(menub2, 0, 0, 91, 29, 388, 400, 0);
343 else
344 al_draw_bitmap_region(menub2, 91, 0, 91, 29, 388, 400, 0);
345
346 if(!hovercancel)
347 al_draw_bitmap_region(menub2, 0, 29, 91, 29, 480, 400, 0);
348 else
349 al_draw_bitmap_region(menub2, 91, 29, 91, 29, 480, 400, 0);
350 }
351 }
352 else
353 {
354 al_draw_bitmap(abg, 0, 0, 0);
355 if(!hovercreate2)
356 al_draw_bitmap_region(creation, 0, 0, 120, 40, 358, 420, 0);
357 else
358 al_draw_bitmap_region(creation, 120, 0, 120, 40, 358, 420, 0);
359 if(!hovercancel2)
360 al_draw_bitmap_region(creation, 0, 40, 120, 40, 480, 420, 0);
361 else
362 al_draw_bitmap_region(creation, 120, 40, 120, 40, 480, 420, 0);
363 if(!okclicked)
364 {
365 al_draw_bitmap(readfirst, 640 / 2 / 2, 480 / 2 / 2, 0);
366 if(!hoverok)
367 al_draw_bitmap_region(menub2, 0, 116, 91, 29, 297, 315, 0);
368 else
369 al_draw_bitmap_region(menub2, 91, 116, 91, 29, 297, 315, 0);
370 }
371 }
372 al_flip_display();
373 }
374 }
375}
How would this make your life easier? 1. It makes it easier to code. If you want to load a new resource, just find the function load_resources and add the necessary code, instead of scrolling around finding the correct line to add the code inside a big main function. It may seem tolerable now, but when your code reaches thousands of lines, it's really painful. Most modern IDEs or even text editors provide the functionality to jump to a function via a drop down. 2. It makes it easier to read your code. The function's name act as a summary of what the code contained inside it does (if you keep a habit of doing so.) This is very important because you will definitely forget your code in a few weeks/months, and when that happens, it's easier to understand what the hell is going on. 3. It makes your code reusable. If you have a functionality that takes a few lines of code to achieve, and you find yourself copy-pasting that code over and over again, then it's best to put it inside a function. There are more to it, but I'm supposed to be working right now!
|
Thomas Fjellstrom
Member #476
June 2000
![]() |
Arthur Kalliokoski said: Shared memory. Shared memory. Repeat until you grok. If its shared, then its not really freed then is it -- |
Matias Persson
Member #15,093
May 2013
|
Edgar Reynaldo said: How is your understanding of classes / structs?
My understanding of structs is not good. But my understand of classes, I would say is rather okay. I will try to study all of you peoples code, that you posted here, and I will play with it until I get a basic understand on how to create my buttons in a better not-hardcoded way Fishcake said:
// The global variables I thought it was bad to use global variables? :S |
Fishcake
Member #8,704
June 2007
![]() |
Matias Persson said:
My understanding of structs is not good. But my understand of classes, I would say is rather okay.
AFAIK, in C++, the difference between a struct and a class is that struct members are public by default, while class members are private. Matias Persson said: I thought it was bad to use global variables? :S
They're generally bad, but it wouldn't hurt to use them in a small, single-file, throwaway projects. Plus, I was just giving an example, so I didn't bother.
|
|
1
2
|