renamed source files back to .c
[cave9.git] / src / game.c
blobbe151721eb1d3ef963d554afcfb063addf5662f6
1 /*
2 This file is part of cave9.
4 cave9 is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 cave9 is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with cave9. If not, see <http://www.gnu.org/licenses/>.
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <math.h>
22 #include <float.h>
23 #include <assert.h>
24 #include <SDL_opengl.h>
25 #include <GL/gl.h>
26 #include "vec.h"
27 #include "game.h"
29 void cave_gen (Cave* cave, Ship* digger)
31 // check if the digger advanced to the next segment
32 int i = (cave->i - 1 + SEGMENT_COUNT) % SEGMENT_COUNT;
33 if (digger->pos[2] > digger->start+1 && digger->pos[2]-SEGMENT_LEN < cave->segs[i][0][2])
34 return;
36 // invalidate GL list for this segment
37 if(glIsList(cave->gl_list[cave->i]))
38 glDeleteLists(cave->gl_list[cave->i], 1);
39 cave->gl_list[cave->i] = 0;
41 if(glIsList(cave->gl_wire_list[cave->i]))
42 glDeleteLists(cave->gl_wire_list[cave->i], 1);
43 cave->gl_wire_list[cave->i] = 0;
45 // generate new segment
46 for( i = 0; i < SECTOR_COUNT; ++i ) {
47 float a = M_PI_2+(i-1)*M_PI*2/SECTOR_COUNT;
48 float r = digger->radius;
49 SET(cave->segs[cave->i][i],
50 digger->pos[0] + r*cos(a) + RAND,
51 digger->pos[1] + r*sin(a) + RAND,
52 ((int)(digger->pos[2]/SEGMENT_LEN))*SEGMENT_LEN
56 // increment segment circular pointer
57 cave->i ++;
58 if( cave->i >= SEGMENT_COUNT ) {
59 cave->i = 0;
61 // place monolith
62 cave->monolith_x = digger->pos[0] + (2*RAND-1)*(digger->radius-MONOLITH_WIDTH);
63 cave->monolith_y = digger->pos[1] + (2*RAND-1)*(digger->radius-MONOLITH_HEIGHT);
64 cave->monolith_yaw = atan2(digger->vel[0], digger->vel[2]);
68 void cave_init (Cave* cave, Ship* digger)
70 cave->i = 0;
71 do {
72 digger_control(digger);
73 ship_move(digger, 1./FPS);
74 cave_gen(cave, digger);
76 while(cave->i != 0);
79 void ship_init (Ship* ship, float radius)
81 SET(ship->pos,0,0,ship->start);
82 SET(ship->vel,0,0,VELOCITY);
83 SET(ship->lookAt,0,0,VELOCITY);
84 ship->radius = radius;
85 ship->dist = FLT_MAX;
88 void ship_move (Ship* ship, float dt)
90 float a = THRUST*dt;
92 if(ship->lefton) {
93 Vec3 leftup = {-a,a/2,0};
94 ADD(ship->vel, leftup);
97 if(ship->righton) {
98 Vec3 rightup = {+a,a/2,0};
99 ADD(ship->vel, rightup);
102 ship->vel[1] -= GRAVITY*dt;
104 ADDSCALE(ship->pos, ship->vel, dt);
107 float smoothness = 0.2;
108 Vec3 d;
109 SUB2 (d, ship->vel, ship->lookAt);
110 ADDSCALE (ship->lookAt, d, smoothness);
114 void digger_control (Ship* ship)
116 float twist_factor = 500;
117 float noise = .1;
118 float twist = 1 - 1/(1 + ship->pos[2]/twist_factor);
119 float max_vel[3] = {
120 MAX_VEL_X * twist,
121 MAX_VEL_Y * twist,
122 MAX_VEL_Z
125 if(
126 ship->vel[1] > max_vel[1] ||
127 ship->vel[1] < -max_vel[1] ||
128 ship->vel[0] > max_vel[0] ||
129 ship->vel[0] < -max_vel[0] ||
130 RAND < twist*noise
133 if(RAND>twist/2)
134 ship->lefton = RAND<twist*noise ? rand()%2 :
135 ship->vel[1] < 0 || ship->vel[0] > +max_vel[0];
137 if(RAND>twist/2)
138 ship->righton = RAND<twist*noise ? rand()%2 :
139 ship->vel[1] < 0 || ship->vel[0] < -max_vel[0];
142 float scale = 1-MIN(1,log(1+ship->pos[2])/log(1+MIN_CAVE_RADIUS_DEPTH));
143 ship->radius = MIN_CAVE_RADIUS+(MAX_CAVE_RADIUS-MIN_CAVE_RADIUS)*scale+RAND;
147 static float X (Cave* cave, int i, float xn, float yn, int k0, int k1)
148 {// used by collision()
150 float x1 = cave->segs[i][k0][0];
151 float y1 = cave->segs[i][k0][1];
152 float x2 = cave->segs[i][k1][0];
153 float y2 = cave->segs[i][k1][1];
154 float t = (yn - y2)/(y1 - y2);
155 if( t < 0 || t > 1 )
156 return 0;
157 float x = (x1 - xn)*t + (x2 - xn)*(1 - t);
158 //printf("t(%f), x(%f)\n", t, x);
159 return x;
162 float collision (Cave* cave, Ship* ship)
164 float min = FLT_MAX;
166 // This method counts the number of intersections of a semi-line
167 // starting from the point being checked against the poligon,
168 // that in this case is the segment of the cave.
169 // If the number of intersections is odd, the point is inside.
171 // In fact we'll check four points around the center of the ship
172 // (to simulate a diamond-shaped bounding box).
174 // The return value is the distance from the ship to the cave.
176 int intersection_count[4];
177 memset(intersection_count, 0, sizeof(intersection_count));
179 int i = cave->i;
180 int k;
181 for( k = 0; k < SECTOR_COUNT; ++k ) {
182 int i0 = (k+0)%SECTOR_COUNT;
183 int i1 = (k+1)%SECTOR_COUNT;
185 Vec3 dist;
186 SUB2(dist, ship->pos, cave->segs[i][i0]);
187 float len = LEN(dist);
188 if(len < min)
189 min = len;
191 // optimize
192 if(cave->segs[i][i0][0] < ship->pos[0]-ship->radius &&
193 cave->segs[i][i1][0] < ship->pos[0]-ship->radius)
194 continue;
195 if(cave->segs[i][i0][1] > ship->pos[1]+ship->radius &&
196 cave->segs[i][i1][1] > ship->pos[1]+ship->radius)
197 continue;
198 if(cave->segs[i][i0][1] < ship->pos[1]-ship->radius &&
199 cave->segs[i][i1][1] < ship->pos[1]-ship->radius)
200 continue;
202 if(X(cave, i, ship->pos[0] - ship->radius, ship->pos[1], i0, i1) > 0)
203 ++intersection_count[0];
205 if(X(cave, i, ship->pos[0], ship->pos[1] + ship->radius, i0, i1) > 0)
206 ++intersection_count[1];
208 if(X(cave, i, ship->pos[0] + ship->radius, ship->pos[1], i0, i1) > 0)
209 ++intersection_count[2];
211 if(X(cave, i, ship->pos[0], ship->pos[1] - ship->radius, i0, i1) > 0)
212 ++intersection_count[3];
215 for(i = 0; i < 4; ++i) {
216 if(intersection_count[i] % 2 == 0) {
217 return ship->dist = 0; // hit
221 ship->dist = min - 2*ship->radius;
222 return min; // miss
225 // vim600:fdm=syntax:fdn=1: