/* * file w32_sprite.c - drawing sprites * * $Id: w32_sprite.c,v 1.4 2006/02/19 13:33:01 lodott Exp $ * * Program XBLAST * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation; either version 2; or (at your option) * any later version * * This program is distributed in the hope that it will be entertaining, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General * Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "xblast.h" #include "w32_sprite.h" #include "gui.h" #include "w32_pixmap.h" #include "w32_image.h" #include "geom.h" #include "image.h" /* * local variables */ static HDC hdcPix = NULL; static HDC hdcSprite = NULL; static HBITMAP pixBombMask[MAX_BOMBS][MAX_BOMB_ANIME]; static HBITMAP pixBombBits[MAX_BOMBS][MAX_BOMB_ANIME]; static HBITMAP pixExplMask[MAX_EXPLOSION]; static HBITMAP pixExplBits[MAX_EXPLOSION]; static HBITMAP pixEpmSpriteBits[MAX_PLAYER][MAX_ANIME_EPM]; static HBITMAP pixEpmSpriteMask[MAX_PLAYER][MAX_ANIME_EPM]; static HBITMAP pixPpmSpriteBits[MAX_ANIME_PPM]; static HBITMAP pixPpmSpriteMask[MAX_ANIME_PPM]; static HBITMAP pixIconBits[MAX_ICON_SPRITES]; static HBITMAP pixIconMask[MAX_ICON_SPRITES]; /* * */ static void ClipSpriteBitmap (HBITMAP bits, HBITMAP mask, int width, int height) { HBITMAP clip; HGDIOBJ oldSprite; HGDIOBJ oldPix; /* create clipping bitmap */ clip = CreateBitmap (width, height, 1, 1, NULL); assert (clip != NULL); oldPix = SelectObject (hdcPix, clip); oldSprite = SelectObject (hdcSprite, mask); BitBlt (hdcPix, 0, 0, width, height, hdcSprite, 0, 0, NOTSRCCOPY); /* now clip bits */ SelectObject (hdcSprite, bits); BitBlt (hdcSprite, 0, 0, width, height, hdcPix, 0, 0, SRCAND); /* clean up */ SelectObject (hdcSprite, oldSprite); SelectObject (hdcPix, oldPix); DeleteObject (clip); } /* ClipSpriteBitmap */ /* * */ XBBool InitSprites (void) { int i, j; HDC hdc; /* create own device contextes */ hdc = GetDC (window); hdcPix = CreateCompatibleDC (hdc); hdcSprite = CreateCompatibleDC (hdc); ReleaseDC (window, hdc); /* zero all arrays */ memset (pixBombMask, 0, sizeof (pixBombMask)); memset (pixBombBits, 0, sizeof (pixBombBits)); memset (pixExplMask, 0, sizeof (pixExplMask)); memset (pixExplBits, 0, sizeof (pixExplBits)); memset (pixEpmSpriteMask, 0, sizeof (pixEpmSpriteMask)); memset (pixEpmSpriteBits, 0, sizeof (pixEpmSpriteBits)); memset (pixPpmSpriteMask, 0, sizeof (pixPpmSpriteMask)); memset (pixPpmSpriteBits, 0, sizeof (pixPpmSpriteBits)); memset (pixIconMask, 0, sizeof (pixIconMask)); memset (pixIconBits, 0, sizeof (pixIconBits)); /* bomb sprites */ for (i = 0; i < MAX_BOMBS; i++) { for (j = 0; j < MAX_BOMB_ANIME; j++) { pixBombMask[i][j] = ReadPbmBitmap (imgPathExpl, imgFileBomb[i][j]); pixBombBits[i][j] = ReadRgbPixmap (imgPathExpl, imgFileBomb[i][j]); if (NULL == pixBombMask[i][j] || NULL == pixBombBits[i][j]) { return XBFalse; } ClipSpriteBitmap (pixBombBits[i][j], pixBombMask[i][j], BLOCK_WIDTH, BLOCK_HEIGHT); } } /* create explosion sprites */ for (i = 0; i < MAX_EXPLOSION; i++) { pixExplMask[i] = ReadPbmBitmap (imgPathExpl, imgFileExpl[i]); pixExplBits[i] = ReadRgbPixmap (imgPathExpl, imgFileExpl[i]); if (NULL == pixExplMask[i] || NULL == pixExplBits[i]) { return XBFalse; } ClipSpriteBitmap (pixExplBits[i], pixExplMask[i], BLOCK_WIDTH, BLOCK_HEIGHT); } /* load icon sprites */ for (i = 0; i < MAX_ICON_SPRITES; i++) { pixIconMask[i] = ReadPbmBitmap (imgPathMisc, imgFileIcon[i]); pixIconBits[i] = ReadCchPixmap (imgPathMisc, imgFileIcon[i], COLOR_BLACK, (i != ISA_Abort) ? COLOR_SPRING_GREEN : COLOR_RED, COLOR_LIGHT_GOLDENROD); if (NULL == pixIconMask[i] || NULL == pixIconBits[i]) { return XBFalse; } ClipSpriteBitmap (pixIconBits[i], pixIconMask[i], imgRectIcon[i].w, imgRectIcon[i].h); } /* create shared players sprites */ for (j = 0; j < MAX_ANIME_PPM; j++) { pixPpmSpriteBits[j] = ReadRgbPixmap (imgPathSprite, imgFileSpritePpm[j]); pixPpmSpriteMask[j] = ReadPbmBitmap (imgPathSprite, imgFileSpritePpm[j]); if (NULL == pixPpmSpriteBits[j] || NULL == pixPpmSpriteMask[j]) { return XBFalse; } ClipSpriteBitmap (pixPpmSpriteBits[j], pixPpmSpriteMask[j], imgRectSprite[j + MAX_ANIME_EPM].w, imgRectSprite[j + MAX_ANIME_EPM].h); } /* everything is fine */ return XBTrue; } /* InitSprites */ /* * clan up the mess */ void FinishSprites (void) { int i, j; /* bomb sprites */ for (i = 0; i < MAX_BOMBS; i++) { for (j = 0; j < MAX_BOMB_ANIME; j++) { if (NULL != pixBombMask[i][j]) { DeleteObject (pixBombMask[i][j]); } if (NULL != pixBombBits[i][j]) { DeleteObject (pixBombBits[i][j]); } } } /* explosion sprites */ for (i = 0; i < MAX_EXPLOSION; i++) { if (NULL != pixExplMask[i]) { DeleteObject (pixExplMask[i]); } if (NULL != pixExplBits[i]) { DeleteObject (pixExplBits[i]); } } /* player sprites */ for (i = 0; i < MAX_PLAYER; i++) { for (j = 0; j < MAX_ANIME_EPM; j++) { if (NULL != pixEpmSpriteMask[i][j]) { DeleteObject (pixEpmSpriteMask[i][j]); } if (NULL != pixEpmSpriteBits[i][j]) { DeleteObject (pixEpmSpriteBits[i][j]); } } } for (i = 0; i < MAX_ANIME_PPM; i++) { if (NULL != pixPpmSpriteMask[i]) { DeleteObject (pixPpmSpriteMask[i]); } if (NULL != pixEpmSpriteBits[i][j]) { DeleteObject (pixPpmSpriteBits[i]); } } /* icons */ for (i = 0; i < MAX_ICON_SPRITES; i++) { if (NULL != pixIconBits[i]) { DeleteObject (pixIconBits[i]); } if (NULL != pixIconMask[i]) { DeleteObject (pixIconMask[i]); } } /* device contextes */ if (NULL != hdcPix) { DeleteDC (hdcPix); } if (NULL != hdcSprite) { DeleteDC (hdcSprite); } } /* FinishSprites */ /* * load sprites for given player */ XBBool GUI_LoadPlayerSprite (int player, int i, const CFGPlayerGraphics * config) { const char *epmName; assert (player < MAX_PLAYER); assert (i < MAX_ANIME_EPM); assert (config != NULL); /* delete old sprite */ if (NULL != pixEpmSpriteMask[player][i]) { DeleteObject (pixEpmSpriteMask[player][i]); pixEpmSpriteMask[player][i] = NULL; } if (NULL != pixEpmSpriteBits[player][i]) { DeleteObject (pixEpmSpriteBits[player][i]); pixEpmSpriteBits[player][i] = NULL; } /* load sprite */ if (ATOM_INVALID == config->shape) { pixEpmSpriteBits[player][i] = NULL; pixEpmSpriteMask[player][i] = NULL; } else { epmName = ImgFileSpriteEpm (config->shape, i); pixEpmSpriteBits[player][i] = ReadEpmPixmap (imgPathSprite, epmName, NUM_PLAYER_COLORS, &config->helmet); pixEpmSpriteMask[player][i] = ReadPbmBitmap (imgPathSprite, epmName); if (NULL == pixEpmSpriteBits[player][i] || NULL == pixEpmSpriteMask[player][i]) { /* error while loading */ return XBFalse; } ClipSpriteBitmap (pixEpmSpriteBits[player][i], pixEpmSpriteMask[player][i], imgRectSprite[i].w, imgRectSprite[i].h); } return XBTrue; } /* GUI_LoadPlayerSprite */ /* * load sprite for color selector */ void GUI_LoadIconSprite (int index, XBColor color) { assert (index >= 0); assert (index < MAX_COLOR_SPRITES); /* free bitmaps if necessary */ if (NULL != pixIconBits[index]) { DeleteObject (pixIconBits[index]); } if (NULL != pixIconMask[index]) { DeleteObject (pixIconMask[index]); } /* now load it */ pixIconBits[index] = ReadCchPixmap (imgPathMisc, imgFileIcon[index], COLOR_BLACK, color, COLOR_LIGHT_GOLDENROD); pixIconMask[index] = ReadPbmBitmap (imgPathMisc, imgFileIcon[index]); ClipSpriteBitmap (pixIconBits[index], pixIconMask[index], imgRectIcon[index].w, imgRectIcon[index].h); } /* GUI_LoadColorSprite */ /* * draw sprite into pixmap buffer */ static void DrawSprite (const BMRectangle * rect, HBITMAP bits, HBITMAP mask) { HGDIOBJ oldPix; HGDIOBJ oldSprite; assert (rect != NULL); assert (bits != NULL); assert (mask != NULL); oldPix = SelectObject (hdcPix, pix); /* draw mask */ oldSprite = SelectObject (hdcSprite, mask); BitBlt (hdcPix, rect->x, rect->y, rect->w, rect->h, hdcSprite, 0, 0, SRCAND); /* draw bits */ SelectObject (hdcSprite, bits); BitBlt (hdcPix, rect->x, rect->y, rect->w, rect->h, hdcSprite, 0, 0, SRCPAINT); /* finish drawing */ SelectObject (hdcPix, oldPix); SelectObject (hdcSprite, oldSprite); } /* DrawSprite */ /* * draw sprite mask into pixmap buffer */ static void DrawMask (const BMRectangle * rect, HBITMAP mask) { HGDIOBJ oldPix; HGDIOBJ oldSprite; assert (rect != NULL); assert (mask != NULL); oldPix = SelectObject (hdcPix, pix); /* draw mask */ oldSprite = SelectObject (hdcSprite, mask); BitBlt (hdcPix, rect->x, rect->y, rect->w, rect->h, hdcSprite, 0, 0, MERGEPAINT); /* finish drawing */ SelectObject (hdcPix, oldPix); SelectObject (hdcSprite, oldSprite); } /* DrawSprite */ /* * copy explosion sprite into a tile */ void CopyExplosion (HBITMAP pix_tile, int i) { HGDIOBJ oldPix; HGDIOBJ oldSprite; /* prepare drawing */ oldPix = SelectObject (hdcPix, pix_tile); /* draw mask */ oldSprite = SelectObject (hdcSprite, pixExplMask[i]); BitBlt (hdcPix, 0, 0, BLOCK_WIDTH, BLOCK_HEIGHT, hdcSprite, 0, 0, SRCAND); /* draw bits */ SelectObject (hdcSprite, pixExplBits[i]); BitBlt (hdcPix, 0, 0, BLOCK_WIDTH, BLOCK_HEIGHT, hdcSprite, 0, 0, SRCPAINT); /* finish drawing */ SelectObject (hdcSprite, oldSprite); SelectObject (hdcPix, oldPix); } /* CopyExplosion */ /* * draw explosion as sprite (fopr intro) */ void GUI_DrawExplosionSprite (int x, int y, int block) { BMRectangle rect; assert (block < MAX_EXPLOSION); /* set region */ rect.x = x * BLOCK_WIDTH; rect.y = y * BLOCK_HEIGHT; rect.w = BLOCK_WIDTH; rect.h = BLOCK_HEIGHT; /* draw sprite */ DrawSprite (&rect, pixExplBits[block], pixExplMask[block]); } /* GUI_DrawExplosionSprite */ /* * draw a bomb sprite */ void GUI_DrawBombSprite (const Sprite * ptr) { int bomb = SpriteBomb (ptr); int anime = SpriteAnime (ptr); assert (bomb < MAX_BOMBS); assert (anime < MAX_BOMB_ANIME); if (SpriteIsMasked (ptr)) { DrawMask (SpriteRectangle (ptr), pixBombMask[bomb][anime]); } else { DrawSprite (SpriteRectangle (ptr), pixBombBits[bomb][anime], pixBombMask[bomb][anime]); } } /* GUI_DrawBombSprite */ /* * draw a player sprite */ void GUI_DrawPlayerSprite (const Sprite * ptr) { HBITMAP bits; HBITMAP mask; int anime = SpriteAnime (ptr); int player = SpritePlayer (ptr); assert (anime < MAX_ANIME); assert (player < MAX_PLAYER); /* get mask an bitmap */ if (anime >= MAX_ANIME_EPM) { bits = pixPpmSpriteBits[anime - MAX_ANIME_EPM]; mask = pixPpmSpriteMask[anime - MAX_ANIME_EPM]; } else { bits = pixEpmSpriteBits[player][anime]; mask = pixEpmSpriteMask[player][anime]; } /* draw sprite */ if (SpriteIsMasked (ptr)) { DrawMask (SpriteRectangle (ptr), mask); } else { DrawSprite (SpriteRectangle (ptr), bits, mask); } } /* GUI_DrawPlayerSprite */ /* * draw color sprite */ void GUI_DrawIconSprite (const Sprite * ptr) { int anime = SpriteAnime (ptr); assert (anime < MAX_ICON_SPRITES); if (!SpriteIsMasked (ptr)) { DrawSprite (SpriteRectangle (ptr), pixIconBits[anime], pixIconMask[anime]); } } /* GUI_DrawColorSprite */ /* * draw textbox sprite */ void GUI_DrawTextSprite (const Sprite * ptr) { GUI_DrawTextbox (SpriteText (ptr), SpriteAnime (ptr), SpriteRectangle (ptr)); } /* GUI_DrawTextSprite */ /* * end of file w32_sprite.c */