labyrinth

view src/game.c @ 3:45b91185b298

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