1 // Shape class implementation file
2 // Author: M.D.Snellgrove
3 // Date: 13/2/2001
4 // History: Original Version 13/2/2001
5 //          Collision added 27/1/2002
6 
7 // Changes by M Harman for Windows version, June 2003:
8 //   Changes for graphics related stuff.
9 
10 // Changes by M Snellgrove 7/7/2003
11 //   Bugfix in screengrab constructor
12 
13 // Changes by M Snellgrove 10/7/2003
14 //   Filename bugfix in readfile, writefile
15 //   Palette bugfix in grab, copy constructor, assigment=
16 //   Palette specification overloaded in read, readfile
17 
18 #include "shape.h"
19 
20 const int BYTESPERPIXEL = 1;
21 
22 // Default Constructor
23 
shape()24 shape :: shape(){
25   surface = NULL;
26   width = 0;
27   height = 0;
28   buffer = 0;
29 }
30 
31 // Screengrab Constructor
32 
shape(SDL_Surface * source,int x,int y,int w,int h)33 shape :: shape(SDL_Surface *source, int x, int y, int w, int h){
34   width = w;
35   height = h;
36   buffer = new char[w * h * BYTESPERPIXEL];
37   char *src_pixels = (char *)source->pixels;
38   for(int i=x;i<x+w;i++){
39     for(int j=y;j<y+h;j++){
40       buffer[ (j-y) * w + (i-x) ] = src_pixels[ j * source->pitch + i ];
41     }
42   }
43   surface = SDL_CreateRGBSurfaceFrom(buffer, width, height, 8 * BYTESPERPIXEL,
44                                      width * BYTESPERPIXEL, 0, 0, 0, 0);
45   for (int c=0;c<256;c++){
46     Uint8 rgb[3];
47     SDL_GetRGB(c, source->format, &rgb[0], &rgb[1], &rgb[2]);
48     SDL_Color col = { rgb[0], rgb[1], rgb[2], 0 };
49     SDL_SetColors(surface, &col, c, 1);
50   }
51 
52 }
53 
54 // Copy Constructor (deep copy)
55 
shape(const shape & s)56 shape :: shape(const shape &s){
57   width = s.width;
58   height = s.height;
59   int buffersize = width * height * BYTESPERPIXEL;
60   buffer = new char[buffersize];
61   for (int i = 0; i < buffersize; i++)
62     buffer[i] = s.buffer[i];
63   surface = SDL_CreateRGBSurfaceFrom(buffer, width, height, 8 * BYTESPERPIXEL,
64                                      width * BYTESPERPIXEL, 0, 0, 0, 0);
65   for (int c=0;c<256;c++){
66     Uint8 rgb[3];
67     SDL_GetRGB(c, s.surface->format, &rgb[0], &rgb[1], &rgb[2]);
68     SDL_Color col = { rgb[0], rgb[1], rgb[2], 0 };
69     SDL_SetColors(surface, &col, c, 1);
70   }
71 
72 }
73 
74 // Destructor
75 
~shape()76 shape :: ~shape(){
77   if (surface != NULL)
78     SDL_FreeSurface(surface);
79   if (buffer != 0) delete [ ]buffer;
80 }
81 
82 // Assignment Operator
83 
operator =(const shape & s)84 shape& shape :: operator= (const shape &s){
85   if (this != &s){
86     if (surface != NULL) SDL_FreeSurface(surface);
87     if (buffer != 0) delete [ ]buffer;
88     width = s.width;
89     height = s.height;
90     int buffersize = width * height * BYTESPERPIXEL;
91     buffer = new char[buffersize];
92     for (int i = 0; i < buffersize; i++)
93       buffer[i] = s.buffer[i];
94     surface = SDL_CreateRGBSurfaceFrom(buffer, width, height, 8 * BYTESPERPIXEL,
95                                        width * BYTESPERPIXEL, 0, 0, 0, 0);
96     for (int c=0;c<256;c++){
97       Uint8 rgb[3];
98       SDL_GetRGB(c, s.surface->format, &rgb[0], &rgb[1], &rgb[2]);
99       SDL_Color col = { rgb[0], rgb[1], rgb[2], 0 };
100       SDL_SetColors(surface, &col, c, 1);
101     }
102 
103   }
104   return *this;
105 }
106 
107 // Accessor functions for private variables
108 
getwidth()109 int shape :: getwidth(){return width;}
getheight()110 int shape :: getheight(){return height;}
getSurface()111 SDL_Surface* shape :: getSurface(){return surface;}
112 //char* shape :: getbuffer(){return buffer;}
113 
114 // Shape Grabber function
115 
grab(SDL_Surface * source,int x,int y,int w,int h)116 void shape :: grab(SDL_Surface *source, int x, int y, int w, int h){
117   if (surface != NULL) SDL_FreeSurface(surface);
118   if (buffer != 0) delete [ ]buffer;
119   width = w;
120   height = h;
121 
122   buffer = new char[w * h * BYTESPERPIXEL];
123   char *src_pixels = (char *)source->pixels;
124   for(int i=x;i<x+w;i++){
125     for(int j=y;j<y+h;j++){
126       buffer[ (j-y) * w + (i-x) ] = src_pixels[ j * source->pitch + i ];
127     }
128   }
129   surface = SDL_CreateRGBSurfaceFrom(buffer, width, height, 8 * BYTESPERPIXEL,
130                                      width * BYTESPERPIXEL, 0, 0, 0, 0);
131   for (int c=0;c<256;c++){
132     Uint8 rgb[3];
133     SDL_GetRGB(c, source->format, &rgb[0], &rgb[1], &rgb[2]);
134     SDL_Color col = { rgb[0], rgb[1], rgb[2], 0 };
135     SDL_SetColors(surface, &col, c, 1);
136   }
137 
138 
139 }
140 
141 // Shape file read function (reference file)
142 
read(ifstream & fin)143 bool shape :: read(ifstream &fin){
144   if (fin.fail()){
145     return false;
146   }
147 
148   if (surface != NULL) SDL_FreeSurface(surface);
149   if (buffer != 0) delete [ ]buffer;
150   fin >> width >> height;
151   if (fin.fail()){
152     return false;
153   }
154   int buffersize = width * height * BYTESPERPIXEL;
155   buffer = new char[buffersize];
156   fin.read(buffer, 1); // Read the extra byte
157   fin.read(buffer, buffersize);
158   surface = SDL_CreateRGBSurfaceFrom(buffer, width, height, 8 * BYTESPERPIXEL,
159                                      width * BYTESPERPIXEL, 0, 0, 0, 0);
160 
161   return true;
162 }
163 
164 // Shape file read function (new file)
165 
readfile(char * filename)166 bool shape :: readfile(char* filename){
167   ifstream fin(filename, ios::binary);
168 
169   if (fin.fail()) return false;
170 
171   if (surface != NULL) SDL_FreeSurface(surface);
172   if (buffer != 0) delete [ ]buffer;
173   fin >> width >> height;
174   int buffersize = width * height * BYTESPERPIXEL;
175   buffer = new char[buffersize];
176   fin.read(buffer, 1); // Read the extra byte
177   fin.read(buffer, buffersize);
178   fin.close();
179   surface = SDL_CreateRGBSurfaceFrom(buffer, width, height, 8 * BYTESPERPIXEL,
180                                      width * BYTESPERPIXEL, 0, 0, 0, 0);
181 
182   return true;
183 }
184 
185 // Shape file read function (reference file with palette)
186 
read(SDL_Surface * palettesource,ifstream & fin)187 bool shape :: read(SDL_Surface *palettesource, ifstream &fin){
188   if (fin.fail()){
189     return false;
190   }
191 
192   if (surface != NULL) SDL_FreeSurface(surface);
193   if (buffer != 0) delete [ ]buffer;
194   fin >> width >> height;
195   if (fin.fail()){
196     return false;
197   }
198   int buffersize = width * height * BYTESPERPIXEL;
199   buffer = new char[buffersize];
200   fin.read(buffer, 1); // Read the extra byte
201   fin.read(buffer, buffersize);
202   surface = SDL_CreateRGBSurfaceFrom(buffer, width, height, 8 * BYTESPERPIXEL,
203                                      width * BYTESPERPIXEL, 0, 0, 0, 0);
204 
205   for (int c=0;c<256;c++){
206     Uint8 rgb[3];
207     SDL_GetRGB(c, palettesource->format, &rgb[0], &rgb[1], &rgb[2]);
208     SDL_Color col = { rgb[0], rgb[1], rgb[2], 0 };
209     SDL_SetColors(surface, &col, c, 1);
210   }
211 
212   return true;
213 }
214 
215 // Shape file read function (new file with palette)
216 
readfile(SDL_Surface * palettesource,char * filename)217 bool shape :: readfile(SDL_Surface *palettesource, char* filename){
218   ifstream fin(filename, ios::binary);
219 
220   if (fin.fail()) return false;
221 
222   if (surface != NULL) SDL_FreeSurface(surface);
223   if (buffer != 0) delete [ ]buffer;
224   fin >> width >> height;
225   int buffersize = width * height * BYTESPERPIXEL;
226   buffer = new char[buffersize];
227   fin.read(buffer, 1); // Read the extra byte
228   fin.read(buffer, buffersize);
229   fin.close();
230   surface = SDL_CreateRGBSurfaceFrom(buffer, width, height, 8 * BYTESPERPIXEL,
231                                      width * BYTESPERPIXEL, 0, 0, 0, 0);
232   for (int c=0;c<256;c++){
233     Uint8 rgb[3];
234     SDL_GetRGB(c, palettesource->format, &rgb[0], &rgb[1], &rgb[2]);
235     SDL_Color col = { rgb[0], rgb[1], rgb[2], 0 };
236     SDL_SetColors(surface, &col, c, 1);
237   }
238 
239 
240   return true;
241 }
242 
243 
244 // Shape blitter (mask on)
245 
blit(SDL_Surface * dest,int x,int y)246 void shape :: blit(SDL_Surface *dest,int x, int y){
247   SDL_SetColorKey(surface, SDL_SRCCOLORKEY, 0);
248   SDL_Rect srcrect;
249     srcrect.x = 0;
250     srcrect.y = 0;
251     srcrect.w = width;
252     srcrect.h = height;
253   SDL_Rect dstrect;
254     dstrect.x = x;
255     dstrect.y = y;
256     dstrect.w = 0;
257     dstrect.h = 0;
258   SDL_BlitSurface(surface, &srcrect, dest, &dstrect);
259   SDL_SetColorKey(surface, 0, 0);
260 }
261 
262 // Shape blitter (mask chosen)
263 
blit(SDL_Surface * dest,int x,int y,bool mask)264 void shape :: blit(SDL_Surface *dest,int x, int y, bool mask){
265   SDL_Rect srcrect;
266     srcrect.x = 0;
267     srcrect.y = 0;
268     srcrect.w = width;
269     srcrect.h = height;
270   SDL_Rect dstrect;
271     dstrect.x = x;
272     dstrect.y = y;
273     dstrect.w = 0;
274     dstrect.h = 0;
275   if (mask)
276     SDL_SetColorKey(surface, SDL_SRCCOLORKEY, 0);
277   SDL_BlitSurface(surface, &srcrect, dest, &dstrect);
278   if (mask)
279     SDL_SetColorKey(surface, 0, 0);
280 }
281 
282 // Shape file write function (reference file)
283 
write(ofstream & fout)284 bool shape :: write(ofstream &fout){
285   if (fout.fail()) return false;
286 
287   fout << width << " " << height << " ";
288   fout.write(buffer, width * height * BYTESPERPIXEL);
289 
290   return true;
291 }
292 
293 // Shape file write function (new file)
294 
writefile(char * filename)295 bool shape :: writefile(char* filename){
296   ofstream fout(filename, ios::binary);
297 
298   if (fout.fail()) return false;
299 
300   fout << width << " " << height << " ";
301   fout.write(buffer, width * height * BYTESPERPIXEL);
302   fout.close();
303 
304   return true;
305 }
306 
307 // Maximization function (for collision detection)
308 
max(int a,int b)309 int shape :: max(int a, int b){
310   if (a > b) return a;
311   return b;
312 }
313 
314 // Minimization function (for collision detection)
315 
min(int a,int b)316 int shape :: min(int a, int b){
317   if (a < b) return a;
318   return b;
319 }
320 
321 // Shape collision detection routine
322 // Checks if the shape at x,y collides with another shape s at sx,sy
323 // NB assumes BYTESPERPIXEL == 1
324 
collide(int x,int y,const shape & s,int sx,int sy)325 bool shape :: collide(int x, int y, const shape &s, int sx, int sy){
326   for(int cx = max(x,sx);cx<min(x+width,sx+s.width);cx++){
327     for(int cy = max(y,sy);cy<min(y+height,sy+s.height);cy++){
328       if ((buffer[cx-x + width*(cy-y)] != 0) &&
329           (s.buffer[cx-sx + s.width*(cy-sy)] != 0)){
330         return true;
331       }
332     }
333   }
334 
335   return false;
336 }
337