I have 2 Monsters, one's direction is left, one's right.
I created RLE sprites of bitmaps, when I assign their direction, the 2nd monster gets the direction of the first one. It's like they're sharing the same sprites:
| 1 | if(dir==0)//right |
| 2 | { |
| 3 | bmp = load_bitmap("ag1.bmp", 0);//walk frame 1 |
| 4 | B1=get_rle_sprite(bmp); |
| 5 | bmp = load_bitmap("ag2.bmp", 0);//walk frame 2 |
| 6 | B2=get_rle_sprite(bmp); |
| 7 | bmp = load_bitmap("ag4.bmp", 0);//attack frame |
| 8 | X=get_rle_sprite(bmp); |
| 9 | } |
| 10 | if(dir==1)//left |
| 11 | { |
| 12 | bmp = load_bitmap("ag1l.bmp", 0); |
| 13 | B1=get_rle_sprite(bmp); |
| 14 | bmp = load_bitmap("ag2l.bmp", 0); |
| 15 | B2=get_rle_sprite(bmp); |
| 16 | bmp = load_bitmap("ag4l.bmp", 0); |
| 17 | X=get_rle_sprite(bmp); |
| 18 | } |
| 19 | destroy_bitmap(bmp); |
| 20 | DEF=B1; |
Later, I use allways DEF and change the sprite when it's needed, like DEF=B2;
I define the objects:
Monster monster(5,5,5,0,0);//4th variable is the direction Monster monster1(5,5,5,1,150);
And drawing the objects:
draw_rle_sprite(screen, monster.DEF, monster.x, monster.y); draw_rle_sprite(screen, monster1.DEF, monster1.x, monster1.y);
Please help
That is a horrible way to manage the loading of bitmaps. Don't let each object handle it's own loading of them, or you will end up with copies. It might not be a problem with just 2 monsters of the same type, but imagine 100 of them, each loading the same bitmap, and all wasting RAM.
You also have some memory leakage in the code you have posted. You load "bmp" 3 times, and only destroy it once. That means there's the memory for the other two loaded copies floating around...somewhere...
It's almost impossible to tell where your problem is without more code. Specifically, more on the monster class. Post more, and lets see if we can't fix it.
Also, if I remember correctly, RLE sprites don't do a whole lot for you anymore unless you are targetting older systems. Because of this, you might want to just pack all of your monster/player/npc graphics into one datafile, load it at the begining of the game, use the graphics directly from it, and unload the datafile at the end of the game. Someone correct me if I'm wrong here.
To use a bitmap from a datafile, It's something like...
BITMAP *bmp = (BITMAP *)data_f[MONSTER_1].dat; masked_blit(bmp, frame_buffer, 0, 0, x, y, bmp->w, bmp->h);
where MONSTER_1 is defined as the bitmap's position in the datafile. Use grabber's auto-header for this.
I understand, now I'm working for a tilesystem, when expanding my project I'll us grabber.
Full Monster class:
| 1 | class Monster |
| 2 | { |
| 3 | public: |
| 4 | float x, y, xe, ye, xv, yv;//e = enemy, v = velecoity |
| 5 | float hp, hptot, att1, att2, power, powertot; |
| 6 | int damage, time,mode,dir,speed;//mode is used to change frames in 60 turns |
| 7 | bool dead, time_set; |
| 8 | volatile int my_time,step,attacktime; |
| 9 | BITMAP *bmp; |
| 10 | RLE_SPRITE *B1,*B2,*X,*DEF; |
| 11 | Monster(int hp,int att1,int power, int dir,int x) |
| 12 | { |
| 13 | |
| 14 | this->hp=hp; |
| 15 | hptot=hp; |
| 16 | this->att1=att1; |
| 17 | this->power=power; |
| 18 | powertot=power; |
| 19 | this->dir=dir; |
| 20 | this->x=x; |
| 21 | xe=100,attacktime=0; |
| 22 | xv=0, x=0, y=50; |
| 23 | dead=false; |
| 24 | mode=0,step=0; |
| 25 | if(dir==0) |
| 26 | { |
| 27 | bmp = load_bitmap("ag1.bmp", 0); |
| 28 | B1=get_rle_sprite(bmp); |
| 29 | bmp = load_bitmap("ag2.bmp", 0); |
| 30 | B2=get_rle_sprite(bmp); |
| 31 | bmp = load_bitmap("ag4.bmp", 0); |
| 32 | X=get_rle_sprite(bmp); |
| 33 | } |
| 34 | if(dir==1) |
| 35 | { |
| 36 | bmp = load_bitmap("ag1l.bmp", 0); |
| 37 | B1=get_rle_sprite(bmp); |
| 38 | bmp = load_bitmap("ag2l.bmp", 0); |
| 39 | B2=get_rle_sprite(bmp); |
| 40 | bmp = load_bitmap("ag4l.bmp", 0); |
| 41 | X=get_rle_sprite(bmp); |
| 42 | } |
| 43 | destroy_bitmap(bmp); |
| 44 | DEF=B1; |
| 45 | } |
| 46 | |
| 47 | void Att1() |
| 48 | { |
| 49 | if(dir==0) |
| 50 | { |
| 51 | if(x+DEF->w<xe) |
| 52 | { |
| 53 | xv=0.5; |
| 54 | } |
| 55 | if(x>xe-20) |
| 56 | { |
| 57 | power=0; |
| 58 | step=1; |
| 59 | mode=0; |
| 60 | } |
| 61 | } |
| 62 | if(dir==1) |
| 63 | { |
| 64 | if(x>xe) |
| 65 | { |
| 66 | xv=-0.5; |
| 67 | } |
| 68 | if(x<xe+20) |
| 69 | { |
| 70 | power=0; |
| 71 | step=1; |
| 72 | mode=0; |
| 73 | } |
| 74 | } |
| 75 | } |
| 76 | void Back() |
| 77 | { |
| 78 | if(dir==0) |
| 79 | { |
| 80 | xv=-0.5; |
| 81 | } |
| 82 | if(dir==1) |
| 83 | { |
| 84 | xv=0.5; |
| 85 | } |
| 86 | if(power!=powertot) |
| 87 | { |
| 88 | power+=0.1; |
| 89 | } |
| 90 | } |
| 91 | void Update() |
| 92 | { |
| 93 | |
| 94 | if(dead==true) |
| 95 | { |
| 96 | y=50; |
| 97 | } |
| 98 | if(power<att1&&step==0) |
| 99 | { |
| 100 | Back(); |
| 101 | }//go back |
| 102 | if(power>=att1) |
| 103 | { |
| 104 | Att1(); |
| 105 | } |
| 106 | if(step==0) |
| 107 | { |
| 108 | Move(); |
| 109 | } |
| 110 | if(step==1) |
| 111 | { |
| 112 | if(attacktime<60) |
| 113 | { |
| 114 | attacktime++; |
| 115 | Attack(); |
| 116 | } |
| 117 | else |
| 118 | { |
| 119 | step=0; |
| 120 | attacktime=0; |
| 121 | mode=0; |
| 122 | } |
| 123 | } |
| 124 | if(key[KEY_SPACE]) |
| 125 | { |
| 126 | hp-=0.1; |
| 127 | } |
| 128 | } |
| 129 | void Damage(int damage) |
| 130 | { |
| 131 | this->damage=damage; |
| 132 | hp-=damage; |
| 133 | if(hp<1) |
| 134 | { |
| 135 | dead=true; |
| 136 | } |
| 137 | } |
| 138 | void Move() |
| 139 | { |
| 140 | mode++; |
| 141 | if(mode==60)//these are frames |
| 142 | { |
| 143 | mode=1; |
| 144 | } |
| 145 | x+=xv; |
| 146 | if(mode==1) |
| 147 | { |
| 148 | DEF=B1; |
| 149 | } |
| 150 | if(mode==10) |
| 151 | {}//frame 1 |
| 152 | if(mode==20) |
| 153 | {} |
| 154 | if(mode==30) |
| 155 | { |
| 156 | |
| 157 | DEF=B2; |
| 158 | } |
| 159 | if(mode==40) |
| 160 | {} |
| 161 | if(mode==50) |
| 162 | {} |
| 163 | } |
| 164 | void Attack() |
| 165 | { |
| 166 | mode++; |
| 167 | |
| 168 | if(mode==60) |
| 169 | { |
| 170 | mode=1; |
| 171 | } |
| 172 | if(mode==2) |
| 173 | { |
| 174 | DEF=X; |
| 175 | } |
| 176 | if(mode==10) |
| 177 | {}//frame 1 |
| 178 | if(mode==20) |
| 179 | {} |
| 180 | if(mode==30) |
| 181 | {} |
| 182 | if(mode==40) |
| 183 | {} |
| 184 | if(mode==50) |
| 185 | {} |
| 186 | } |
| 187 | }; |
I usualy use a bitmap-handler singleton for managing that sort of thing. It becomes quite elegant;
//In monsters constructor: BitmapHandler *b = BitmapHandler.getInstance(), myBitmap = b->getBitmap("monster1");
And the bitmap-handler looks through an stl map, looking any reference to a bitmap named monster1 - if it finds it, it returns the pointer to it. If not, it loads it, adds it to the map and returns the pointer.
Also, OP; You should probably not create all your monsters etc on the stack like you do now. A better way is probably Monster *monster = new Monster(....); And then access the members with '->' insetad of '.'
This way it wont be automaticly deleted when you leave the function it was created in, and you can send the pointer to a function without having to send all the data in the class.
Very stupid of me (cost 2 days...):
When drawing:
First
draw_rle_sprite(buffer, monster.DEF, monster.x, monster.y); draw_rle_sprite(buffer, monster.DEF, monster1.x, monster1.y);
Now, corrected:
draw_rle_sprite(buffer, monster.DEF, monster.x, monster.y); draw_rle_sprite(buffer, monster1.DEF, monster1.x, monster1.y);
Jonatan:
ooh, pretty!
I am currently using load_datafile() since I use < 2Mb data, but I've studied closely the "load from disk as needed" that can be seen in Doom and Diablo 2. It brings the problem of 'heavy disk activity when new monster arrives', but in a game with large "possible" resource contents, it's that or "loading - please wait" 
Anyway, your method makes it highly readable. And it's still possible to pre-load any amount of often-used data by putting a series of:
b->getBitmap("player_walk1");
b->getBitmap("player_walk2");
b->getBitmap("player_walk3");
b->getBitmap("player_walk4");
(...)
at moments where disk activity should go unnoticed.
Yeah just make sure you fix those memory leaks! ex
| 1 | if(dir==0)//right |
| 2 | { |
| 3 | bmp = load_bitmap("ag1.bmp", 0);//walk frame 1 |
| 4 | B1=get_rle_sprite(bmp); |
| 5 | destroy_bitmap(bmp); //;) |
| 6 | bmp = load_bitmap("ag2.bmp", 0);//walk frame 2 |
| 7 | B2=get_rle_sprite(bmp); |
| 8 | destroy_bitmap(bmp); //;) |
| 9 | bmp = load_bitmap("ag4.bmp", 0);//attack frame |
| 10 | X=get_rle_sprite(bmp); |
| 11 | destroy_bitmap(bmp); //;) |
| 12 | } |
| 13 | if(dir==1)//left |
| 14 | { |
| 15 | bmp = load_bitmap("ag1l.bmp", 0); |
| 16 | B1=get_rle_sprite(bmp); |
| 17 | destroy_bitmap(bmp); //;) |
| 18 | bmp = load_bitmap("ag2l.bmp", 0); |
| 19 | B2=get_rle_sprite(bmp); |
| 20 | destroy_bitmap(bmp); //;) |
| 21 | bmp = load_bitmap("ag4l.bmp", 0); |
| 22 | X=get_rle_sprite(bmp); |
| 23 | destroy_bitmap(bmp); //;) |
| 24 | } |
| 25 | DEF=B1; |