|
Sand Game Help |
Bingocat
Member #15,424
December 2013
|
I'm a beginner to c++ and allegro, so the code is bad. Whenever the amount of sand gets near or above 2000 the game freezes. Is there a better way to do collision with it? 1#include <allegro5\allegro.h>
2#include <allegro5\allegro_primitives.h>
3#include <allegro5\allegro_font.h>
4#include <allegro5\allegro_ttf.h>
5
6int width = 640;
7int height = 480;
8
9struct Particle
10{
11 int x;
12 int y;
13 int prevX;
14 int prevY;
15 bool active;
16 bool collision;
17};
18
19void InitSand(Particle sand[], int maxSand);
20void NewSand(Particle sand[], int maxSand, int x, int y, int &sandNum);
21void UpdateSand(Particle sand[], int maxSand);
22void DrawSand(Particle sand[], int maxSand);
23void CollideSand(Particle sand[], int maxSand);
24
25ALLEGRO_FONT *font18 = NULL;
26
27int main() {
28 int FPS = 60;
29 bool done = false;
30 bool redraw = true;
31 const int maxSand = 10000;
32 Particle sand[maxSand];
33 int mouseX;
34 int mouseY;
35 bool mouseHold = false;
36 int sandNum = 0;
37
38 al_init();
39 al_init_primitives_addon();
40 al_init_font_addon();
41 al_init_ttf_addon();
42 al_install_mouse();
43 InitSand(sand, maxSand);
44
45 ALLEGRO_DISPLAY *display = NULL;
46 ALLEGRO_EVENT_QUEUE *event_queue = NULL;
47 ALLEGRO_TIMER *timer = NULL;
48
49 display = al_create_display(width, height);
50 event_queue = al_create_event_queue();
51 timer = al_create_timer(1.0 / FPS);
52 font18 = al_load_font("arial.ttf", 18, 0);
53
54 al_register_event_source(event_queue, al_get_display_event_source(display));
55 al_register_event_source(event_queue, al_get_mouse_event_source());
56 al_register_event_source(event_queue, al_get_timer_event_source(timer));
57
58 al_start_timer(timer);
59
60
61 while (!done) {
62 ALLEGRO_EVENT ev;
63 al_wait_for_event(event_queue, &ev);
64
65 if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE)
66 done = true;
67 else if (ev.type == ALLEGRO_EVENT_TIMER) {
68 redraw = true;
69
70 for (int i = 0; i < maxSand; i++) {
71 if (sand[i].active) {
72 sand[i].prevX = sand[i].x;
73 sand[i].prevY = sand[i].y;
74 }
75 }
76
77 UpdateSand(sand, maxSand);
78 CollideSand(sand, sandNum);
79 }
80 else if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_DOWN) {
81 if (ev.mouse.button == 1)
82 mouseHold = true;
83 else if (ev.mouse.button == 2) {
84 InitSand(sand, maxSand);
85 sandNum = 0;
86 }
87 }
88 else if (ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) {
89 if (ev.mouse.button == 1)
90 mouseHold = false;
91 }
92 else if (ev.type == ALLEGRO_EVENT_MOUSE_AXES) {
93 mouseX = ev.mouse.x;
94 mouseY = ev.mouse.y;
95 }
96
97 if (mouseHold) {
98 NewSand(sand, maxSand, mouseX, mouseY, sandNum);
99 }
100
101 if (redraw && al_is_event_queue_empty(event_queue)) {
102 redraw = false;
103
104 al_draw_textf(font18, al_map_rgb(255, 255, 255), 0, 100, 0, "Amout of sand: %i %i %i", sandNum, mouseX, mouseY);
105 DrawSand(sand, maxSand);
106 al_flip_display();
107 al_clear_to_color(al_map_rgb(0,0,0));
108 }
109 }
110
111 al_destroy_display(display);
112 al_destroy_event_queue(event_queue);
113 al_destroy_timer(timer);
114 return 0;
115}
116
117void InitSand(Particle sand[], int maxSand) {
118 for (int i = 0; i < maxSand; i++) {
119 sand[i].active = false;
120 sand[i].x = 0;
121 sand[i].y = 0;
122 sand[i].collision = false;
123 }
124}
125void NewSand(Particle sand[], int maxSand, int x, int y, int &sandNum) {
126 for (int t = 0; t < 5; t++) {
127 for (int i = 0; i < maxSand; i++) {
128 if (!sand[i].active) {
129 sand[i].x = x + rand() % 10 - 5;
130 sand[i].y = y + rand() % 10 - 5;
131 sand[i].active = true;
132 sandNum++;
133 break;
134 }
135 }
136 }
137}
138void UpdateSand(Particle sand[], int maxSand) {
139 for (int i = 0; i < maxSand; i++) {
140 if (sand[i].active) {
141 sand[i].y += 1;
142 }
143 }
144}
145void DrawSand(Particle sand[], int maxSand) {
146 for (int i = 0; i < maxSand; i++) {
147 if (sand[i].active) {
148 al_draw_pixel(sand[i].x, sand[i].y, al_map_rgb(255, 195, 33));
149 //al_draw_filled_rectangle(sand[i].x, sand[i].y, sand[i].x + 5, sand[i].y + 5, al_map_rgb(255, 195, 33));
150 }
151 }
152}
153
154void CollideSand(Particle sand[], int maxSand) {
155 for (int i = 0; i < maxSand; i++) {
156 if (sand[i].y >= height)
157 sand[i].y = height;
158 if (sand[i].active) {
159 for (int j = 0; j < maxSand; j++) {
160 if (sand[j].active && i != j) {
161 if (sand[i].x == sand[j].x && sand[i].y == sand[j].y) {
162 if (sand[i].prevY <= sand[j].y)
163 sand[i].y = sand[j].y - 1;
164 }
165 }
166 }
167 }
168 }
169}
|
hyreia77
Member #13,742
November 2011
|
I see two main issues: yes the collision and the other is the drawing. Let's tackle the drawing first. That's a slightly easier fix. You're drawing 10,000 pixels to the screen 60 times a second. Now, the collision is much more complicated: you're testing 10,000 objects against 9,999 other objects. That's 99,990,000 tests I think. If all you're doing is stopping the sand from falling when it encounters more sand, instead consider just testing the next pixel it might move to to see if it's sand colored. al_get_pixel, but be sure to lock the bitmap before you start this process for the same reason. This is from my experience, maybe try that and see if anyone comes along to tell you otherwise. |
|