SPR.CPP
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:37k
源码类别:
Windows编程
开发平台:
Visual C++
- //---------------------------------------------------------------------------
- // Spr.cpp
- //---------------------------------------------------------------------------
- // Sprite handler
- //---------------------------------------------------------------------------
- // (C) Copyright 1992-1997 by Microsoft Corporation. All rights reserved.
- //
- // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
- // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
- // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
- // PARTICULAR PURPOSE.
- //---------------------------------------------------------------------------
- #include "Main.h"
- #pragma hdrstop
- #include "Spr.h"
- #include <math.h>
- //---------------------------------------------------------------------------
- // DEBUG info
- //---------------------------------------------------------------------------
- SZTHISFILE
- //---------------------------------------------------------------------------
- // Global Variables
- //---------------------------------------------------------------------------
- ITypeInfo *g_ptinfoClsSpriteClass = NULL;
- ITypeInfo *g_ptinfoIntSpriteClass = NULL;
- ITypeInfo *g_ptinfoClsSprite = NULL;
- ITypeInfo *g_ptinfoIntSprite = NULL;
- HBITMAP g_hbmpStock = NULL;
- HBRUSH g_hbrushStock = NULL;
- HDC g_hdcMem = NULL;
- //***************************************************************************
- //***************************************************************************
- //**
- //** Display Class
- //**
- //***************************************************************************
- //***************************************************************************
- //---------------------------------------------------------------------------
- // Initialize display surface for sprites
- //---------------------------------------------------------------------------
- CDisplay::CDisplay
- (
- HINSTANCE hinst,
- HWND hwnd,
- HDC hdc,
- IUnknown *punkParent,
- PFNCOLLIDE pfnCollide,
- int cimg,
- PIMG prgimg,
- UINT idbmp
- )
- {
- RECT rect;
- INIT_SIGNATURE(SIG_Display);
- // Create an HDC and get the stock bitmap
- if (!g_hdcMem)
- {
- HBITMAP hbmp;
- g_hdcMem = CreateCompatibleDC(NULL);
- hbmp = CreateCompatibleBitmap(g_hdcMem, 1, 1);
- g_hbmpStock = (HBITMAP)SelectObject(g_hdcMem, hbmp);
- SelectObject(g_hdcMem, g_hbmpStock);
- DeleteObject(hbmp);
- g_hbrushStock = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
- }
- // Stash away values & init member variables
- m_hinst = hinst;
- m_hdc = hdc;
- GetClientRect(hwnd, &rect);
- m_cx = rect.right;
- m_cy = rect.bottom;
- m_pfnCollide = pfnCollide;
- m_csc = 0;
- m_cimg = cimg;
- m_prgimg = prgimg;
- m_idbmp = idbmp;
- m_psprFirst = NULL;
- m_psprLast = NULL;
- m_punkParent = punkParent;
- m_hbmp = NULL;
- m_hbrushBack = NULL;
- this->SetBackColor(0x00c0c0c0);
- m_hwnd = hwnd;
- // Compute animated images
- for (int i=0; i<cimg; i++)
- if (prgimg[i].iimgNext != iimgNONE &&
- prgimg[i].iimgNext != iimgREMOVE)
- prgimg[i].pimgNext = &prgimg[prgimg[i].iimgNext];
- // Load in all hbmp
- m_hbmp = LoadBitmap(m_hinst, MAKEINTRESOURCE(m_idbmp));
- }
- //---------------------------------------------------------------------------
- // Terminate Sprite Sytem
- //---------------------------------------------------------------------------
- CDisplay::~CDisplay
- (
- void
- )
- {
- CHECK_SIGNATURE(SIG_Display);
- if (m_hbrushBack)
- {
- SelectObject(g_hdcMem, g_hbrushStock);
- DeleteObject(m_hbrushBack);
- m_hbrushBack = NULL;
- }
- if (g_hdcMem)
- {
- SelectObject(g_hdcMem, g_hbmpStock);
- DeleteDC(g_hdcMem);
- g_hdcMem = NULL;
- }
- if (m_hbmp)
- {
- // Delete all loaded bitmaps:
- DeleteObject((HGDIOBJ)m_hbmp);
- m_hbmp = (HBITMAP)NULL;
- }
- DESTROY_SIGNATURE(SIG_Display);
- }
- //---------------------------------------------------------------------------
- // Free all sprites on Display.
- //---------------------------------------------------------------------------
- void CDisplay::DestroyAll
- (
- void
- )
- {
- CSprite *pspr;
- while (m_psprFirst)
- {
- pspr = m_psprFirst;
- pspr->_Unlink(FALSE);
- pspr->Release();
- }
- }
- //---------------------------------------------------------------------------
- // Move all sprites on Display.
- //---------------------------------------------------------------------------
- void CDisplay::Timer
- (
- void
- )
- {
- CSprite *pspr;
- CSprite *psprPrev;
- for (pspr=m_psprLast; pspr; pspr=psprPrev)
- {
- psprPrev = pspr->m_psprPrev;
- // Fire Tick event, if sprite exists
- if (!pspr->m_fFree)
- {
- if (--pspr->m_tickEvt <= 0)
- {
- pspr->m_psc->FireTick(pspr);
- pspr->m_tickEvt = pspr->m_tickEvtMax;
- }
- }
- // Move sprite, if it still exits (FireTick might have killed it.)
- if (!pspr->m_fFree)
- {
- if (--pspr->m_tickMove <= 0)
- {
- long xOldFull;
- long yOldFull;
- pspr->m_tickMove = pspr->m_tickMoveMax;
- // Does this sprite have a "MoveAt" sprite attached?
- if (pspr->m_psprAt)
- pspr->DoMoveAt(pspr->m_psprAt, pspr->m_dMaxAt, pspr->m_scaleAt, pspr->m_flagsAt, TRUE);
- xOldFull = pspr->m_xFull;
- yOldFull = pspr->m_yFull;
- if (HIWORD(xOldFull + pspr->m_vxFull) == HIWORD(xOldFull) &&
- HIWORD(yOldFull + pspr->m_vyFull) == HIWORD(yOldFull))
- {
- // Movement was only fractional, so don't need to redraw sprite.
- pspr->m_xFull += pspr->m_vxFull;
- pspr->m_yFull += pspr->m_vyFull;
- }
- else
- {
- pspr->_Erase();
- pspr->m_xFull += pspr->m_vxFull;
- pspr->m_yFull += pspr->m_vyFull;
- if (pspr->m_pimg->iimgNext == iimgREMOVE)
- pspr->Remove();
- else if (pspr->m_pimg->iimgNext != iimgNONE)
- {
- pspr->m_iimg = pspr->m_pimg->iimgNext;
- pspr->m_pimg = pspr->m_pimg->pimgNext;
- }
- if (!pspr->_FDraw(TRUE))
- {
- pspr->m_xFull = xOldFull;
- pspr->m_yFull = yOldFull;
- pspr->_FDraw(FALSE);
- }
- }
- // Calculate Friction
- if (pspr->m_fFriction)
- {
- pspr->m_vxFull = (long)((FLOAT)pspr->m_vxFull * pspr->m_fx);
- pspr->m_vyFull = (long)((FLOAT)pspr->m_vyFull * pspr->m_fy);
- }
- // Calculate AccelerationFriction
- if (pspr->m_psc->m_fFrictionAccel)
- {
- pspr->m_axFull = (long)((FLOAT)pspr->m_axFull * pspr->m_psc->m_frictionAccel);
- pspr->m_ayFull = (long)((FLOAT)pspr->m_ayFull * pspr->m_psc->m_frictionAccel);
- }
- // Calculate Acceleration
- pspr->m_vxFull += pspr->m_axFull;
- pspr->m_vyFull += pspr->m_ayFull;
- // Ensure Vel is not over max allowed for SpriteClass
- if (pspr->m_vxFull > pspr->m_psc->m_vFullMax)
- pspr->m_vxFull = pspr->m_psc->m_vFullMax;
- else if (pspr->m_vxFull < -pspr->m_psc->m_vFullMax)
- pspr->m_vxFull = -pspr->m_psc->m_vFullMax;
- if (pspr->m_vyFull > pspr->m_psc->m_vFullMax)
- pspr->m_vyFull = pspr->m_psc->m_vFullMax;
- else if (pspr->m_vyFull < -pspr->m_psc->m_vFullMax)
- pspr->m_vyFull = -pspr->m_psc->m_vFullMax;
- }
- }
- if (pspr->m_fFree)
- {
- pspr->_Unlink(TRUE);
- pspr->Release();
- }
- }
- }
- //---------------------------------------------------------------------------
- // Paint all sprites.
- //---------------------------------------------------------------------------
- void CDisplay::Paint
- (
- HDC hdc
- )
- {
- CSprite *pspr;
- if (hdc == NULL)
- hdc = m_hdc;
- for (pspr=m_psprLast; pspr; pspr=pspr->m_psprPrev)
- {
- if (!pspr->m_fFree && !pspr->m_fHidden)
- {
- SelectObject(g_hdcMem, m_hbmp);
- BitBlt(hdc, pspr->m_x, pspr->m_y, pspr->m_pimg->cx, pspr->m_pimg->cy, g_hdcMem, pspr->m_pimg->x, pspr->m_pimg->y, SRCCOPY);
- }
- }
- SelectObject(g_hdcMem, g_hbmpStock);
- }
- //---------------------------------------------------------------------------
- // Paint any sprites with fNeedRefresh set.
- //---------------------------------------------------------------------------
- void CDisplay::Refresh
- (
- void
- )
- {
- CSprite *pspr;
- HDC hdc = m_hdc;
- for (pspr=m_psprLast; pspr; pspr=pspr->m_psprPrev)
- {
- if (pspr->m_fNeedRefresh && !pspr->m_fHidden)
- {
- pspr->m_fNeedRefresh = FALSE;
- SelectObject(g_hdcMem, m_hbmp);
- BitBlt(hdc, pspr->m_x, pspr->m_y, pspr->m_pimg->cx, pspr->m_pimg->cy, g_hdcMem, pspr->m_pimg->x, pspr->m_pimg->y, SRCCOPY);
- }
- }
- SelectObject(g_hdcMem, g_hbmpStock);
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- void CDisplay::SetBackColor
- (
- COLORREF c
- )
- {
- static LOGBRUSH lb = {BS_SOLID, 0x00c0c0c0, 0};
- if (m_colorBack == c)
- return;
- m_colorBack = c;
- lb.lbColor = c;
- if (m_hbrushBack)
- DeleteObject(m_hbrushBack);
- m_hbrushBack = CreateBrushIndirect(&lb);
- }
- //---------------------------------------------------------------------------
- // Send Collide event back to the fn passed into the constructor.
- //---------------------------------------------------------------------------
- void CDisplay::FireCollide
- (
- CSprite *psprLowId,
- CSprite *psprHighId,
- int maskCollide
- )
- {
- (*m_pfnCollide)(psprLowId, psprHighId, maskCollide);
- }
- //***************************************************************************
- //***************************************************************************
- //**
- //** SpriteClass Class
- //**
- //***************************************************************************
- //***************************************************************************
- HRESULT s_hr = S_OK;
- //---------------------------------------------------------------------------
- // Create function for SpriteClass. Use instead of "new CSpriteClass".
- //---------------------------------------------------------------------------
- HRESULT CSpriteClass::Create
- (
- CDisplay *pdisp,
- CSpriteClass **ppscOut
- )
- {
- if (!ppscOut)
- return E_INVALIDARG;
- *ppscOut = new CSpriteClass(pdisp);
- if (!*ppscOut)
- return E_OUTOFMEMORY;
- return S_OK;
- }
- //---------------------------------------------------------------------------
- // Constructor for SpriteClass
- //---------------------------------------------------------------------------
- CSpriteClass::CSpriteClass
- (
- CDisplay *pdisp
- )
- {
- INIT_SIGNATURE(SIG_SpriteClass);
- m_id = ++(pdisp->m_csc);
- m_pdisp = pdisp;
- m_brd = SPR_brdALL;
- m_maskCollide = 0;
- m_iimg = 0;
- m_cspr = 0;
- m_cref = 1;
- m_pdispBaseObject = NULL;
- VariantInit(&m_varTag);
- m_friction = (FLOAT)1.0;
- m_frictionAccel = (FLOAT)1.0;
- m_fFrictionAccel = FALSE;
- m_vFullMax = 0x000a0000;
- m_aFullMax = 0x00010000;
- }
- //---------------------------------------------------------------------------
- // Destructor for Sprite
- //---------------------------------------------------------------------------
- void CSpriteClass::Close
- (
- void
- )
- {
- CHECK_SIGNATURE(SIG_SpriteClass);
- CSprite *pspr;
- CSprite *psprPrev;
- // Destroy all sprites of this SpriteClass
- for (pspr=m_pdisp->m_psprLast; pspr; pspr=psprPrev)
- {
- psprPrev = pspr->m_psprPrev;
- if (pspr->m_psc == this)
- {
- pspr->_Unlink(FALSE);
- pspr->m_psc = NULL;
- pspr->Release();
- }
- }
- // Unadvise all event sinks
- m_cp.Close();
- // Clear incase this is an object
- VariantClear(&m_varTag);
- }
- //---------------------------------------------------------------------------
- // Destructor for Sprite
- //---------------------------------------------------------------------------
- CSpriteClass::~CSpriteClass
- (
- void
- )
- {
- CHECK_SIGNATURE(SIG_SpriteClass);
- this->Close();
- DESTROY_SIGNATURE(SIG_SpriteClass);
- }
- //***************************************************************************
- // IUnknown Interface
- //***************************************************************************
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::QueryInterface
- (
- REFIID iid,
- LPVOID* ppvObjOut
- )
- {
- if (!ppvObjOut)
- return E_INVALIDARG;
- *ppvObjOut = NULL;
- if (iid == IID_IUnknown)
- *ppvObjOut = this->GetUnknown();
- else if (iid == IID_IDispatch)
- *ppvObjOut = this->GetDispatch();
- else if (iid == IID_ISpriteClass)
- *ppvObjOut = (ISpriteClass *)this;
- else if (iid == IID_IConnectionPointContainer)
- *ppvObjOut = (IConnectionPointContainer *)this;
- else if (iid == IID_IProvideClassInfo)
- *ppvObjOut = (IProvideClassInfo *)this;
- if (*ppvObjOut)
- {
- this->AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CSpriteClass::AddRef
- (
- void
- )
- {
- return ++m_cref;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CSpriteClass::Release
- (
- void
- )
- {
- ASSERT(m_cref, "bad m_cref");
- m_cref--;
- if (!m_cref)
- {
- this->Close();
- if (!m_cref && !m_cp.m_cref)
- {
- delete this;
- return 0;
- }
- }
- return m_cref;
- }
- //***************************************************************************
- // IDispatch Interface
- //***************************************************************************
- //---------------------------------------------------------------------------
- // Method needed by COleAuto, so it can implement IDispatch for us.
- //---------------------------------------------------------------------------
- HRESULT CSpriteClass::GetTypeLibInfo
- (
- HINSTANCE *phinstOut,
- const GUID **pplibidOut,
- SHORT *pwMajLib,
- SHORT *pwMinLib,
- const CLSID **ppclsidOut,
- const IID **ppiidOut,
- ITypeLib ***ppptlOut
- )
- {
- *phinstOut = g_hinst;
- *pplibidOut = &LIBID_SPRUUIDS;
- *pwMajLib = 1;
- *pwMinLib = 0;
- *ppclsidOut = &CLSID_SpriteClass;
- *ppiidOut = &IID_ISpriteClass;
- *ppptlOut = &g_ptlMain;
- return S_OK;
- }
- //***************************************************************************
- // IProvideClassInfo Interface
- //***************************************************************************
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::GetClassInfo
- (
- ITypeInfo** pptinfoOut
- )
- {
- HRESULT hr = ((COleAuto *)this)->CheckTypeInfo(0, 0x0409);
- if (hr)
- return hr;
- *pptinfoOut = g_ptinfoClsSpriteClass;
- (*pptinfoOut)->AddRef();
- return S_OK;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::GetGUID
- (
- DWORD dwGuidKind,
- GUID* pGUID
- )
- {
- if (pGUID)
- return E_INVALIDARG;
- if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
- return E_INVALIDARG;
- *pGUID = DIID_ISpriteClassEvents;
- return S_OK;
- }
- //***************************************************************************
- // IConnectionPointContainer Interface
- //***************************************************************************
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::EnumConnectionPoints
- (
- LPENUMCONNECTIONPOINTS* ppEnum
- )
- {
- return E_NOTIMPL; // UNDONE: Implement this method
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::FindConnectionPoint
- (
- REFIID iid,
- LPCONNECTIONPOINT* ppCpOut
- )
- {
- if (!ppCpOut)
- return E_INVALIDARG;
- if (iid == DIID_ISpriteClassEvents || iid == IID_IDispatch)
- {
- *ppCpOut = &m_cp;
- (*ppCpOut)->AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
- }
- //***************************************************************************
- // Embedded IConnectionPoint Class
- //***************************************************************************
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- CSpriteClass::XCP::XCP
- (
- void
- )
- {
- m_cref = 1;
- for (int i=0; i<SC_cADVISE; i++)
- m_rgpdisp[i] = NULL;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- void CSpriteClass::XCP::Close
- (
- void
- )
- {
- for (int i=0; i<SC_cADVISE; i++)
- if (m_rgpdisp[i])
- {
- m_rgpdisp[i]->Release();
- m_rgpdisp[i] = NULL;
- }
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::XCP::QueryInterface
- (
- REFIID iid,
- LPVOID* ppvObjOut
- )
- {
- if (!ppvObjOut)
- return E_INVALIDARG;
- *ppvObjOut = NULL;
- if (iid == IID_IUnknown)
- *ppvObjOut = this->GetUnknown();
- else if (iid == IID_IConnectionPoint)
- *ppvObjOut = (IConnectionPoint *)this;
- if (*ppvObjOut)
- {
- this->AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CSpriteClass::XCP::AddRef
- (
- void
- )
- {
- return ++m_cref;
- }
- #define SCOFCP(pcp) ((CSpriteClass *)((char *)pcp - (char *)&(((CSpriteClass *)0)->m_cp)))
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CSpriteClass::XCP::Release
- (
- void
- )
- {
- CSpriteClass *psc = SCOFCP(this);
- ASSERT(m_cref, "bad m_cref");
- m_cref--;
- if (!m_cref && !psc->m_cref)
- {
- delete psc;
- return 0;
- }
- return m_cref;
- }
- //***************************************************************************
- // IConnectionPoint Interface
- //***************************************************************************
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::XCP::GetConnectionInterface
- (
- IID* piid
- )
- {
- if (!piid)
- return E_INVALIDARG;
- memcpy(piid, &DIID_ISpriteClassEvents, sizeof(IID));
- return S_OK;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::XCP::GetConnectionPointContainer
- (
- IConnectionPointContainer** ppCpcOut
- )
- {
- if (!ppCpcOut)
- return E_INVALIDARG;
- *ppCpcOut = SCOFCP(this);
- (*ppCpcOut)->AddRef();
- return S_OK;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::XCP::Advise
- (
- IUnknown* punkSink,
- DWORD* pdwCookie
- )
- {
- IDispatch *psce = NULL;
- IDispatch **ppdisp;
- HRESULT hr;
- if (!punkSink || !pdwCookie)
- return E_INVALIDARG;
- *pdwCookie = 0;
- // Look for empty slot
- for (ppdisp=m_rgpdisp; *ppdisp && ppdisp<&m_rgpdisp[SC_cADVISE]; ppdisp++)
- ;
- // Did we find one?
- if (ppdisp >= &m_rgpdisp[SC_cADVISE])
- return E_FAIL; // UNDONE: Error?
- // Now see if sink supports correct interface
- hr = punkSink->QueryInterface(DIID_ISpriteClassEvents, (void **)&psce);
- if (hr == E_NOINTERFACE)
- {
- hr = punkSink->QueryInterface(IID_IDispatch, (void **)&psce);
- if (hr)
- return hr;
- }
- ASSERT(psce, "QI but no ptr");
- // Finish advise by stashing punkSink QI'd to our interface
- *ppdisp = psce; // AddRef'd from QI
- *pdwCookie = (ppdisp - m_rgpdisp) + 1;
- return S_OK;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::XCP::Unadvise
- (
- DWORD dwCookie
- )
- {
- if (!dwCookie || dwCookie > SC_cADVISE)
- return E_INVALIDARG;
- m_rgpdisp[dwCookie-1]->Release();
- m_rgpdisp[dwCookie-1] = NULL;
- return S_OK;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSpriteClass::XCP::EnumConnections
- (
- LPENUMCONNECTIONS* ppEnum
- )
- {
- return E_NOTIMPL; // UNDONE: Implement this method
- }
- //***************************************************************************
- //***************************************************************************
- //**
- //** Sprite Class
- //**
- //***************************************************************************
- //***************************************************************************
- //---------------------------------------------------------------------------
- // Constructor for Sprite
- //---------------------------------------------------------------------------
- CSprite::CSprite
- (
- CSpriteClass *psc,
- int x,
- int y,
- CSprite *psprPrev, // NULL==1st, -1==Last
- VARIANT *pvarUser
- )
- {
- INIT_SIGNATURE(SIG_Sprite);
- m_pdisp = psc->m_pdisp;
- m_psprNext = NULL;
- m_psprPrev = psprPrev;
- m_xFull = 0;
- m_x = x;
- m_yFull = 0;
- m_y = y;
- m_vxFull = 0;
- m_vyFull = 0;
- m_axFull = 0;
- m_ayFull = 0;
- m_fx = psc->m_friction;
- m_fy = psc->m_friction;
- m_fFriction = (psc->m_friction != 1.0);
- m_tickEvt = 0x7fffffff;
- m_tickEvtMax = 0x7fffffff;
- m_tickMove = 1;
- m_tickMoveMax = 1;
- m_iimg = psc->m_iimg;
- m_pimg = &m_pdisp->m_prgimg[m_iimg];
- m_psc = psc;
- m_fNeedRefresh = TRUE;
- m_fFree = FALSE;
- m_fIgnoreMove = FALSE;
- m_fLinked = FALSE;
- m_fHidden = 2; // Set to 2 instead of TRUE to detect if user explicitly hides it during _Init event
- m_cref = 1;
- m_psprAt = NULL;
- m_pdispBaseObject = NULL;
- VariantInit(&m_varTag);
- this->_Link();
- m_psc->FireInit(this, pvarUser);
- if (m_fHidden == 2)
- m_fHidden = FALSE; // If not explicitly hidden in event, show it
- }
- //---------------------------------------------------------------------------
- // Destructor for Sprite
- //---------------------------------------------------------------------------
- CSprite::~CSprite
- (
- void
- )
- {
- CHECK_SIGNATURE(SIG_Sprite);
- VariantClear(&m_varTag);
- if (m_psprAt)
- {
- m_psprAt->Release();
- m_psprAt = NULL;
- }
- this->_Unlink(TRUE);
- DESTROY_SIGNATURE(SIG_Sprite);
- }
- //---------------------------------------------------------------------------
- // Change the class of an existing pspr
- //---------------------------------------------------------------------------
- CSprite *CSprite::PsprMutate
- (
- CSpriteClass *psc,
- VARIANT *pvarUser
- )
- {
- m_x += m_pimg->cx >> 1;
- m_y += m_pimg->cy >> 1;
- m_iimg = psc->m_iimg;
- m_pimg = &m_pdisp->m_prgimg[m_iimg];
- m_x -= m_pimg->cx >> 1;
- m_y -= m_pimg->cy >> 1;
- m_psc->m_cspr--;
- m_psc = psc;
- m_psc->m_cspr++;
- m_tickEvt = 0x7fffffff;
- m_tickEvtMax = 0x7fffffff;
- m_tickMove = 0;
- m_tickMoveMax = 1;
- m_fHidden = 2; // Set to 2 instead of TRUE to detect if user explicitly hides it during _Init event
- m_psc->FireInit(this, pvarUser);
- if (m_fHidden == 2)
- m_fHidden = FALSE; // If not explicitly hidden in event, show it
- return this;
- }
- //---------------------------------------------------------------------------
- // Free a SPR structure
- //---------------------------------------------------------------------------
- void CSprite::MarkFree
- (
- void
- )
- {
- if (m_psprAt)
- {
- m_psprAt->Release();
- m_psprAt = NULL;
- }
- m_psc->FireTerm(this);
- m_fFree = TRUE;
- }
- //---------------------------------------------------------------------------
- // Link a sprite into the display list
- //---------------------------------------------------------------------------
- void CSprite::_Link
- (
- void
- )
- {
- if (!m_psprPrev)
- {
- m_psprNext = m_pdisp->m_psprFirst;
- m_pdisp->m_psprFirst = this;
- if (m_psprNext)
- m_psprNext->m_psprPrev = this;
- if (!m_pdisp->m_psprLast)
- m_pdisp->m_psprLast = this;
- }
- else if (m_psprPrev == (CSprite *)-1)
- {
- m_psprNext = NULL;
- m_psprPrev = m_pdisp->m_psprLast;
- if (m_pdisp->m_psprLast)
- m_pdisp->m_psprLast->m_psprNext = this;
- else
- m_pdisp->m_psprFirst = this;
- m_pdisp->m_psprLast = this;
- }
- else
- {
- // UNDONE: Fix this up.
- m_psprNext = m_pdisp->m_psprLast->m_psprNext;
- m_pdisp->m_psprLast->m_psprNext = this;
- m_psprNext->m_psprPrev = this;
- if (m_pdisp->m_psprLast == m_pdisp->m_psprLast)
- m_pdisp->m_psprLast = this;
- }
- m_fLinked = TRUE;
- m_psc->m_cspr++;
- //this->_FDraw(FALSE); // Require "s.Refresh" to avoid spurious paint before img set
- }
- //---------------------------------------------------------------------------
- // Unlink a sprite into the display list
- //---------------------------------------------------------------------------
- void CSprite::_Unlink
- (
- BOOL fFireEvt
- )
- {
- if (!m_fLinked)
- return;
- this->_Erase();
- if (m_pdisp->m_psprFirst == this)
- m_pdisp->m_psprFirst = m_psprNext;
- if (m_pdisp->m_psprLast == this)
- m_pdisp->m_psprLast = m_psprPrev;
- if (m_psprPrev)
- m_psprPrev->m_psprNext = m_psprNext;
- if (m_psprNext)
- m_psprNext->m_psprPrev = m_psprPrev;
- m_fLinked = FALSE;
- m_fHidden = TRUE;
- // Track # of sprites of this kind. If there are no more, then
- // fire the _LastTerm event.
- m_psc->m_cspr--;
- if (fFireEvt && !m_psc->m_cspr)
- m_psc->FireLastTerm();
- if (m_psprAt)
- {
- m_psprAt->Release();
- m_psprAt = NULL;
- }
- }
- //---------------------------------------------------------------------------
- // Draw the given sprite
- //---------------------------------------------------------------------------
- BOOL CSprite::_FDraw
- (
- BOOL fCollide
- )
- {
- CSprite *psprT;
- CSprite *psprNext;
- int x = m_x;
- int y = m_y;
- int cx = m_pimg->cx;
- int cy = m_pimg->cy;
- HDC hdc = m_pdisp->m_hdc;
- if (fCollide && !m_fFree)
- {
- int maskCollide = m_psc->m_maskCollide;
- if (m_fHidden)
- goto DoneWithColl;
- for (psprT=m_pdisp->m_psprFirst; psprT; psprT=psprNext)
- {
- psprNext = psprT->m_psprNext;
- if (psprT != this && // Never collide w/self
- ((psprT->m_psc != m_psc) || (maskCollide & 1)) && // Coll w/like kind only if bit 1 set
- (maskCollide & psprT->m_psc->m_maskCollide & ~1) && // Coll w/other kinds only if masks overlap
- x <= psprT->m_x+psprT->m_pimg->cx && x+cx >= psprT->m_x && // Coll only if actually touch
- y <= psprT->m_y+psprT->m_pimg->cy && y+cy >= psprT->m_y)
- {
- m_fIgnoreMove = FALSE;
- if (m_psc->m_id <= psprT->m_psc->m_id)
- m_pdisp->FireCollide(this, psprT, maskCollide & psprT->m_psc->m_maskCollide);
- else
- m_pdisp->FireCollide(psprT, this, maskCollide & psprT->m_psc->m_maskCollide);
- if (m_fFree)
- return TRUE;
- if (m_fIgnoreMove)
- return FALSE;
- if (psprT->m_fFree)
- goto DoneWithColl;
- }
- }
- DoneWithColl:;
- if ((m_psc->m_brd & SPR_brdALL))
- {
- BRD brd = 0;
- if (m_psc->m_brd & SPR_brdIN)
- {
- if (x < 0) brd = SPR_brdINLEFT;
- if (y < 0) brd |= SPR_brdINTOP;
- if (x+cx > m_pdisp->m_cx) brd |= SPR_brdINRIGHT;
- if (y+cy > m_pdisp->m_cy) brd |= SPR_brdINBOTTOM;
- }
- if (m_psc->m_brd & SPR_brdOUT)
- {
- if (x+cx < 0) brd = SPR_brdOUTLEFT;
- if (y+cy < 0) brd |= SPR_brdOUTTOP;
- if (x > m_pdisp->m_cx) brd |= SPR_brdOUTRIGHT;
- if (y > m_pdisp->m_cy) brd |= SPR_brdOUTBOTTOM;
- }
- if (brd)
- {
- m_fIgnoreMove = FALSE;
- m_psc->FireBorder(this, brd);
- if (m_fFree)
- return TRUE;
- if (m_fIgnoreMove)
- return FALSE;
- }
- }
- }
- // Don't draw if not visible
- if (m_fHidden)
- return TRUE;
- SelectObject(g_hdcMem, m_pdisp->m_hbmp);
- BitBlt(hdc, m_x, m_y, cx, cy, g_hdcMem, m_pimg->x, m_pimg->y, SRCCOPY);
- m_fNeedRefresh = FALSE;
- for (psprT=m_psprPrev; psprT; psprT=psprT->m_psprPrev)
- {
- if (!psprT->m_fNeedRefresh &&
- x <= psprT->m_x+psprT->m_pimg->cx && x+cx >= psprT->m_x &&
- y <= psprT->m_y+psprT->m_pimg->cy && y+cy >= psprT->m_y)
- {
- psprT->m_fNeedRefresh = TRUE;
- }
- }
- SelectObject(g_hdcMem, g_hbmpStock);
- return TRUE;
- }
- //---------------------------------------------------------------------------
- // Erase the given sprite
- //---------------------------------------------------------------------------
- void CSprite::_Erase
- (
- void
- )
- {
- int x = m_x;
- int y = m_y;
- int cx = m_pimg->cx;
- int cy = m_pimg->cy;
- HDC hdc = m_pdisp->m_hdc;
- CSprite *psprT;
- SelectObject(hdc, (HGDIOBJ)(m_pdisp->m_hbrushBack ? m_pdisp->m_hbrushBack : g_hbrushStock));
- PatBlt(hdc, m_x, m_y, cx, cy, PATCOPY);
- for (psprT=m_pdisp->m_psprLast; psprT; psprT=psprT->m_psprPrev)
- {
- if (psprT != this && !psprT->m_fNeedRefresh &&
- x <= psprT->m_x+psprT->m_pimg->cx && x+cx >= psprT->m_x &&
- y <= psprT->m_y+psprT->m_pimg->cy && y+cy >= psprT->m_y)
- psprT->m_fNeedRefresh = TRUE;
- }
- SelectObject(g_hdcMem, g_hbrushStock);
- }
- //---------------------------------------------------------------------------
- // Move the given sprite to new location
- //---------------------------------------------------------------------------
- BOOL CSprite::MoveToFull
- (
- long xFull,
- long yFull,
- BOOL fCollide
- )
- {
- long xOldFull = m_xFull;
- long yOldFull = m_yFull;
- this->_Erase();
- m_xFull = xFull;
- m_yFull = yFull;
- if (m_pimg->iimgNext == iimgREMOVE)
- this->Remove();
- else if (m_pimg->iimgNext != iimgNONE)
- {
- m_iimg = m_pimg->iimgNext;
- m_pimg = m_pimg->pimgNext;
- }
- if (!this->_FDraw(fCollide))
- {
- m_xFull = xOldFull;
- m_yFull = yOldFull;
- this->_FDraw(FALSE);
- return FALSE;
- }
- return TRUE;
- }
- //---------------------------------------------------------------------------
- // Move the given sprite to new location
- //---------------------------------------------------------------------------
- BOOL CSprite::MoveByFull
- (
- long dxFull,
- long dyFull,
- BOOL fCollide
- )
- {
- long xOldFull = m_xFull;
- long yOldFull = m_yFull;
- if (HIWORD(xOldFull + dxFull) == HIWORD(xOldFull) &&
- HIWORD(yOldFull + dyFull) == HIWORD(yOldFull))
- {
- m_xFull += dxFull;
- m_yFull += dyFull;
- return TRUE;
- }
- this->_Erase();
- m_xFull += dxFull;
- m_yFull += dyFull;
- if (m_pimg->iimgNext == iimgREMOVE)
- this->Remove();
- else if (m_pimg->iimgNext != iimgNONE)
- {
- m_iimg = m_pimg->iimgNext;
- m_pimg = m_pimg->pimgNext;
- }
- if (!this->_FDraw(fCollide))
- {
- m_xFull = xOldFull;
- m_yFull = yOldFull;
- this->_FDraw(FALSE);
- return FALSE;
- }
- return TRUE;
- }
- //---------------------------------------------------------------------------
- // flags: 1=X, 2=Y;
- // 4=Pos, 8=Vel, 16=Accel;
- // 32=Less With Distance (default=More);
- // 128=Remember
- //---------------------------------------------------------------------------
- BOOL CSprite::DoMoveAt
- (
- CSprite *psprAt,
- float scale,
- float dMax,
- long flags,
- BOOL fCollide
- )
- {
- long dx = psprAt->m_xFull - m_xFull;
- long dy = psprAt->m_yFull - m_yFull;
- if (flags & MAS_RECIPDIST)
- {
- dx = FULLOFFLOAT((FLOAT)1.0 / FLOATOFFULL(dx | 0xffff));
- dy = FULLOFFLOAT((FLOAT)1.0 / FLOATOFFULL(dy | 0xffff));
- }
- float d = FLOATOFFULL(dx) * scale;
- if (d > dMax)
- d = dMax;
- else if (d < -dMax)
- d = -dMax;
- dx = FULLOFFLOAT(d);
- d = FLOATOFFULL(dy) * scale;
- if (d > dMax)
- d = dMax;
- else if (d < -dMax)
- d = -dMax;
- dy = FULLOFFLOAT(d);
- if (flags & MAS_X)
- {
- if (flags & MAS_VEL)
- {
- m_vxFull += dx;
- if (m_vxFull > m_psc->m_vFullMax)
- m_vxFull = m_psc->m_vFullMax;
- else if (m_vxFull < -m_psc->m_vFullMax)
- m_vxFull = -m_psc->m_vFullMax;
- }
- if (flags & MAS_ACCEL)
- {
- m_axFull += dx;
- if (m_axFull > m_psc->m_aFullMax)
- m_axFull = m_psc->m_aFullMax;
- else if (m_axFull < -m_psc->m_aFullMax)
- m_axFull = -m_psc->m_aFullMax;
- }
- if (!(flags & MAS_POS))
- dx = 0;
- }
- else
- dx = 0;
- if (flags & MAS_Y)
- {
- if (flags & MAS_VEL)
- {
- m_vyFull += dy;
- if (m_vyFull > m_psc->m_vFullMax)
- m_vyFull = m_psc->m_vFullMax;
- else if (m_vyFull < -m_psc->m_vFullMax)
- m_vyFull = -m_psc->m_vFullMax;
- }
- if (flags & MAS_ACCEL)
- {
- m_ayFull += dy;
- if (m_ayFull > m_psc->m_aFullMax)
- m_ayFull = m_psc->m_aFullMax;
- else if (m_ayFull < -m_psc->m_aFullMax)
- m_ayFull = -m_psc->m_aFullMax;
- }
- if (!(flags & MAS_POS))
- dy = 0;
- }
- else
- dy = 0;
- if (dx || dy)
- return this->MoveByFull(dx, dy, fCollide);
- return TRUE;
- }
- //***************************************************************************
- // IUnknown Interface
- //***************************************************************************
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP CSprite::QueryInterface
- (
- REFIID iid,
- LPVOID* ppvObjOut
- )
- {
- if (!ppvObjOut)
- return E_INVALIDARG;
- *ppvObjOut = NULL;
- if (iid == IID_IUnknown)
- *ppvObjOut = this->GetUnknown();
- else if (iid == IID_IDispatch)
- *ppvObjOut = this->GetDispatch();
- else if (iid == IID_ISprite)
- *ppvObjOut = (ISprite *)this;
- if (*ppvObjOut)
- {
- this->AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CSprite::AddRef
- (
- void
- )
- {
- return ++m_cref;
- }
- //---------------------------------------------------------------------------
- //
- //---------------------------------------------------------------------------
- STDMETHODIMP_(ULONG) CSprite::Release
- (
- void
- )
- {
- ASSERT(m_cref, "bad m_cref");
- m_cref--;
- if (!m_cref)
- {
- delete this;
- return 0;
- }
- return m_cref;
- }
- //***************************************************************************
- // IDispatch Interface
- //***************************************************************************
- //---------------------------------------------------------------------------
- // Method needed by COleAuto, so it can implement IDispatch for us.
- //---------------------------------------------------------------------------
- HRESULT CSprite::GetTypeLibInfo
- (
- HINSTANCE *phinstOut,
- const GUID **pplibidOut,
- SHORT *pwMajLib,
- SHORT *pwMinLib,
- const CLSID **ppclsidOut,
- const IID **ppiidOut,
- ITypeLib ***ppptlOut
- )
- {
- *phinstOut = g_hinst;
- *pplibidOut = &LIBID_SPRUUIDS;
- *pwMajLib = 1;
- *pwMinLib = 0;
- *ppclsidOut = &CLSID_Sprite;
- *ppiidOut = &IID_ISprite;
- *ppptlOut = &g_ptlMain;
- return S_OK;
- }
- //--- EOF -------------------------------------------------------------------