/************************************************* * sprite.cpp * * * * Copyright (C) 1995-1999 Microsoft Inc. * * * *************************************************/ // sprite.cpp : implementation file // #include "stdafx.h" #include "dib.h" #include "spriteno.h" #include "sprite.h" #ifdef _DEBUG #undef THIS_FILE static char BASED_CODE THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CSprite IMPLEMENT_SERIAL(CSprite, CDIB, 0 /* schema number*/ ) CSprite::CSprite() { m_x = 0; m_y = 0; m_z = 50; m_bTransIndex = 0; m_pNotifyObj = NULL; } CSprite::~CSprite() { } // Set the initial state of the sprite from its DIB image void CSprite::Initialize() { // Get the address of the top, left pixel BYTE* p = (BYTE*)GetPixelAddress(0, 0); ASSERT(p); if ( p == NULL ) { m_bTransIndex = 0; return; } // get the pixel value and save it m_bTransIndex = *p; } ///////////////////////////////////////////////////////////////////////////// // CSprite serialization void CSprite::Serialize(CArchive& ar) { CDIB::Serialize(ar); if (ar.IsStoring()) { ar << (DWORD) m_x; ar << (DWORD) m_y; ar << (DWORD) m_z; } else { DWORD dw; ar >> dw; m_x = (int) dw; ar >> dw; m_y = (int) dw; ar >> dw; m_z = (int) dw; // now generate the other parameters from the DIB Initialize(); } } ///////////////////////////////////////////////////////////////////////////// // CSprite commands // Render a sprite to a DIB void CSprite::Render(CDIB* pDIB, CRect* pClipRect) { ASSERT(pDIB); // Get the sprite rectangle CRect rcDraw; GetRect(&rcDraw); // If a clip rectangle was supplied, see if the sprite // is visible in the rectangle if (pClipRect) { if (!rcDraw.IntersectRect(pClipRect, &rcDraw)) { return; // not visible } } // Copy the image of the sprite CopyBits(pDIB, // dest DIB rcDraw.left, // dest x rcDraw.top, // dest y rcDraw.right - rcDraw.left, // width rcDraw.bottom - rcDraw.top, // height rcDraw.left - m_x, // source x rcDraw.top - m_y, // source y PALETTEINDEX(m_bTransIndex)); // trans color index } void PrintRGB(CDIB* pDib,int n) { RGBQUAD *prgb = pDib->GetClrTabAddress(); TRACE("%d>(%d,%d,%d)\n",n,prgb[n].rgbBlue, prgb[n].rgbGreen, prgb[n].rgbRed); } void Copy(CDIB* pdibSrc,CDIB* pdibDest, int xd, int yd, int w, int h, int xs, int ys, COLORREF clrTrans) { ASSERT(pdibDest); // test for strange cases if (w == 0 || h == 0) return; // get pointers to the start points in the source // and destination DIBs. Note that this will be the bottom left // corner of the DIB as the scan lines are reversed in memory BYTE* pSrc = (BYTE*)(pdibSrc->GetPixelAddress(xs, ys + h - 1)); ASSERT(pSrc); BYTE* pDest = (BYTE*)pdibDest->GetPixelAddress(xd, yd + h - 1); ASSERT(pDest); // get the scan line widths of each DIB int iScanS = pdibSrc->StorageWidth(); int iScanD = pdibDest->StorageWidth(); RGBQUAD *prgbSrc = pdibSrc->GetClrTabAddress(); RGBQUAD *prgbDest = pdibDest->GetClrTabAddress(); { // copy lines with transparency // We only accept a PALETTEINDEX description // for the color definition BYTE bTransClr = LOBYTE(LOWORD(clrTrans)); int iSinc = iScanS - w; // source inc value int iDinc = iScanD - w; // dest inc value int iCount; BYTE pixel; while (h--) { iCount = w; // no of pixels to scan while (iCount--) { pixel = *pSrc++; // only copy pixel if not transparent if (pixel != bTransClr) { { *pDest++ = 1; } } else { pDest++; } } // move on to the next line pSrc += iSinc; pDest += iDinc; } } } void CSprite::Coverage(CDIB* pDIB) { ASSERT(pDIB); // Get the sprite rectangle CRect rcDraw; GetRect(&rcDraw); // Copy the image of the sprite Copy(this,pDIB, // dest DIB 0, // dest x 0, // dest y DibWidth(), // width DibHeight(), // height 0, // source x 0, // source y PALETTEINDEX(m_bTransIndex)); // trans color index } // Load a sprite image from a disk file BOOL CSprite::Load(CBitmap* pBmp) { if (!CDIB::Load(pBmp)) { return FALSE; } Initialize(); return TRUE; } BOOL CSprite::Load(char* pszFileName) { if (!CDIB::Load(pszFileName)) { return FALSE; } Initialize(); /* { BYTE* pBits = NULL; HBITMAP hBmp; CDC* pDC = GetDC(); hBmp = CreateDIBSection(pDC->GetSafeHdc(), pBmpInfo, DIB_PAL_COLORS, (VOID **) &pBits, NULL, 0); ReleaseDC(pDC); Create(GetWidth } */ return TRUE; } // Load a sprite image from a disk file BOOL CSprite::Load(CFile *fp) { if (!CDIB::Load(fp)) { return FALSE; } Initialize(); return TRUE; } // Map colors to palette BOOL CSprite::MapColorsToPalette(CPalette *pPal) { BOOL bResult = CDIB::MapColorsToPalette(pPal); // get the transparency info again // Note: local call only don't any derived class CSprite::Initialize(); return bResult; } // get the bounding rectangle void CSprite::GetRect(CRect* pRect) { ASSERT(pRect); pRect->left = m_x; pRect->top = m_y; pRect->right = m_x + GetWidth(); pRect->bottom = m_y + GetHeight(); } // Test for a hit in a non-transparent area BOOL CSprite::HitTest(CPoint point) { // Test if the point is inside the sprite rectangle if ((point.x > m_x) && (point.x < m_x + GetWidth()) && (point.y > m_y) && (point.y < m_y + GetHeight())) { // See if this point is transparent by testing to // see if the pixel value is the same as the top // left corner value. Note that top left of the // image is bottom left in the DIB. BYTE* p = (BYTE*)GetPixelAddress(point.x - m_x, point.y - m_y); if (( p != NULL ) && (*p != m_bTransIndex) ) { return TRUE; // hit } } return FALSE; } void CSprite::Disappear() { CRect rcOld; GetRect(&rcOld); if (m_pNotifyObj) { m_pNotifyObj->Change(this, CSpriteNotifyObj::IMAGE, &rcOld, NULL); } } // set a new x,y position void CSprite::SetPosition(int x, int y) { // Save the current position CRect rcOld; GetRect(&rcOld); // move to new position m_x = x; m_y = y; CRect rcNew; GetRect(&rcNew); // notify that we have moved from our old position to // our new position if (m_pNotifyObj) { m_pNotifyObj->Change(this, CSpriteNotifyObj::POSITION, &rcOld, &rcNew); } } // Set a new Z order void CSprite::SetZ(int z) { if (m_z != z) { m_z = z; // See if we have to notify anyone if (m_pNotifyObj) { CRect rc; GetRect(&rc); m_pNotifyObj->Change(this, CSpriteNotifyObj::ZORDER, &rc); } } }