3194196faedbcb15b3dd9ddf5ca790403c586794
[vrlugburz] / src / game.c
1 #include <stdio.h>
2 #include <assert.h>
3 #include "cgmath/cgmath.h"
4 #include "game.h"
5 #include "opengl.h"
6 #include "level.h"
7 #include "player.h"
8 #include "scenefile.h"
9 #include "sdr.h"
10
11 static void draw_level(void);
12
13 struct level lvl;
14 struct player player;
15
16 int win_width, win_height;
17 float win_aspect;
18 int mouse_x, mouse_y;
19 int bnstate[8];
20
21 float cam_dist;
22 float view_matrix[16], proj_matrix[16];
23
24 unsigned int sdr_foo;
25
26 int game_init(void)
27 {
28         if(init_opengl() == -1) {
29                 return -1;
30         }
31
32         glEnable(GL_DEPTH_TEST);
33         glEnable(GL_CULL_FACE);
34
35         if(!(sdr_foo = create_program_load("sdr/foo.v.glsl", "sdr/foo.p.glsl"))) {
36                 return -1;
37         }
38         glBindAttribLocation(sdr_foo, MESH_ATTR_VERTEX, "apos");
39         glBindAttribLocation(sdr_foo, MESH_ATTR_NORMAL, "anorm");
40         glBindAttribLocation(sdr_foo, MESH_ATTR_TANGENT, "atang");
41         glBindAttribLocation(sdr_foo, MESH_ATTR_TEXCOORD, "atex");
42         link_program(sdr_foo);
43
44         if(load_level(&lvl, "data/test.lvl") == -1) {
45                 return -1;
46         }
47         gen_level_geom(&lvl);
48
49         init_player(&player);
50         player.lvl = &lvl;
51         player.cx = lvl.px;
52         player.cy = lvl.py;
53
54         return 0;
55 }
56
57 void game_shutdown(void)
58 {
59         destroy_level(&lvl);
60         free_program(sdr_foo);
61 }
62
63 #define STEP_INTERVAL   128
64
65 void update(float dt)
66 {
67         static long prev_step;
68         int dir;
69         int step[][2] = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
70
71         cgm_vec3 vdir = {0, 0, -1};
72
73         cgm_vmul_m3v3(&vdir, player.view_xform);
74
75         player.dir = (int)(2.0f * (-atan2(vdir.z, vdir.x) + M_PI) / M_PI + 0.5f) & 3;
76
77         if(time_msec - prev_step >= STEP_INTERVAL) {
78                 if(input_state[INP_FWD]) {
79                         player.cx += step[player.dir][0];
80                         player.cy += step[player.dir][1];
81                         prev_step = time_msec;
82                         printf("step[%d] %d,%d\n", player.dir, player.cx, player.cy);
83                 }
84                 if(input_state[INP_BACK]) {
85                         player.cx -= step[player.dir][0];
86                         player.cy -= step[player.dir][1];
87                         prev_step = time_msec;
88                         printf("step[%d] %d,%d\n", player.dir, player.cx, player.cy);
89                 }
90                 if(input_state[INP_LEFT]) {
91                         dir = (player.dir + 3) & 3;
92                         player.cx += step[dir][0];
93                         player.cy += step[dir][1];
94                         prev_step = time_msec;
95                         printf("step[%d] %d,%d\n", player.dir, player.cx, player.cy);
96                 }
97                 if(input_state[INP_RIGHT]) {
98                         dir = (player.dir + 1) & 3;
99                         player.cx += step[dir][0];
100                         player.cy += step[dir][1];
101                         prev_step = time_msec;
102                         printf("step[%d] %d,%d\n", player.dir, player.cx, player.cy);
103                 }
104                 memset(input_state, 0, sizeof input_state);
105         }
106
107         upd_player_xform(&player);
108 }
109
110 void game_display(void)
111 {
112         float dt;
113         static long prev_msec;
114
115         dt = (prev_msec - time_msec) / 1000.0f;
116         prev_msec = time_msec;
117
118         update(dt);
119
120         glClearColor(0.1, 0.1, 0.1, 1);
121         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
122
123         cgm_midentity(proj_matrix);
124         cgm_mperspective(proj_matrix, cgm_deg_to_rad(50), win_aspect, 0.5, 500.0);
125         glMatrixMode(GL_PROJECTION);
126         glLoadMatrixf(proj_matrix);
127
128         glMatrixMode(GL_MODELVIEW);
129         glLoadIdentity();
130         glTranslatef(0, 0, -cam_dist);
131         glMultMatrixf(player.view_xform);
132
133         draw_level();
134
135         game_swap_buffers();
136         assert(glGetError() == GL_NO_ERROR);
137 }
138
139 static void draw_level(void)
140 {
141         int i, j, k;
142         struct cell *cell;
143         float xform[16];
144
145         glUseProgram(sdr_foo);
146
147         cell = lvl.cells;
148         for(i=0; i<lvl.height; i++) {
149                 for(j=0; j<lvl.width; j++) {
150                         cgm_mtranslation(xform, j * lvl.cell_size, 0, -i * lvl.cell_size);
151
152                         glPushMatrix();
153                         glMultMatrixf(xform);
154
155                         for(k=0; k<cell->num_mgrp; k++) {
156                                 draw_meshgroup(cell->mgrp + k);
157                         }
158                         cell++;
159
160                         glPopMatrix();
161                 }
162         }
163
164         glUseProgram(0);
165 }
166
167 void game_reshape(int x, int y)
168 {
169         glViewport(0, 0, x, y);
170         win_width = x;
171         win_height = y;
172         win_aspect = (float)x / (float)y;
173 }
174
175 void game_keyboard(int key, int press)
176 {
177         if(press && key == 27) {
178                 game_quit();
179                 return;
180         }
181
182         switch(key) {
183         case 'w':
184                 input_state[INP_FWD] = press;
185                 break;
186
187         case 'a':
188                 input_state[INP_LEFT] = press;
189                 break;
190
191         case 's':
192                 input_state[INP_BACK] = press;
193                 break;
194
195         case 'd':
196                 input_state[INP_RIGHT] = press;
197                 break;
198         }
199 }
200
201 void game_mbutton(int bn, int press, int x, int y)
202 {
203         bnstate[bn] = press;
204         mouse_x = x;
205         mouse_y = y;
206 }
207
208 void game_mmotion(int x, int y)
209 {
210         int dx = x - mouse_x;
211         int dy = y - mouse_y;
212         mouse_x = x;
213         mouse_y = y;
214
215         if(!(dx | dy)) return;
216
217         if(bnstate[0]) {
218                 player.theta -= cgm_deg_to_rad(dx * 0.5f);
219                 player.phi -= cgm_deg_to_rad(dy * 0.5f);
220                 if(player.phi < -M_PI/2) player.phi = -M_PI/2;
221                 if(player.phi > M_PI/2) player.phi = M_PI/2;
222         }
223         if(bnstate[2]) {
224                 cam_dist += dy * 0.1;
225                 if(cam_dist < 0) cam_dist = 0;
226         }
227 }