Help with bullets in my Allegro 5 game. (Soon to be game)

Every time I fire my bullets, it always fires them out all in one burst. But I found that deleting break; at line 213 solves this. However, I think deleting this line just makes all the circles bunched together and it still takes my bullet count to 0 - as I can tell from bulletCount
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
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_font.h>
#include <allegro5/allegro_ttf.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_image.h>
#include "objects.h"

#define width 800
#define height 600
//Prototpyes
void initPlayer(Player &player);
void moveUp(Player &player);
void moveDown(Player &player);
void moveLeft(Player &player);
void moveRight(Player &player);
void initBullet(Bullet bullet[], int size);
void drawBullet(Bullet bullet[], int size);
void fireBullet(Bullet bullet[], int size, Player &player);
void updateBullet(Bullet bullet[], int size);


//Global Variables
enum direction {DOWN, LEFT, RIGHT, UP};
int dir = DOWN;
int bulletCount = 5;
const int NUM_BULLETS = 5;

int main()
{
	
	ALLEGRO_DISPLAY *display;

	if(!al_init())
	{
		al_show_native_message_box(NULL, NULL, "Error", "Falied to initialize allegro", NULL, NULL);
		return -1;
	}
	
	display = al_create_display(width, height);

	if(!display)
	{
		al_show_native_message_box(NULL, NULL, "Error", "Falied to initialize the display", NULL, NULL);
		return -1;
	}

	Player player;
	Bullet bullet[NUM_BULLETS];
	bool done = false, active = false, draw = true;
	int sourceX = 32, sourceY = 0;
	const float FPS = 55.0;


	al_init_image_addon();
	al_init_primitives_addon();
	al_install_keyboard();
	al_init_font_addon();
	al_init_ttf_addon();
	initPlayer(player);
	initBullet(bullet, NUM_BULLETS);

	ALLEGRO_KEYBOARD_STATE keystate;
	ALLEGRO_BITMAP *character = al_load_bitmap("spritesheet(guns).png");
	ALLEGRO_FONT *font = al_load_font("arialnb.ttf", 23, 0);
	ALLEGRO_TIMER *timer = al_create_timer(1.0/FPS);
	ALLEGRO_EVENT_QUEUE *event_queue = al_create_event_queue();
	al_register_event_source(event_queue, al_get_keyboard_event_source());
	al_register_event_source(event_queue, al_get_timer_event_source(timer));
	al_register_event_source(event_queue, al_get_display_event_source(display));

	al_start_timer(timer);
	while(!done)
	{
		ALLEGRO_EVENT event;
		al_wait_for_event(event_queue, &event);
		al_get_keyboard_state(&keystate);
			
		if(al_key_down(&keystate, ALLEGRO_KEY_ESCAPE))
		{
			done = true;
		}
		else if(event.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
		{
			done = true;
		}
		
		
		else if(event.type == ALLEGRO_EVENT_TIMER)
		{
			updateBullet(bullet, NUM_BULLETS);
			active = true;
		if(al_key_down(&keystate, ALLEGRO_KEY_UP))
		{
			moveUp(player);
		}
		else if(al_key_down(&keystate, ALLEGRO_KEY_DOWN))
		{
			
			moveDown(player);
		}
		else if(al_key_down(&keystate, ALLEGRO_KEY_RIGHT))
		{
			moveRight(player);
		}
		else if(al_key_down(&keystate, ALLEGRO_KEY_LEFT))
		{
			moveLeft(player);
		}
		else 
		{
			active = false;
		}
		if(active)
		{
			sourceX += al_get_bitmap_width(character) / 3;
		}
		else 
		{
			sourceX = 32; 
		}
		if(sourceX >= al_get_bitmap_width(character))
		{
			sourceX = 0;
		}
			sourceY = dir;
				draw = true;
				updateBullet(bullet, NUM_BULLETS);
		
	}
	if(al_key_down(&keystate, ALLEGRO_KEY_SPACE))
	{
		fireBullet(bullet, NUM_BULLETS, player);
	}
		


	if(draw && al_is_event_queue_empty(event_queue))
	{
	draw = false;
	al_draw_bitmap_region(character, sourceX, sourceY * al_get_bitmap_height(character) / 4, 32, 32, player.x, player.y, NULL);
	drawBullet(bullet,NUM_BULLETS);
	al_draw_textf(font, al_map_rgb(44,117, 255), 10, 500, 0, "Bullets: %i", bulletCount);
	al_flip_display();
	al_clear_to_color(al_map_rgb(255,255,255));
	}
  }

	return 0;
}
void initPlayer(Player &player)
{
	player.x = 10;
	player.y = 10;
	player.ID = PLAYER;
	player.lives = 3;
	player.speed = 5;
	player.score = 0;
}
void moveUp(Player &player)
{
	player.y -= player.speed;
	dir = UP;

}
void moveDown(Player &player)
{
	player.y += player.speed;
	dir = DOWN;
}
void moveLeft(Player &player)
{
	player.x -= player.speed;
	dir = LEFT;
}
void moveRight(Player &player)
{
	player.x += player.speed;
	dir = RIGHT;
}


void initBullet(Bullet bullet[], int size)
{
	for(int i = 0; i < size; i++)
	{
		bullet[i].ID = BULLET;
		bullet[i].speed = 3.5;
		bullet[i].live = false;
	}
}
void drawBullet(Bullet bullet[], int size)
{
	for(int i = 0; i < size; i++)
	{
		if(bullet[i].live)
		{
			al_draw_filled_circle(bullet[i].x, bullet[i].y, 2, al_map_rgb(0,0,0));
		}
	}
}

void fireBullet(Bullet bullet[], int size, Player &player)
{
	for( int i = 0; i < size; i++)
	{
		if(!bullet[i].live)
		{
			--bulletCount;
			bullet[i].x = player.x + 17;
			bullet[i].y = player.y;
			bullet[i].live = true;
			break;
		}
	}
}
void updateBullet(Bullet bullet[], int size)
{
	for(int i = 0; i < size; i++)
	{
		if(bullet[i].live)
		{
			bullet[i].x += bullet[i].speed;
			if(bullet[i].x > width && bulletCount >= size)
			{
				bullet[i].live = false;
			}

		}
		
	}
}

Objects.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
enum IDS {PLAYER, BULLET, ENEMY};

class Player
{
	public:
		int x;
		int y;
		int ID;
		int lives;
		int score;
		float speed;
	
};
class Bullet
{
	public:
		int ID;
		int x;
		int y;
		bool live;
		float speed;

};
closed account (D80DSL3A)
I'm not familiar with Allegro, but I don't think that matters here. It's a logic problem.

The call to fireBullet() on line 233 is being made at whatever the render rate is in frames per second, which may be really fast.
With the break statement at line 213 in place a call to fireBullet gets one bullet fired (the first for which live is found false). You said they fire "all at once" but I hope you meant 'rapidly'.
Removing that break would cause all bullets to actually be fired at once in a single call to fireBullet. The bullets would all have the exact same position values assigned so the lump of shots would appear to be a single shot.

You need to control the rate at which the fireBullet() function is being called.
Here's a simple solution which should enable semi-auto fire (one shot per press of the spacebar).
I am adapting from your code starting at line 131:
1
2
3
4
5
6
7
8
9
10
11
static bool fired = false;// static so the value persists between calls.
if(al_key_down(&keystate, ALLEGRO_KEY_SPACE) && !fired)
{
	fireBullet(bullet, NUM_BULLETS, player);
        fired = true;
}
// poll for 'spacebar up' state too
if(al_key_up(&keystate, ALLEGRO_KEY_SPACE))// is al_key_up valid? I'm guessing here.
{
        fired = false;// fire button released. OK to fire again.
}

Setting up a looping counter to support full-auto fire, but at a controlled rate, is also fairly simple. Let me know if you would like an example.

Your shot pool management method is similar to mine. I have found (through long use) that it works fine. You can even limit bursts just by making the pool size small because the only consequence of 'no shots left' is 'no shot fired'.

EDIT: This simpler code may also work:
1
2
3
4
5
6
7
8
static bool fired = false;
if(al_key_down(&keystate, ALLEGRO_KEY_SPACE) && !fired)
{
	fireBullet(bullet, NUM_BULLETS, player);
        fired = true;
}
else
    fired = false;
Last edited on
Thanks you! :D But your exact code didn't work, however fired did. And with working out where else it would need to go I got it to work. Thanks again
Last edited on
closed account (D80DSL3A)
Yeah, I may have misinterpreted some parts of your code. eg. I just noticed that the '}' line 130 is the match to '{' on line 90 so the code isn't organized as I was thinking.

I'm glad you got it working anyways.

EDIT:
Removing stuff not asked for.
Last edited on
Topic archived. No new replies allowed.