Confusing problem using vector in game

Pages: 12
So, I'm using Allegro, the game programming library, I am working on adding rockets to the game. When the game starts, and the rocket object goes through its first animation routine, (update rockets, move them along, draw if need be), the vector reads that 5 rockets have already been fired. On top of that, a rocket show up in the top left screen, never updated and never deleted.

rocket.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#include "collarea.h"
#include <vector>
#ifndef R1_H
#define R1_H
#define PI 3.14159265
class ALLEGRO_BITMAP;
class collarea;
using std::vector;
class rocket
{
public:
	rocket(float sp,float w,float h);
	~rocket();

	collarea area;
	
	struct rk {
		float x,y,dx,dy,theta;
		int seq;
	};
	vector<struct rk> rockets;
	
	int limit;
	int launched;
	int internal_ptr;
	
	void setlimit(int a);
	
	void renew();
	void update();

	void setrocket(ALLEGRO_BITMAP*& a,ALLEGRO_BITMAP*& b);
	void launch(float xx, float yy,float ttheta);
	void launch(collarea you, collarea other);
	int draw(float *xx, float *yy, float *ttheta);
	void checkexplode(collarea a);
	int sequence(); //for explosion scene
	int checkkill(collarea a);
	int drawexplosion(float *xx, float *yy, float *w,float *h);
	void move(collarea a);
	
private:
	float width, height;
	float speed;
	float killdist;
	//float x,y,dx,dy;
	float dist;
	float destx,desty;
	float ox,oy;
	//int seq;
	int vdist; //for explosion sequence
	
};
#endif 


rocket.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
#include "rocket.h"
#include <math.h>
#include <stdio.h>
#define abs(x) (((x)>0) ? (x) : (-(x)))
#define growth(x) (1+.18*((x)*(x)))
rocket::rocket(float sp,float w,float h)
{
	speed = sp;
	launched=0;
	limit=0;
	internal_ptr=0;
	width=w;
	height=h;
	rockets.clear();
}
void rocket::setlimit(int a)
{
	rockets.resize(a);
	limit=a;
}
void rocket::setrocket(ALLEGRO_BITMAP*& a,ALLEGRO_BITMAP*& b)
{
	area.sethitboundaries(a);
	float w = al_get_bitmap_width(b);
	float h = al_get_bitmap_height(b);
	killdist = sqrt((w*w)+(h*h));
}
void rocket::launch(float xx, float yy,float ttheta)
{
	if(launched<limit)
	{
		struct rk next;
		next.x=xx; next.y=yy; next.theta=ttheta;
		next.dx = speed * cos(ttheta);
		next.dy = speed * sin(ttheta);
		next.seq=0;
		launched++;
		rockets.push_back(next);
	}
}
void rocket::launch(collarea you, collarea other)
{
	if(launched<limit)
	{
		struct rk next;
		float xx,yy;
		you.getxy(&xx,&yy);
		next.x=xx; next.y=yy;
		other.getxy(&xx,&yy);
		float ratio = (next.y-yy)/(next.x-xx);
		next.theta = atan(ratio);
		next.dx = speed * cos(next.theta);
		next.dy = speed * sin(next.theta);
		next.seq=0;
		launched++;
		rockets.push_back(next);
	}
}
int rocket::draw(float *xx, float *yy, float *ttheta)
{
	if(internal_ptr>=rockets.size())
	{
		internal_ptr=0;
		return 0;
	}
	else if(rockets.at(internal_ptr).seq>0)
	{
		return -1;
	}
	else
	{
		*xx=rockets.at(internal_ptr).x;
		*yy=rockets.at(internal_ptr).y;
		*ttheta=rockets.at(internal_ptr).theta;
		internal_ptr++;
		return 1;
	}
}
void rocket::checkexplode(collarea a)
{
	int g = rockets.size();
	fprintf(stdout,"In checkexplode(), rockets fired: %i\n",g);
	for(int i=0;i<g;i++)
	{
		if(!rockets.at(i).seq)
		{
			float x=rockets.at(i).x;
			float y=rockets.at(i).y;
			float xx,yy;
			a.toxy(&xx,&yy,a.getbl());
			float bx,by;
			a.toxy(&bx,&by,a.getbr());
			xx = (abs(x-xx)<abs(x-bx)) ? xx : bx;
			yy = (abs(y-yy)<abs(y-by)) ? yy : by;
			a.toxy(&bx,&by,a.gettl());
			xx = (abs(x-xx)<abs(x-bx)) ? xx : bx;
			yy = (abs(y-yy)<abs(y-by)) ? yy : by;
			a.toxy(&bx,&by,a.gettr());
			xx = (abs(x-xx)<abs(x-bx)) ? xx : bx;
			yy = (abs(y-yy)<abs(y-by)) ? yy : by;
			float dd = sqrt((x-xx)*(x-xx) + (y-yy)*(y-yy));
			//fprintf(stdout,"dd: %f, killdist: %f\n",dd,killdist);
			if(dd < killdist)
			{
				fprintf(stdout,"\n\n\n\n\n\n\n\n\n\nRocket should explode\n\n\n\n\n\n\n\n\n\n");
				rk temp = rockets.at(i);
				rockets.erase(rockets.begin()+i);
				temp.seq=1;
				rockets.push_back(temp);
			}
		}
	}
	
}
int rocket::sequence() //for explosion scene
{
	return rockets.at(internal_ptr).seq;
}
int rocket::checkkill(collarea a)
{
	float x = rockets.at(internal_ptr).x;
	float y = rockets.at(internal_ptr).y;
	float seq = rockets.at(internal_ptr).seq;
	if(!seq)
	{
		return 0;
	}
	else 
	{
		float ref = killdist * growth(seq);
		ref = ref/2;
		float centerx = x - ref*cos(PI/4);
		float centery = y - ref*sin(PI/4);
		float xx,yy;
		a.toxy(&xx,&yy,a.getbl());
		float bx,by;
		a.toxy(&bx,&by,a.getbr());
		xx  = (abs(centerx-xx)<abs(centerx-bx)) ? xx : bx;
		yy = (abs(centery-yy)<abs(centery-by)) ? yy : by;
		a.toxy(&bx,&by,a.gettl());
		xx = (abs(centerx-xx)<abs(centerx-bx)) ? xx : bx;
		yy = (abs(centery-yy)<abs(centery-by)) ? yy : by;
		a.toxy(&bx,&by,a.gettr());
		xx = (abs(centerx-xx)<abs(centerx-bx)) ? xx : bx;
		yy = (abs(centery-yy)<abs(centery-by)) ? yy : by;
		float dd = sqrt((x-xx)*(x-xx) + (y-yy)*(y-yy));
		return (dd < ref);
	}
}
void rocket::update()
{
	int j=rockets.size();
	for(int i=0;i<j;i++)
	{
		rk temp = rockets.at(0);
		rockets.erase(rockets.begin());
		if(temp.seq)
		{
			temp.seq++;
		}
		else 
		{
			temp.x+=temp.dx;
			temp.y+=temp.dy;
			//rockets.push_back(temp); //this lets me at least shoot rockets
		}
		//rockets.push_back(temp); //this freezes the game
	}
}
void rocket::renew()
{
	int j=rockets.size();
	for(int i=0;i<j;i++)
	{
		rk temp = rockets.at(0);
		rockets.erase(rockets.begin());
		if(!((temp.x<0)||(temp.x>width)||(temp.y<0)||(temp.y>height)||(temp.seq>3)))
		{
			rockets.push_back(temp);
		}
	}
}
int rocket::drawexplosion(float *xx, float *yy, float *w,float *h)
{
	float x = rockets.at(internal_ptr).x;
	float y = rockets.at(internal_ptr).y;
	if(rockets.at(internal_ptr).seq<3)
	{
		float ref = killdist * growth(rockets.at(internal_ptr).seq);
		float expdist = (ref - killdist)/2;
		*xx = x - expdist * cos(PI/4);
		*yy = y - expdist * sin(PI/4);
		*w = ref * cos(PI/4);
		*h = ref * sin(PI/4);
		/*rk temp = rockets.at(internal_ptr);
		rockets.erase(rockets.begin()+internal_ptr);
		temp.seq++;
		rockets.push_back(temp);*/
		internal_ptr++;
		return 1;
	}
	else 
	{
		internal_ptr++;
		return 0;
	}
}
void rocket::move(collarea a)
{
	checkexplode(a);
	renew();
	update();
}
rocket::~rocket()
{
	while(rockets.size())
	{
		rockets.erase(rockets.begin());
	}
	rockets.resize(0);
}


I think it has something to do with how I'm initializing the vector. I can't see how though
Well first, the #ifndef R1_H #define R1_H should be lines 1 and 2 in the header file from what I've been told. Second, you will get a lot more help if you post this to the forums at http://www.allegro.cc because they use Allegro more than the users here.
There is no implementation code here, we would have to see how you are using this object to tell you for sure what is wrong. But if I had to guess I would say that the fact that the game reads 5 rockets launched when you only intended to launch one has something to do with the way you are detecting user input, or because you have passed 5 to your setlimit function so the size of the "rockets" vector is 5.

For certain I can tell you the rocket that appears in the top left corner is because of the way you fill your vector, and the way you wrote your draw function. You are setting a definite amount of "rk" objects to be drawn to the screen with your setlimit function. Anytime your draw function returns a 0 or a -1 it does not set the coordinates for that instance of that "rk" object, assuming nothing else has modified the coordinates and that "rk" is using the default constructor and you end up with the coordinates (0, 0) or the top left corner of the screen. The solution is, if you can, eliminate your "rk" object and treat each instance of the "rocket" class as an individual rocket. Or if you can't do that for whatever reason then re-write your setlimit and\or your draw function.
Last edited on
@Computergeek01 What you're saying makes a lot of sense, but I'm looking through the code and trying to figure what it is I did wrong and I'm not seeing it. The reason I went with a class member of vector of structs is because I felt that would save memory and code. I get turned off by the idea of creating multiple objects and I do it reluctantly if I feel its unavoidable. But I'm a newb so I never completely diregard an idea. Anyways:

Main.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
#include "tank.h"
#include "collarea.h"
#include "rocket.h"
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#include <stdio.h>
#include <cstdlib>
#define PI 3.14159265
#define degtorad(x) ((x/180) * PI)
int height=480;
int width=640;
int margin=40;
float speed=1;
float bullet_speed=speed+.5;
int it = 8;
ALLEGRO_COLOR wallcolor;

ALLEGRO_DISPLAY* display;
ALLEGRO_BITMAP* back;
ALLEGRO_BITMAP* t1 = 0;
ALLEGRO_BITMAP* t2 = 0;
ALLEGRO_BITMAP* bul = 0;
ALLEGRO_BITMAP* dt = 0;
ALLEGRO_BITMAP* rk = 0;
ALLEGRO_BITMAP* exp = 0;

ALLEGRO_TIMER *timer;
const float FPS = 150; //doing angles kinda requires a high frame rate

rocket rock(bullet_speed+2,width,height);

gun tank1(speed,bullet_speed,0,width,height,margin);
gun tank2(speed,bullet_speed,1,width,height,margin);
float w1,w2,wd,wb,h1,h2,hd,hb,rw,rh,ew,eh;

void draw();
int setup();
void initializetanks();

int setup()
{
	int i=0;
	if(!al_init())
	{
		fprintf(stderr, "Allegro failed to initialize\n");
		i= 1;
	}
	if(!al_init_image_addon())
	{
		fprintf(stderr, "failed to initialize images\n");
		i= 2;
	}
	display = al_create_display(width, height);
	if(!display)
	{
		fprintf(stderr, "failed to create display\n");
		i= 3;
	}
	if(!al_install_keyboard())
	{
		fprintf(stderr, "failed to install keyboard\n");
		i= 4;
	}
	if(!al_install_mouse())
	{
		fprintf(stderr, "failed to install mouse\n");
		i= 5;
	}
	timer = al_create_timer(1.0/FPS);
	if(!timer)
	{
		fprintf(stderr,"Failed to create timer\n");
		i=6;
	}
	t1 = al_load_bitmap("tank1.bmp");
	t2 = al_load_bitmap("tank2.bmp");
	dt = al_load_bitmap("dtank.bmp");
	bul = al_load_bitmap("bullet.bmp");
	rk = al_load_bitmap("rocket2.bmp");
	exp = al_load_bitmap("concussion2.bmp");
	if((!t1)||(!t2)||(!dt)||(!bul)||(!rk)||(!exp))
	{
		fprintf(stderr,"Images didn't load");
		i=7;
	}
	else
	{
	al_convert_mask_to_alpha(t1,al_map_rgb(255,0,255));
	al_convert_mask_to_alpha(t2,al_map_rgb(255,0,255));
	al_convert_mask_to_alpha(dt,al_map_rgb(255,0,255));
	al_convert_mask_to_alpha(bul,al_map_rgb(255,0,255));
	al_convert_mask_to_alpha(rk,al_map_rgb(255,0,255));
	al_convert_mask_to_alpha(exp,al_map_rgb(255,0,255));
	w1=al_get_bitmap_width(t1);
	w2=al_get_bitmap_width(t2);
	wd=al_get_bitmap_width(dt);
	wb=al_get_bitmap_width(bul);
	h1=al_get_bitmap_height(t1);
	h2=al_get_bitmap_height(t2);
	hd=al_get_bitmap_height(dt);
	hb=al_get_bitmap_height(bul);
	rw=al_get_bitmap_width(rk);
	rh=al_get_bitmap_height(rk);
	ew=al_get_bitmap_width(exp);
	eh=al_get_bitmap_height(exp);
	rock.setrocket(rk,exp);
	rock.setlimit(5);
	al_set_target_bitmap(al_get_backbuffer(display));
	}
	return i;
}
void initializetanks()
{
	tank1.getbitmaps(t1,bul);
	tank2.getbitmaps(t2,bul);
}
void draw()
{
	al_set_target_bitmap(al_get_backbuffer(display));
	al_clear_to_color(wallcolor);
	float x, y, theta;
	tank1.drawtank(&x,&y,&theta);
	if(tank1.notdead())
	{
		al_draw_rotated_bitmap(t1,w1/2,h1/2,x,y,theta+(PI/2),0);
	}
	else 
	{
		al_draw_rotated_bitmap(dt,wd/2,hd/2,x,y,theta+(PI/2),0);
	}
	tank2.drawtank(&x,&y,&theta);
	if(tank2.notdead())
	{
		al_draw_rotated_bitmap(t2,w2/2,h2/2,x,y,theta+(PI/2),0);
	}
	else 
	{
		al_draw_rotated_bitmap(dt,wd/2,hd/2,x,y,theta+(PI/2),0);
	}
	while(tank1.drawbullet(&x,&y,&theta))
	{
		al_draw_rotated_bitmap(bul,wb/2,hb/2,x,y,theta+(PI/2),0);
	}
	while(tank2.drawbullet(&x,&y,&theta))
	{
		al_draw_rotated_bitmap(bul,wb/2,hb/2,x,y,theta+(PI/2),0);
	}
	int i=0;
	float w,h;
	do {
		i = rock.draw(&x,&y,&theta);
		if(i)
		{
			al_draw_rotated_bitmap(rk,rw/2,rh/2,x,y,theta+(PI/2),0);
		}
		else if(i==-1)
		{
			if(rock.drawexplosion(&x,&y,&w,&h))
			{
				al_draw_scaled_bitmap(exp,0,0,ew,eh,x,y,w,h,0);
			}
			if(rock.checkkill(tank2.tankarea))
			{
				tank2.kill();
			}
		}
	} while (i!=0);
	al_flip_display();
}
int main(int argc, char **argv)
{
	int i = setup();
	initializetanks();
	wallcolor = al_map_rgb(50,230,10);
	if(i != 0)
	{
		return i;
	}
	else
	{
	ALLEGRO_EVENT_QUEUE *queue;
	queue = al_create_event_queue();
	if(!queue) {
		fprintf(stderr, "failed to create event queue!\n");
		al_destroy_display(display);
		return -1;
	}
	al_register_event_source(queue, al_get_display_event_source(display));
	al_register_event_source(queue, al_get_keyboard_event_source());
	al_register_event_source(queue, al_get_mouse_event_source());
	al_register_event_source(queue, al_get_timer_event_source(timer));
	al_start_timer(timer);
	int quit = 0;
	int redraw = 0;
		while (!quit)
		{
					ALLEGRO_EVENT ev;
					al_wait_for_event(queue, &ev);
					if (ev.type == ALLEGRO_EVENT_KEY_DOWN)
					{
						if(ev.keyboard.keycode==ALLEGRO_KEY_LEFT)
						{
							tank1.turn(-1);
						}
						else if(ev.keyboard.keycode==ALLEGRO_KEY_RIGHT)
						{
							tank1.turn(1);
						}
						else if(ev.keyboard.keycode==ALLEGRO_KEY_DOWN)
						{
							tank1.goback();
						}
						else if(ev.keyboard.keycode==ALLEGRO_KEY_SPACE)
						{
							tank1.startstop();
						}
						else if(ev.keyboard.keycode==ALLEGRO_KEY_UP)
						{
							tank1.shoot();
						}
						else if(ev.keyboard.keycode==ALLEGRO_KEY_ESCAPE)
						{
							quit=1;
						}
						else if(ev.keyboard.keycode==ALLEGRO_KEY_D)
						{
							tank1.kill();
						}
						else if(ev.keyboard.keycode==ALLEGRO_KEY_R)
						{
							float x,y,theta;
							tank1.drawtank(&x,&y,&theta);
							rock.launch(x,y,theta);
						}
						else if(ev.keyboard.keycode==ALLEGRO_KEY_N)
						{
							rock.setlimit(5);
						}
					}
					else if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
					{
						quit = 1;
					}
					else if(ev.type == ALLEGRO_EVENT_TIMER)
					{
						redraw = 1;
					}
					if(redraw && al_is_event_queue_empty(queue))
					{
						rock.move(tank2.tankarea);
						tank1.move(tank2);
						tank2.move(tank1);
						draw();
					}
		}
		al_destroy_event_queue(queue);
	}
	al_destroy_bitmap(t1);
	al_destroy_bitmap(t2);
	al_destroy_bitmap(bul);
	al_destroy_bitmap(dt);
	al_destroy_bitmap(rk);
	al_destroy_bitmap(exp);
	al_destroy_display(display);
	al_destroy_timer(timer);
	fprintf(stdout,"made it to last line\n");
	return 0;
}


The only goal I had when writing this was to make sure as little logic was in the draw() method as possible. As I was warned about that. It could be written better.
I solved part of the problem. vectors don't put limits on how much can be stored. What they do instead is when you call resize(int) it adds empty elements until the vector contains that many elements. Explaining the phantom rockets that don't move.

One thing I can't figure out is why would renew() and update() be called twice in a row. My program still freezes when a rocket is supposed to explode.

EDIT:
The problem is here: in main.cpp draw():
else if(i==-1)

Mystery deepens
Last edited on
One thing I want to mention, don't allocate variables\objects inside of your main running loop (I'm referring to Line 197 with the ALLEGRO_EVENT) in this case it isn't too terrible but it's something to keep in mind because it can get out of hand quickly.

Try rewriting what you know is wrong right now and see if after that you still have the trouble with the update and renew functions. I have a feeling that your "gun" object is what is invoking the functions from your rocket object and the files for that object aren't here.
I'm pretty sure what your talking about isn't happening, because tank doesn't hold any references, nor does it invoke any method from rocket. In fact Rocket takes some data input from tank, and that's it.

I'm in the process of rewriting. All I'm doing is taking out the explosion sequence part out of rocket, and I'm making a new object called explosionhandler handle all explosion sequnces. But now I have another problem:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
void explosionhandler::gettype(int ttype,ALLEGRO_BITMAP** b,int *nseq, float *aa, float *ee, float *mm)
{
	struct explosion_type *a = type;
	while((a->type!=ttype)&&(a!=0))
	{
		a=a->next;
	}
	*b = a->exp;
	*nseq = a->num_seq;
	*aa = a->a;
	*ee = a->e;
	*mm = a->m;
}
...
explosion x;
	for(int i;i<g;i++)
	{
		x = explosions.at(0);
		explosions.erase(explosions.begin());
		gettype(x.type,&exp,&nseq,&aa,&ee,&mm); //right here 

terminal:
1
2
3
explosionhandler.cpp: In member function ‘void explosionhandler::drawexplosions(ALLEGRO_BITMAP*)’:
explosionhandler.cpp:70: error: no matching function for call to ‘explosionhandler::gettype(int&, ALLEGRO_BITMAP**, float*, float*, float*, float*)’
explosionhandler.cpp:26: note: candidates are: void explosionhandler::gettype(int, ALLEGRO_BITMAP**, int*, float*, float*, float*)



huh?
The function "drawexplosions" is trying to call this function and pass in a reference to an integer and four float data types. You just have to change that.
Last edited on
Look, I just don't get it. does "at(int)" return a pointer or reference or something? Wow I didn't know that. OK.
So I tried:

1
2
3
x = explosions.at(0);
		explosions.erase(explosions.begin());
		gettype((*x).type,&exp,&nseq,&aa,&ee,&mm);


how the hell do I dereference a reference? The only time I ever dealt with references is when I used them in functions
Don't complicate things, just use the bracket operator []: http://www.cplusplus.com/reference/stl/vector/operator[]/

you know what, slap me across the face. That has got to be the dumbest question I ever asked. Cringe worthy.
I have one more question: This code right here is giving me a segfault:

1
2
3
4
5
6
7
8
9
10
11
12
13
void explosionhandler::registerexplosion(int *ttype, ALLEGRO_BITMAP* exp,int seq, float a, float m,float e)
{
	explosion_type *d;
	d->exp=exp;
	d->num_seq=seq;
	d->a=a;
	d->m=m;
	d->e=e;
	d->type=num_types;
	push(type,d);
	*ttype=num_types;
	num_types++;
}


I'm positive it has soemthing to do with "ALLEGRO_BITMAP* exp" What this code is create a new thing of struct explosion_type, which stores a pointer to a pic and other useful info so when I am drawing to the canvas I can quickly sort through the linked list for the pic. Is that stupid? What am I doing wrong?

EDIT: explosion_type is a linked list of structs that I use to store data on various explosion types from different weapons.
Last edited on
For the hell of it I tried the following:
1
2
3
4
5
6
7
8
9
10
11
12
void explosionhandler::registerbitmap(int ttype, ALLEGRO_BITMAP*& b)
{
	struct explosion_type *a = type;
	while((a->type!=ttype)&&(a!=0))
	{
		a=a->next;
	}
	if(a!=0)
	{
		*(a->exp)=b;
	}
}


and error message:
1
2
3
explosionhandler.cpp: In member function ‘void explosionhandler::registerbitmap(int, ALLEGRO_BITMAP*&)’:
explosionhandler.cpp:29: error: invalid use of incomplete type ‘struct ALLEGRO_BITMAP’
/usr/local/include/allegro5/mouse.h:99: error: forward declaration of ‘struct ALLEGRO_BITMAP’


I think I might be in the right track. I cut out the middle man so registerbitmap is being called in the main
OK so I changed the function registerexplosion to such:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void explosionhandler::registerexplosion(int& ttype,int seq,float a,float m,float e)
{
	//ttype=num_types;
	//num_types++;
	if(type==0)
	{
		type = new explosion_type;
		type->num_seq=seq;
		type->a=a;
		type->m=m;
		type->e=e;
		type->type=num_types;
		type->next=0;
	}
	else {
		explosion_type* d = new explosion_type;
		d->num_seq=seq;
		d->a=a;
		d->m=m;
		d->e=e;
		d->type=num_types;
		//push(type,d);
		d->next=type;
		type = d;
	}
	ttype=num_types; //gdb indicates this here is the problem. num_types is set to 0 in constructor.
	num_types++;
}


Not sure what to do here
@dancks
You have a possible memory leak in that registerexplosion function. You test if type is null and if it isn't (memory has been assigned) you allocate more memory and assign it to type leaking the previously allocated memory.
Last edited on
This is the part that is so strange:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "explosionhandler.h"
#include <math.h>
explosionhandler::explosionhandler()
{
	type=0;
	num_types=0;
}
void explosionhandler::registerexplosion(int& ttype,int seq,float a,float m,float e)
{
	/*if(!num_types)
	{
		type = new explosion_type;
		type->num_seq=seq;
		type->a=a;
		type->m=m;
		type->e=e;
		type->type=num_types;
		type->next=0;
	}
	else {
		explosion_type* d = new explosion_type;
		d->num_seq=seq;
		d->a=a;
		d->m=m;
		d->e=e;
		d->type=num_types;
		push(type,d);
	}
	ttype=num_types;
	num_types++;*/
	add(type);
}
void explosionhandler::add(explosion_type*& a)
{
	if(a!=0)
	{
		struct explosion_type* nnew = new explosion_type;
		nnew->a=100;
		nnew->m=30;
		nnew->e=10;
		nnew->num_seq=2;
		nnew->type=num_types;
		nnew->next = a;
		a = nnew;
	}
	else {
		a = new explosion_type;
		if(a==0)
		{
			throw "In add, new operator failed";
		}
		a->a=100;
		a->m=30;
		a->e=10;
		a->num_seq=2;
		a->type=-1;
		a->next=0;
	}
	num_types++;
}


There are a lot of attempts shown here, I changed some stuff around in register, I added a different method as an experiment, Here's the part thats so confusing:
Look at GDB's error output:
1
2
3
4
5
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000018
[Switching to process 26465]
0x000000010000804c in explosionhandler::add (this=0x0, a=@0x18) at explosionhandler.cpp:35
35		if(a!=0)


I honestly don't know what could cause this, unless its a bad pointer being passed. But I initialize to null in constructor so that can't be it. I'm not sure what the keyword 'this' points to
closed account (o3hC5Di1)
Hi there,

I'm no expert, but this line seems strange to me:

void explosionhandler::add(explosion_type*& a)

It seems to me like you're trying to pass a pointer by reference, in which case it would make more sense to me to pass a pointer to that pointer?

this returns a pointer to the current object it is used in.

All the best,
NwN
I guess it wouldn't matter. But hold on a sec:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void explosionhandler::add(explosion_type** a)
{
    if(a)
    {
        explosion_type n = new explosion_type;
        /* fill it up**/
        n->next = *a;
       *a = n;
       or
       **a = *n;
       or
       a = &n;   
       ????????
     }
     else
     {
          *a = new explosion_type;
          /** fill it up**/
      }
}


my gut tells me that the 2nd option is the best but IDK

still, GDB is telling me it fails at if(a)

so before anything else I need to figure out why that would fail. Unless its crashing somewhere else and it makes it to that line before it goes. The only thing I can think of is the memory pointed to by A is either bad or overwritten or something. But how? What do I look for?
Last edited on
closed account (o3hC5Di1)
Well what are you passing into the function?

Are you actually passing a pointer to a pointer - or just a pointer?

All the best,
NwN
when it was explosionhandler::add(explosion_type** a) it was add(&type) and for explosionhandler::add(explosion_type*& a) it was add(type). type is a pointer to struct explosion_type made in header, initialized to 0 in constructor:
.h:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef W_H
#define W_H
class explosionhandler {
public:
	...
	struct explosion {
		int type;
		int seq;
		float x,y;
		float radius;
	};
	vector<struct explosion> explosions;
	struct explosion_type {
		int type;
		int num_seq;
		//equation: size(#) = a + m*# - e*#^2
		float a,e,m;
		ALLEGRO_BITMAP* exp;
		explosion_type *next;
	} *type;
	int num_types;
	...
};
#endif 


and in .cpp:
1
2
3
4
explosionhandler::explosionhandler()
{
     type=0;
}
Pages: 12