1 #include <math.h>
2 #include "config.h"
3 #include "sparkles.h"
4 #include "datafun.h"
5 #include "guru_meditation.h"
6 #include "ship.h"
7 #include "globals.h"
8 #include "random_gen.h"
9 
10 struct black_point_struct {
11   int x, y;
12 };
13 static struct black_point_struct black_point[MAX_BLACK_POINTS], *blackptr =
14   black_point;
15 
16 SDL_Surface *surf_small_ship;
17 sdl_surfaces_t *surfaces_ship;
18 struct sprite ship_sprite;
19 ship_t shipdata;
20 
21 
draw_little_ships(int nships,SDL_Surface * surf_screen)22 void draw_little_ships(int nships, SDL_Surface * surf_screen) {
23   int i;
24   SDL_Rect dest;
25 
26   for(i = 0; i < nships - 1; i++) {
27     dest.w = surf_small_ship->w;
28     dest.h = surf_small_ship->h;
29     dest.x = (i + 1) * (surf_small_ship->w + 10);
30     dest.y = 40;
31     SDL_BlitSurface(surf_small_ship, NULL, surf_screen, &dest);
32   }
33 }
34 
draw_ship(SDL_Surface * surf_screen)35 void draw_ship(SDL_Surface * surf_screen) {
36   static SDL_Rect dest;
37   dest.w = 0; //src.w;
38   dest.h = 0; //src.h;
39   dest.x = (int) shipdata.xship;
40   dest.y = (int) shipdata.yship;
41   SDL_BlitSurface(get_current_sprite_surface(&ship_sprite, last_ticks), NULL, surf_screen, &dest);
42 }
43 
outline_detector()44 void outline_detector() {
45   char buf[256][256];
46   int x, y;
47   SDL_Surface *surf_ship = get_current_sprite_surface(&ship_sprite, last_ticks);
48 
49   SDL_LockSurface(surf_ship);
50   RD_VIDEO_TYPE *raw_pixels = (RD_VIDEO_TYPE *) surf_ship->pixels;
51   x = surf_ship->w - 1;
52   y = surf_ship->h - 1;
53   RD_VIDEO_TYPE background = raw_pixels[y * surf_ship->pitch / sizeof(RD_VIDEO_TYPE) + x];
54   memset(buf, 0, sizeof(buf));
55   for(y = 0; y < surf_ship->h; y++) {
56     for(x = 0; x < surf_ship->w; x++) {
57       buf[x + 1][y + 1] = raw_pixels[y * surf_ship->pitch / sizeof(RD_VIDEO_TYPE) + x] != background;
58     }
59   }
60   for(y = 0; y < surf_ship->h + 2; y++) {
61     for(x = 0; x < surf_ship->w + 2; x++) {
62       if(buf[x][y] && (!buf[x][y - 1] || !buf[x][y + 1] || !buf[x - 1][y] || !buf[x + 1][y])) printf("%d %d\t", x - 1, y - 1);
63     }
64     putchar('\n');
65   }
66   SDL_UnlockSurface(surf_ship);
67 }
68 
init_ship()69 SDL_Surface *init_ship() {
70   int i, j, numblack;
71   SDL_Surface *surf_ship;
72 
73   // Load the spaceship surface from the spaceship file
74   if((surfaces_ship = load_images_ck("ship.%02x.png", 0, 255, 0)) == NULL) {
75     fprintf(stderr, "%s\n", SDL_GetError());
76     guru_meditation(GM_FLAGS_DEADEND | GM_FLAGS_ABORTIFY, GM_SS_Graphics | GM_GE_IOError | GURU_SEC_ship, (void*)0x53484950);
77     //We never return from there...
78   }
79   init_sprite2(&ship_sprite, surfaces_ship, 117, initticks);
80 
81   /*
82    * Remember that we assume that the ship has always *exactly* the
83    * same size. If not you will get funny effects. And you will
84    * explode all the time, of course.
85    */
86   surf_ship = surfaces_ship->surfaces[0];
87   // Create the array of black points;
88   SDL_LockSurface(surf_ship);
89   RD_VIDEO_TYPE *raw_pixels = (RD_VIDEO_TYPE *) surf_ship->pixels;
90   numblack = 0;
91   for(i = 0; i < surf_ship->w; i++)
92     for(j = 0; j < surf_ship->h; j++)
93       if(raw_pixels[j * surf_ship->pitch / sizeof(RD_VIDEO_TYPE) + i] == 0) {
94 	blackptr->x = i;
95 	blackptr->y = j;
96 	blackptr++;
97 	if(++numblack > MAX_BLACK_POINTS)
98 	  return NULL;
99       }
100   SDL_UnlockSurface(surf_ship);
101   //outline_detector();
102   return surf_ship;
103 }
104 
draw_ship_shield(SDL_Surface * surf_screen)105 void draw_ship_shield(SDL_Surface * surf_screen) {
106   // Show the freaky shields
107   RD_VIDEO_TYPE *raw_pixels = (RD_VIDEO_TYPE *) surf_screen->pixels;
108   struct black_point_struct *p;
109   int x, y;
110   RD_VIDEO_TYPE c;
111 
112   SDL_LockSurface(surf_screen);
113   if(initialshield > 0) {
114     initialshield -= movementrate;
115     c = SDL_MapRGB(surf_screen->format, 0, 255, 255);
116   } else {
117     c = heatcolor[(int) shieldlevel];
118     shieldlevel -= movementrate;
119   }
120 
121   shieldpulse += 0.1;
122   for(p = black_point; p < blackptr; p++) {
123     x = p->x + (int) shipdata.xship + (rnd() + rnd() - 1) * sin(shieldpulse) * 4 + 1;
124     y = p->y + (int) shipdata.yship + (rnd() + rnd() - 1) * sin(shieldpulse) * 4 + 1;
125     if(x > 0 && y > 0 && x < xsize && y < ysize) {
126       int offset = surf_screen->pitch / sizeof(RD_VIDEO_TYPE) * y + x;
127       raw_pixels[offset] = c;
128     }
129   }
130   SDL_UnlockSurface(surf_screen);
131 }
132 
133 
ship_check_collision(SDL_Surface * surf_screen)134 int ship_check_collision(SDL_Surface * surf_screen) {
135   struct black_point_struct *p;
136   RD_VIDEO_TYPE *raw_pixels;
137   int bang = 0;
138 
139   SDL_LockSurface(surf_screen);
140   raw_pixels = (RD_VIDEO_TYPE *) surf_screen->pixels;
141   // When the shields are off, check that the black points
142   // on the ship are still black, and not covered up by rocks
143   for(p = black_point; p < blackptr; p++) {
144     int offset =
145       surf_screen->pitch / sizeof(RD_VIDEO_TYPE) * (p->y + (int) shipdata.yship) + p->x + (int) shipdata.xship;
146     if(raw_pixels[offset]) {
147       // Set the bang flag, a collision with something happened
148       bang = 1;
149       break;
150     }
151   }
152   SDL_UnlockSurface(surf_screen);
153   return bang;
154 }
155 
ship_update_position(void)156 void ship_update_position(void) {
157   SDL_Surface *surf_ship = get_current_sprite_surface(&ship_sprite, last_ticks);
158 
159   // FRICTION? In space? Oh well.
160   shipdata.xvel *= powf(0.9, movementrate);
161   shipdata.yvel *= powf(0.9, movementrate);
162   // if (abs(shipdata.xvel)<0.00001) shipdata.xvel=0;
163   // if (abs(shipdata.yvel)<0.00001) shipdata.yvel=0;
164 
165   // INERTIA
166   shipdata.xship += shipdata.xvel * movementrate;
167   shipdata.yship += shipdata.yvel * movementrate;
168 
169   // BOUNCE X  (okay, throwing all pretense of realism out the
170   // window)
171   if(shipdata.xship < 0 || shipdata.xship > xsize - surf_ship->w) {
172     // BOUNCE from left and right wall
173     shipdata.xship -= shipdata.xvel * movementrate;
174     shipdata.xvel *= -0.99;
175   }
176   // BOUNCE Y
177   if(shipdata.yship < 0 || shipdata.yship > ysize - surf_ship->h) {
178     // BOUNCE from top and bottom wall
179     shipdata.yship -= shipdata.yvel * movementrate;
180     shipdata.yvel *= -0.99;
181   }
182 }
183 
way_of_the_exploding_ship(void)184 void way_of_the_exploding_ship(void) {
185   makebangdots(shipdata.xship, shipdata.yship, shipdata.xvel, shipdata.yvel, get_current_sprite_surface(&ship_sprite, last_ticks), 30, 3);
186 }
187