1 /*
2  * file w32_sprite.c - drawing sprites
3  *
4  * $Id: w32_sprite.c,v 1.4 2006/02/19 13:33:01 lodott Exp $
5  *
6  * Program XBLAST
7  * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published
11  * by the Free Software Foundation; either version 2; or (at your option)
12  * any later version
13  *
14  * This program is distributed in the hope that it will be entertaining,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.
21  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 #include "xblast.h"
24 #include "w32_sprite.h"
25 #include "gui.h"
26 
27 #include "w32_pixmap.h"
28 #include "w32_image.h"
29 
30 #include "geom.h"
31 #include "image.h"
32 
33 /*
34  * local variables
35  */
36 static HDC hdcPix = NULL;
37 static HDC hdcSprite = NULL;
38 
39 static HBITMAP pixBombMask[MAX_BOMBS][MAX_BOMB_ANIME];
40 static HBITMAP pixBombBits[MAX_BOMBS][MAX_BOMB_ANIME];
41 static HBITMAP pixExplMask[MAX_EXPLOSION];
42 static HBITMAP pixExplBits[MAX_EXPLOSION];
43 static HBITMAP pixEpmSpriteBits[MAX_PLAYER][MAX_ANIME_EPM];
44 static HBITMAP pixEpmSpriteMask[MAX_PLAYER][MAX_ANIME_EPM];
45 static HBITMAP pixPpmSpriteBits[MAX_ANIME_PPM];
46 static HBITMAP pixPpmSpriteMask[MAX_ANIME_PPM];
47 static HBITMAP pixIconBits[MAX_ICON_SPRITES];
48 static HBITMAP pixIconMask[MAX_ICON_SPRITES];
49 
50 /*
51  *
52  */
53 static void
ClipSpriteBitmap(HBITMAP bits,HBITMAP mask,int width,int height)54 ClipSpriteBitmap (HBITMAP bits, HBITMAP mask, int width, int height)
55 {
56 	HBITMAP clip;
57 	HGDIOBJ oldSprite;
58 	HGDIOBJ oldPix;
59 
60 	/* create clipping bitmap */
61 	clip = CreateBitmap (width, height, 1, 1, NULL);
62 	assert (clip != NULL);
63 	oldPix = SelectObject (hdcPix, clip);
64 	oldSprite = SelectObject (hdcSprite, mask);
65 	BitBlt (hdcPix, 0, 0, width, height, hdcSprite, 0, 0, NOTSRCCOPY);
66 	/* now clip bits */
67 	SelectObject (hdcSprite, bits);
68 	BitBlt (hdcSprite, 0, 0, width, height, hdcPix, 0, 0, SRCAND);
69 	/* clean up */
70 	SelectObject (hdcSprite, oldSprite);
71 	SelectObject (hdcPix, oldPix);
72 	DeleteObject (clip);
73 }								/* ClipSpriteBitmap */
74 
75 /*
76  *
77  */
78 XBBool
InitSprites(void)79 InitSprites (void)
80 {
81 	int i, j;
82 	HDC hdc;
83 
84 	/* create own device contextes */
85 	hdc = GetDC (window);
86 	hdcPix = CreateCompatibleDC (hdc);
87 	hdcSprite = CreateCompatibleDC (hdc);
88 	ReleaseDC (window, hdc);
89 	/* zero all arrays */
90 	memset (pixBombMask, 0, sizeof (pixBombMask));
91 	memset (pixBombBits, 0, sizeof (pixBombBits));
92 	memset (pixExplMask, 0, sizeof (pixExplMask));
93 	memset (pixExplBits, 0, sizeof (pixExplBits));
94 	memset (pixEpmSpriteMask, 0, sizeof (pixEpmSpriteMask));
95 	memset (pixEpmSpriteBits, 0, sizeof (pixEpmSpriteBits));
96 	memset (pixPpmSpriteMask, 0, sizeof (pixPpmSpriteMask));
97 	memset (pixPpmSpriteBits, 0, sizeof (pixPpmSpriteBits));
98 	memset (pixIconMask, 0, sizeof (pixIconMask));
99 	memset (pixIconBits, 0, sizeof (pixIconBits));
100 	/* bomb sprites */
101 	for (i = 0; i < MAX_BOMBS; i++) {
102 		for (j = 0; j < MAX_BOMB_ANIME; j++) {
103 			pixBombMask[i][j] = ReadPbmBitmap (imgPathExpl, imgFileBomb[i][j]);
104 			pixBombBits[i][j] = ReadRgbPixmap (imgPathExpl, imgFileBomb[i][j]);
105 			if (NULL == pixBombMask[i][j] || NULL == pixBombBits[i][j]) {
106 				return XBFalse;
107 			}
108 			ClipSpriteBitmap (pixBombBits[i][j], pixBombMask[i][j], BLOCK_WIDTH, BLOCK_HEIGHT);
109 		}
110 	}
111 	/* create explosion sprites */
112 	for (i = 0; i < MAX_EXPLOSION; i++) {
113 		pixExplMask[i] = ReadPbmBitmap (imgPathExpl, imgFileExpl[i]);
114 		pixExplBits[i] = ReadRgbPixmap (imgPathExpl, imgFileExpl[i]);
115 		if (NULL == pixExplMask[i] || NULL == pixExplBits[i]) {
116 			return XBFalse;
117 		}
118 		ClipSpriteBitmap (pixExplBits[i], pixExplMask[i], BLOCK_WIDTH, BLOCK_HEIGHT);
119 	}
120 	/* load icon sprites */
121 	for (i = 0; i < MAX_ICON_SPRITES; i++) {
122 		pixIconMask[i] = ReadPbmBitmap (imgPathMisc, imgFileIcon[i]);
123 		pixIconBits[i] = ReadCchPixmap (imgPathMisc, imgFileIcon[i], COLOR_BLACK,
124 										(i != ISA_Abort) ? COLOR_SPRING_GREEN : COLOR_RED,
125 										COLOR_LIGHT_GOLDENROD);
126 		if (NULL == pixIconMask[i] || NULL == pixIconBits[i]) {
127 			return XBFalse;
128 		}
129 		ClipSpriteBitmap (pixIconBits[i], pixIconMask[i], imgRectIcon[i].w, imgRectIcon[i].h);
130 	}
131 	/* create shared players sprites */
132 	for (j = 0; j < MAX_ANIME_PPM; j++) {
133 		pixPpmSpriteBits[j] = ReadRgbPixmap (imgPathSprite, imgFileSpritePpm[j]);
134 		pixPpmSpriteMask[j] = ReadPbmBitmap (imgPathSprite, imgFileSpritePpm[j]);
135 		if (NULL == pixPpmSpriteBits[j] || NULL == pixPpmSpriteMask[j]) {
136 			return XBFalse;
137 		}
138 		ClipSpriteBitmap (pixPpmSpriteBits[j], pixPpmSpriteMask[j],
139 						  imgRectSprite[j + MAX_ANIME_EPM].w, imgRectSprite[j + MAX_ANIME_EPM].h);
140 	}
141 	/* everything is fine */
142 	return XBTrue;
143 }								/* InitSprites */
144 
145 /*
146  * clan up the mess
147  */
148 void
FinishSprites(void)149 FinishSprites (void)
150 {
151 	int i, j;
152 
153 	/* bomb sprites */
154 	for (i = 0; i < MAX_BOMBS; i++) {
155 		for (j = 0; j < MAX_BOMB_ANIME; j++) {
156 			if (NULL != pixBombMask[i][j]) {
157 				DeleteObject (pixBombMask[i][j]);
158 			}
159 			if (NULL != pixBombBits[i][j]) {
160 				DeleteObject (pixBombBits[i][j]);
161 			}
162 		}
163 	}
164 	/* explosion sprites */
165 	for (i = 0; i < MAX_EXPLOSION; i++) {
166 		if (NULL != pixExplMask[i]) {
167 			DeleteObject (pixExplMask[i]);
168 		}
169 		if (NULL != pixExplBits[i]) {
170 			DeleteObject (pixExplBits[i]);
171 		}
172 	}
173 	/* player sprites */
174 	for (i = 0; i < MAX_PLAYER; i++) {
175 		for (j = 0; j < MAX_ANIME_EPM; j++) {
176 			if (NULL != pixEpmSpriteMask[i][j]) {
177 				DeleteObject (pixEpmSpriteMask[i][j]);
178 			}
179 			if (NULL != pixEpmSpriteBits[i][j]) {
180 				DeleteObject (pixEpmSpriteBits[i][j]);
181 			}
182 		}
183 	}
184 	for (i = 0; i < MAX_ANIME_PPM; i++) {
185 		if (NULL != pixPpmSpriteMask[i]) {
186 			DeleteObject (pixPpmSpriteMask[i]);
187 		}
188 		if (NULL != pixEpmSpriteBits[i][j]) {
189 			DeleteObject (pixPpmSpriteBits[i]);
190 		}
191 	}
192 	/* icons */
193 	for (i = 0; i < MAX_ICON_SPRITES; i++) {
194 		if (NULL != pixIconBits[i]) {
195 			DeleteObject (pixIconBits[i]);
196 		}
197 		if (NULL != pixIconMask[i]) {
198 			DeleteObject (pixIconMask[i]);
199 		}
200 	}
201 	/* device contextes */
202 	if (NULL != hdcPix) {
203 		DeleteDC (hdcPix);
204 	}
205 	if (NULL != hdcSprite) {
206 		DeleteDC (hdcSprite);
207 	}
208 }								/* FinishSprites */
209 
210 /*
211  * load sprites for given player
212  */
213 XBBool
GUI_LoadPlayerSprite(int player,int i,const CFGPlayerGraphics * config)214 GUI_LoadPlayerSprite (int player, int i, const CFGPlayerGraphics * config)
215 {
216 	const char *epmName;
217 
218 	assert (player < MAX_PLAYER);
219 	assert (i < MAX_ANIME_EPM);
220 	assert (config != NULL);
221 
222 	/* delete old sprite */
223 	if (NULL != pixEpmSpriteMask[player][i]) {
224 		DeleteObject (pixEpmSpriteMask[player][i]);
225 		pixEpmSpriteMask[player][i] = NULL;
226 	}
227 	if (NULL != pixEpmSpriteBits[player][i]) {
228 		DeleteObject (pixEpmSpriteBits[player][i]);
229 		pixEpmSpriteBits[player][i] = NULL;
230 	}
231 	/* load sprite */
232 	if (ATOM_INVALID == config->shape) {
233 		pixEpmSpriteBits[player][i] = NULL;
234 		pixEpmSpriteMask[player][i] = NULL;
235 	}
236 	else {
237 		epmName = ImgFileSpriteEpm (config->shape, i);
238 		pixEpmSpriteBits[player][i] =
239 			ReadEpmPixmap (imgPathSprite, epmName, NUM_PLAYER_COLORS, &config->helmet);
240 		pixEpmSpriteMask[player][i] = ReadPbmBitmap (imgPathSprite, epmName);
241 		if (NULL == pixEpmSpriteBits[player][i] || NULL == pixEpmSpriteMask[player][i]) {
242 			/* error while loading */
243 			return XBFalse;
244 		}
245 		ClipSpriteBitmap (pixEpmSpriteBits[player][i], pixEpmSpriteMask[player][i],
246 						  imgRectSprite[i].w, imgRectSprite[i].h);
247 	}
248 	return XBTrue;
249 }								/* GUI_LoadPlayerSprite */
250 
251 /*
252  * load sprite for color selector
253  */
254 void
GUI_LoadIconSprite(int index,XBColor color)255 GUI_LoadIconSprite (int index, XBColor color)
256 {
257 	assert (index >= 0);
258 	assert (index < MAX_COLOR_SPRITES);
259 
260 	/* free bitmaps if necessary */
261 	if (NULL != pixIconBits[index]) {
262 		DeleteObject (pixIconBits[index]);
263 	}
264 	if (NULL != pixIconMask[index]) {
265 		DeleteObject (pixIconMask[index]);
266 	}
267 	/* now load it */
268 	pixIconBits[index] =
269 		ReadCchPixmap (imgPathMisc, imgFileIcon[index], COLOR_BLACK, color, COLOR_LIGHT_GOLDENROD);
270 	pixIconMask[index] = ReadPbmBitmap (imgPathMisc, imgFileIcon[index]);
271 	ClipSpriteBitmap (pixIconBits[index], pixIconMask[index], imgRectIcon[index].w,
272 					  imgRectIcon[index].h);
273 }								/* GUI_LoadColorSprite */
274 
275 /*
276  * draw sprite into pixmap buffer
277  */
278 static void
DrawSprite(const BMRectangle * rect,HBITMAP bits,HBITMAP mask)279 DrawSprite (const BMRectangle * rect, HBITMAP bits, HBITMAP mask)
280 {
281 	HGDIOBJ oldPix;
282 	HGDIOBJ oldSprite;
283 
284 	assert (rect != NULL);
285 	assert (bits != NULL);
286 	assert (mask != NULL);
287 	oldPix = SelectObject (hdcPix, pix);
288 	/* draw mask */
289 	oldSprite = SelectObject (hdcSprite, mask);
290 	BitBlt (hdcPix, rect->x, rect->y, rect->w, rect->h, hdcSprite, 0, 0, SRCAND);
291 	/* draw bits */
292 	SelectObject (hdcSprite, bits);
293 	BitBlt (hdcPix, rect->x, rect->y, rect->w, rect->h, hdcSprite, 0, 0, SRCPAINT);
294 	/* finish drawing */
295 	SelectObject (hdcPix, oldPix);
296 	SelectObject (hdcSprite, oldSprite);
297 }								/* DrawSprite */
298 
299 /*
300  * draw sprite mask into pixmap buffer
301  */
302 static void
DrawMask(const BMRectangle * rect,HBITMAP mask)303 DrawMask (const BMRectangle * rect, HBITMAP mask)
304 {
305 	HGDIOBJ oldPix;
306 	HGDIOBJ oldSprite;
307 
308 	assert (rect != NULL);
309 	assert (mask != NULL);
310 	oldPix = SelectObject (hdcPix, pix);
311 	/* draw mask */
312 	oldSprite = SelectObject (hdcSprite, mask);
313 	BitBlt (hdcPix, rect->x, rect->y, rect->w, rect->h, hdcSprite, 0, 0, MERGEPAINT);
314 	/* finish drawing */
315 	SelectObject (hdcPix, oldPix);
316 	SelectObject (hdcSprite, oldSprite);
317 }								/* DrawSprite */
318 
319 /*
320  * copy explosion sprite into a tile
321  */
322 void
CopyExplosion(HBITMAP pix_tile,int i)323 CopyExplosion (HBITMAP pix_tile, int i)
324 {
325 	HGDIOBJ oldPix;
326 	HGDIOBJ oldSprite;
327 
328 	/* prepare drawing */
329 	oldPix = SelectObject (hdcPix, pix_tile);
330 	/* draw mask */
331 	oldSprite = SelectObject (hdcSprite, pixExplMask[i]);
332 	BitBlt (hdcPix, 0, 0, BLOCK_WIDTH, BLOCK_HEIGHT, hdcSprite, 0, 0, SRCAND);
333 	/* draw bits */
334 	SelectObject (hdcSprite, pixExplBits[i]);
335 	BitBlt (hdcPix, 0, 0, BLOCK_WIDTH, BLOCK_HEIGHT, hdcSprite, 0, 0, SRCPAINT);
336 	/* finish drawing */
337 	SelectObject (hdcSprite, oldSprite);
338 	SelectObject (hdcPix, oldPix);
339 }								/* CopyExplosion */
340 
341 /*
342  * draw explosion as sprite (fopr intro)
343  */
344 void
GUI_DrawExplosionSprite(int x,int y,int block)345 GUI_DrawExplosionSprite (int x, int y, int block)
346 {
347 	BMRectangle rect;
348 
349 	assert (block < MAX_EXPLOSION);
350 	/* set region */
351 	rect.x = x * BLOCK_WIDTH;
352 	rect.y = y * BLOCK_HEIGHT;
353 	rect.w = BLOCK_WIDTH;
354 	rect.h = BLOCK_HEIGHT;
355 	/* draw sprite */
356 	DrawSprite (&rect, pixExplBits[block], pixExplMask[block]);
357 }								/* GUI_DrawExplosionSprite */
358 
359 /*
360  * draw a bomb sprite
361  */
362 void
GUI_DrawBombSprite(const Sprite * ptr)363 GUI_DrawBombSprite (const Sprite * ptr)
364 {
365 	int bomb = SpriteBomb (ptr);
366 	int anime = SpriteAnime (ptr);
367 
368 	assert (bomb < MAX_BOMBS);
369 	assert (anime < MAX_BOMB_ANIME);
370 	if (SpriteIsMasked (ptr)) {
371 		DrawMask (SpriteRectangle (ptr), pixBombMask[bomb][anime]);
372 	}
373 	else {
374 		DrawSprite (SpriteRectangle (ptr), pixBombBits[bomb][anime], pixBombMask[bomb][anime]);
375 	}
376 }								/* GUI_DrawBombSprite */
377 
378 /*
379  * draw a player sprite
380  */
381 void
GUI_DrawPlayerSprite(const Sprite * ptr)382 GUI_DrawPlayerSprite (const Sprite * ptr)
383 {
384 	HBITMAP bits;
385 	HBITMAP mask;
386 	int anime = SpriteAnime (ptr);
387 	int player = SpritePlayer (ptr);
388 
389 	assert (anime < MAX_ANIME);
390 	assert (player < MAX_PLAYER);
391 	/* get mask an bitmap */
392 	if (anime >= MAX_ANIME_EPM) {
393 		bits = pixPpmSpriteBits[anime - MAX_ANIME_EPM];
394 		mask = pixPpmSpriteMask[anime - MAX_ANIME_EPM];
395 	}
396 	else {
397 		bits = pixEpmSpriteBits[player][anime];
398 		mask = pixEpmSpriteMask[player][anime];
399 	}
400 	/* draw sprite */
401 	if (SpriteIsMasked (ptr)) {
402 		DrawMask (SpriteRectangle (ptr), mask);
403 	}
404 	else {
405 		DrawSprite (SpriteRectangle (ptr), bits, mask);
406 	}
407 }								/* GUI_DrawPlayerSprite */
408 
409 /*
410  * draw color sprite
411  */
412 void
GUI_DrawIconSprite(const Sprite * ptr)413 GUI_DrawIconSprite (const Sprite * ptr)
414 {
415 	int anime = SpriteAnime (ptr);
416 
417 	assert (anime < MAX_ICON_SPRITES);
418 	if (!SpriteIsMasked (ptr)) {
419 		DrawSprite (SpriteRectangle (ptr), pixIconBits[anime], pixIconMask[anime]);
420 	}
421 }								/* GUI_DrawColorSprite */
422 
423 /*
424  * draw textbox sprite
425  */
426 void
GUI_DrawTextSprite(const Sprite * ptr)427 GUI_DrawTextSprite (const Sprite * ptr)
428 {
429 	GUI_DrawTextbox (SpriteText (ptr), SpriteAnime (ptr), SpriteRectangle (ptr));
430 }								/* GUI_DrawTextSprite */
431 
432 /*
433  *  end of file w32_sprite.c
434  */
435