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