labyrinth

annotate src/game.c @ 8:d3f1f74067b0

ops, forgot to swapbuffers on the android side
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 04 May 2015 04:56:44 +0300
parents 45b91185b298
children
rev   line source
nuclear@3 1 #include <stdio.h>
nuclear@3 2 #include <stdlib.h>
nuclear@3 3 #include <math.h>
nuclear@3 4 #include "opengl.h"
nuclear@3 5 #include "game.h"
nuclear@3 6 #include "player.h"
nuclear@3 7 #include "level.h"
nuclear@3 8 #include "noise.h"
nuclear@3 9 #include "texture.h"
nuclear@3 10 #include "mesh.h"
nuclear@3 11
nuclear@3 12 #define PLAYER_EYE_HEIGHT 1.65
nuclear@3 13
nuclear@3 14 static void draw_scene(unsigned long msec);
nuclear@3 15
nuclear@3 16 static int win_width, win_height;
nuclear@3 17 static struct level level;
nuclear@3 18 static struct player player;
nuclear@3 19 static int mouselook, freelook = 1;
nuclear@3 20 static char keystate[256];
nuclear@3 21
nuclear@3 22 static struct mesh *monkey_mesh;
nuclear@3 23 static unsigned int envmap;
nuclear@3 24 static unsigned int win_tex;
nuclear@3 25
nuclear@3 26 static int game_won;
nuclear@3 27
nuclear@3 28 static float dbg_cam_dist = 0.0;
nuclear@3 29
nuclear@3 30
nuclear@3 31 int game_init(void)
nuclear@3 32 {
nuclear@3 33 glEnable(GL_DEPTH_TEST);
nuclear@3 34 glEnable(GL_CULL_FACE);
nuclear@3 35 glEnable(GL_LIGHTING);
nuclear@3 36 glEnable(GL_NORMALIZE);
nuclear@3 37
nuclear@3 38 glEnable(GL_LIGHT0);
nuclear@3 39 glEnable(GL_LIGHT1);
nuclear@3 40
nuclear@3 41 /* set a slightly bluish cold ambient light */
nuclear@3 42 {
nuclear@3 43 float ambient[] = {0.08, 0.1, 0.3, 1.0};
nuclear@3 44 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient);
nuclear@3 45 }
nuclear@3 46
nuclear@3 47 level_init(&level);
nuclear@3 48 if(level_load(&level, "data/0.level") == -1) {
nuclear@3 49 fprintf(stderr, "level loading failed\n");
nuclear@3 50 return -1;
nuclear@3 51 }
nuclear@3 52
nuclear@3 53 if(!(level.wall_tex = load_texture("data/wall.ppm"))) {
nuclear@3 54 return -1;
nuclear@3 55 }
nuclear@3 56 if(!(level.floor_tex = load_texture("data/floor.ppm"))) {
nuclear@3 57 return -1;
nuclear@3 58 }
nuclear@3 59 level.floor_tex_scale = 1.0;
nuclear@3 60 if(!(level.ceil_tex = load_texture("data/ceil.ppm"))) {
nuclear@3 61 return -1;
nuclear@3 62 }
nuclear@3 63 level.ceil_tex_scale = 2.0;
nuclear@3 64
nuclear@3 65
nuclear@3 66 if(!(monkey_mesh = load_mesh("data/monkey.obj"))) {
nuclear@3 67 return -1;
nuclear@3 68 }
nuclear@3 69 if(!(envmap = load_texture("data/refmap.ppm"))) {
nuclear@3 70 return -1;
nuclear@3 71 }
nuclear@3 72
nuclear@3 73 if(!(win_tex = load_texture("data/done.ppm"))) {
nuclear@3 74 return -1;
nuclear@3 75 }
nuclear@3 76
nuclear@3 77 player_init(&player, &level);
nuclear@8 78
nuclear@8 79 glClearColor(1, 0, 0, 1);
nuclear@3 80 return 0;
nuclear@3 81 }
nuclear@3 82
nuclear@3 83 void game_shutdown(void)
nuclear@3 84 {
nuclear@3 85 }
nuclear@3 86
nuclear@3 87 static void update(unsigned long msec)
nuclear@3 88 {
nuclear@3 89 static unsigned long prev_upd;
nuclear@3 90 float dfwd = 0.0f;
nuclear@3 91 float dright = 0.0f;
nuclear@3 92 float walk_speed = 8.0;
nuclear@3 93
nuclear@3 94 float dt = (float)(msec - prev_upd) / 1000.0f;
nuclear@3 95 prev_upd = msec;
nuclear@3 96
nuclear@3 97 if(game_won) return;
nuclear@3 98
nuclear@3 99 if(freelook) {
nuclear@3 100 if(keystate['w'] || keystate['W']) {
nuclear@3 101 dfwd += walk_speed * dt;
nuclear@3 102 }
nuclear@3 103 if(keystate['s'] || keystate['S']) {
nuclear@3 104 dfwd -= walk_speed * dt;
nuclear@3 105 }
nuclear@3 106 if(keystate['d'] || keystate['D']) {
nuclear@3 107 dright += walk_speed * dt * 0.6;
nuclear@3 108 }
nuclear@3 109 if(keystate['a'] || keystate['A']) {
nuclear@3 110 dright -= walk_speed * dt * 0.6;
nuclear@3 111 }
nuclear@3 112
nuclear@3 113 player_move(&player, dfwd, dright);
nuclear@3 114 }
nuclear@3 115
nuclear@3 116 if(level_cell_at(&level, player.x, player.y) == 'x') {
nuclear@3 117 game_won = 1;
nuclear@3 118 }
nuclear@3 119 }
nuclear@3 120
nuclear@3 121 void game_display(unsigned long msec)
nuclear@3 122 {
nuclear@3 123 float flicker = 1.0f;
nuclear@3 124
nuclear@3 125 update(msec);
nuclear@3 126
nuclear@3 127 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
nuclear@3 128
nuclear@3 129 glMatrixMode(GL_MODELVIEW);
nuclear@3 130 glLoadIdentity();
nuclear@3 131 glTranslatef(0, 0, -dbg_cam_dist);
nuclear@3 132 /* set view matrix according to player pos/rot */
nuclear@3 133 player_setup_view_matrix(&player);
nuclear@3 134 glTranslatef(0, -PLAYER_EYE_HEIGHT, 0);
nuclear@3 135
nuclear@3 136 /* setup lights */
nuclear@3 137 flicker = fbm1((float)msec / 500.0f, 2) * 0.4 + 0.6;
nuclear@3 138 set_light_position(0, player.x, PLAYER_EYE_HEIGHT + 0.2, player.y);
nuclear@3 139 set_light_color(0, 1.0 * flicker, 0.6 * flicker, 0.3 * flicker);
nuclear@3 140 set_light_attenuation(0, 0.5, 0, 0.04);
nuclear@3 141
nuclear@3 142 set_light_position(1, level.goal_pos[0], 0.8, level.goal_pos[1]);
nuclear@3 143 set_light_color(1, 0.955, 0.75, 0.06);
nuclear@3 144 set_light_attenuation(1, 0.9, 0, 0.05);
nuclear@3 145
nuclear@3 146 /* draw the scene */
nuclear@3 147 draw_scene(msec);
nuclear@3 148 }
nuclear@3 149
nuclear@3 150 void game_reshape(int x, int y)
nuclear@3 151 {
nuclear@3 152 win_width = x;
nuclear@3 153 win_height = y;
nuclear@3 154 glViewport(0, 0, x, y);
nuclear@3 155 glMatrixMode(GL_PROJECTION);
nuclear@3 156 glLoadIdentity();
nuclear@3 157 gluPerspective(55.0, (float)x / (float)y, 0.5, 500.0);
nuclear@3 158 }
nuclear@3 159
nuclear@3 160
nuclear@3 161 static void draw_scene(unsigned long msec)
nuclear@3 162 {
nuclear@3 163 float x, y;
nuclear@3 164 float tsec = (float)msec / 1000.0f;
nuclear@3 165
nuclear@3 166 level_draw(&level);
nuclear@3 167
nuclear@3 168 /* draw the golden monkey */
nuclear@3 169 if(level_obj_pos(&level, 'x', &x, &y)) {
nuclear@3 170 /* TODO: GLES doesn't have tex-gen... recalc manually */
nuclear@3 171 #ifndef GL_MOBILE
nuclear@3 172 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
nuclear@3 173 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
nuclear@3 174 glEnable(GL_TEXTURE_GEN_S);
nuclear@3 175 glEnable(GL_TEXTURE_GEN_T);
nuclear@3 176
nuclear@3 177 glBindTexture(GL_TEXTURE_2D, envmap);
nuclear@3 178 glEnable(GL_TEXTURE_2D);
nuclear@3 179 #endif
nuclear@3 180
nuclear@3 181 set_mtl_diffuse(0.1, 0.1, 0.1, 1);
nuclear@3 182 set_mtl_specular(0.955, 0.75, 0.06);
nuclear@3 183 set_mtl_shininess(80.0);
nuclear@3 184 set_mtl_emission(0.955, 0.75 * 0.7, 0.06 * 0.1);
nuclear@3 185
nuclear@3 186 glMatrixMode(GL_MODELVIEW);
nuclear@3 187 glPushMatrix();
nuclear@3 188 glTranslatef(x, 0.8 + sin(tsec * 2.0) * 0.1, y);
nuclear@3 189 glRotatef(tsec * 100.0, 0, 1, 0);
nuclear@3 190 glRotatef(sin(tsec * 3.0) * 10.0, 1, 0, 0);
nuclear@3 191 glScalef(0.3, 0.3, 0.3);
nuclear@3 192
nuclear@3 193 render_mesh(monkey_mesh);
nuclear@3 194
nuclear@3 195 glPopMatrix();
nuclear@3 196
nuclear@3 197 set_mtl_emission(0, 0, 0);
nuclear@3 198
nuclear@3 199 #ifndef GL_MOBILE
nuclear@3 200 glDisable(GL_TEXTURE_2D);
nuclear@3 201
nuclear@3 202 glDisable(GL_TEXTURE_GEN_S);
nuclear@3 203 glDisable(GL_TEXTURE_GEN_T);
nuclear@3 204 #endif
nuclear@3 205 }
nuclear@3 206
nuclear@3 207 /* draw the win text */
nuclear@3 208 if(game_won) {
nuclear@3 209 glMatrixMode(GL_MODELVIEW);
nuclear@3 210 glPushMatrix();
nuclear@3 211 glLoadIdentity();
nuclear@3 212 glMatrixMode(GL_PROJECTION);
nuclear@3 213 glPushMatrix();
nuclear@3 214 glLoadIdentity();
nuclear@3 215 glScalef((float)win_height / (float)win_width, 1, 1);
nuclear@3 216
nuclear@3 217 glBindTexture(GL_TEXTURE_2D, win_tex);
nuclear@3 218 glEnable(GL_TEXTURE_2D);
nuclear@3 219
nuclear@3 220 glEnable(GL_BLEND);
nuclear@3 221 glBlendFunc(GL_ONE, GL_ONE);
nuclear@3 222 glDisable(GL_LIGHTING);
nuclear@3 223
nuclear@3 224 glBegin(GL_QUADS);
nuclear@3 225 glTexCoord2f(0, 1); glVertex2f(-1, -1);
nuclear@3 226 glTexCoord2f(1, 1); glVertex2f(1, -1);
nuclear@3 227 glTexCoord2f(1, 0); glVertex2f(1, 1);
nuclear@3 228 glTexCoord2f(0, 0); glVertex2f(-1, 1);
nuclear@3 229 glEnd();
nuclear@3 230
nuclear@3 231 glDisable(GL_BLEND);
nuclear@3 232 glDisable(GL_TEXTURE_2D);
nuclear@3 233 glEnable(GL_LIGHTING);
nuclear@3 234
nuclear@3 235 glPopMatrix();
nuclear@3 236 glMatrixMode(GL_MODELVIEW);
nuclear@3 237 glPopMatrix();
nuclear@3 238 }
nuclear@3 239 }
nuclear@3 240
nuclear@3 241 static int warping_mouse;
nuclear@3 242
nuclear@3 243 void game_keyboard(int key, int pressed)
nuclear@3 244 {
nuclear@3 245 keystate[key] = pressed;
nuclear@3 246
nuclear@3 247 if(!pressed) return;
nuclear@3 248
nuclear@3 249 switch(key) {
nuclear@3 250 case 27:
nuclear@3 251 exit(0);
nuclear@3 252
nuclear@3 253 case 'a':
nuclear@3 254 if(!freelook && !game_won) {
nuclear@3 255 player_turn(&player, -90, 0);
nuclear@3 256 }
nuclear@3 257 break;
nuclear@3 258
nuclear@3 259 case 'd':
nuclear@3 260 if(!freelook && !game_won) {
nuclear@3 261 player_turn(&player, 90, 0);
nuclear@3 262 }
nuclear@3 263 break;
nuclear@3 264
nuclear@3 265 case 'w':
nuclear@3 266 case 's':
nuclear@3 267 if(!freelook && !game_won) {
nuclear@3 268 float prev_x = player.x;
nuclear@3 269 float prev_y = player.y;
nuclear@3 270 float sign = key == 'w' ? 1.0 : -1.0;
nuclear@3 271
nuclear@3 272 if(!player_move(&player, level.cell_size * sign, 0)) {
nuclear@3 273 player.x = prev_x;
nuclear@3 274 player.y = prev_y;
nuclear@3 275 }
nuclear@3 276 }
nuclear@3 277 break;
nuclear@3 278
nuclear@3 279 case '`':
nuclear@3 280 case '~':
nuclear@3 281 mouselook = !mouselook;
nuclear@3 282 if(mouselook) {
nuclear@3 283 warping_mouse = 1;
nuclear@3 284 set_mouse_pos(win_width / 2, win_height / 2);
nuclear@3 285 set_mouse_cursor(0);
nuclear@3 286 } else {
nuclear@3 287 set_mouse_cursor(1);
nuclear@3 288 }
nuclear@3 289 break;
nuclear@3 290
nuclear@3 291 case 'b':
nuclear@3 292 case 'B':
nuclear@3 293 freelook = !freelook;
nuclear@3 294 break;
nuclear@3 295
nuclear@3 296 case 'r':
nuclear@3 297 case 'R':
nuclear@3 298 game_won = 0;
nuclear@3 299 player_init(&player, &level);
nuclear@3 300 break;
nuclear@3 301
nuclear@3 302 default:
nuclear@3 303 break;
nuclear@3 304 }
nuclear@3 305 }
nuclear@3 306
nuclear@3 307 #define MAX_TOUCH_IDS 16
nuclear@3 308 static struct {
nuclear@3 309 int bnstate[8];
nuclear@3 310 int prev_x, prev_y;
nuclear@3 311 } mstate[MAX_TOUCH_IDS];
nuclear@3 312
nuclear@3 313 void game_mouse_button(int id, int bn, int pressed, int x, int y)
nuclear@3 314 {
nuclear@3 315 if(id >= MAX_TOUCH_IDS) return;
nuclear@3 316
nuclear@3 317 mstate[id].prev_x = x;
nuclear@3 318 mstate[id].prev_y = y;
nuclear@3 319 mstate[id].bnstate[bn] = pressed;
nuclear@3 320 }
nuclear@3 321
nuclear@3 322 void game_mouse_motion(int id, int x, int y)
nuclear@3 323 {
nuclear@3 324 int dx, dy, cx, cy;
nuclear@3 325
nuclear@3 326 if(id >= MAX_TOUCH_IDS) return;
nuclear@3 327
nuclear@3 328 cx = win_width / 2;
nuclear@3 329 cy = win_height / 2;
nuclear@3 330
nuclear@3 331 if(warping_mouse) {
nuclear@3 332 warping_mouse = 0;
nuclear@3 333 return;
nuclear@3 334 }
nuclear@3 335
nuclear@3 336 dx = x - (mouselook ? cx : mstate[id].prev_x);
nuclear@3 337 dy = y - (mouselook ? cy : mstate[id].prev_y);
nuclear@3 338 mstate[id].prev_x = x;
nuclear@3 339 mstate[id].prev_y = y;
nuclear@3 340
nuclear@3 341 if(!dx && !dy) return;
nuclear@3 342
nuclear@3 343 if(mouselook || mstate[id].bnstate[0]) {
nuclear@3 344 player_turn(&player, dx * 0.5, dy * 0.5);
nuclear@3 345 }
nuclear@3 346 if(mstate[id].bnstate[2]) {
nuclear@3 347 dbg_cam_dist += 0.1 * dy;
nuclear@3 348 if(dbg_cam_dist < 0.0) dbg_cam_dist = 0.0;
nuclear@3 349 }
nuclear@3 350
nuclear@3 351 if(mouselook) {
nuclear@3 352 warping_mouse = 1;
nuclear@3 353 set_mouse_pos(cx, cy);
nuclear@3 354 mstate[id].prev_x = cx;
nuclear@3 355 mstate[id].prev_y = cy;
nuclear@3 356 }
nuclear@3 357 }
nuclear@3 358