[EDIT: first question removed! (Stupid, stupid, stupid!)]
Now, my second question (particle panic!) involves linked-lists which I have had absolutely no experience with. My program has been freezing occasionally since I added the particle engine. Which seems to me like it's a memory leak. I just wanted to know if this looked alright before I dived into really hunting it down:
particle.h:
typedef struct part_list{ double x, y, z; double dx, dy, dz; // direction double rx, ry, rz; // randomness double tx, ty, tz; // last location int visible, life, birth; struct part_list *next; }particle_list;
particle.c:
1 | void update_particles() |
2 | { |
3 | |
4 | int r_x, r_y, r_z; |
5 | |
6 | particle_list *tmp, *next; |
7 | for(tmp = p_head; tmp; tmp = next){ |
8 | next = tmp->next; |
9 | |
10 | if( tmp->life > 0 ) { |
11 | |
12 | if( tmp->birth<=0 ) { |
13 | |
14 | tmp->tx = tmp->x; |
15 | tmp->ty = tmp->y; |
16 | tmp->tz = tmp->z; |
17 | |
18 | tmp->x += tmp->dx; |
19 | tmp->y += tmp->dy; |
20 | tmp->z += tmp->dz; |
21 | |
22 | if(tmp->rx > 0) tmp->x += random_particle_direction((tmp->rx*2)) - tmp->rx; |
23 | if(tmp->ry > 0) tmp->y += random_particle_direction((tmp->ry*2)) - tmp->ry; |
24 | if(tmp->rz > 0) tmp->z += random_particle_direction((tmp->rz*2)) - tmp->rz; |
25 | |
26 | tmp->life--; |
27 | |
28 | if(tmp->life<=0) tmp->visible=0; |
29 | |
30 | } else { |
31 | |
32 | tmp->birth--; |
33 | |
34 | if(tmp->birth==0) tmp->visible=1; |
35 | |
36 | } |
37 | |
38 | } |
39 | |
40 | } |
41 | |
42 | clean_particle_tree(); |
43 | |
44 | } |
45 | |
46 | void clean_particle_tree() { |
47 | |
48 | particle_list *tmp, *next; |
49 | for(tmp = p_head; tmp; tmp = next){ |
50 | |
51 | next = tmp->next; |
52 | |
53 | if(tmp->life <= 0) { |
54 | delete_particle_node(tmp->x, tmp->y, tmp->z); |
55 | } |
56 | |
57 | } |
58 | |
59 | } |
60 | |
61 | void render_particles() { |
62 | |
63 | particle_list *tmp, *next; |
64 | for(tmp = p_head; tmp; tmp = next){ |
65 | |
66 | next = tmp->next; |
67 | |
68 | if(tmp->visible) |
69 | render_object (buffer, particle, camera.angle, camera.x + itofix(tmp->x), camera.y + itofix(tmp->y), camera.z - itofix(tmp->z), camera); |
70 | |
71 | } |
72 | |
73 | } |
74 | |
75 | void add_particle_node(int birth, int life, |
76 | int x, int y, int z, |
77 | int dx, int dy, int dz, |
78 | int rx, int ry, int rz |
79 | ){ |
80 | |
81 | particle_list *tmp = (particle_list *)malloc(sizeof(particle_list)); |
82 | if(!tmp) return; |
83 | |
84 | tmp->x = x; tmp->y = y; tmp->z = z; |
85 | tmp->dz = dz; tmp->dx = dx; tmp->dy = dy; |
86 | tmp->rx = rx; tmp->ry = ry; tmp->rz = rz; |
87 | |
88 | tmp->birth = birth; |
89 | tmp->visible = 0; |
90 | tmp->life = life; |
91 | tmp->next = p_head; |
92 | |
93 | p_head = tmp; |
94 | |
95 | } |
96 | |
97 | void delete_particle_node(int x, int y, int z){ |
98 | |
99 | particle_list *tmp, *next, *prev; |
100 | for(tmp = p_head, prev = p_head; tmp; prev = tmp, tmp = next){ |
101 | |
102 | next = tmp->next; |
103 | |
104 | if(tmp->x == x && tmp->y == y && tmp->z == z){ |
105 | |
106 | free(tmp); |
107 | |
108 | if(prev == tmp) { |
109 | p_head = next; |
110 | } else { |
111 | prev->next = next; |
112 | } |
113 | |
114 | } |
115 | |
116 | } |
117 | |
118 | } |
119 | |
120 | void destroy_all_particles(){ |
121 | |
122 | particle_list *tmp, *next; |
123 | for(tmp = p_head; tmp; tmp = next){ |
124 | |
125 | next = tmp->next; |
126 | free(tmp); |
127 | |
128 | } |
129 | p_head = NULL; |
130 | |
131 | } |
]]>
Use arc for drawing partial circles (arcs). Just increase angle every frame.
]]>Why do you use the x,y,z coordinates to identify a particle to delete? Why not the pointer itself?
Like this you have to do a test for equality of doubles, which should always be avoided I think. And, although unlikely, you could have two particles at exactly the same spot.
]]>Good point! I changed my code. Is this what you mean?
1 | void clean_particle_tree() { |
2 | |
3 | particle_list *tmp, *next; |
4 | for(tmp = p_head; tmp; tmp = next){ |
5 | |
6 | next = tmp->next; |
7 | |
8 | if(tmp->life <= 0) { |
9 | delete_particle_node(tmp); |
10 | } |
11 | |
12 | } |
13 | |
14 | } |
15 | |
16 | void delete_particle_node(particle_list *tmp_t){ |
17 | |
18 | particle_list *tmp, *next, *prev; |
19 | for(tmp = p_head, prev = p_head; tmp; prev = tmp, tmp = next){ |
20 | |
21 | next = tmp->next; |
22 | |
23 | if(tmp == tmp_t){ |
24 | |
25 | free(tmp); |
26 | |
27 | if(prev == tmp) { |
28 | p_head = next; |
29 | } else { |
30 | prev->next = next; |
31 | } |
32 | |
33 | } |
34 | |
35 | } |
36 | |
37 | } |
]]>
You shouldn't remove questions, even stupid ones since someone else might have same problem and get here through search.
Also, in C if you write function like foo() it means that function take varying number of arguments, for no arguments use foo(void).
]]>Problem with do_circle (arcs isn't what I wanted):
1 | int c_click; |
2 | |
3 | void draw_spawn_point(BITMAP *bmp, int x, int y, int d) { |
4 | |
5 | int i; |
6 | |
7 | c_click++; |
8 | if(c_click == d) { |
9 | |
10 | add_object_node(1, x, y, 0); |
11 | |
12 | for(i = 0; i < 10; i++) { |
13 | |
14 | add_particle_node(rand()%50, rand()%150, |
15 | (x - 5) + rand()%20, (y - 5) + rand()%20, rand()%10, |
16 | 0, 0, 2, |
17 | 0, 0, 0); |
18 | |
19 | } |
20 | |
21 | c_click = 0; |
22 | |
23 | } |
24 | |
25 | } |
26 | |
27 | void create_spawn_point(int size, int s_size, int x_s, int y_s) { |
28 | |
29 | c_click = 0; |
30 | |
31 | add_object_node(1, x_s, y_s, 0); // add centre node |
32 | |
33 | do_circle(buffer, x_s, y_s, size, s_size, draw_spawn_point); |
34 | |
35 | } |
Now. The code works but when I have it placing a sprite within do_circle I end up with a huge amount of sprites per circle. So I wanted to cut that down. I thought that if I passed s_size as 10(which become d in draw_spawn_point). It would only draw a sprite every 10 calls to draw_spawn_point. Sadly, this doesn't work. It seems like it only calls the function for some areas of the circle, but not for others?! This is confusing as, if I remove the c_click counter, the entire circle is drawn.
Do I not understand the callback functionality?
]]>void clean_particle_tree() { particle_list *tmp, *next; for(tmp = p_head; tmp; tmp = next){ //You're always skipping the head of the list: next = tmp->next; if(tmp->life <= 0) { delete_particle_node(tmp->x, tmp->y, tmp->z); } } }
The head of the list never gets deleted, or anything else.....
Edit; oops, n/m I'm wrong.
]]>