labyrinth
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/main.c Thu Jan 15 14:59:38 2015 +0200 1.3 @@ -0,0 +1,382 @@ 1.4 +#include <stdio.h> 1.5 +#include <stdlib.h> 1.6 +#include <math.h> 1.7 +#include <assert.h> 1.8 +#include "opengl.h" 1.9 +#include "player.h" 1.10 +#include "level.h" 1.11 +#include "noise.h" 1.12 +#include "texture.h" 1.13 +#include "mesh.h" 1.14 + 1.15 +#define PLAYER_EYE_HEIGHT 1.65 1.16 + 1.17 +static int init(void); 1.18 +static void update(unsigned int msec); 1.19 +static void display(void); 1.20 +static void draw_scene(unsigned int msec); 1.21 +static void idle(void); 1.22 +static void reshape(int x, int y); 1.23 +static void key_down(unsigned char key, int x, int y); 1.24 +static void key_up(unsigned char key, int x, int y); 1.25 +static void mouse(int bn, int state, int x, int y); 1.26 +static void motion(int x, int y); 1.27 + 1.28 +static int win_width, win_height; 1.29 +static struct level level; 1.30 +static struct player player; 1.31 +static int mouselook, freelook = 1; 1.32 +static char keystate[256]; 1.33 + 1.34 +static struct mesh *monkey_mesh; 1.35 +static unsigned int envmap; 1.36 +static unsigned int win_tex; 1.37 + 1.38 +static int game_won; 1.39 + 1.40 +static float dbg_cam_dist = 0.0; 1.41 + 1.42 +int main(int argc, char **argv) 1.43 +{ 1.44 + glutInit(&argc, argv); 1.45 + glutInitWindowSize(1280, 800); 1.46 + glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE); 1.47 + glutCreateWindow("labyrinth game example"); 1.48 + 1.49 + glutDisplayFunc(display); 1.50 + glutIdleFunc(idle); 1.51 + glutReshapeFunc(reshape); 1.52 + glutKeyboardFunc(key_down); 1.53 + glutKeyboardUpFunc(key_up); 1.54 + glutMouseFunc(mouse); 1.55 + glutMotionFunc(motion); 1.56 + 1.57 + if(init() == -1) { 1.58 + return 1; 1.59 + } 1.60 + glutMainLoop(); 1.61 + return 0; 1.62 +} 1.63 + 1.64 + 1.65 +static int init(void) 1.66 +{ 1.67 + glEnable(GL_DEPTH_TEST); 1.68 + glEnable(GL_CULL_FACE); 1.69 + glEnable(GL_LIGHTING); 1.70 + glEnable(GL_NORMALIZE); 1.71 + 1.72 + glEnable(GL_LIGHT0); 1.73 + glEnable(GL_LIGHT1); 1.74 + 1.75 + /* set a slightly bluish cold ambient light */ 1.76 + { 1.77 + float ambient[] = {0.08, 0.1, 0.3, 1.0}; 1.78 + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); 1.79 + } 1.80 + 1.81 + level_init(&level); 1.82 + if(level_load(&level, "data/0.level") == -1) { 1.83 + fprintf(stderr, "level loading failed\n"); 1.84 + return -1; 1.85 + } 1.86 + 1.87 + if(!(level.wall_tex = load_texture("data/wall.ppm"))) { 1.88 + return -1; 1.89 + } 1.90 + if(!(level.floor_tex = load_texture("data/floor.ppm"))) { 1.91 + return -1; 1.92 + } 1.93 + level.floor_tex_scale = 1.0; 1.94 + if(!(level.ceil_tex = load_texture("data/ceil.ppm"))) { 1.95 + return -1; 1.96 + } 1.97 + level.ceil_tex_scale = 2.0; 1.98 + 1.99 + 1.100 + if(!(monkey_mesh = load_mesh("data/monkey.obj"))) { 1.101 + return -1; 1.102 + } 1.103 + if(!(envmap = load_texture("data/refmap.ppm"))) { 1.104 + return -1; 1.105 + } 1.106 + 1.107 + if(!(win_tex = load_texture("data/done.ppm"))) { 1.108 + return -1; 1.109 + } 1.110 + 1.111 + player_init(&player, &level); 1.112 + return 0; 1.113 +} 1.114 + 1.115 +static void update(unsigned int msec) 1.116 +{ 1.117 + static unsigned int prev_upd; 1.118 + float dfwd = 0.0f; 1.119 + float dright = 0.0f; 1.120 + float walk_speed = 8.0; 1.121 + 1.122 + float dt = (float)(msec - prev_upd) / 1000.0f; 1.123 + prev_upd = msec; 1.124 + 1.125 + if(game_won) return; 1.126 + 1.127 + if(freelook) { 1.128 + if(keystate['w'] || keystate['W']) { 1.129 + dfwd += walk_speed * dt; 1.130 + } 1.131 + if(keystate['s'] || keystate['S']) { 1.132 + dfwd -= walk_speed * dt; 1.133 + } 1.134 + if(keystate['d'] || keystate['D']) { 1.135 + dright += walk_speed * dt * 0.6; 1.136 + } 1.137 + if(keystate['a'] || keystate['A']) { 1.138 + dright -= walk_speed * dt * 0.6; 1.139 + } 1.140 + 1.141 + player_move(&player, dfwd, dright); 1.142 + } 1.143 + 1.144 + if(level_cell_at(&level, player.x, player.y) == 'x') { 1.145 + game_won = 1; 1.146 + } 1.147 +} 1.148 + 1.149 +static void display(void) 1.150 +{ 1.151 + float flicker = 1.0f; 1.152 + unsigned int msec = glutGet(GLUT_ELAPSED_TIME); 1.153 + 1.154 + update(msec); 1.155 + 1.156 + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 1.157 + 1.158 + glMatrixMode(GL_MODELVIEW); 1.159 + glLoadIdentity(); 1.160 + glTranslatef(0, 0, -dbg_cam_dist); 1.161 + /* set view matrix according to player pos/rot */ 1.162 + player_setup_view_matrix(&player); 1.163 + glTranslatef(0, -PLAYER_EYE_HEIGHT, 0); 1.164 + 1.165 + /* setup lights */ 1.166 + flicker = fbm1((float)msec / 500.0f, 2) * 0.4 + 0.6; 1.167 + set_light_position(0, player.x, PLAYER_EYE_HEIGHT + 0.2, player.y); 1.168 + set_light_color(0, 1.0 * flicker, 0.6 * flicker, 0.3 * flicker); 1.169 + set_light_attenuation(0, 0.5, 0, 0.04); 1.170 + 1.171 + set_light_position(1, level.goal_pos[0], 0.8, level.goal_pos[1]); 1.172 + set_light_color(1, 0.955, 0.75, 0.06); 1.173 + set_light_attenuation(1, 0.9, 0, 0.05); 1.174 + 1.175 + /* draw the scene */ 1.176 + draw_scene(msec); 1.177 + 1.178 + glutSwapBuffers(); 1.179 + assert(glGetError() == GL_NO_ERROR); 1.180 +} 1.181 + 1.182 +static void draw_scene(unsigned int msec) 1.183 +{ 1.184 + float x, y; 1.185 + float tsec = (float)msec / 1000.0f; 1.186 + 1.187 + level_draw(&level); 1.188 + 1.189 + /* draw the golden monkey */ 1.190 + if(level_obj_pos(&level, 'x', &x, &y)) { 1.191 + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); 1.192 + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); 1.193 + glEnable(GL_TEXTURE_GEN_S); 1.194 + glEnable(GL_TEXTURE_GEN_T); 1.195 + 1.196 + glBindTexture(GL_TEXTURE_2D, envmap); 1.197 + glEnable(GL_TEXTURE_2D); 1.198 + 1.199 + set_mtl_diffuse(0.1, 0.1, 0.1, 1); 1.200 + set_mtl_specular(0.955, 0.75, 0.06); 1.201 + set_mtl_shininess(80.0); 1.202 + set_mtl_emission(0.955, 0.75 * 0.7, 0.06 * 0.1); 1.203 + 1.204 + glMatrixMode(GL_MODELVIEW); 1.205 + glPushMatrix(); 1.206 + glTranslatef(x, 0.8 + sin(tsec * 2.0) * 0.1, y); 1.207 + glRotatef(tsec * 100.0, 0, 1, 0); 1.208 + glRotatef(sin(tsec * 3.0) * 10.0, 1, 0, 0); 1.209 + glScalef(0.3, 0.3, 0.3); 1.210 + 1.211 + render_mesh(monkey_mesh); 1.212 + 1.213 + glPopMatrix(); 1.214 + 1.215 + set_mtl_emission(0, 0, 0); 1.216 + 1.217 + glDisable(GL_TEXTURE_2D); 1.218 + 1.219 + glDisable(GL_TEXTURE_GEN_S); 1.220 + glDisable(GL_TEXTURE_GEN_T); 1.221 + } 1.222 + 1.223 + /* draw the win text */ 1.224 + if(game_won) { 1.225 + glMatrixMode(GL_MODELVIEW); 1.226 + glPushMatrix(); 1.227 + glLoadIdentity(); 1.228 + glMatrixMode(GL_PROJECTION); 1.229 + glPushMatrix(); 1.230 + glLoadIdentity(); 1.231 + glScalef((float)win_height / (float)win_width, 1, 1); 1.232 + 1.233 + glBindTexture(GL_TEXTURE_2D, win_tex); 1.234 + glEnable(GL_TEXTURE_2D); 1.235 + 1.236 + glEnable(GL_BLEND); 1.237 + glBlendFunc(GL_ONE, GL_ONE); 1.238 + glDisable(GL_LIGHTING); 1.239 + 1.240 + glBegin(GL_QUADS); 1.241 + glTexCoord2f(0, 1); glVertex2f(-1, -1); 1.242 + glTexCoord2f(1, 1); glVertex2f(1, -1); 1.243 + glTexCoord2f(1, 0); glVertex2f(1, 1); 1.244 + glTexCoord2f(0, 0); glVertex2f(-1, 1); 1.245 + glEnd(); 1.246 + 1.247 + glDisable(GL_BLEND); 1.248 + glDisable(GL_TEXTURE_2D); 1.249 + glEnable(GL_LIGHTING); 1.250 + 1.251 + glPopMatrix(); 1.252 + glMatrixMode(GL_MODELVIEW); 1.253 + glPopMatrix(); 1.254 + } 1.255 +} 1.256 + 1.257 +static void idle(void) 1.258 +{ 1.259 + glutPostRedisplay(); 1.260 +} 1.261 + 1.262 +static void reshape(int x, int y) 1.263 +{ 1.264 + win_width = x; 1.265 + win_height = y; 1.266 + glViewport(0, 0, x, y); 1.267 + glMatrixMode(GL_PROJECTION); 1.268 + glLoadIdentity(); 1.269 + gluPerspective(50.0, (float)x / (float)y, 0.5, 500.0); 1.270 +} 1.271 + 1.272 +static int warping_mouse; 1.273 + 1.274 +static void key_down(unsigned char key, int x, int y) 1.275 +{ 1.276 + keystate[key] = 1; 1.277 + 1.278 + switch(key) { 1.279 + case 27: 1.280 + exit(0); 1.281 + 1.282 + case 'a': 1.283 + if(!freelook && !game_won) { 1.284 + player_turn(&player, -90, 0); 1.285 + } 1.286 + break; 1.287 + 1.288 + case 'd': 1.289 + if(!freelook && !game_won) { 1.290 + player_turn(&player, 90, 0); 1.291 + } 1.292 + break; 1.293 + 1.294 + case 'w': 1.295 + case 's': 1.296 + if(!freelook && !game_won) { 1.297 + float prev_x = player.x; 1.298 + float prev_y = player.y; 1.299 + float sign = key == 'w' ? 1.0 : -1.0; 1.300 + 1.301 + if(!player_move(&player, level.cell_size * sign, 0)) { 1.302 + player.x = prev_x; 1.303 + player.y = prev_y; 1.304 + } 1.305 + } 1.306 + break; 1.307 + 1.308 + case '`': 1.309 + case '~': 1.310 + mouselook = !mouselook; 1.311 + if(mouselook) { 1.312 + warping_mouse = 1; 1.313 + glutWarpPointer(win_width / 2, win_height / 2); 1.314 + glutPassiveMotionFunc(motion); 1.315 + glutSetCursor(GLUT_CURSOR_NONE); 1.316 + } else { 1.317 + glutPassiveMotionFunc(0); 1.318 + glutSetCursor(GLUT_CURSOR_INHERIT); 1.319 + } 1.320 + break; 1.321 + 1.322 + case 'b': 1.323 + case 'B': 1.324 + freelook = !freelook; 1.325 + break; 1.326 + 1.327 + case 'r': 1.328 + case 'R': 1.329 + game_won = 0; 1.330 + player_init(&player, &level); 1.331 + break; 1.332 + 1.333 + default: 1.334 + break; 1.335 + } 1.336 +} 1.337 + 1.338 +static void key_up(unsigned char key, int x, int y) 1.339 +{ 1.340 + keystate[key] = 0; 1.341 +} 1.342 + 1.343 +static int bnstate[16]; 1.344 +static int prev_x, prev_y; 1.345 + 1.346 +static void mouse(int bn, int state, int x, int y) 1.347 +{ 1.348 + prev_x = x; 1.349 + prev_y = y; 1.350 + bnstate[bn - GLUT_LEFT_BUTTON] = state == GLUT_DOWN ? 1 : 0; 1.351 +} 1.352 + 1.353 +static void motion(int x, int y) 1.354 +{ 1.355 + int dx, dy; 1.356 + int cx = win_width / 2; 1.357 + int cy = win_height / 2; 1.358 + 1.359 + if(warping_mouse) { 1.360 + warping_mouse = 0; 1.361 + return; 1.362 + } 1.363 + 1.364 + dx = x - (mouselook ? cx : prev_x); 1.365 + dy = y - (mouselook ? cy : prev_y); 1.366 + prev_x = x; 1.367 + prev_y = y; 1.368 + 1.369 + if(!dx && !dy) return; 1.370 + 1.371 + if(mouselook || bnstate[0]) { 1.372 + player_turn(&player, dx * 0.5, dy * 0.5); 1.373 + } 1.374 + if(bnstate[2]) { 1.375 + dbg_cam_dist += 0.1 * dy; 1.376 + if(dbg_cam_dist < 0.0) dbg_cam_dist = 0.0; 1.377 + } 1.378 + 1.379 + if(mouselook) { 1.380 + warping_mouse = 1; 1.381 + glutWarpPointer(cx, cy); 1.382 + prev_x = cx; 1.383 + prev_y = cy; 1.384 + } 1.385 +}