Initial revision
[newkind] / threed.c
CommitLineData
84bbd123 1/*
2 * Elite - The New Kind.
3 *
4 * Reverse engineered from the BBC disk version of Elite.
5 * Additional material by C.J.Pinder.
6 *
7 * The original Elite code is (C) I.Bell & D.Braben 1984.
8 * This version re-engineered in C by C.J.Pinder 1999-2001.
9 *
10 * email: <christian@newkind.co.uk>
11 *
12 */
13
14#include <string.h>
15#include <stdlib.h>
16#include <stdio.h>
17#include <math.h>
18#include <ctype.h>
19
20#include "config.h"
21#include "elite.h"
22#include "gfx.h"
23#include "planet.h"
24#include "vector.h"
25#include "shipdata.h"
26#include "shipface.h"
27#include "threed.h"
28#include "space.h"
29#include "random.h"
30
31#define MAX(x,y) (((x) > (y)) ? (x) : (y))
32
33
34#define LAND_X_MAX 128
35#define LAND_Y_MAX 128
36
37static unsigned char landscape[LAND_X_MAX+1][LAND_Y_MAX+1];
38
39static struct point point_list[100];
40
41
42/*
43 * The following routine is used to draw a wireframe represtation of a ship.
44 *
45 * caveat: it is a work in progress.
46 * A number of features (such as not showing detail at distance) have not yet been implemented.
47 *
48 */
49
50void draw_wireframe_ship (struct univ_object *univ)
51{
52 Matrix trans_mat;
53 int i;
54 int sx,sy,ex,ey;
55 double rx,ry,rz;
56 int visible[32];
57 Vector vec;
58 Vector camera_vec;
59 double cos_angle;
60 double tmp;
61 struct ship_face_normal *ship_norm;
62 int num_faces;
63 struct ship_data *ship;
64 int lasv;
65
66 ship = ship_list[univ->type];
67
68 for (i = 0; i < 3; i++)
69 trans_mat[i] = univ->rotmat[i];
70
71 camera_vec = univ->location;
72 mult_vector (&camera_vec, trans_mat);
73 camera_vec = unit_vector (&camera_vec);
74
75 num_faces = ship->num_faces;
76
77 for (i = 0; i < num_faces; i++)
78 {
79 ship_norm = ship->normals;
80
81 vec.x = ship_norm[i].x;
82 vec.y = ship_norm[i].y;
83 vec.z = ship_norm[i].z;
84
85 if ((vec.x == 0) && (vec.y == 0) && (vec.z == 0))
86 visible[i] = 1;
87 else
88 {
89 vec = unit_vector (&vec);
90 cos_angle = vector_dot_product (&vec, &camera_vec);
91 visible[i] = (cos_angle < -0.2);
92 }
93 }
94
95 tmp = trans_mat[0].y;
96 trans_mat[0].y = trans_mat[1].x;
97 trans_mat[1].x = tmp;
98
99 tmp = trans_mat[0].z;
100 trans_mat[0].z = trans_mat[2].x;
101 trans_mat[2].x = tmp;
102
103 tmp = trans_mat[1].z;
104 trans_mat[1].z = trans_mat[2].y;
105 trans_mat[2].y = tmp;
106
107 for (i = 0; i < ship->num_points; i++)
108 {
109 vec.x = ship->points[i].x;
110 vec.y = ship->points[i].y;
111 vec.z = ship->points[i].z;
112
113 mult_vector (&vec, trans_mat);
114
115 rx = vec.x + univ->location.x;
116 ry = vec.y + univ->location.y;
117 rz = vec.z + univ->location.z;
118
119 sx = (rx * 256) / rz;
120 sy = (ry * 256) / rz;
121
122 sy = -sy;
123
124 sx += 128;
125 sy += 96;
126
127 sx *= GFX_SCALE;
128 sy *= GFX_SCALE;
129
130 point_list[i].x = sx;
131 point_list[i].y = sy;
132
133 }
134
135 for (i = 0; i < ship->num_lines; i++)
136 {
137 if (visible[ship->lines[i].face1] ||
138 visible[ship->lines[i].face2])
139 {
140 sx = point_list[ship->lines[i].start_point].x;
141 sy = point_list[ship->lines[i].start_point].y;
142
143 ex = point_list[ship->lines[i].end_point].x;
144 ey = point_list[ship->lines[i].end_point].y;
145
146 gfx_draw_line (sx, sy, ex, ey);
147 }
148 }
149
150
151 if (univ->flags & FLG_FIRING)
152 {
153 lasv = ship_list[univ->type]->front_laser;
154 gfx_draw_line (point_list[lasv].x, point_list[lasv].y,
155 univ->location.x > 0 ? 0 : 511, rand255() * 2);
156 }
157}
158
159
160
161
162/*
163 * Hacked version of the draw ship routine to display solid ships...
164 * This needs a lot of tidying...
165 *
166 * Check for hidden surface supplied by T.Harte.
167 */
168
169void draw_solid_ship (struct univ_object *univ)
170{
171 int i;
172 int sx,sy;
173 double rx,ry,rz;
174 struct vector vec;
175 struct vector camera_vec;
176 double tmp;
177 struct ship_face *face_data;
178 int num_faces;
179 int num_points;
180 int poly_list[16];
181 int zavg;
182 struct ship_solid *solid_data;
183 struct ship_data *ship;
184 Matrix trans_mat;
185 int lasv;
186 int col;
187
188 solid_data = &ship_solids[univ->type];
189 ship = ship_list[univ->type];
190
191 for (i = 0; i < 3; i++)
192 trans_mat[i] = univ->rotmat[i];
193
194 camera_vec = univ->location;
195 mult_vector (&camera_vec, trans_mat);
196 camera_vec = unit_vector (&camera_vec);
197
198 num_faces = solid_data->num_faces;
199 face_data = solid_data->face_data;
200
201/*
202 for (i = 0; i < num_faces; i++)
203 {
204 vec.x = face_data[i].norm_x;
205 vec.y = face_data[i].norm_y;
206 vec.z = face_data[i].norm_z;
207
208 vec = unit_vector (&vec);
209 cos_angle = vector_dot_product (&vec, &camera_vec);
210
211 visible[i] = (cos_angle < -0.13);
212 }
213*/
214
215 tmp = trans_mat[0].y;
216 trans_mat[0].y = trans_mat[1].x;
217 trans_mat[1].x = tmp;
218
219 tmp = trans_mat[0].z;
220 trans_mat[0].z = trans_mat[2].x;
221 trans_mat[2].x = tmp;
222
223 tmp = trans_mat[1].z;
224 trans_mat[1].z = trans_mat[2].y;
225 trans_mat[2].y = tmp;
226
227
228 for (i = 0; i < ship->num_points; i++)
229 {
230 vec.x = ship->points[i].x;
231 vec.y = ship->points[i].y;
232 vec.z = ship->points[i].z;
233
234 mult_vector (&vec, trans_mat);
235
236 rx = vec.x + univ->location.x;
237 ry = vec.y + univ->location.y;
238 rz = vec.z + univ->location.z;
239
240 if (rz <= 0)
241 rz = 1;
242
243 sx = (rx * 256) / rz;
244 sy = (ry * 256) / rz;
245
246 sy = -sy;
247
248 sx += 128;
249 sy += 96;
250
251 sx *= GFX_SCALE;
252 sy *= GFX_SCALE;
253
254 point_list[i].x = sx;
255 point_list[i].y = sy;
256 point_list[i].z = rz;
257
258 }
259
260 for (i = 0; i < num_faces; i++)
261 {
262 if (((point_list[face_data[i].p1].x - point_list[face_data[i].p2].x) *
263 (point_list[face_data[i].p3].y - point_list[face_data[i].p2].y) -
264 (point_list[face_data[i].p1].y - point_list[face_data[i].p2].y) *
265 (point_list[face_data[i].p3].x - point_list[face_data[i].p2].x)) <= 0)
266 {
267 num_points = face_data[i].points;
268
269 poly_list[0] = point_list[face_data[i].p1].x;
270 poly_list[1] = point_list[face_data[i].p1].y;
271 zavg = point_list[face_data[i].p1].z;
272
273 poly_list[2] = point_list[face_data[i].p2].x;
274 poly_list[3] = point_list[face_data[i].p2].y;
275 zavg = MAX(zavg,point_list[face_data[i].p2].z);
276
277 if (num_points > 2)
278 {
279 poly_list[4] = point_list[face_data[i].p3].x;
280 poly_list[5] = point_list[face_data[i].p3].y;
281 zavg = MAX(zavg,point_list[face_data[i].p3].z);
282 }
283
284 if (num_points > 3)
285 {
286 poly_list[6] = point_list[face_data[i].p4].x;
287 poly_list[7] = point_list[face_data[i].p4].y;
288 zavg = MAX(zavg,point_list[face_data[i].p4].z);
289 }
290
291 if (num_points > 4)
292 {
293 poly_list[8] = point_list[face_data[i].p5].x;
294 poly_list[9] = point_list[face_data[i].p5].y;
295 zavg = MAX(zavg,point_list[face_data[i].p5].z);
296 }
297
298 if (num_points > 5)
299 {
300 poly_list[10] = point_list[face_data[i].p6].x;
301 poly_list[11] = point_list[face_data[i].p6].y;
302 zavg = MAX(zavg,point_list[face_data[i].p6].z);
303 }
304
305 if (num_points > 6)
306 {
307 poly_list[12] = point_list[face_data[i].p7].x;
308 poly_list[13] = point_list[face_data[i].p7].y;
309 zavg = MAX(zavg,point_list[face_data[i].p7].z);
310 }
311
312 if (num_points > 7)
313 {
314 poly_list[14] = point_list[face_data[i].p8].x;
315 poly_list[15] = point_list[face_data[i].p8].y;
316 zavg = MAX(zavg,point_list[face_data[i].p8].z);
317 }
318
319
320 gfx_render_polygon (face_data[i].points, poly_list, face_data[i].colour, zavg);
321
322 }
323 }
324
325 if (univ->flags & FLG_FIRING)
326 {
327 lasv = ship_list[univ->type]->front_laser;
328 col = (univ->type == SHIP_VIPER) ? GFX_COL_CYAN : GFX_COL_WHITE;
329
330 gfx_render_line (point_list[lasv].x, point_list[lasv].y,
331 univ->location.x > 0 ? 0 : 511, rand255() * 2,
332 point_list[lasv].z, col);
333 }
334}
335
336
337
338
339
340/*
341 * Colour map used to generate a SNES Elite style planet.
342 * This is a quick hack and needs tidying up.
343 */
344
345int snes_planet_colour[] =
346{
347 102, 102,
348 134, 134, 134, 134,
349 167, 167, 167, 167,
350 213, 213,
351 255,
352 83,83,83,83,
353 122,
354 83,83,
355 249,249,249,249,
356 83,
357 122,
358 249,249,249,249,249,249,
359 83, 83,
360 122,
361 83,83, 83, 83,
362 255,
363 213, 213,
364 167,167, 167, 167,
365 134,134, 134, 134,
366 102, 102
367};
368
369
370/*
371 * Generate a landscape map for a SNES Elite style planet.
372 */
373
374void generate_snes_landscape (void)
375{
376 int x,y;
377 int colour;
378
379 for (y = 0; y <= LAND_Y_MAX; y++)
380 {
381 colour = snes_planet_colour[y * (sizeof(snes_planet_colour)/sizeof(int)) / LAND_Y_MAX];
382 for (x = 0; x <= LAND_X_MAX; x++)
383 {
384 landscape[x][y] = colour;
385 }
386 }
387}
388
389
390
391
392/*
393 * Guassian random number generator.
394 * Returns a number between -7 and +8 with Gaussian distribution.
395 */
396
397int grand (void)
398{
399 int i;
400 int r;
401
402 r = 0;
403 for (i = 0; i < 12; i++)
404 r += randint() & 15;
405
406 r /= 12;
407 r -= 7;
408
409 return r;
410}
411
412
413/*
414 * Calculate the midpoint between two given points.
415 */
416
417int calc_midpoint (int sx, int sy, int ex, int ey)
418{
419 int a,b,n;
420
421 a = landscape[sx][sy];
422 b = landscape[ex][ey];
423
424 n = ((a + b) / 2) + grand();
425 if (n < 0)
426 n = 0;
427 if (n > 255)
428 n = 255;
429
430 return n;
431}
432
433
434/*
435 * Calculate a square on the midpoint map.
436 */
437
438void midpoint_square (int tx, int ty, int w)
439{
440 int mx,my;
441 int bx,by;
442 int d;
443
444 d = w / 2;
445 mx = tx + d;
446 my = ty + d;
447 bx = tx + w;
448 by = ty + w;
449
450 landscape[mx][ty] = calc_midpoint(tx,ty,bx,ty);
451 landscape[mx][by] = calc_midpoint(tx,by,bx,by);
452 landscape[tx][my] = calc_midpoint(tx,ty,tx,by);
453 landscape[bx][my] = calc_midpoint(bx,ty,bx,by);
454 landscape[mx][my] = calc_midpoint(tx,my,bx,my);
455
456 if (d == 1)
457 return;
458
459 midpoint_square (tx,ty,d);
460 midpoint_square (mx,ty,d);
461 midpoint_square (tx,my,d);
462 midpoint_square (mx,my,d);
463}
464
465
466/*
467 * Generate a fractal landscape.
468 * Uses midpoint displacement method.
469 */
470
471void generate_fractal_landscape (int rnd_seed)
472{
473 int x,y,d,h;
474 double dist;
475 int dark;
476 int old_seed;
477
478 old_seed = get_rand_seed();
479 set_rand_seed(rnd_seed);
480
481 d = LAND_X_MAX / 8;
482
483 for (y = 0; y <= LAND_Y_MAX; y += d)
484 for (x = 0; x <= LAND_X_MAX; x += d)
485 landscape[x][y] = randint() & 255;
486
487 for (y = 0; y < LAND_Y_MAX; y += d)
488 for (x = 0; x < LAND_X_MAX; x += d)
489 midpoint_square (x,y,d);
490
491 for (y = 0; y <= LAND_Y_MAX; y++)
492 {
493 for (x = 0; x <= LAND_X_MAX; x++)
494 {
495 dist = x*x + y*y;
496 dark = dist > 10000;
497 h = landscape[x][y];
498 if (h > 166)
499 landscape[x][y] = dark ? GFX_COL_GREEN_1 : GFX_COL_GREEN_2;
500 else
501 landscape[x][y] = dark ? GFX_COL_BLUE_2 : GFX_COL_BLUE_1;
502
503 }
504 }
505
506 set_rand_seed (old_seed);
507}
508
509
510void generate_landscape (int rnd_seed)
511{
512 switch (planet_render_style)
513 {
514 case 0: /* Wireframe... do nothing for now... */
515 break;
516
517 case 1:
518 /* generate_green_landscape (); */
519 break;
520
521 case 2:
522 generate_snes_landscape();
523 break;
524
525 case 3:
526 generate_fractal_landscape (rnd_seed);
527 break;
528 }
529}
530
531
532
533/*
534 * Draw a line of the planet with appropriate rotation.
535 */
536
537
538void render_planet_line (int xo, int yo, int x, int y, int radius, int vx, int vy)
539{
540 int lx, ly;
541 int rx, ry;
542 int colour;
543 int sx,sy;
544 int ex;
545 int div;
546
547 sy = y + yo;
548
549 if ((sy < GFX_VIEW_TY + GFX_Y_OFFSET) ||
550 (sy > GFX_VIEW_BY + GFX_Y_OFFSET))
551 return;
552
553 sx = xo - x;
554 ex = xo + x;
555
556 rx = -x * vx - y * vy;
557 ry = -x * vy + y * vx;
558 rx += radius << 16;
559 ry += radius << 16;
560 div = radius << 10; /* radius * 2 * LAND_X_MAX >> 16 */
561
562
563 for (; sx <= ex; sx++)
564 {
565 if ((sx >= (GFX_VIEW_TX + GFX_X_OFFSET)) && (sx <= (GFX_VIEW_BX + GFX_X_OFFSET)))
566 {
567 lx = rx / div;
568 ly = ry / div;
569 colour = landscape[lx][ly];
570
571 gfx_fast_plot_pixel (sx, sy, colour);
572 }
573 rx += vx;
574 ry += vy;
575 }
576}
577
578
579/*
580 * Draw a solid planet. Based on Doros circle drawing alogorithm.
581 */
582
583void render_planet (int xo, int yo, int radius, struct vector *vec)
584{
585 int x,y;
586 int s;
587 int vx,vy;
588
589 xo += GFX_X_OFFSET;
590 yo += GFX_Y_OFFSET;
591
592 vx = vec[1].x * 65536;
593 vy = vec[1].y * 65536;
594
595 s = radius;
596 x = radius;
597 y = 0;
598
599 s -= x + x;
600 while (y <= x)
601 {
602 render_planet_line (xo, yo, x, y, radius, vx, vy);
603 render_planet_line (xo, yo, x,-y, radius, vx, vy);
604 render_planet_line (xo, yo, y, x, radius, vx, vy);
605 render_planet_line (xo, yo, y,-x, radius, vx, vy);
606
607 s += y + y + 1;
608 y++;
609 if (s >= 0)
610 {
611 s -= x + x + 2;
612 x--;
613 }
614 }
615}
616
617
618/*
619 * Draw a wireframe planet.
620 * At the moment we just draw a circle.
621 * Need to add in the two arcs that the original Elite had.
622 */
623
624void draw_wireframe_planet (int xo, int yo, int radius, struct vector *vec)
625{
626 gfx_draw_circle (xo, yo, radius, GFX_COL_WHITE);
627}
628
629
630/*
631 * Draw a planet.
632 * We can currently do three different types of planet...
633 * - Wireframe.
634 * - Fractal landscape.
635 * - SNES Elite style.
636 */
637
638void draw_planet (struct univ_object *planet)
639{
640 int x,y;
641 int radius;
642
643 x = (planet->location.x * 256) / planet->location.z;
644 y = (planet->location.y * 256) / planet->location.z;
645
646 y = -y;
647
648 x += 128;
649 y += 96;
650
651 x *= GFX_SCALE;
652 y *= GFX_SCALE;
653
654 radius = 6291456 / planet->distance;
655// radius = 6291456 / ship_vec.z; /* Planets are BIG! */
656
657 radius *= GFX_SCALE;
658
659 if ((x + radius < 0) ||
660 (x - radius > 511) ||
661 (y + radius < 0) ||
662 (y - radius > 383))
663 return;
664
665 switch (planet_render_style)
666 {
667 case 0:
668 draw_wireframe_planet (x, y, radius, planet->rotmat);
669 break;
670
671 case 1:
672 gfx_draw_filled_circle (x, y, radius, GFX_COL_GREEN_1);
673 break;
674
675 case 2:
676 case 3:
677 render_planet (x, y, radius, planet->rotmat);
678 break;
679 }
680}
681
682
683void render_sun_line (int xo, int yo, int x, int y, int radius)
684{
685 int sy = yo + y;
686 int sx,ex;
687 int colour;
688 int dx,dy;
689 int distance;
690 int inner,outer;
691 int inner2;
692 int mix;
693
694 if ((sy < GFX_VIEW_TY + GFX_Y_OFFSET) ||
695 (sy > GFX_VIEW_BY + GFX_Y_OFFSET))
696 return;
697
698 sx = xo - x;
699 ex = xo + x;
700
701 sx -= (radius * (2 + (randint() & 7))) >> 8;
702 ex += (radius * (2 + (randint() & 7))) >> 8;
703
704 if ((sx > GFX_VIEW_BX + GFX_X_OFFSET) ||
705 (ex < GFX_VIEW_TX + GFX_X_OFFSET))
706 return;
707
708 if (sx < GFX_VIEW_TX + GFX_X_OFFSET)
709 sx = GFX_VIEW_TX + GFX_X_OFFSET;
710
711 if (ex > GFX_VIEW_BX + GFX_X_OFFSET)
712 ex = GFX_VIEW_BX + GFX_X_OFFSET;
713
714 inner = (radius * (200 + (randint() & 7))) >> 8;
715 inner *= inner;
716
717 inner2 = (radius * (220 + (randint() & 7))) >> 8;
718 inner2 *= inner2;
719
720 outer = (radius * (239 + (randint() & 7))) >> 8;
721 outer *= outer;
722
723 dy = y * y;
724 dx = sx - xo;
725
726 for (; sx <= ex; sx++,dx++)
727 {
728 mix = (sx ^ y) & 1;
729 distance = dx * dx + dy;
730
731 if (distance < inner)
732 colour = GFX_COL_WHITE;
733 else if (distance < inner2)
734 colour = GFX_COL_YELLOW_4;
735 else if (distance < outer)
736 colour = GFX_ORANGE_3;
737 else
738 colour = mix ? GFX_ORANGE_1 : GFX_ORANGE_2;
739
740 gfx_fast_plot_pixel (sx, sy, colour);
741 }
742}
743
744
745void render_sun (int xo, int yo, int radius)
746{
747 int x,y;
748 int s;
749
750 xo += GFX_X_OFFSET;
751 yo += GFX_Y_OFFSET;
752
753 s = -radius;
754 x = radius;
755 y = 0;
756
757 // s -= x + x;
758 while (y <= x)
759 {
760 render_sun_line (xo, yo, x, y, radius);
761 render_sun_line (xo, yo, x,-y, radius);
762 render_sun_line (xo, yo, y, x, radius);
763 render_sun_line (xo, yo, y,-x, radius);
764
765 s += y + y + 1;
766 y++;
767 if (s >= 0)
768 {
769 s -= x + x + 2;
770 x--;
771 }
772 }
773}
774
775
776
777void draw_sun (struct univ_object *planet)
778{
779 int x,y;
780 int radius;
781
782 x = (planet->location.x * 256) / planet->location.z;
783 y = (planet->location.y * 256) / planet->location.z;
784
785 y = -y;
786
787 x += 128;
788 y += 96;
789
790 x *= GFX_SCALE;
791 y *= GFX_SCALE;
792
793 radius = 6291456 / planet->distance;
794
795 radius *= GFX_SCALE;
796
797 if ((x + radius < 0) ||
798 (x - radius > 511) ||
799 (y + radius < 0) ||
800 (y - radius > 383))
801 return;
802
803 render_sun (x, y, radius);
804}
805
806
807
808void draw_explosion (struct univ_object *univ)
809{
810 int i;
811 int z;
812 int q;
813 int pr;
814 int px,py;
815 int cnt;
816 int sizex,sizey,psx,psy;
817 Matrix trans_mat;
818 int sx,sy;
819 double rx,ry,rz;
820 int visible[32];
821 struct vector vec;
822 struct vector camera_vec;
823 double cos_angle;
824 double tmp;
825 struct ship_face_normal *ship_norm;
826 struct ship_point *sp;
827 struct ship_data *ship;
828 int np;
829 int old_seed;
830
831
832 if (univ->exp_delta > 251)
833 {
834 univ->flags |= FLG_REMOVE;
835 return;
836 }
837
838 univ->exp_delta += 4;
839
840 if (univ->location.z <= 0)
841 return;
842
843 ship = ship_list[univ->type];
844
845 for (i = 0; i < 3; i++)
846 trans_mat[i] = univ->rotmat[i];
847
848 camera_vec = univ->location;
849 mult_vector (&camera_vec, trans_mat);
850 camera_vec = unit_vector (&camera_vec);
851
852 ship_norm = ship->normals;
853
854 for (i = 0; i < ship->num_faces; i++)
855 {
856 vec.x = ship_norm[i].x;
857 vec.y = ship_norm[i].y;
858 vec.z = ship_norm[i].z;
859
860 vec = unit_vector (&vec);
861 cos_angle = vector_dot_product (&vec, &camera_vec);
862
863 visible[i] = (cos_angle < -0.13);
864 }
865
866 tmp = trans_mat[0].y;
867 trans_mat[0].y = trans_mat[1].x;
868 trans_mat[1].x = tmp;
869
870 tmp = trans_mat[0].z;
871 trans_mat[0].z = trans_mat[2].x;
872 trans_mat[2].x = tmp;
873
874 tmp = trans_mat[1].z;
875 trans_mat[1].z = trans_mat[2].y;
876 trans_mat[2].y = tmp;
877
878 sp = ship->points;
879 np = 0;
880
881 for (i = 0; i < ship->num_points; i++)
882 {
883 if (visible[sp[i].face1] || visible[sp[i].face2] ||
884 visible[sp[i].face3] || visible[sp[i].face4])
885 {
886 vec.x = sp[i].x;
887 vec.y = sp[i].y;
888 vec.z = sp[i].z;
889
890 mult_vector (&vec, trans_mat);
891
892 rx = vec.x + univ->location.x;
893 ry = vec.y + univ->location.y;
894 rz = vec.z + univ->location.z;
895
896 sx = (rx * 256) / rz;
897 sy = (ry * 256) / rz;
898
899 sy = -sy;
900
901 sx += 128;
902 sy += 96;
903
904 sx *= GFX_SCALE;
905 sy *= GFX_SCALE;
906
907 point_list[np].x = sx;
908 point_list[np].y = sy;
909 np++;
910 }
911 }
912
913
914 z = (int)univ->location.z;
915
916 if (z >= 0x2000)
917 q = 254;
918 else
919 q = (z / 32) | 1;
920
921 pr = (univ->exp_delta * 256) / q;
922
923// if (pr > 0x1C00)
924// q = 254;
925// else
926
927 q = pr / 32;
928
929 old_seed = get_rand_seed();
930 set_rand_seed (univ->exp_seed);
931
932 for (cnt = 0; cnt < np; cnt++)
933 {
934 sx = point_list[cnt].x;
935 sy = point_list[cnt].y;
936
937 for (i = 0; i < 16; i++)
938 {
939 px = rand255() - 128;
940 py = rand255() - 128;
941
942 px = (px * q) / 256;
943 py = (py * q) / 256;
944
945 px = px + px + sx;
946 py = py + py + sy;
947
948 sizex = (randint() & 1) + 1;
949 sizey = (randint() & 1) + 1;
950
951 for (psy = 0; psy < sizey; psy++)
952 for (psx = 0; psx < sizex; psx++)
953 gfx_plot_pixel (px+psx, py+psy, GFX_COL_WHITE);
954 }
955 }
956
957 set_rand_seed (old_seed);
958}
959
960
961
962/*
963 * Draws an object in the universe.
964 * (Ship, Planet, Sun etc).
965 */
966
967void draw_ship (struct univ_object *ship)
968{
969
970 if ((current_screen != SCR_FRONT_VIEW) && (current_screen != SCR_REAR_VIEW) &&
971 (current_screen != SCR_LEFT_VIEW) && (current_screen != SCR_RIGHT_VIEW) &&
972 (current_screen != SCR_INTRO_ONE) && (current_screen != SCR_INTRO_TWO) &&
973 (current_screen != SCR_GAME_OVER) && (current_screen != SCR_ESCAPE_POD))
974 return;
975
976 if ((ship->flags & FLG_DEAD) && !(ship->flags & FLG_EXPLOSION))
977 {
978 ship->flags |= FLG_EXPLOSION;
979 ship->exp_seed = randint();
980 ship->exp_delta = 18;
981 }
982
983 if (ship->flags & FLG_EXPLOSION)
984 {
985 draw_explosion (ship);
986 return;
987 }
988
989 if (ship->location.z <= 0) /* Only display ships in front of us. */
990 return;
991
992 if (ship->type == SHIP_PLANET)
993 {
994 draw_planet (ship);
995 return;
996 }
997
998 if (ship->type == SHIP_SUN)
999 {
1000 draw_sun (ship);
1001 return;
1002 }
1003
1004 if ((fabs(ship->location.x) > ship->location.z) || /* Check for field of vision. */
1005 (fabs(ship->location.y) > ship->location.z))
1006 return;
1007
1008 if (wireframe)
1009 draw_wireframe_ship (ship);
1010 else
1011 draw_solid_ship (ship);
1012}
1013