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/>.
24 #include <SDL_opengl.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])
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
58 if( cave
->i
>= SEGMENT_COUNT
) {
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
)
72 digger_control(digger
);
73 ship_move(digger
, 1./FPS
);
74 cave_gen(cave
, digger
);
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
;
88 void ship_move (Ship
* ship
, float dt
)
93 Vec3 leftup
= {-a
,a
/2,0};
94 ADD(ship
->vel
, leftup
);
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;
109 SUB2 (d
, ship
->vel
, ship
->lookAt
);
110 ADDSCALE (ship
->lookAt
, d
, smoothness
);
114 void digger_control (Ship
* ship
)
116 float twist_factor
= 500;
118 float twist
= 1 - 1/(1 + ship
->pos
[2]/twist_factor
);
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] ||
134 ship
->lefton
= RAND
<twist
*noise
? rand()%2 :
135 ship
->vel
[1] < 0 || ship
->vel
[0] > +max_vel
[0];
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
);
157 float x
= (x1
- xn
)*t
+ (x2
- xn
)*(1 - t
);
158 //printf("t(%f), x(%f)\n", t, x);
162 float collision (Cave
* cave
, Ship
* ship
)
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
));
181 for( k
= 0; k
< SECTOR_COUNT
; ++k
) {
182 int i0
= (k
+0)%SECTOR_COUNT
;
183 int i1
= (k
+1)%SECTOR_COUNT
;
186 SUB2(dist
, ship
->pos
, cave
->segs
[i
][i0
]);
187 float len
= LEN(dist
);
192 if(cave
->segs
[i
][i0
][0] < ship
->pos
[0]-ship
->radius
&&
193 cave
->segs
[i
][i1
][0] < ship
->pos
[0]-ship
->radius
)
195 if(cave
->segs
[i
][i0
][1] > ship
->pos
[1]+ship
->radius
&&
196 cave
->segs
[i
][i1
][1] > ship
->pos
[1]+ship
->radius
)
198 if(cave
->segs
[i
][i0
][1] < ship
->pos
[1]-ship
->radius
&&
199 cave
->segs
[i
][i1
][1] < ship
->pos
[1]-ship
->radius
)
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
;
225 // vim600:fdm=syntax:fdn=1: