dungeon_crawler

view prototype/src/level.cc @ 49:303743485aba

pretty much implemented the positional torch sound sources
author John Tsiombikas <nuclear@member.fsf.org>
date Tue, 18 Sep 2012 00:34:29 +0300
parents aa9e28670ae2
children c40efa9cf844
line source
1 #include <stdio.h>
2 #include <string.h>
3 #include <errno.h>
4 #include "opengl.h"
5 #include "level.h"
6 #include "tile.h"
7 #include "tileset.h"
8 #include "cfg.h"
10 Level::Level()
11 {
12 cell_size = 1.0;
14 cells = 0;
15 xsz = ysz = 0;
16 }
18 Level::~Level()
19 {
20 delete [] cells;
22 for(auto cell : cell_list) {
23 delete cell;
24 }
25 }
27 bool Level::load(const char *fname)
28 {
29 if(!fname) {
30 return false;
31 }
33 TileSet *tileset = get_active_tileset();
34 if(!tileset) {
35 fprintf(stderr, "level loading failed: no active tileset\n");
36 return false;
37 }
38 Tile *deftile = tileset->get_tile("default");
39 if(!deftile) {
40 fprintf(stderr, "level loading failed: active tileset has no default tile\n");
41 return false;
42 }
44 FILE *fp = fopen(fname, "r");
45 if(!fp) {
46 fprintf(stderr, "failed to open level: %s: %s\n", fname, strerror(errno));
47 return false;
48 }
50 char buf[512];
51 fgets(buf, sizeof buf, fp);
52 if(sscanf(buf, "SIZE %dx%d", &xsz, &ysz) != 2) {
53 fprintf(stderr, "invalid or corrupt level file: %s\n", fname);
54 fclose(fp);
55 return false;
56 }
57 printf("level size: %dx%d\n", xsz, ysz);
59 cells = new GridCell*[xsz * ysz];
60 memset(cells, 0, xsz * ysz * sizeof *cells);
62 int y = 0;
63 GridCell **grid_row = cells;
65 while(fgets(buf, sizeof buf, fp)) {
66 for(int i=0; i<xsz; i++) {
67 if(!buf[i] || buf[i] == '\r' || buf[i] == '\n') {
68 grid_row += xsz - i;
69 break;
70 }
72 if(isalpha(buf[i]) || buf[i] == ' ') {
73 GridCell *cell = new GridCell(deftile);
74 *grid_row = cell;
75 cell_list.push_back(*grid_row);
77 // add any audio sources in this grid-cell to the level static audio manager
78 std::list<Tile::AudioSourceDesc> asrc = cell->get_audio_sources();
79 for(auto sdesc : asrc) {
80 AudioSource *s = new AudioSource;
81 s->set_sample(sdesc.sample);
82 s->set_position(sdesc.pos + get_cell_pos(i, y));
83 austatic.add_source(s);
84 }
85 }
86 grid_row++;
87 }
89 if(++y >= ysz) {
90 break;
91 }
92 }
93 fclose(fp);
95 return true;
96 }
98 bool Level::save(const char *fname) const
99 {
100 return false;
101 }
103 const GridCell *Level::get_cell(int x, int y) const
104 {
105 if(x < 0 || x >= xsz || y < 0 || y >= ysz) {
106 return 0;
107 }
108 return cells[y * xsz + x];
109 }
111 Vector3 Level::get_cell_pos(int x, int y) const
112 {
113 float posx = (float)x * cell_size;
114 float posy = (float)y * cell_size;
115 posx -= cell_size * (float)xsz / 2.0f;
116 posy -= cell_size * (float)ysz / 2.0f;
117 return Vector3(posx, 0, posy);
118 }
120 void Level::get_cell_coords_at(const Vector3 &pos, int *xptr, int *yptr) const
121 {
122 float posx = pos.x + cell_size * (float)xsz / 2.0f;
123 float posy = pos.z + cell_size * (float)ysz / 2.0f;
124 *xptr = (int)round(posx / cell_size);
125 *yptr = (int)round(posy / cell_size);
126 }
128 unsigned int Level::get_cell_dirmask(int x, int y) const
129 {
130 unsigned int dmask = TILE_ALL;
131 if(y > 0 && get_cell(x, y - 1)) {
132 dmask &= ~TILE_NORTH;
133 }
134 if(y < ysz - 1 && get_cell(x, y + 1)) {
135 dmask &= ~TILE_SOUTH;
136 }
137 if(x > 0 && get_cell(x - 1, y)) {
138 dmask &= ~TILE_WEST;
139 }
140 if(x < xsz - 1 && get_cell(x + 1, y)) {
141 dmask &= ~TILE_EAST;
142 }
143 return dmask;
144 }
146 void Level::set_player_position(const Vector3 &ppos)
147 {
148 player_pos = ppos;
149 }
151 void Level::update(unsigned long msec, float dt)
152 {
153 for(auto cell : cell_list) {
154 cell->update(msec, dt);
155 }
157 // activate the closest audio sources
158 if(cfg.sound) {
159 austatic.active_range(player_pos, 2.0);
160 }
161 }
163 void Level::draw() const
164 {
165 glMatrixMode(GL_MODELVIEW);
167 for(int i=0; i<ysz; i++) {
168 for(int j=0; j<xsz; j++) {
169 const GridCell *cell = get_cell(j, i);
170 if(cell) {
171 Vector3 pos = get_cell_pos(j, i);
172 glPushMatrix();
173 glTranslatef(pos.x, pos.y, pos.z);
174 glScalef(cell_size, cell_size, cell_size);
176 unsigned int dmask = get_cell_dirmask(j, i);
178 cell->draw(dmask);
179 glPopMatrix();
180 }
181 }
182 }
183 }
185 void Level::draw_lights() const
186 {
187 glMatrixMode(GL_MODELVIEW);
189 for(int i=0; i<ysz; i++) {
190 for(int j=0; j<xsz; j++) {
191 const GridCell *cell = get_cell(j, i);
192 if(cell) {
193 Vector3 pos = get_cell_pos(j, i);
195 glPushMatrix();
196 glTranslatef(pos.x, pos.y, pos.z);
197 glScalef(cell_size, cell_size, cell_size);
199 unsigned int dmask = get_cell_dirmask(j, i);
200 cell->draw_lights(dmask);
202 glPopMatrix();
203 }
204 }
205 }
206 }
208 void Level::draw_post() const
209 {
210 glMatrixMode(GL_MODELVIEW);
212 for(int i=0; i<ysz; i++) {
213 for(int j=0; j<xsz; j++) {
214 const GridCell *cell = get_cell(j, i);
215 if(cell) {
216 Vector3 pos = get_cell_pos(j, i);
217 glPushMatrix();
218 glTranslatef(pos.x, pos.y, pos.z);
219 glScalef(cell_size, cell_size, cell_size);
221 unsigned int dmask = get_cell_dirmask(j, i);
223 cell->draw_post(dmask);
224 glPopMatrix();
225 }
226 }
227 }
228 }
230 void Level::draw_grid() const
231 {
232 float xlen = xsz * cell_size;
233 float ylen = ysz * cell_size;
235 glPushAttrib(GL_ENABLE_BIT);
236 glDisable(GL_LIGHTING);
238 glBegin(GL_LINES);
239 glColor3f(0.4, 0.4, 0.4);
241 float y = -ylen / 2.0 - cell_size / 2.0;
242 for(int i=0; i<ysz; i++) {
243 glVertex3f(-xlen / 2.0, 0, y);
244 glVertex3f(xlen / 2.0, 0, y);
245 y += cell_size;
246 }
248 float x = -xlen / 2.0 - cell_size / 2.0;
249 for(int i=0; i<xsz; i++) {
250 glVertex3f(x, 0, -ylen / 2.0);
251 glVertex3f(x, 0, ylen / 2.0);
252 x += cell_size;
253 }
254 glEnd();
256 glPopAttrib();
257 }
260 AudioSample *Level::get_sample(int x, int y, int which) const
261 {
262 const GridCell *cell = get_cell(x, y);
263 if(!cell) {
264 return 0;
265 }
266 return cell->get_sample(which);
267 }
270 GridCell::GridCell(Tile *tile)
271 {
272 if(tile) {
273 add_tile(tile);
274 }
275 }
277 void GridCell::add_tile(Tile *tile)
278 {
279 if(!tile) {
280 return;
281 }
283 tiles.push_back(tile);
285 /* instanciate any particle systems */
286 int num_psattr = tile->get_unique_psys_count();
288 for(int i=0; i<num_psattr; i++) {
289 const struct psys_attributes *psattr = tile->get_unique_psys(i);
290 struct psys_emitter *emitter = psys_create();
291 emitter->attr = *psattr;
292 psys.push_back(emitter);
293 }
294 }
296 void GridCell::update(unsigned long msec, float dt)
297 {
298 for(auto ps : psys) {
299 psys_update(ps, (float)msec / 1000.0f);
300 }
301 }
303 void GridCell::draw(unsigned int draw_mask) const
304 {
305 for(auto tile : tiles) {
306 tile->draw(draw_mask);
307 }
308 }
310 void GridCell::draw_lights(unsigned int draw_mask) const
311 {
312 for(auto tile : tiles) {
313 tile->draw_lights(draw_mask);
314 }
315 }
317 void GridCell::draw_post(unsigned int draw_mask) const
318 {
319 for(auto tile : tiles) {
320 tile->draw_post(draw_mask);
321 }
322 for(auto ps : psys) {
323 psys_draw(ps);
324 }
325 }
327 AudioSample *GridCell::get_sample(int which) const
328 {
329 for(auto tile : tiles) {
330 AudioSample *s = tile->get_sample(which);
331 if(s) {
332 return s;
333 }
334 }
335 return 0;
336 }
338 std::list<Tile::AudioSourceDesc> GridCell::get_audio_sources() const
339 {
340 std::list<Tile::AudioSourceDesc> srclist;
342 for(auto tile : tiles) {
343 int num_src = tile->get_audio_source_count();
344 for(int i=0; i<num_src; i++) {
345 srclist.push_back(tile->get_audio_source(i));
346 }
347 }
348 return srclist;
349 }