My code uses a class that I made called SPRITE. Now SPRITE contains an array of BITMAP*s, the problem is that the first time I come to try and blit one of those BITMAP*s the whole programme crashes.
Now it didn't used to do this, so I don't know why it is doing it now.
This is the header and constructor for the SPRITE class:
| 1 | class SPRITE { |
| 2 | public: |
| 3 | int offset_x; //Draw offset x |
| 4 | int offset_y; //Draw offset y |
| 5 | int max_frames; //Frames in sprite (array bounds 0 - max_frames) |
| 6 | int width; //Sprite width (all frames) |
| 7 | int height; //Sprite height (all frames) |
| 8 | int id; //Individual sprite ID |
| 9 | bool operator == (SPRITE &class1); //Comparison (checks IDs) |
| 10 | BITMAP * spr_sheet(); //Returns a BITMAP of the entire sprite sheet, horizontally. |
| 11 | BITMAP ** frames; //The pointer to the array of BITMAP*s, the main point of this |
| 12 | SPRITE(BITMAP * load_sprite, int load_width, int load_height, int frame_num, int load_offset_x = 0, int load_offset_y = 0, int offset_x = 0, int offset_y = 0, bool debug_me = 0); //The constructor, self explanitory |
| 13 | SPRITE(); //Empty Constructor |
| 14 | ~SPRITE(); //Destructor |
| 15 | void draw(int x, int y, int frame, int alpha = 255, bool debug_me = 0); //Normal draw function |
| 16 | |
| 17 | }; |
| 1 | SPRITE::SPRITE(BITMAP* load_sprite, int load_width, int load_height, int frame_num, int load_offset_x, int load_offset_y, int draw_offset_x, int draw_offset_y, bool debug_me ) { |
| 2 | if (load_sprite != NULL){ |
| 3 | id = spr::get_safe_id(); |
| 4 | |
| 5 | frames = new BITMAP* [frame_num]; |
| 6 | width = (int)(std::abs((float)(load_width))); |
| 7 | height = load_height; |
| 8 | max_frames = frame_num; |
| 9 | offset_x = draw_offset_x; |
| 10 | offset_y = draw_offset_y; |
| 11 | for (int a = 0; a < frame_num; a++){ |
| 12 | frames[a] = create_bitmap(width, height); |
| 13 | blit(load_sprite, frames[a], load_offset_x + a*width, load_offset_y, 0, 0, width, height); |
| 14 | } |
| 15 | destroy_bitmap(load_sprite); |
| 16 | } |
| 17 | else allegro_message("Error loading a certain sprite"); |
| 18 | } |
This is the init() function, which is the first one called within main():
| 1 | |
| 2 | void init() { |
| 3 | int depth, res; |
| 4 | allegro_init(); |
| 5 | depth = desktop_color_depth(); |
| 6 | if (depth == 0) depth = 32; |
| 7 | set_color_depth(depth); |
| 8 | res = set_gfx_mode(GFX_AUTODETECT_WINDOWED, 480, 320, 0, 0); |
| 9 | if (res != 0) { |
| 10 | allegro_message(allegro_error); |
| 11 | exit(-1); |
| 12 | } |
| 13 | |
| 14 | install_timer(); |
| 15 | install_keyboard(); |
| 16 | install_mouse(); |
| 17 | load_bitmaps(); |
| 18 | install_sound( DIGI_AUTODETECT, MIDI_AUTODETECT, NULL); |
| 19 | load_sounds(); |
| 20 | /* add other initializations here */ |
| 21 | set_close_button_callback(End); |
| 22 | |
| 23 | link = OBJ_LINK(); //Construct link |
| 24 | helmaroc = OBJ_HELMAROC(); //Construct the helmaroc |
| 25 | heart_system = OBJ_HEARTS(8, 8); //Construct the heart system |
| 26 | SoundMeter = soundMeter(); //Construct the sound meter |
| 27 | rupees = rupeeSystem(8, 142); //construct the rupee system |
| 28 | rmtower = clROOM(tower); //create the tower room |
| 29 | } |
Now I cannot see any way that a BITMAP* could go astray and create a pointer error, unless it happens in one of those constructors (which I don't think it does, but if you want to see them you can).
The problem comes later when this code is run:
link.spr_link_right_walk.draw(105 + 0, 40, 0, 255, 1);
This calls the draw function in the SPRITE class, which simply draws a translucent copy of that frame.
I don't know what could be going wrong, so could someone please help me? I've been stuck on this bug for a while, and it completely stops the programme
.
i hear somewhere the story of the Fucking Manual and the Evil 'I contain bitmap and contruct them before allegro is loaded' Class.
Maybe you should search more on my story.
I'm sorry but i use C, so i do not have the problem you got.
Are you compiling with gcc? Try to debug that, it should give you the answer.
Gull, although that is most likely to be the problem all of the constructors are called after allegro_init(), only the declarations of the classes are called before allegro_init(), and that does not involve any creation of BITMAPs, i think.
if your program crashes, and you dont know how to find the bug, you need to learn how to use a debugger.
Yes I do, Dev-C++s tells me where it goes wrong, but I don't know how to do anything else.
all of the constructors are called after allegro_init()
It is my understanding that constructors are called when the variable is declared. Your variables look to be declared before allegro_init(). But even if you do declare them below allegro_init(), I'm not sure if it is guarenteed that the constructors are called after it (it might be though).
As a rule of thumb, don't call Allegro functions from inside a constructor function. There are cases where you can do this, but when in doubt, don't do it.
Well there are actually two constructors for all of those things, and when they are declared globally, and pre allegro_init() it doesn't run any allegro functions because it's just a blank constructor.
What does Draw do? Are you sure you are not running out of memory when allocating bitmaps? Can you attach the code? Or debug it to see inside the Draw function to see exactly in which line it crashes, and not only the function.
I know exactly where it crashes, on the draw_trans_sprite.
And how can you run out of memory? :S
The computer doesn't crash, just the programme.
But can you examine if the pointer is NULL, if the trans table is broken in some way, etc?
...
It is NULL, which is weird.
Why is it weird? Cause it's not NULL in the constructor.
How did this happen?
(top of main.cpp if you need it)
| 1 | #include <allegro.h> |
| 2 | #include "vardec.h" |
| 3 | #include "timeline.h" |
| 4 | #include "link.h" |
| 5 | #include "helmaroc.h" |
| 6 | #include "systems.h" |
| 7 | #include "keypress.h" |
| 8 | |
| 9 | |
| 10 | void init(); |
| 11 | void deinit(); |
| 12 | void Buffer2Screen(); |
| 13 | void load_sounds(); |
| 14 | void unload_sounds(); |
| 15 | void load_bitmaps(); |
| 16 | void unload_bitmaps(); |
| 17 | void allrooms(); |
| 18 | void room_change(int newroom); |
| 19 | OBJ_LINK link; |
| 20 | OBJ_HEARTS heart_system; |
| 21 | OBJ_HELMAROC helmaroc; |
| 22 | soundMeter SoundMeter; |
| 23 | rupeeSystem rupees; |
| 24 | |
| 25 | clROOM rmtower; |
| 26 | |
| 27 | BITMAP *press_start, *title_screen, *sbuffer, *tower, *rock, *door_way; |
| 28 | SAMPLE *sndLinkHurt, *sndswordSwipe; |
| 29 | MIDI * tower_music; |
| 30 | bool run = 1, B2S = 1; |
| 31 | int stepcounter = 4, room = ROOM_TITLE, view_x = 0, view_y; |
| 32 | |
| 33 | int main(){ |
| 34 | init(); |
Edit:
Whoops, I just found that my OBJ_LINK doesn't have a blank constructor.
And now that it does, it doesn't make any difference.
It looks like this:
OBJ_LINK::OBJ_LINK(){ vary = varx = direction = mode = frame = speed = key_length_up = key_length_down = key_length_right = alarm[0] = attacked = 0; }
As opposed to:
| 1 | OBJ_LINK::OBJ_LINK(int x, int y): |
| 2 | spr_link_up_walk(load_bitmap("link_dir_up.bmp", NULL), 18, 28, 10, 18, 0), |
| 3 | spr_link_down_walk(load_bitmap("link_dir_down.bmp", NULL), 18, 28, 11, 18, 0), |
| 4 | spr_link_left_walk(load_bitmap("link_dir_left.bmp", NULL), 22, 27, 10, 19, 0), |
| 5 | spr_link_right_walk(load_bitmap("link_dir_right.bmp", NULL), 22, 27, 10, 19, 0), |
| 6 | spr_link_up_stand(load_bitmap("link_dir_up.bmp", NULL), 18, 28, 1, 0, 0), |
| 7 | spr_link_down_stand(load_bitmap("link_dir_down.bmp", NULL), 18, 28, 1, 0, 0), |
| 8 | spr_link_left_stand(load_bitmap("link_dir_left.bmp", NULL), 19, 27, 1, 0, 0), |
| 9 | spr_link_right_stand(load_bitmap("link_dir_right.bmp", NULL), 19, 27, 1, 0, 0), |
| 10 | spr_link_up_sword(load_bitmap("link_dir_up.bmp", NULL), 37, 31, 6, 0, 28, 13, 2), |
| 11 | spr_link_down_sword(load_bitmap("link_dir_down.bmp", NULL), 41, 40, 6, 0, 28, 9, 0), |
| 12 | spr_link_left_sword(load_bitmap("link_dir_left.bmp", NULL), 33, 42, 7, 0, 27, 15, 3), |
| 13 | spr_link_right_sword(load_bitmap("link_dir_right.bmp", NULL), 33, 42, 7, 0, 27, -1, 2), |
| 14 | sprite_index(0) |
| 15 | { |
| 16 | |
| 17 | varx = x; |
| 18 | vary = y; |
| 19 | direction = LINK_DIR_DOWN; |
| 20 | mode = MODE_STAND; |
| 21 | |
| 22 | frame = 0; |
| 23 | speed = 4; |
| 24 | key_length_up = 0; |
| 25 | key_length_down = 0; |
| 26 | key_length_left = 0; |
| 27 | key_length_right = 0; |
| 28 | alarm[0] = -1; |
| 29 | attacked = 0; |
| 30 | } |
Is it still running the sprite constructors?