doing stuff
[ld42_outofspace] / src / gamescr.cc
1 #include <vector>
2 #include <gmath/gmath.h>
3 #include "game.h"
4 #include "screen.h"
5 #include "opengl.h"
6 #include "texture.h"
7
8 /* NOTES:
9  * - whistle hhgg music
10  * - colliding particles merge
11  * - select objects and center camera on them
12  */
13
14 struct Particle {
15         float mass;
16         Vec2 pos;
17         Vec2 vel;
18 };
19
20 struct Emitter {
21         Vec2 pos;
22         float mass;
23         float rate, chunk;
24         float angle, spread;
25 };
26
27
28 #define SIM_DT          0.016
29
30 #define GRID_SIZE       4096
31 #define GRID_BITS       12
32 #define GRID_X(idx)     (((idx) >> GRID_BITS) & (GRID_SIZE - 1))
33 #define GRID_Y(idx)     ((idx) & (GRID_SIZE - 1))
34
35 #define FIELD_SIZE      2048
36 #define MIN_CAM_DIST    1.0f
37 #define MAX_CAM_DIST    350.0f
38
39 static int pos_to_grid(float x, float y);
40
41 static float grid[GRID_SIZE * GRID_SIZE];
42 static Particle grid_part[GRID_SIZE * GRID_SIZE];
43
44 static std::vector<Emitter> emitters;
45
46 static Texture *grid_tex;
47
48 static float cam_theta;
49 static float cam_dist = 100.0f;
50 static Vec2 *targ_pos;
51 static Mat4 view_matrix, proj_matrix;
52
53
54 bool GameScreen::init()
55 {
56         grid_tex = new Texture;
57         if(!grid_tex->load("data/purple_grid.png")) {
58                 return false;
59         }
60         grid_tex->set_anisotropy(glcaps.max_aniso);
61
62         return true;
63 }
64
65 void GameScreen::destroy()
66 {
67         delete grid_tex;
68 }
69
70 static void simstep()
71 {
72 }
73
74 static void update()
75 {
76         static float interval;
77
78         interval += frame_dt;
79         if(interval >= SIM_DT) {
80                 interval -= SIM_DT;
81                 simstep();
82         }
83
84         // update projection matrix
85         proj_matrix.perspective(deg_to_rad(60.0f), win_aspect, 0.5, 5000.0);
86
87         // update view matrix
88         Vec3 targ;
89         if(targ_pos) {
90                 targ.x = targ_pos->x;
91                 targ.z = targ_pos->y;
92         }
93
94         float theta = -deg_to_rad(cam_theta);
95         Vec3 camdir = Vec3(sin(theta) * cam_dist, pow(cam_dist * 0.1, 2.0) + 0.5, cos(theta) * cam_dist);
96         Vec3 campos = targ + camdir;
97
98         view_matrix.inv_lookat(campos, targ, Vec3(0, 1, 0));
99 }
100
101 void GameScreen::draw()
102 {
103         update();
104
105         glClearColor(0.01, 0.01, 0.01, 1);
106         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
107
108         glMatrixMode(GL_PROJECTION);
109         glLoadMatrixf(proj_matrix[0]);
110         glMatrixMode(GL_MODELVIEW);
111         glLoadMatrixf(view_matrix[0]);
112
113         glPushAttrib(GL_ENABLE_BIT);
114         glDisable(GL_LIGHTING);
115         glDisable(GL_CULL_FACE);
116
117         glEnable(GL_TEXTURE_2D);
118         bind_texture(grid_tex);
119
120         float maxu = FIELD_SIZE / 32.0f;
121         float maxv = FIELD_SIZE / 32.0f;
122         float hsz = FIELD_SIZE * 0.5f;
123
124         glBegin(GL_QUADS);
125         glColor3f(1, 1, 1);
126         glTexCoord2f(0, 0);
127         glVertex3f(-hsz, 0, -hsz);
128         glTexCoord2f(maxu, 0);
129         glVertex3f(hsz, 0, -hsz);
130         glTexCoord2f(maxu, maxv);
131         glVertex3f(hsz, 0, hsz);
132         glTexCoord2f(0, maxv);
133         glVertex3f(-hsz, 0, hsz);
134         glEnd();
135
136         glPopAttrib();
137 }
138
139 void GameScreen::reshape(int x, int y)
140 {
141 }
142
143
144
145 void GameScreen::keyboard(int key, bool pressed)
146 {
147         if(pressed) {
148                 switch(key) {
149                 case KEY_ESC:
150                         pop_screen();
151                         break;
152
153                 default:
154                         break;
155                 }
156         }
157 }
158
159 static int prev_x, prev_y;
160
161 void GameScreen::mbutton(int bn, bool pressed, int x, int y)
162 {
163         prev_x = x;
164         prev_y = y;
165 }
166
167 void GameScreen::mmotion(int x, int y)
168 {
169         int dx = x - prev_x;
170         int dy = y - prev_y;
171         prev_x = x;
172         prev_y = y;
173
174         if(game_bnstate(2)) {
175                 cam_theta += dx * 0.5;
176         }
177 }
178
179 void GameScreen::mwheel(int dir, int x, int y)
180 {
181         cam_dist -= dir * cam_dist * 0.05f;
182         if(cam_dist <= MIN_CAM_DIST) cam_dist = MIN_CAM_DIST;
183         if(cam_dist > MAX_CAM_DIST) cam_dist = MAX_CAM_DIST;
184 }