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
|