Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » 2 class objects same reaction.

This thread is locked; no one can reply to it. rss feed Print
2 class objects same reaction.
Tony Montana
Member #7,365
June 2006

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:

1if(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 :-/

Elverion
Member #6,239
September 2005
avatar

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.

--
SolarStrike Software - MicroMacro home - Automation software.

Tony Montana
Member #7,365
June 2006

I understand, now I'm working for a tilesystem, when expanding my project I'll us grabber.
Full Monster class:

1class Monster
2{
3public:
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};

Jonatan Hedborg
Member #4,886
July 2004
avatar

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.

Tony Montana
Member #7,365
June 2006

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);

Audric
Member #907
January 2001

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.

Ron Novy
Member #6,982
March 2006
avatar

Yeah just make sure you fix those memory leaks! ex

1if(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;

----
Oh... Bieber! I thought everyone was chanting Beaver... Now it doesn't make any sense at all. :-/

Go to: