ship list further de-uglyfied
[cave9.git] / src / game.cpp
bloba923bf037d07b15e1349f2f4878d9914c27ab4fe
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <math.h>
6 #include <float.h>
7 #include <assert.h>
8 #include <SDL_opengl.h>
9 #include <GL/gl.h>
10 #include "vec.h"
11 #include "game.h"
13 void cave_gen(Cave* cave, Ship* digger)
15 // check if the digger advanced to the next segment
16 int i = (cave->i-1+SEGMENT_COUNT)%SEGMENT_COUNT;
17 if( digger->pos[2] > digger->start+1 && digger->pos[2] - SEGMENT_LEN < cave->segs[i][0][2] )
18 return;
20 // invalidate GL list for this segment
21 if(glIsList(cave->gl_list[cave->i]))
22 glDeleteLists(cave->gl_list[cave->i], 1);
23 cave->gl_list[cave->i] = 0;
25 if(glIsList(cave->gl_wire_list[cave->i]))
26 glDeleteLists(cave->gl_wire_list[cave->i], 1);
27 cave->gl_wire_list[cave->i] = 0;
29 // generate new segment
30 for( i = 0; i < SECTOR_COUNT; ++i ) {
31 float a = M_PI_2+(i-1)*M_PI*2/SECTOR_COUNT;
32 float r = digger->radius;
33 SET(cave->segs[cave->i][i],
34 digger->pos[0] + r*cos(a),
35 digger->pos[1] + r*sin(a),
36 ((int)(digger->pos[2]/SEGMENT_LEN))*SEGMENT_LEN
40 // increment segment circular pointer
41 cave->i ++;
42 if( cave->i >= SEGMENT_COUNT ) {
43 cave->i = 0;
45 // place monolith
46 cave->monolith_x = digger->pos[0] + (2*RAND-1)*(digger->radius-MONOLITH_WIDTH);
47 cave->monolith_y = digger->pos[1] + (2*RAND-1)*(digger->radius-MONOLITH_HEIGHT);
48 cave->monolith_yaw = atan2(digger->vel[0], digger->vel[2]);
52 void cave_init(Cave* cave, Ship* digger)
54 cave->i = 0;
55 do {
56 digger_control(digger);
57 ship_move(digger, 1./FPS);
58 cave_gen(cave, digger);
60 while(cave->i != 0);
63 void ship_init(Ship* ship, float radius)
65 SET(ship->pos,0,0,ship->start);
66 SET(ship->vel,0,0,VELOCITY);
67 SET(ship->lookAt,0,0,VELOCITY);
68 ship->radius = radius;
69 ship->dist = FLT_MAX;
72 void ship_move(Ship* ship, float dt)
74 #if 1
75 float a = THRUST*dt;
77 if(ship->lefton) {
78 Vec3 leftup = {-a,a/2,0};
79 ADD(ship->vel, leftup);
82 if(ship->righton) {
83 Vec3 rightup = {+a,a/2,0};
84 ADD(ship->vel, rightup);
87 ship->vel[1] -= GRAVITY*dt;
89 ADDSCALE(ship->pos, ship->vel, dt);
92 Vec3 d;
93 float smoothness = 0.2;
94 SUB2 (d, ship->vel, ship->lookAt);
95 ADDSCALE (ship->lookAt, d, smoothness);
98 #else
99 if(ship->lefton)
100 ship->vel[1] += THRUST*dt;
102 ship->vel[1] -= GRAVITY*dt;
104 ship->pos[1] += ship->vel[1]*dt;
105 #endif
108 void digger_control(Ship* ship)
110 float twist_factor = 500;
111 float noise = .1;
112 float twist = 1-1/(1+ ship->pos[2]/twist_factor );
113 float max_vel[3] = {
114 MAX_VEL_X * twist,
115 MAX_VEL_Y * twist,
116 MAX_VEL_Z
119 if(
120 ship->vel[1] > max_vel[1] ||
121 ship->vel[1] < -max_vel[1] ||
122 ship->vel[0] > max_vel[0] ||
123 ship->vel[0] < -max_vel[0] ||
124 RAND<twist*noise
127 if(RAND>twist/2)
128 ship->lefton = RAND<twist*noise ? rand()%2 :
129 ship->vel[1] < 0 || ship->vel[0] > +max_vel[0];
131 if(RAND>twist/2)
132 ship->righton = RAND<twist*noise ? rand()%2 :
133 ship->vel[1] < 0 || ship->vel[0] < -max_vel[0];
136 float scale = 1-MIN(1,log(1+ship->pos[2])/log(1+MIN_CAVE_RADIUS_DEPTH));
137 ship->radius = MIN_CAVE_RADIUS+(MAX_CAVE_RADIUS-MIN_CAVE_RADIUS)*scale+RAND;
140 static float X(Cave* cave, int i, float xn, float yn, int k0, int k1)
141 {// used by collision()
143 float x1 = cave->segs[i][k0][0];
144 float y1 = cave->segs[i][k0][1];
145 float x2 = cave->segs[i][k1][0];
146 float y2 = cave->segs[i][k1][1];
147 float t = (yn - y2)/(y1 - y2);
148 if( t < 0 || t > 1 )
149 return 0;
150 float x = (x1 - xn)*t + (x2 - xn)*(1 - t);
151 //printf("t(%f), x(%f)\n", t, x);
152 return x;
155 float collision(Cave* cave, Ship* ship)
157 float min = FLT_MAX;
159 // This method counts the number of intersections of a semi-line
160 // starting from the point being checked against the poligon,
161 // that in this case is the segment of the cave.
162 // If the number of intersections is odd, the point is inside.
164 // In fact we'll check four points around the center of the ship
165 // (to simulate a diamond-shaped bounding box).
167 // The return value is the distance from the ship to the cave.
169 int intersection_count[4];
170 memset(intersection_count, 0, sizeof(intersection_count));
172 int i = cave->i;
173 int k;
174 for( k = 0; k < SECTOR_COUNT; ++k ) {
175 int i0 = (k+0)%SECTOR_COUNT;
176 int i1 = (k+1)%SECTOR_COUNT;
178 Vec3 dist;
179 SUB2(dist, ship->pos, cave->segs[i][i0]);
180 float len = LEN(dist);
181 if(len < min)
182 min = len;
184 // optimize
185 if(cave->segs[i][i0][0] < ship->pos[0]-ship->radius &&
186 cave->segs[i][i1][0] < ship->pos[0]-ship->radius)
187 continue;
188 if(cave->segs[i][i0][1] > ship->pos[1]+ship->radius &&
189 cave->segs[i][i1][1] > ship->pos[1]+ship->radius)
190 continue;
191 if(cave->segs[i][i0][1] < ship->pos[1]-ship->radius &&
192 cave->segs[i][i1][1] < ship->pos[1]-ship->radius)
193 continue;
195 if(X(cave, i, ship->pos[0] - ship->radius, ship->pos[1], i0, i1) > 0)
196 ++intersection_count[0];
198 if(X(cave, i, ship->pos[0], ship->pos[1] + ship->radius, i0, i1) > 0)
199 ++intersection_count[1];
201 if(X(cave, i, ship->pos[0] + ship->radius, ship->pos[1], i0, i1) > 0)
202 ++intersection_count[2];
204 if(X(cave, i, ship->pos[0], ship->pos[1] - ship->radius, i0, i1) > 0)
205 ++intersection_count[3];
208 for(i = 0; i < 4; ++i) {
209 if(intersection_count[i] % 2 == 0) {
210 return ship->dist = 0; // hit
214 ship->dist = min - 2*ship->radius;
215 return min; // miss
218 // vim600:fdm=syntax:fdn=1: