2007694df12ea6cff8a73cd6c091b9198c65c659
[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
48         init_player(&player);
49         player.lvl = &lvl;
50         player.cx = lvl.px;
51         player.cy = lvl.py;
52
53         return 0;
54 }
55
56 void game_shutdown(void)
57 {
58         destroy_level(&lvl);
59         free_program(sdr_foo);
60 }
61
62 #define STEP_INTERVAL   128
63
64 void update(float dt)
65 {
66         static long prev_step;
67         int dir;
68         int step[][2] = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
69
70         cgm_vec3 vdir = {0, 0, -1};
71
72         cgm_vmul_m3v3(&vdir, player.view_xform);
73
74         player.dir = (int)(2.0f * (-atan2(vdir.z, vdir.x) + M_PI) / M_PI + 0.5f) & 3;
75
76         if(time_msec - prev_step >= STEP_INTERVAL) {
77                 if(input_state[INP_FWD]) {
78                         player.cx += step[player.dir][0];
79                         player.cy += step[player.dir][1];
80                         prev_step = time_msec;
81                         printf("step[%d] %d,%d\n", player.dir, player.cx, player.cy);
82                 }
83                 if(input_state[INP_BACK]) {
84                         player.cx -= step[player.dir][0];
85                         player.cy -= step[player.dir][1];
86                         prev_step = time_msec;
87                         printf("step[%d] %d,%d\n", player.dir, player.cx, player.cy);
88                 }
89                 if(input_state[INP_LEFT]) {
90                         dir = (player.dir + 3) & 3;
91                         player.cx += step[dir][0];
92                         player.cy += step[dir][1];
93                         prev_step = time_msec;
94                         printf("step[%d] %d,%d\n", player.dir, player.cx, player.cy);
95                 }
96                 if(input_state[INP_RIGHT]) {
97                         dir = (player.dir + 1) & 3;
98                         player.cx += step[dir][0];
99                         player.cy += step[dir][1];
100                         prev_step = time_msec;
101                         printf("step[%d] %d,%d\n", player.dir, player.cx, player.cy);
102                 }
103                 memset(input_state, 0, sizeof input_state);
104         }
105
106         upd_player_xform(&player);
107 }
108
109 void game_display(void)
110 {
111         float dt;
112         static long prev_msec;
113
114         dt = (prev_msec - time_msec) / 1000.0f;
115         prev_msec = time_msec;
116
117         update(dt);
118
119         glClearColor(0.1, 0.1, 0.1, 1);
120         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
121
122         cgm_midentity(proj_matrix);
123         cgm_mperspective(proj_matrix, cgm_deg_to_rad(50), win_aspect, 0.5, 500.0);
124         glMatrixMode(GL_PROJECTION);
125         glLoadMatrixf(proj_matrix);
126
127         glMatrixMode(GL_MODELVIEW);
128         glLoadIdentity();
129         glTranslatef(0, 0, -cam_dist);
130         glMultMatrixf(player.view_xform);
131
132         draw_level();
133
134         game_swap_buffers();
135         assert(glGetError() == GL_NO_ERROR);
136 }
137
138 static void draw_level(void)
139 {
140         int i, j, k;
141         struct cell *cell;
142         float xform[16];
143
144         glUseProgram(sdr_foo);
145
146         cell = lvl.cells;
147         for(i=0; i<lvl.height; i++) {
148                 for(j=0; j<lvl.width; j++) {
149                         cgm_mtranslation(xform, j * lvl.cell_size, 0, -i * lvl.cell_size);
150
151                         glPushMatrix();
152                         glMultMatrixf(xform);
153
154                         if(cell->tile) {
155                                 cgm_mrotation_y(xform, cell->tilerot * M_PI / 2.0f);
156
157                                 glPushMatrix();
158                                 glMultMatrixf(xform);
159                                 draw_meshgroup(&cell->tile->mgrp);
160                                 glPopMatrix();
161                         }
162
163                         for(k=0; k<cell->num_mgrp; k++) {
164                                 draw_meshgroup(cell->mgrp + k);
165                         }
166                         cell++;
167
168                         glPopMatrix();
169                 }
170         }
171
172         glUseProgram(0);
173 }
174
175 void game_reshape(int x, int y)
176 {
177         glViewport(0, 0, x, y);
178         win_width = x;
179         win_height = y;
180         win_aspect = (float)x / (float)y;
181 }
182
183 void game_keyboard(int key, int press)
184 {
185         if(press && key == 27) {
186                 game_quit();
187                 return;
188         }
189
190         switch(key) {
191         case 'w':
192                 input_state[INP_FWD] = press;
193                 break;
194
195         case 'a':
196                 input_state[INP_LEFT] = press;
197                 break;
198
199         case 's':
200                 input_state[INP_BACK] = press;
201                 break;
202
203         case 'd':
204                 input_state[INP_RIGHT] = press;
205                 break;
206         }
207 }
208
209 void game_mbutton(int bn, int press, int x, int y)
210 {
211         bnstate[bn] = press;
212         mouse_x = x;
213         mouse_y = y;
214 }
215
216 void game_mmotion(int x, int y)
217 {
218         int dx = x - mouse_x;
219         int dy = y - mouse_y;
220         mouse_x = x;
221         mouse_y = y;
222
223         if(!(dx | dy)) return;
224
225         if(bnstate[0]) {
226                 player.theta -= cgm_deg_to_rad(dx * 0.5f);
227                 player.phi -= cgm_deg_to_rad(dy * 0.5f);
228                 if(player.phi < -M_PI/2) player.phi = -M_PI/2;
229                 if(player.phi > M_PI/2) player.phi = M_PI/2;
230         }
231         if(bnstate[2]) {
232                 cam_dist += dy * 0.1;
233                 if(cam_dist < 0) cam_dist = 0;
234         }
235 }