labyrinth

view src/main.c @ 0:8ba79034e8a6

labyrinth example initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 15 Jan 2015 14:59:38 +0200
parents
children e3b9707504df
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <assert.h>
5 #include "opengl.h"
6 #include "player.h"
7 #include "level.h"
8 #include "noise.h"
9 #include "texture.h"
10 #include "mesh.h"
12 #define PLAYER_EYE_HEIGHT 1.65
14 static int init(void);
15 static void update(unsigned int msec);
16 static void display(void);
17 static void draw_scene(unsigned int msec);
18 static void idle(void);
19 static void reshape(int x, int y);
20 static void key_down(unsigned char key, int x, int y);
21 static void key_up(unsigned char key, int x, int y);
22 static void mouse(int bn, int state, int x, int y);
23 static void motion(int x, int y);
25 static int win_width, win_height;
26 static struct level level;
27 static struct player player;
28 static int mouselook, freelook = 1;
29 static char keystate[256];
31 static struct mesh *monkey_mesh;
32 static unsigned int envmap;
33 static unsigned int win_tex;
35 static int game_won;
37 static float dbg_cam_dist = 0.0;
39 int main(int argc, char **argv)
40 {
41 glutInit(&argc, argv);
42 glutInitWindowSize(1280, 800);
43 glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
44 glutCreateWindow("labyrinth game example");
46 glutDisplayFunc(display);
47 glutIdleFunc(idle);
48 glutReshapeFunc(reshape);
49 glutKeyboardFunc(key_down);
50 glutKeyboardUpFunc(key_up);
51 glutMouseFunc(mouse);
52 glutMotionFunc(motion);
54 if(init() == -1) {
55 return 1;
56 }
57 glutMainLoop();
58 return 0;
59 }
62 static int init(void)
63 {
64 glEnable(GL_DEPTH_TEST);
65 glEnable(GL_CULL_FACE);
66 glEnable(GL_LIGHTING);
67 glEnable(GL_NORMALIZE);
69 glEnable(GL_LIGHT0);
70 glEnable(GL_LIGHT1);
72 /* set a slightly bluish cold ambient light */
73 {
74 float ambient[] = {0.08, 0.1, 0.3, 1.0};
75 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
76 }
78 level_init(&level);
79 if(level_load(&level, "data/0.level") == -1) {
80 fprintf(stderr, "level loading failed\n");
81 return -1;
82 }
84 if(!(level.wall_tex = load_texture("data/wall.ppm"))) {
85 return -1;
86 }
87 if(!(level.floor_tex = load_texture("data/floor.ppm"))) {
88 return -1;
89 }
90 level.floor_tex_scale = 1.0;
91 if(!(level.ceil_tex = load_texture("data/ceil.ppm"))) {
92 return -1;
93 }
94 level.ceil_tex_scale = 2.0;
97 if(!(monkey_mesh = load_mesh("data/monkey.obj"))) {
98 return -1;
99 }
100 if(!(envmap = load_texture("data/refmap.ppm"))) {
101 return -1;
102 }
104 if(!(win_tex = load_texture("data/done.ppm"))) {
105 return -1;
106 }
108 player_init(&player, &level);
109 return 0;
110 }
112 static void update(unsigned int msec)
113 {
114 static unsigned int prev_upd;
115 float dfwd = 0.0f;
116 float dright = 0.0f;
117 float walk_speed = 8.0;
119 float dt = (float)(msec - prev_upd) / 1000.0f;
120 prev_upd = msec;
122 if(game_won) return;
124 if(freelook) {
125 if(keystate['w'] || keystate['W']) {
126 dfwd += walk_speed * dt;
127 }
128 if(keystate['s'] || keystate['S']) {
129 dfwd -= walk_speed * dt;
130 }
131 if(keystate['d'] || keystate['D']) {
132 dright += walk_speed * dt * 0.6;
133 }
134 if(keystate['a'] || keystate['A']) {
135 dright -= walk_speed * dt * 0.6;
136 }
138 player_move(&player, dfwd, dright);
139 }
141 if(level_cell_at(&level, player.x, player.y) == 'x') {
142 game_won = 1;
143 }
144 }
146 static void display(void)
147 {
148 float flicker = 1.0f;
149 unsigned int msec = glutGet(GLUT_ELAPSED_TIME);
151 update(msec);
153 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
155 glMatrixMode(GL_MODELVIEW);
156 glLoadIdentity();
157 glTranslatef(0, 0, -dbg_cam_dist);
158 /* set view matrix according to player pos/rot */
159 player_setup_view_matrix(&player);
160 glTranslatef(0, -PLAYER_EYE_HEIGHT, 0);
162 /* setup lights */
163 flicker = fbm1((float)msec / 500.0f, 2) * 0.4 + 0.6;
164 set_light_position(0, player.x, PLAYER_EYE_HEIGHT + 0.2, player.y);
165 set_light_color(0, 1.0 * flicker, 0.6 * flicker, 0.3 * flicker);
166 set_light_attenuation(0, 0.5, 0, 0.04);
168 set_light_position(1, level.goal_pos[0], 0.8, level.goal_pos[1]);
169 set_light_color(1, 0.955, 0.75, 0.06);
170 set_light_attenuation(1, 0.9, 0, 0.05);
172 /* draw the scene */
173 draw_scene(msec);
175 glutSwapBuffers();
176 assert(glGetError() == GL_NO_ERROR);
177 }
179 static void draw_scene(unsigned int msec)
180 {
181 float x, y;
182 float tsec = (float)msec / 1000.0f;
184 level_draw(&level);
186 /* draw the golden monkey */
187 if(level_obj_pos(&level, 'x', &x, &y)) {
188 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
189 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
190 glEnable(GL_TEXTURE_GEN_S);
191 glEnable(GL_TEXTURE_GEN_T);
193 glBindTexture(GL_TEXTURE_2D, envmap);
194 glEnable(GL_TEXTURE_2D);
196 set_mtl_diffuse(0.1, 0.1, 0.1, 1);
197 set_mtl_specular(0.955, 0.75, 0.06);
198 set_mtl_shininess(80.0);
199 set_mtl_emission(0.955, 0.75 * 0.7, 0.06 * 0.1);
201 glMatrixMode(GL_MODELVIEW);
202 glPushMatrix();
203 glTranslatef(x, 0.8 + sin(tsec * 2.0) * 0.1, y);
204 glRotatef(tsec * 100.0, 0, 1, 0);
205 glRotatef(sin(tsec * 3.0) * 10.0, 1, 0, 0);
206 glScalef(0.3, 0.3, 0.3);
208 render_mesh(monkey_mesh);
210 glPopMatrix();
212 set_mtl_emission(0, 0, 0);
214 glDisable(GL_TEXTURE_2D);
216 glDisable(GL_TEXTURE_GEN_S);
217 glDisable(GL_TEXTURE_GEN_T);
218 }
220 /* draw the win text */
221 if(game_won) {
222 glMatrixMode(GL_MODELVIEW);
223 glPushMatrix();
224 glLoadIdentity();
225 glMatrixMode(GL_PROJECTION);
226 glPushMatrix();
227 glLoadIdentity();
228 glScalef((float)win_height / (float)win_width, 1, 1);
230 glBindTexture(GL_TEXTURE_2D, win_tex);
231 glEnable(GL_TEXTURE_2D);
233 glEnable(GL_BLEND);
234 glBlendFunc(GL_ONE, GL_ONE);
235 glDisable(GL_LIGHTING);
237 glBegin(GL_QUADS);
238 glTexCoord2f(0, 1); glVertex2f(-1, -1);
239 glTexCoord2f(1, 1); glVertex2f(1, -1);
240 glTexCoord2f(1, 0); glVertex2f(1, 1);
241 glTexCoord2f(0, 0); glVertex2f(-1, 1);
242 glEnd();
244 glDisable(GL_BLEND);
245 glDisable(GL_TEXTURE_2D);
246 glEnable(GL_LIGHTING);
248 glPopMatrix();
249 glMatrixMode(GL_MODELVIEW);
250 glPopMatrix();
251 }
252 }
254 static void idle(void)
255 {
256 glutPostRedisplay();
257 }
259 static void reshape(int x, int y)
260 {
261 win_width = x;
262 win_height = y;
263 glViewport(0, 0, x, y);
264 glMatrixMode(GL_PROJECTION);
265 glLoadIdentity();
266 gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0);
267 }
269 static int warping_mouse;
271 static void key_down(unsigned char key, int x, int y)
272 {
273 keystate[key] = 1;
275 switch(key) {
276 case 27:
277 exit(0);
279 case 'a':
280 if(!freelook && !game_won) {
281 player_turn(&player, -90, 0);
282 }
283 break;
285 case 'd':
286 if(!freelook && !game_won) {
287 player_turn(&player, 90, 0);
288 }
289 break;
291 case 'w':
292 case 's':
293 if(!freelook && !game_won) {
294 float prev_x = player.x;
295 float prev_y = player.y;
296 float sign = key == 'w' ? 1.0 : -1.0;
298 if(!player_move(&player, level.cell_size * sign, 0)) {
299 player.x = prev_x;
300 player.y = prev_y;
301 }
302 }
303 break;
305 case '`':
306 case '~':
307 mouselook = !mouselook;
308 if(mouselook) {
309 warping_mouse = 1;
310 glutWarpPointer(win_width / 2, win_height / 2);
311 glutPassiveMotionFunc(motion);
312 glutSetCursor(GLUT_CURSOR_NONE);
313 } else {
314 glutPassiveMotionFunc(0);
315 glutSetCursor(GLUT_CURSOR_INHERIT);
316 }
317 break;
319 case 'b':
320 case 'B':
321 freelook = !freelook;
322 break;
324 case 'r':
325 case 'R':
326 game_won = 0;
327 player_init(&player, &level);
328 break;
330 default:
331 break;
332 }
333 }
335 static void key_up(unsigned char key, int x, int y)
336 {
337 keystate[key] = 0;
338 }
340 static int bnstate[16];
341 static int prev_x, prev_y;
343 static void mouse(int bn, int state, int x, int y)
344 {
345 prev_x = x;
346 prev_y = y;
347 bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN ? 1 : 0;
348 }
350 static void motion(int x, int y)
351 {
352 int dx, dy;
353 int cx = win_width / 2;
354 int cy = win_height / 2;
356 if(warping_mouse) {
357 warping_mouse = 0;
358 return;
359 }
361 dx = x - (mouselook ? cx : prev_x);
362 dy = y - (mouselook ? cy : prev_y);
363 prev_x = x;
364 prev_y = y;
366 if(!dx && !dy) return;
368 if(mouselook || bnstate[0]) {
369 player_turn(&player, dx * 0.5, dy * 0.5);
370 }
371 if(bnstate[2]) {
372 dbg_cam_dist += 0.1 * dy;
373 if(dbg_cam_dist < 0.0) dbg_cam_dist = 0.0;
374 }
376 if(mouselook) {
377 warping_mouse = 1;
378 glutWarpPointer(cx, cy);
379 prev_x = cx;
380 prev_y = cy;
381 }
382 }