![]() |
|
Drawing to display in class member functions not working |
mir0slaw
Member #15,677
July 2014
|
Hi! In "Globals.h" which is included by everything, I have It's happened in two different places and right now I just moved those troublesome drawing sequences into the main, next to the place where Render() would be called. But it's really annoying and my code will soon get messy if I don't know how to handle this. Please, help me! |
Elias
Member #358
May 2000
|
Replace the "static" with "extern". "static" means to make a new copy of the variable for each file it is included from (so for you they are all uninitialized as the one in main.cpp is different from all the others). -- |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
But using 'static' compiles? I thought it would give redefinition errors. :/ 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 |
mir0slaw
Member #15,677
July 2014
|
I'll try extern in a few minutes. I don't really understand the static thingy, but I hoped it would let me make display global and visible to all classes defined in .h files that #included "Globals.h". Now I'll try to work on my code and use this extern keyword. I'll tell you what the results are. Thanks for helping me out EDIT: Now I got this (http://s30.postimg.org/7wauftgb3/Bez_tytu_u.png) (don't pay attention to the warning, it's been there before and is not causing any problems). |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
Yeah, to make a variable globally visible you use the extern keyword. You declare it once in your header as extern : header.h #ifndef HEADER_H #define HEADER_H extern ALLEGRO_DISPLAY* display; #endif // HEADER_H And then define it once in one source module somewhere. module.cpp #include "header.h" ALLEGRO_DISPLAY* display = 0;
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 |
mir0slaw
Member #15,677
July 2014
|
So I have 3 questions now. 1) Should I do this #ifndef stuff for each of my externs? 2) I did as you advised me and I still have problems with the program. 1void Player::Render()
2{
3 GameObject::Render();
4
5 al_draw_filled_circle(x, y, radius, color1);
6 al_draw_line(x, y, x + radius*cos(aimAngle), y - radius*sin(aimAngle), color3, barrelWidth);
7 ALLEGRO_FONT *font = al_load_font("aSongForJennifer.ttf", 30, NULL);
8 //HEALTH:
9 al_draw_textf(font, al_map_rgb(210, 15, 0), 25, 345, ALLEGRO_ALIGN_CENTER, "%d", static_cast<int>(maxHealth));
10 //al_draw_bitmap_region(healthBar, 0, 0, health / maxHealth, al_get_bitmap_height(healthBar), 50, 345, 0); //THIS WAS CAUSING PROBLEMS
11 al_draw_rectangle(50, 345, 250, 375, al_map_rgb(1, 2, 3), 1);
12 al_draw_textf(font, al_map_rgb(210, 15, 0), 275, 345, ALLEGRO_ALIGN_CENTER, "%d", static_cast<int>(maxHealth));
13 al_destroy_font(font);
14}
With al_draw_bitmap_region commented out the program works properly, but it also worked like this before, when I had static ALLEGRO_DISPLAY in my Globals.h With al_draw_bitmap_region not commented out it still gives me the same "unhandled exception" error just after I run the program. And there's a yellow arrow pointing at this, so this is where the error happens: 1for (iter = objects.begin(); iter != objects.end(); ++iter)
2 (*iter)->Render();
And one more question: in the example above I have to load the font again, I would like not to have to do this and only load it once, somewhere. I suppose the solution to this might be similar to the solution to my main problem, but anyway I don't know how to do that. Cheers! |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
mir0slaw said: 1) Should I do this #ifndef stuff for each of my externs? No, you just do it once for each header that you have. It prevents it from being accidentally included twice, which would cause errors. Quote: 2) I did as you advised me and I still have problems with the program. You haven't checked any return values. Your fonts and bitmaps might not always load properly, and you have to check for that yourself. Is HealthBar a valid bitmap that has been created somewhere else? Show more code after you check the return values if you're still having a problem. Quote: And one more question: in the example above I have to load the font again, I would like not to have to do this and only load it once, somewhere. I suppose the solution to this might be similar to the solution to my main problem, but anyway I don't know how to do that. Either pass the font as a parameter to the function, or make the font global like you just did with 'display'. 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
|
A better design is not to have global variables, but functions that return pointers to them. For example if you have a display.c that is responsible for opening the display then in that you can put 1static ALLEGRO_DISPLAY * my_display = NULL;
2
3ALLEGRO_DISPLAY * display my_create_display(int w, int h) {
4 my_display = al_create_display(w, h);
5 return my_display;
6}
7
8
9ALLEGRO_DISPLAY * display my_get_display() {
10 return my_display;
11}
In the header file display.h 1ALLEGRO_DISPLAY * display my_create_display(int w, int h);
2ALLEGRO_DISPLAY * display my_get_display();
And then include that header file in any .c filewhere you need to use the display. And use my_create_display to open the display, and my_get_display to get a reference to it. |
mir0slaw
Member #15,677
July 2014
|
To beoran: I'll check if the suggestions from both of you work in a minute. Thanks! EDIT: display.h: 1#pragma once
2#include<allegro5\allegro5.h>
3
4ALLEGRO_DISPLAY * my_create_display(int w, int h);
5ALLEGRO_DISPLAY * my_get_display();
display.cpp: 1#include "display.h"
2
3static ALLEGRO_DISPLAY *my_display = NULL;
4
5ALLEGRO_DISPLAY * my_create_display(int w, int h)
6{
7 my_display = al_create_display(w, h);
8 return my_display;
9}
10ALLEGRO_DISPLAY * my_get_display()
11{
12 return my_display;
13}
FloorGenerator.h: Then we have FloorGenerator.cpp, with a function Update() which causes the unhandled exception. I don't load any fonts or samples, so it's not where the problem is. 1void Floor::Update()
2{
3 al_set_target_bitmap(floorMap);
4 int width = al_get_bitmap_width(floorMap);
5 int height = al_get_bitmap_height(floorMap);
6 for (int j = 0; j < getFloorSize(); j++)
7 {
8 for (int i = 0; i < getFloorSize(); i++)
9 {
10 if (getRoomSpawned(i + j*getFloorSize()))
11 {
12 al_draw_filled_rectangle(i*width / (getFloorSize()), j*height / (getFloorSize()),
13 (i + 1)*width / (getFloorSize()) - 1, (j + 1)*height / (getFloorSize()) - 1, lightGrey);
14 al_draw_rectangle(i*width / (getFloorSize()), j*height / (getFloorSize()),
15 (i + 1)*width / (getFloorSize()) - 1, (j + 1)*height / (getFloorSize()) - 1, simplyBlack, 1);
16 }
17
18
19 else
20 {
21 al_draw_filled_rectangle(i*width / (getFloorSize()), j*height / (getFloorSize()),
22 (i + 1)*width / (getFloorSize()) - 1, (j + 1)*height / (getFloorSize()) - 1, darkGrey);
23 al_draw_rectangle(i*width / (getFloorSize()), j*height / (getFloorSize()),
24 (i + 1)*width / (getFloorSize()) - 1, (j + 1)*height / (getFloorSize()) - 1, simplyBlack, 1);
25 }
26 }
27 }
28 al_set_target_bitmap(al_get_backbuffer(my_get_display()));
29}
30
31void Floor::Render()
32{
33//STUFF THAT'S CERTAINLY WORKING
34al_draw_scaled_bitmap(floorMap, 0, 0, al_get_bitmap_width(floorMap), al_get_bitmap_height(floorMap), 15, 15, 270, 270, 0);
35}
I just want to mention, that the exact same code put in main worked, of course if I created the floorMap in main too. What's the cause of the problem? My other problem is in the Player::Render() but it's probably caused by a similar thing. I will get to that once we deal with that. Cheers |
beoran
Member #12,636
March 2011
|
mir0slaw yes, that's what I ment. Are you using any multi-treading perchance? you can only render to the display from the thread that opened it (OS limitation). |
mir0slaw
Member #15,677
July 2014
|
Oh man, I have absolutely no idea what those threads mean and what they do. But I have the following project settings: http://s17.postimg.org/y3watnzfj/Bez_tytu_u.png I use them because now I can use Advanced Installer to make an installer for my game. I learnt that from the following tutorial: https://www.youtube.com/watch?v=Ny-rsCSYkzU |
beoran
Member #12,636
March 2011
|
Well, if you don't know what threads are then I doubt you are using them. So please don't worry about it for now. Which briings us back to your problem. Perhaps, if you don't mind you could just zip up all the sources of your project and post them here (of a link if they are on a code hosting site like GitHub or so). Then we can try to compile and run them ourselves to try to help you better. |
mir0slaw
Member #15,677
July 2014
|
Oh yeah, sure. That'd be great. |
beoran
Member #12,636
March 2011
|
Thanks for posting this. Sorry to say this, but I feel I can't help you yet with Allegro, because after reading your code, I feel you still need to learn more about the basics of programming. I'd recommend to forget about object orientation or C++ and focus on just C. Once you get proficient in C, you can always learn C++ later if need be. But to use Allegro, there is no need to learn any C++ or object orientation at all. One good book I used myself way back when to learn C programming is this one: http://www.amazon.com/C-Plain-English-Brian-Overland/dp/1558284303. There are many other resources available online as well for learning C. And sorry to be not so helpful to you. |
Edgar Reynaldo
Major Reynaldo
May 2007
![]() |
You do not want to be using static variables in a header. If you need to share variables between source modules then you need to declare them as 'extern' and define them in ONE source file w/o the extern on the definition. my_header.h extern int setting; my_source.cpp #include "my_header.h" int setting = 0; http://en.wikipedia.org/wiki/Static_%28keyword%29 To show you why, here is a little demo code : globals.h #ifndef globals_HPP #define globals_HPP #include <cstdio> struct ALLEGRO_DISPLAY; static ALLEGRO_DISPLAY* display = 0; void mod2(); #endif // globals_HPP module1.cpp 1
2#include "globals.h"
3
4int main(int argc , char** argv) {
5
6
7 (void)argc;
8 (void)argv;
9
10 printf("Main says address of display is %p\n" , &display);
11
12 mod2();
13
14 return 0;
15}
module2.cpp #include "globals.h" void mod2() { printf("Module 2 says address of display is %p\n" , &display); } Output of program : c:\ctwoplus\progcode\allegro5\test\statictest>statictest.exe Main says address of display is 00407020 Module 2 says address of display is 00407024 So each module is getting its own copy of each variable declared as static. That's not what you want. You want one instance of each variable shared among modules, and that's what extern is for. Also, there were a ton of warnings compiling your code. I understand it is still in development but you should enable warnings and remove as many of them as you can. 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 |
mir0slaw
Member #15,677
July 2014
|
That's strange, I only have had one warning before starting to mess with the externs, it was the warning that my switch does only have default and doesn't have any cases. Cheers |
|