home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / internet / scripting / spruuids / spr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-12  |  37.0 KB  |  1,451 lines

  1. //---------------------------------------------------------------------------
  2. // Spr.cpp
  3. //---------------------------------------------------------------------------
  4. // Sprite handler
  5. //---------------------------------------------------------------------------
  6. // (C) Copyright 1992-1997 by Microsoft Corporation.  All rights reserved.
  7. //
  8. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
  9. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
  10. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
  11. // PARTICULAR PURPOSE.
  12. //---------------------------------------------------------------------------
  13.  
  14. #include "Main.h"
  15. #pragma hdrstop
  16. #include "Spr.h"
  17. #include <math.h>
  18.  
  19.  
  20. //---------------------------------------------------------------------------
  21. // DEBUG info
  22. //---------------------------------------------------------------------------
  23. SZTHISFILE
  24.  
  25.  
  26. //---------------------------------------------------------------------------
  27. // Global Variables
  28. //---------------------------------------------------------------------------
  29. ITypeInfo *g_ptinfoClsSpriteClass = NULL;
  30. ITypeInfo *g_ptinfoIntSpriteClass = NULL;
  31. ITypeInfo *g_ptinfoClsSprite      = NULL;
  32. ITypeInfo *g_ptinfoIntSprite      = NULL;
  33. HBITMAP    g_hbmpStock            = NULL;
  34. HBRUSH     g_hbrushStock          = NULL;
  35. HDC        g_hdcMem               = NULL;
  36.  
  37.  
  38. //***************************************************************************
  39. //***************************************************************************
  40. //**
  41. //**  Display Class
  42. //**
  43. //***************************************************************************
  44. //***************************************************************************
  45.  
  46. //---------------------------------------------------------------------------
  47. // Initialize display surface for sprites
  48. //---------------------------------------------------------------------------
  49. CDisplay::CDisplay
  50. (
  51.   HINSTANCE  hinst,
  52.   HWND       hwnd,
  53.   HDC        hdc,
  54.   IUnknown  *punkParent,
  55.   PFNCOLLIDE pfnCollide,
  56.   int        cimg,
  57.   PIMG       prgimg,
  58.   UINT       idbmp
  59. )
  60. {
  61.   RECT rect;
  62.  
  63.   INIT_SIGNATURE(SIG_Display);
  64.  
  65.   // Create an HDC and get the stock bitmap
  66.   if (!g_hdcMem)
  67.     {
  68.     HBITMAP hbmp;
  69.  
  70.     g_hdcMem = CreateCompatibleDC(NULL);
  71.     hbmp = CreateCompatibleBitmap(g_hdcMem, 1, 1);
  72.     g_hbmpStock = (HBITMAP)SelectObject(g_hdcMem, hbmp);
  73.     SelectObject(g_hdcMem, g_hbmpStock);
  74.     DeleteObject(hbmp);
  75.     g_hbrushStock = (HBRUSH)GetStockObject(LTGRAY_BRUSH);
  76.     }
  77.  
  78.   // Stash away values & init member variables
  79.   m_hinst      = hinst;
  80.   m_hdc        = hdc;
  81.   GetClientRect(hwnd, &rect);
  82.   m_cx         = rect.right;
  83.   m_cy         = rect.bottom;
  84.   m_pfnCollide = pfnCollide;
  85.   m_csc        = 0;
  86.   m_cimg       = cimg;
  87.   m_prgimg     = prgimg;
  88.   m_idbmp      = idbmp;
  89.   m_psprFirst  = NULL;
  90.   m_psprLast   = NULL;
  91.   m_punkParent = punkParent;
  92.   m_hbmp       = NULL;
  93.   m_hbrushBack = NULL;
  94.   this->SetBackColor(0x00c0c0c0);
  95.   m_hwnd       = hwnd;
  96.  
  97.   // Compute animated images
  98.   for (int i=0; i<cimg; i++)
  99.     if (prgimg[i].iimgNext != iimgNONE &&
  100.         prgimg[i].iimgNext != iimgREMOVE)
  101.       prgimg[i].pimgNext = &prgimg[prgimg[i].iimgNext];
  102.  
  103.   // Load in all hbmp
  104.   m_hbmp = LoadBitmap(m_hinst, MAKEINTRESOURCE(m_idbmp));
  105. }
  106.  
  107.  
  108. //---------------------------------------------------------------------------
  109. // Terminate Sprite Sytem
  110. //---------------------------------------------------------------------------
  111. CDisplay::~CDisplay
  112. (
  113.   void
  114. )
  115. {
  116.   CHECK_SIGNATURE(SIG_Display);
  117.  
  118.   if (m_hbrushBack)
  119.     {
  120.     SelectObject(g_hdcMem, g_hbrushStock);
  121.     DeleteObject(m_hbrushBack);
  122.     m_hbrushBack = NULL;
  123.     }
  124.  
  125.   if (g_hdcMem)
  126.     {
  127.     SelectObject(g_hdcMem, g_hbmpStock);
  128.     DeleteDC(g_hdcMem);
  129.     g_hdcMem = NULL;
  130.     }
  131.  
  132.   if (m_hbmp)
  133.     {
  134.     // Delete all loaded bitmaps:
  135.     DeleteObject((HGDIOBJ)m_hbmp);
  136.     m_hbmp = (HBITMAP)NULL;
  137.     }
  138.  
  139.   DESTROY_SIGNATURE(SIG_Display);
  140. }
  141.  
  142.  
  143. //---------------------------------------------------------------------------
  144. // Free all sprites on Display.
  145. //---------------------------------------------------------------------------
  146. void CDisplay::DestroyAll
  147. (
  148.   void
  149. )
  150. {
  151.   CSprite *pspr;
  152.  
  153.   while (m_psprFirst)
  154.     {
  155.     pspr = m_psprFirst;
  156.     pspr->_Unlink(FALSE);
  157.     pspr->Release();
  158.     }
  159. }
  160.  
  161.  
  162. //---------------------------------------------------------------------------
  163. // Move all sprites on Display.
  164. //---------------------------------------------------------------------------
  165. void CDisplay::Timer
  166. (
  167.   void
  168. )
  169. {
  170.   CSprite *pspr;
  171.   CSprite *psprPrev;
  172.  
  173.   for (pspr=m_psprLast; pspr; pspr=psprPrev)
  174.     {
  175.     psprPrev = pspr->m_psprPrev;
  176.  
  177.     // Fire Tick event, if sprite exists
  178.     if (!pspr->m_fFree)
  179.       {
  180.       if (--pspr->m_tickEvt <= 0)
  181.         {
  182.         pspr->m_psc->FireTick(pspr);
  183.         pspr->m_tickEvt = pspr->m_tickEvtMax;
  184.         }
  185.       }
  186.  
  187.     // Move sprite, if it still exits (FireTick might have killed it.)
  188.     if (!pspr->m_fFree)
  189.       {
  190.       if (--pspr->m_tickMove <= 0)
  191.         {
  192.         long xOldFull;
  193.         long yOldFull;
  194.  
  195.         pspr->m_tickMove = pspr->m_tickMoveMax;
  196.  
  197.         // Does this sprite have a "MoveAt" sprite attached?
  198.         if (pspr->m_psprAt)
  199.           pspr->DoMoveAt(pspr->m_psprAt, pspr->m_dMaxAt, pspr->m_scaleAt, pspr->m_flagsAt, TRUE);
  200.  
  201.         xOldFull = pspr->m_xFull;
  202.         yOldFull = pspr->m_yFull;
  203.         if (HIWORD(xOldFull + pspr->m_vxFull) == HIWORD(xOldFull) &&
  204.             HIWORD(yOldFull + pspr->m_vyFull) == HIWORD(yOldFull))
  205.           {
  206.           // Movement was only fractional, so don't need to redraw sprite.
  207.           pspr->m_xFull += pspr->m_vxFull;
  208.           pspr->m_yFull += pspr->m_vyFull;
  209.           }
  210.         else
  211.           {
  212.           pspr->_Erase();
  213.           pspr->m_xFull += pspr->m_vxFull;
  214.           pspr->m_yFull += pspr->m_vyFull;
  215.           if (pspr->m_pimg->iimgNext == iimgREMOVE)
  216.             pspr->Remove();
  217.           else if (pspr->m_pimg->iimgNext != iimgNONE)
  218.             {
  219.             pspr->m_iimg = pspr->m_pimg->iimgNext;
  220.             pspr->m_pimg = pspr->m_pimg->pimgNext;
  221.             }
  222.           if (!pspr->_FDraw(TRUE))
  223.             {
  224.             pspr->m_xFull = xOldFull;
  225.             pspr->m_yFull = yOldFull;
  226.             pspr->_FDraw(FALSE);
  227.             }
  228.           }
  229.  
  230.         // Calculate Friction
  231.         if (pspr->m_fFriction)
  232.           {
  233.           pspr->m_vxFull = (long)((FLOAT)pspr->m_vxFull * pspr->m_fx);
  234.           pspr->m_vyFull = (long)((FLOAT)pspr->m_vyFull * pspr->m_fy);
  235.           }
  236.  
  237.         // Calculate AccelerationFriction
  238.         if (pspr->m_psc->m_fFrictionAccel)
  239.           {
  240.           pspr->m_axFull = (long)((FLOAT)pspr->m_axFull * pspr->m_psc->m_frictionAccel);
  241.           pspr->m_ayFull = (long)((FLOAT)pspr->m_ayFull * pspr->m_psc->m_frictionAccel);
  242.           }
  243.  
  244.         // Calculate Acceleration
  245.         pspr->m_vxFull += pspr->m_axFull;
  246.         pspr->m_vyFull += pspr->m_ayFull;
  247.  
  248.         // Ensure Vel is not over max allowed for SpriteClass
  249.         if (pspr->m_vxFull > pspr->m_psc->m_vFullMax)
  250.           pspr->m_vxFull = pspr->m_psc->m_vFullMax;
  251.         else if (pspr->m_vxFull < -pspr->m_psc->m_vFullMax)
  252.           pspr->m_vxFull = -pspr->m_psc->m_vFullMax;
  253.         if (pspr->m_vyFull > pspr->m_psc->m_vFullMax)
  254.           pspr->m_vyFull = pspr->m_psc->m_vFullMax;
  255.         else if (pspr->m_vyFull < -pspr->m_psc->m_vFullMax)
  256.           pspr->m_vyFull = -pspr->m_psc->m_vFullMax;
  257.         }
  258.       }
  259.  
  260.     if (pspr->m_fFree)
  261.       {
  262.       pspr->_Unlink(TRUE);
  263.       pspr->Release();
  264.       }
  265.     }
  266. }
  267.  
  268.  
  269. //---------------------------------------------------------------------------
  270. // Paint all sprites.
  271. //---------------------------------------------------------------------------
  272. void CDisplay::Paint
  273. (
  274.   HDC hdc
  275. )
  276. {
  277.   CSprite *pspr;
  278.  
  279.   if (hdc == NULL)
  280.     hdc = m_hdc;
  281.  
  282.   for (pspr=m_psprLast; pspr; pspr=pspr->m_psprPrev)
  283.     {
  284.     if (!pspr->m_fFree && !pspr->m_fHidden)
  285.       {
  286.       SelectObject(g_hdcMem, m_hbmp);
  287.       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);
  288.       }
  289.     }
  290.   SelectObject(g_hdcMem, g_hbmpStock);
  291. }
  292.  
  293.  
  294. //---------------------------------------------------------------------------
  295. // Paint any sprites with fNeedRefresh set.
  296. //---------------------------------------------------------------------------
  297. void CDisplay::Refresh
  298. (
  299.   void
  300. )
  301. {
  302.   CSprite *pspr;
  303.   HDC       hdc = m_hdc;
  304.  
  305.   for (pspr=m_psprLast; pspr; pspr=pspr->m_psprPrev)
  306.     {
  307.     if (pspr->m_fNeedRefresh && !pspr->m_fHidden)
  308.       {
  309.       pspr->m_fNeedRefresh = FALSE;
  310.       SelectObject(g_hdcMem, m_hbmp);
  311.       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);
  312.       }
  313.     }
  314.   SelectObject(g_hdcMem, g_hbmpStock);
  315. }
  316.  
  317.  
  318. //---------------------------------------------------------------------------
  319. //
  320. //---------------------------------------------------------------------------
  321. void CDisplay::SetBackColor
  322. (
  323.   COLORREF c
  324. )
  325. {
  326.   static LOGBRUSH lb = {BS_SOLID, 0x00c0c0c0, 0};
  327.  
  328.   if (m_colorBack == c)
  329.     return;
  330.   m_colorBack = c;
  331.   lb.lbColor = c;
  332.   if (m_hbrushBack)
  333.     DeleteObject(m_hbrushBack);
  334.   m_hbrushBack = CreateBrushIndirect(&lb);
  335. }
  336.  
  337.  
  338. //---------------------------------------------------------------------------
  339. // Send Collide event back to the fn passed into the constructor.
  340. //---------------------------------------------------------------------------
  341. void CDisplay::FireCollide
  342. (
  343.   CSprite *psprLowId,
  344.   CSprite *psprHighId,
  345.   int      maskCollide
  346. )
  347. {
  348.   (*m_pfnCollide)(psprLowId, psprHighId, maskCollide);
  349. }
  350.  
  351.  
  352. //***************************************************************************
  353. //***************************************************************************
  354. //**
  355. //**  SpriteClass Class
  356. //**
  357. //***************************************************************************
  358. //***************************************************************************
  359.  
  360. HRESULT s_hr = S_OK;
  361.  
  362.  
  363. //---------------------------------------------------------------------------
  364. // Create function for SpriteClass.  Use instead of "new CSpriteClass".
  365. //---------------------------------------------------------------------------
  366. HRESULT CSpriteClass::Create
  367. (
  368.   CDisplay      *pdisp,
  369.   CSpriteClass **ppscOut
  370. )
  371. {
  372.   if (!ppscOut)
  373.     return E_INVALIDARG;
  374.  
  375.   *ppscOut = new CSpriteClass(pdisp);
  376.   if (!*ppscOut)
  377.     return E_OUTOFMEMORY;
  378.  
  379.   return S_OK;
  380. }
  381.  
  382.  
  383. //---------------------------------------------------------------------------
  384. // Constructor for SpriteClass
  385. //---------------------------------------------------------------------------
  386. CSpriteClass::CSpriteClass
  387. (
  388.   CDisplay *pdisp
  389. )
  390. {
  391.   INIT_SIGNATURE(SIG_SpriteClass);
  392.  
  393.   m_id              = ++(pdisp->m_csc);
  394.   m_pdisp           = pdisp;
  395.   m_brd             = SPR_brdALL;
  396.   m_maskCollide     = 0;
  397.   m_iimg            = 0;
  398.   m_cspr            = 0;
  399.   m_cref            = 1;
  400.   m_pdispBaseObject = NULL;
  401.   VariantInit(&m_varTag);
  402.   m_friction        = (FLOAT)1.0;
  403.   m_frictionAccel   = (FLOAT)1.0;
  404.   m_fFrictionAccel  = FALSE;
  405.   m_vFullMax    = 0x000a0000;
  406.   m_aFullMax    = 0x00010000;
  407. }
  408.  
  409.  
  410. //---------------------------------------------------------------------------
  411. // Destructor for Sprite
  412. //---------------------------------------------------------------------------
  413. void CSpriteClass::Close
  414. (
  415.   void
  416. )
  417. {
  418.   CHECK_SIGNATURE(SIG_SpriteClass);
  419.  
  420.   CSprite *pspr;
  421.   CSprite *psprPrev;
  422.  
  423.   // Destroy all sprites of this SpriteClass
  424.   for (pspr=m_pdisp->m_psprLast; pspr; pspr=psprPrev)
  425.     {
  426.     psprPrev = pspr->m_psprPrev;
  427.  
  428.     if (pspr->m_psc == this)
  429.       {
  430.       pspr->_Unlink(FALSE);
  431.       pspr->m_psc = NULL;
  432.       pspr->Release();
  433.       }
  434.     }
  435.  
  436.   // Unadvise all event sinks
  437.   m_cp.Close();
  438.  
  439.   // Clear incase this is an object
  440.   VariantClear(&m_varTag);
  441. }
  442.  
  443.  
  444. //---------------------------------------------------------------------------
  445. // Destructor for Sprite
  446. //---------------------------------------------------------------------------
  447. CSpriteClass::~CSpriteClass
  448. (
  449.   void
  450. )
  451. {
  452.   CHECK_SIGNATURE(SIG_SpriteClass);
  453.   this->Close();
  454.   DESTROY_SIGNATURE(SIG_SpriteClass);
  455. }
  456.  
  457.  
  458. //***************************************************************************
  459. // IUnknown Interface
  460. //***************************************************************************
  461.  
  462. //---------------------------------------------------------------------------
  463. // 
  464. //---------------------------------------------------------------------------
  465. STDMETHODIMP CSpriteClass::QueryInterface
  466. (
  467.   REFIID  iid,
  468.   LPVOID* ppvObjOut
  469. )
  470. {
  471.   if (!ppvObjOut)
  472.     return E_INVALIDARG;
  473.  
  474.   *ppvObjOut = NULL;
  475.  
  476.   if (iid == IID_IUnknown)
  477.     *ppvObjOut = this->GetUnknown();
  478.   else if (iid == IID_IDispatch)
  479.     *ppvObjOut = this->GetDispatch();
  480.   else if (iid == IID_ISpriteClass)
  481.     *ppvObjOut = (ISpriteClass *)this;
  482.   else if (iid == IID_IConnectionPointContainer)
  483.     *ppvObjOut = (IConnectionPointContainer *)this;
  484.   else if (iid == IID_IProvideClassInfo)
  485.     *ppvObjOut = (IProvideClassInfo *)this;
  486.  
  487.   if (*ppvObjOut)
  488.     {
  489.     this->AddRef();
  490.     return S_OK;
  491.     }
  492.  
  493.   return E_NOINTERFACE;
  494. }
  495.  
  496.  
  497. //---------------------------------------------------------------------------
  498. // 
  499. //---------------------------------------------------------------------------
  500. STDMETHODIMP_(ULONG) CSpriteClass::AddRef
  501. (
  502.   void 
  503. )
  504. {
  505.   return ++m_cref;
  506. }
  507.  
  508.  
  509. //---------------------------------------------------------------------------
  510. // 
  511. //---------------------------------------------------------------------------
  512. STDMETHODIMP_(ULONG) CSpriteClass::Release
  513. (
  514.   void 
  515. )
  516. {
  517.   ASSERT(m_cref, "bad m_cref");
  518.   m_cref--;
  519.   if (!m_cref)
  520.     {
  521.     this->Close();
  522.     if (!m_cref && !m_cp.m_cref)
  523.       {
  524.       delete this;
  525.       return 0;
  526.       }
  527.     }
  528.   return m_cref;
  529. }
  530.  
  531.  
  532. //***************************************************************************
  533. // IDispatch Interface
  534. //***************************************************************************
  535.  
  536. //---------------------------------------------------------------------------
  537. // Method needed by COleAuto, so it can implement IDispatch for us.
  538. //---------------------------------------------------------------------------
  539. HRESULT CSpriteClass::GetTypeLibInfo
  540. (
  541.   HINSTANCE    *phinstOut,
  542.   const GUID  **pplibidOut, 
  543.   SHORT        *pwMajLib, 
  544.   SHORT        *pwMinLib,
  545.   const CLSID **ppclsidOut, 
  546.   const IID   **ppiidOut, 
  547.   ITypeLib   ***ppptlOut
  548. )
  549. {
  550.   *phinstOut  = g_hinst;
  551.   *pplibidOut = &LIBID_SPRUUIDS;
  552.   *pwMajLib   = 1;
  553.   *pwMinLib   = 0;
  554.   *ppclsidOut = &CLSID_SpriteClass;
  555.   *ppiidOut   = &IID_ISpriteClass;
  556.   *ppptlOut   = &g_ptlMain;
  557.   return S_OK;
  558. }
  559.  
  560.  
  561. //***************************************************************************
  562. // IProvideClassInfo Interface
  563. //***************************************************************************
  564.  
  565. //---------------------------------------------------------------------------
  566. // 
  567. //---------------------------------------------------------------------------
  568. STDMETHODIMP CSpriteClass::GetClassInfo
  569. (
  570.   ITypeInfo** pptinfoOut
  571. )
  572. {
  573.   HRESULT hr = ((COleAuto *)this)->CheckTypeInfo(0, 0x0409);
  574.   if (hr)
  575.     return hr;
  576.   *pptinfoOut = g_ptinfoClsSpriteClass;
  577.   (*pptinfoOut)->AddRef();
  578.   return S_OK;
  579. }
  580.  
  581.  
  582. //---------------------------------------------------------------------------
  583. // 
  584. //---------------------------------------------------------------------------
  585. STDMETHODIMP CSpriteClass::GetGUID
  586. (
  587.   DWORD dwGuidKind,
  588.   GUID* pGUID
  589. )
  590. {
  591.   if (pGUID)
  592.     return E_INVALIDARG;
  593.  
  594.   if (dwGuidKind != GUIDKIND_DEFAULT_SOURCE_DISP_IID)
  595.     return E_INVALIDARG;
  596.  
  597.   *pGUID = DIID_ISpriteClassEvents;
  598.   return S_OK;
  599. }
  600.  
  601.  
  602. //***************************************************************************
  603. // IConnectionPointContainer Interface
  604. //***************************************************************************
  605.  
  606. //---------------------------------------------------------------------------
  607. // 
  608. //---------------------------------------------------------------------------
  609. STDMETHODIMP CSpriteClass::EnumConnectionPoints
  610. (
  611.   LPENUMCONNECTIONPOINTS* ppEnum
  612. )
  613. {
  614.   return E_NOTIMPL;   // UNDONE: Implement this method
  615. }
  616.  
  617.  
  618. //---------------------------------------------------------------------------
  619. // 
  620. //---------------------------------------------------------------------------
  621. STDMETHODIMP CSpriteClass::FindConnectionPoint
  622. (
  623.   REFIID             iid,
  624.   LPCONNECTIONPOINT* ppCpOut
  625. )
  626. {
  627.   if (!ppCpOut)
  628.     return E_INVALIDARG;
  629.  
  630.   if (iid == DIID_ISpriteClassEvents || iid == IID_IDispatch)
  631.     {
  632.     *ppCpOut = &m_cp;
  633.     (*ppCpOut)->AddRef();
  634.     return S_OK;
  635.     }
  636.     
  637.   return E_NOINTERFACE;
  638. }
  639.  
  640.  
  641. //***************************************************************************
  642. // Embedded IConnectionPoint Class
  643. //***************************************************************************
  644.  
  645. //---------------------------------------------------------------------------
  646. // 
  647. //---------------------------------------------------------------------------
  648. CSpriteClass::XCP::XCP
  649. (
  650.   void
  651. )
  652. {
  653.   m_cref = 1;
  654.   for (int i=0; i<SC_cADVISE; i++)
  655.     m_rgpdisp[i] = NULL;
  656. }
  657.  
  658.  
  659. //---------------------------------------------------------------------------
  660. // 
  661. //---------------------------------------------------------------------------
  662. void CSpriteClass::XCP::Close
  663. (
  664.   void
  665. )
  666. {
  667.   for (int i=0; i<SC_cADVISE; i++)
  668.     if (m_rgpdisp[i])
  669.       {
  670.       m_rgpdisp[i]->Release();
  671.       m_rgpdisp[i] = NULL;
  672.       }
  673. }
  674.  
  675.  
  676. //---------------------------------------------------------------------------
  677. // 
  678. //---------------------------------------------------------------------------
  679. STDMETHODIMP CSpriteClass::XCP::QueryInterface
  680. (
  681.   REFIID  iid,
  682.   LPVOID* ppvObjOut
  683. )
  684. {
  685.   if (!ppvObjOut)
  686.     return E_INVALIDARG;
  687.  
  688.   *ppvObjOut = NULL;
  689.  
  690.   if (iid == IID_IUnknown)
  691.     *ppvObjOut = this->GetUnknown();
  692.   else if (iid == IID_IConnectionPoint)
  693.     *ppvObjOut = (IConnectionPoint *)this;
  694.  
  695.   if (*ppvObjOut)
  696.     {
  697.     this->AddRef();
  698.     return S_OK;
  699.     }
  700.  
  701.   return E_NOINTERFACE;
  702. }
  703.  
  704.  
  705. //---------------------------------------------------------------------------
  706. // 
  707. //---------------------------------------------------------------------------
  708. STDMETHODIMP_(ULONG) CSpriteClass::XCP::AddRef
  709. (
  710.   void 
  711. )
  712. {
  713.   return ++m_cref;
  714. }
  715.  
  716.  
  717. #define SCOFCP(pcp)  ((CSpriteClass *)((char *)pcp - (char *)&(((CSpriteClass *)0)->m_cp)))
  718. //---------------------------------------------------------------------------
  719. // 
  720. //---------------------------------------------------------------------------
  721. STDMETHODIMP_(ULONG) CSpriteClass::XCP::Release
  722. (
  723.   void 
  724. )
  725. {
  726.   CSpriteClass *psc = SCOFCP(this);
  727.  
  728.   ASSERT(m_cref, "bad m_cref");
  729.   m_cref--;
  730.   if (!m_cref && !psc->m_cref)
  731.     {
  732.     delete psc;
  733.     return 0;
  734.     }
  735.   return m_cref;
  736. }
  737.  
  738.  
  739. //***************************************************************************
  740. // IConnectionPoint Interface
  741. //***************************************************************************
  742.  
  743. //---------------------------------------------------------------------------
  744. // 
  745. //---------------------------------------------------------------------------
  746. STDMETHODIMP CSpriteClass::XCP::GetConnectionInterface
  747. (
  748.   IID* piid
  749. )
  750. {
  751.   if (!piid)
  752.     return E_INVALIDARG;
  753.  
  754.   memcpy(piid, &DIID_ISpriteClassEvents, sizeof(IID));
  755.   return S_OK;
  756. }
  757.  
  758.  
  759. //---------------------------------------------------------------------------
  760. // 
  761. //---------------------------------------------------------------------------
  762. STDMETHODIMP CSpriteClass::XCP::GetConnectionPointContainer
  763. (
  764.   IConnectionPointContainer** ppCpcOut
  765. )
  766. {
  767.   if (!ppCpcOut)
  768.     return E_INVALIDARG;
  769.  
  770.   *ppCpcOut = SCOFCP(this);
  771.   (*ppCpcOut)->AddRef();
  772.   return S_OK;
  773. }
  774.  
  775.  
  776. //---------------------------------------------------------------------------
  777. // 
  778. //---------------------------------------------------------------------------
  779. STDMETHODIMP CSpriteClass::XCP::Advise
  780. (
  781.   IUnknown* punkSink,
  782.   DWORD*    pdwCookie
  783. )
  784. {
  785.   IDispatch  *psce = NULL;
  786.   IDispatch **ppdisp;
  787.   HRESULT     hr;
  788.  
  789.   if (!punkSink || !pdwCookie)
  790.     return E_INVALIDARG;
  791.   *pdwCookie = 0;
  792.  
  793.   // Look for empty slot
  794.   for (ppdisp=m_rgpdisp; *ppdisp && ppdisp<&m_rgpdisp[SC_cADVISE]; ppdisp++)
  795.     ;
  796.   // Did we find one?
  797.   if (ppdisp >= &m_rgpdisp[SC_cADVISE])
  798.     return E_FAIL;          // UNDONE: Error?
  799.  
  800.   // Now see if sink supports correct interface
  801.   hr = punkSink->QueryInterface(DIID_ISpriteClassEvents, (void **)&psce);
  802.   if (hr == E_NOINTERFACE)
  803.     {
  804.     hr = punkSink->QueryInterface(IID_IDispatch, (void **)&psce);
  805.     if (hr)
  806.       return hr;
  807.     }
  808.   ASSERT(psce, "QI but no ptr");
  809.  
  810.   // Finish advise by stashing punkSink QI'd to our interface
  811.   *ppdisp = psce;       // AddRef'd from QI
  812.   *pdwCookie = (ppdisp - m_rgpdisp) + 1;
  813.  
  814.   return S_OK;
  815. }
  816.  
  817.  
  818. //---------------------------------------------------------------------------
  819. // 
  820. //---------------------------------------------------------------------------
  821. STDMETHODIMP CSpriteClass::XCP::Unadvise
  822. (
  823.   DWORD dwCookie
  824. )
  825. {
  826.   if (!dwCookie || dwCookie > SC_cADVISE)
  827.     return E_INVALIDARG;
  828.  
  829.   m_rgpdisp[dwCookie-1]->Release();
  830.   m_rgpdisp[dwCookie-1] = NULL;
  831.   return S_OK;
  832. }
  833.  
  834.  
  835. //---------------------------------------------------------------------------
  836. // 
  837. //---------------------------------------------------------------------------
  838. STDMETHODIMP CSpriteClass::XCP::EnumConnections
  839. (
  840.   LPENUMCONNECTIONS* ppEnum
  841. )
  842. {
  843.   return E_NOTIMPL;   // UNDONE: Implement this method
  844. }
  845.  
  846.  
  847.  
  848. //***************************************************************************
  849. //***************************************************************************
  850. //**
  851. //**  Sprite Class
  852. //**
  853. //***************************************************************************
  854. //***************************************************************************
  855.  
  856. //---------------------------------------------------------------------------
  857. // Constructor for Sprite
  858. //---------------------------------------------------------------------------
  859. CSprite::CSprite
  860. (
  861.   CSpriteClass *psc,
  862.   int           x,
  863.   int           y,
  864.   CSprite      *psprPrev,      // NULL==1st, -1==Last
  865.   VARIANT      *pvarUser
  866. )
  867. {
  868.   INIT_SIGNATURE(SIG_Sprite);
  869.  
  870.   m_pdisp        = psc->m_pdisp;
  871.   m_psprNext     = NULL;
  872.   m_psprPrev     = psprPrev;
  873.   m_xFull        = 0;
  874.   m_x            = x;
  875.   m_yFull        = 0;
  876.   m_y            = y;
  877.   m_vxFull       = 0;
  878.   m_vyFull       = 0;
  879.   m_axFull       = 0;
  880.   m_ayFull       = 0;
  881.   m_fx           = psc->m_friction;
  882.   m_fy           = psc->m_friction;
  883.   m_fFriction    = (psc->m_friction != 1.0);
  884.   m_tickEvt      = 0x7fffffff;
  885.   m_tickEvtMax   = 0x7fffffff;
  886.   m_tickMove     = 1;
  887.   m_tickMoveMax  = 1;
  888.   m_iimg         = psc->m_iimg;
  889.   m_pimg         = &m_pdisp->m_prgimg[m_iimg];
  890.   m_psc          = psc;
  891.   m_fNeedRefresh = TRUE;
  892.   m_fFree        = FALSE;
  893.   m_fIgnoreMove  = FALSE;
  894.   m_fLinked      = FALSE;
  895.   m_fHidden      = 2;     // Set to 2 instead of TRUE to detect if user explicitly hides it during _Init event
  896.   m_cref         = 1;
  897.   m_psprAt       = NULL;
  898.   m_pdispBaseObject = NULL;
  899.   VariantInit(&m_varTag);
  900.   this->_Link();
  901.  
  902.   m_psc->FireInit(this, pvarUser);
  903.   if (m_fHidden == 2) 
  904.     m_fHidden = FALSE;    // If not explicitly hidden in event, show it
  905. }
  906.  
  907.  
  908. //---------------------------------------------------------------------------
  909. // Destructor for Sprite
  910. //---------------------------------------------------------------------------
  911. CSprite::~CSprite
  912. (
  913.   void
  914. )
  915. {
  916.   CHECK_SIGNATURE(SIG_Sprite);
  917.   VariantClear(&m_varTag);
  918.   if (m_psprAt)
  919.     {
  920.     m_psprAt->Release();
  921.     m_psprAt = NULL;
  922.     }
  923.   this->_Unlink(TRUE);
  924.   DESTROY_SIGNATURE(SIG_Sprite);
  925. }
  926.  
  927.  
  928. //---------------------------------------------------------------------------
  929. // Change the class of an existing pspr
  930. //---------------------------------------------------------------------------
  931. CSprite *CSprite::PsprMutate
  932. (
  933.   CSpriteClass *psc,
  934.   VARIANT      *pvarUser
  935. )
  936. {
  937.   m_x          += m_pimg->cx >> 1;
  938.   m_y          += m_pimg->cy >> 1;
  939.   m_iimg        = psc->m_iimg;
  940.   m_pimg        = &m_pdisp->m_prgimg[m_iimg];
  941.   m_x          -= m_pimg->cx >> 1;
  942.   m_y          -= m_pimg->cy >> 1;
  943.   m_psc->m_cspr--;
  944.   m_psc         = psc;
  945.   m_psc->m_cspr++;
  946.   m_tickEvt     = 0x7fffffff;
  947.   m_tickEvtMax  = 0x7fffffff;
  948.   m_tickMove    = 0;
  949.   m_tickMoveMax = 1;
  950.   m_fHidden     = 2;     // Set to 2 instead of TRUE to detect if user explicitly hides it during _Init event
  951.   
  952.   m_psc->FireInit(this, pvarUser);
  953.   if (m_fHidden == 2) 
  954.     m_fHidden = FALSE;    // If not explicitly hidden in event, show it
  955.   return this;
  956. }
  957.  
  958.  
  959. //---------------------------------------------------------------------------
  960. // Free a SPR structure
  961. //---------------------------------------------------------------------------
  962. void CSprite::MarkFree
  963. (
  964.   void
  965. )
  966. {
  967.   if (m_psprAt)
  968.     {
  969.     m_psprAt->Release();
  970.     m_psprAt = NULL;
  971.     }
  972.   m_psc->FireTerm(this);
  973.   m_fFree = TRUE;
  974. }
  975.  
  976.  
  977. //---------------------------------------------------------------------------
  978. // Link a sprite into the display list
  979. //---------------------------------------------------------------------------
  980. void CSprite::_Link
  981. (
  982.   void
  983. )
  984. {
  985.   if (!m_psprPrev)
  986.     {
  987.     m_psprNext = m_pdisp->m_psprFirst;
  988.     m_pdisp->m_psprFirst = this;
  989.     if (m_psprNext)
  990.       m_psprNext->m_psprPrev = this;
  991.     if (!m_pdisp->m_psprLast)
  992.       m_pdisp->m_psprLast = this;
  993.     }
  994.   else if (m_psprPrev == (CSprite *)-1)
  995.     {
  996.     m_psprNext = NULL;
  997.     m_psprPrev = m_pdisp->m_psprLast;
  998.     if (m_pdisp->m_psprLast)
  999.       m_pdisp->m_psprLast->m_psprNext = this;
  1000.     else
  1001.       m_pdisp->m_psprFirst = this;
  1002.     m_pdisp->m_psprLast = this;
  1003.     }
  1004.   else
  1005.     {
  1006.     // UNDONE: Fix this up.
  1007.     m_psprNext = m_pdisp->m_psprLast->m_psprNext;
  1008.     m_pdisp->m_psprLast->m_psprNext = this;
  1009.     m_psprNext->m_psprPrev = this;
  1010.     if (m_pdisp->m_psprLast == m_pdisp->m_psprLast)
  1011.       m_pdisp->m_psprLast = this;
  1012.     }
  1013.  
  1014.   m_fLinked = TRUE;
  1015.   m_psc->m_cspr++;
  1016.   //this->_FDraw(FALSE);      // Require "s.Refresh" to avoid spurious paint before img set
  1017. }
  1018.  
  1019.  
  1020. //---------------------------------------------------------------------------
  1021. // Unlink a sprite into the display list
  1022. //---------------------------------------------------------------------------
  1023. void CSprite::_Unlink
  1024. (
  1025.   BOOL fFireEvt
  1026. )
  1027. {
  1028.   if (!m_fLinked)
  1029.     return;
  1030.  
  1031.   this->_Erase();
  1032.  
  1033.   if (m_pdisp->m_psprFirst == this)
  1034.     m_pdisp->m_psprFirst = m_psprNext;
  1035.   if (m_pdisp->m_psprLast  == this)
  1036.     m_pdisp->m_psprLast  = m_psprPrev;
  1037.  
  1038.   if (m_psprPrev)
  1039.     m_psprPrev->m_psprNext = m_psprNext;
  1040.   if (m_psprNext)
  1041.     m_psprNext->m_psprPrev = m_psprPrev;
  1042.  
  1043.   m_fLinked = FALSE;
  1044.   m_fHidden = TRUE;
  1045.  
  1046.   // Track # of sprites of this kind.  If there are no more, then
  1047.   // fire the _LastTerm event.
  1048.   m_psc->m_cspr--;
  1049.   if (fFireEvt && !m_psc->m_cspr)
  1050.     m_psc->FireLastTerm();
  1051.  
  1052.   if (m_psprAt)
  1053.     {
  1054.     m_psprAt->Release();
  1055.     m_psprAt = NULL;
  1056.     }
  1057. }
  1058.  
  1059.  
  1060. //---------------------------------------------------------------------------
  1061. // Draw the given sprite
  1062. //---------------------------------------------------------------------------
  1063. BOOL CSprite::_FDraw
  1064. (
  1065.   BOOL    fCollide
  1066. )
  1067. {
  1068.   CSprite *psprT;
  1069.   CSprite *psprNext;
  1070.   int x   = m_x;
  1071.   int y   = m_y;
  1072.   int cx  = m_pimg->cx;
  1073.   int cy  = m_pimg->cy;
  1074.   HDC hdc = m_pdisp->m_hdc;
  1075.  
  1076.   if (fCollide && !m_fFree)
  1077.     {
  1078.     int maskCollide = m_psc->m_maskCollide;
  1079.  
  1080.     if (m_fHidden)
  1081.       goto DoneWithColl;
  1082.  
  1083.     for (psprT=m_pdisp->m_psprFirst; psprT; psprT=psprNext)
  1084.       {
  1085.       psprNext = psprT->m_psprNext;
  1086.       if (psprT != this &&                                    // Never collide w/self
  1087.           ((psprT->m_psc != m_psc) || (maskCollide & 1)) &&   // Coll w/like kind only if bit 1 set
  1088.           (maskCollide & psprT->m_psc->m_maskCollide & ~1) && // Coll w/other kinds only if masks overlap
  1089.           x <= psprT->m_x+psprT->m_pimg->cx && x+cx >= psprT->m_x && // Coll only if actually touch
  1090.           y <= psprT->m_y+psprT->m_pimg->cy && y+cy >= psprT->m_y)
  1091.         {
  1092.         m_fIgnoreMove = FALSE;
  1093.         if (m_psc->m_id <= psprT->m_psc->m_id)
  1094.           m_pdisp->FireCollide(this, psprT, maskCollide & psprT->m_psc->m_maskCollide);
  1095.         else
  1096.           m_pdisp->FireCollide(psprT, this, maskCollide & psprT->m_psc->m_maskCollide);
  1097.         if (m_fFree)
  1098.           return TRUE;
  1099.         if (m_fIgnoreMove)
  1100.           return FALSE;
  1101.         if (psprT->m_fFree)
  1102.           goto DoneWithColl;
  1103.         }
  1104.       }
  1105. DoneWithColl:;
  1106.     if ((m_psc->m_brd & SPR_brdALL))
  1107.       {
  1108.       BRD brd = 0;
  1109.       if (m_psc->m_brd & SPR_brdIN)
  1110.         {
  1111.         if (x < 0) brd    = SPR_brdINLEFT;
  1112.         if (y < 0) brd |= SPR_brdINTOP;
  1113.         if (x+cx > m_pdisp->m_cx) brd |= SPR_brdINRIGHT;
  1114.         if (y+cy > m_pdisp->m_cy) brd |= SPR_brdINBOTTOM;
  1115.         }
  1116.       if (m_psc->m_brd & SPR_brdOUT)
  1117.         {
  1118.         if (x+cx < 0) brd  = SPR_brdOUTLEFT;
  1119.         if (y+cy < 0) brd |= SPR_brdOUTTOP;
  1120.         if (x > m_pdisp->m_cx) brd |= SPR_brdOUTRIGHT;
  1121.         if (y > m_pdisp->m_cy) brd |= SPR_brdOUTBOTTOM;
  1122.         }
  1123.       if (brd)
  1124.         {
  1125.         m_fIgnoreMove = FALSE;
  1126.         m_psc->FireBorder(this, brd);
  1127.  
  1128.         if (m_fFree)
  1129.           return TRUE;
  1130.         if (m_fIgnoreMove)
  1131.           return FALSE;
  1132.         }
  1133.       }
  1134.     }
  1135.  
  1136.   // Don't draw if not visible
  1137.   if (m_fHidden)
  1138.     return TRUE;
  1139.  
  1140.   SelectObject(g_hdcMem, m_pdisp->m_hbmp);
  1141.   BitBlt(hdc, m_x, m_y, cx, cy, g_hdcMem, m_pimg->x, m_pimg->y, SRCCOPY);
  1142.   m_fNeedRefresh = FALSE;
  1143.   for (psprT=m_psprPrev; psprT; psprT=psprT->m_psprPrev)
  1144.     {
  1145.     if (!psprT->m_fNeedRefresh &&
  1146.         x <= psprT->m_x+psprT->m_pimg->cx && x+cx >= psprT->m_x &&
  1147.         y <= psprT->m_y+psprT->m_pimg->cy && y+cy >= psprT->m_y)
  1148.       {
  1149.       psprT->m_fNeedRefresh = TRUE;
  1150.       }
  1151.     }
  1152.   SelectObject(g_hdcMem, g_hbmpStock);
  1153.   return TRUE;
  1154. }
  1155.  
  1156.  
  1157. //---------------------------------------------------------------------------
  1158. // Erase the given sprite
  1159. //---------------------------------------------------------------------------
  1160. void CSprite::_Erase
  1161. (
  1162.   void
  1163. )
  1164. {
  1165.   int      x   = m_x;
  1166.   int      y   = m_y;
  1167.   int      cx  = m_pimg->cx;
  1168.   int      cy  = m_pimg->cy;
  1169.   HDC      hdc = m_pdisp->m_hdc;
  1170.   CSprite *psprT;
  1171.  
  1172.   SelectObject(hdc, (HGDIOBJ)(m_pdisp->m_hbrushBack ? m_pdisp->m_hbrushBack : g_hbrushStock));
  1173.   PatBlt(hdc, m_x, m_y, cx, cy, PATCOPY);
  1174.   for (psprT=m_pdisp->m_psprLast; psprT; psprT=psprT->m_psprPrev)
  1175.     {
  1176.     if (psprT != this && !psprT->m_fNeedRefresh &&
  1177.         x <= psprT->m_x+psprT->m_pimg->cx && x+cx >= psprT->m_x &&
  1178.         y <= psprT->m_y+psprT->m_pimg->cy && y+cy >= psprT->m_y)
  1179.       psprT->m_fNeedRefresh = TRUE;
  1180.     }
  1181.   SelectObject(g_hdcMem, g_hbrushStock);
  1182. }
  1183.  
  1184.  
  1185. //---------------------------------------------------------------------------
  1186. // Move the given sprite to new location
  1187. //---------------------------------------------------------------------------
  1188. BOOL CSprite::MoveToFull
  1189. (
  1190.   long    xFull,
  1191.   long    yFull,
  1192.   BOOL    fCollide
  1193. )
  1194. {
  1195.   long xOldFull = m_xFull;
  1196.   long yOldFull = m_yFull;
  1197.  
  1198.   this->_Erase();
  1199.   m_xFull = xFull;
  1200.   m_yFull = yFull;
  1201.   if (m_pimg->iimgNext == iimgREMOVE)
  1202.     this->Remove();
  1203.   else if (m_pimg->iimgNext != iimgNONE)
  1204.     {
  1205.     m_iimg = m_pimg->iimgNext;
  1206.     m_pimg = m_pimg->pimgNext;
  1207.     }
  1208.   if (!this->_FDraw(fCollide))
  1209.     {
  1210.     m_xFull = xOldFull;
  1211.     m_yFull = yOldFull;
  1212.     this->_FDraw(FALSE);
  1213.     return FALSE;
  1214.     }
  1215.   return TRUE;
  1216. }
  1217.  
  1218.  
  1219. //---------------------------------------------------------------------------
  1220. // Move the given sprite to new location
  1221. //---------------------------------------------------------------------------
  1222. BOOL CSprite::MoveByFull
  1223. (
  1224.   long    dxFull,
  1225.   long    dyFull,
  1226.   BOOL    fCollide
  1227. )
  1228. {
  1229.   long xOldFull = m_xFull;
  1230.   long yOldFull = m_yFull;
  1231.  
  1232.   if (HIWORD(xOldFull + dxFull) == HIWORD(xOldFull) &&
  1233.       HIWORD(yOldFull + dyFull) == HIWORD(yOldFull))
  1234.     {
  1235.     m_xFull += dxFull;
  1236.     m_yFull += dyFull;
  1237.     return TRUE;
  1238.     }
  1239.  
  1240.   this->_Erase();
  1241.   m_xFull += dxFull;
  1242.   m_yFull += dyFull;
  1243.   if (m_pimg->iimgNext == iimgREMOVE)
  1244.     this->Remove();
  1245.   else if (m_pimg->iimgNext != iimgNONE)
  1246.     {
  1247.     m_iimg = m_pimg->iimgNext;
  1248.     m_pimg = m_pimg->pimgNext;
  1249.     }
  1250.  
  1251.   if (!this->_FDraw(fCollide))
  1252.     {
  1253.     m_xFull = xOldFull;
  1254.     m_yFull = yOldFull;
  1255.     this->_FDraw(FALSE);
  1256.     return FALSE;
  1257.     }
  1258.   return TRUE;
  1259. }
  1260.  
  1261.  
  1262. //---------------------------------------------------------------------------
  1263. // flags: 1=X, 2=Y;
  1264. //        4=Pos, 8=Vel, 16=Accel;
  1265. //        32=Less With Distance (default=More);
  1266. //        128=Remember
  1267. //---------------------------------------------------------------------------
  1268. BOOL CSprite::DoMoveAt
  1269. (
  1270.   CSprite *psprAt,
  1271.   float    scale,
  1272.   float    dMax,
  1273.   long     flags,
  1274.   BOOL     fCollide
  1275. )
  1276.   {
  1277.   long dx = psprAt->m_xFull - m_xFull;
  1278.   long dy = psprAt->m_yFull - m_yFull;
  1279.  
  1280.   if (flags & MAS_RECIPDIST)
  1281.     {
  1282.     dx = FULLOFFLOAT((FLOAT)1.0 / FLOATOFFULL(dx | 0xffff));
  1283.     dy = FULLOFFLOAT((FLOAT)1.0 / FLOATOFFULL(dy | 0xffff));
  1284.     }
  1285.  
  1286.   float d = FLOATOFFULL(dx) * scale;
  1287.   if (d > dMax)
  1288.     d = dMax;
  1289.   else if (d < -dMax)
  1290.     d = -dMax;
  1291.   dx = FULLOFFLOAT(d);
  1292.   d = FLOATOFFULL(dy) * scale;
  1293.   if (d > dMax)
  1294.     d = dMax;
  1295.   else if (d < -dMax)
  1296.     d = -dMax;
  1297.   dy = FULLOFFLOAT(d);
  1298.  
  1299.   if (flags & MAS_X)
  1300.     {
  1301.     if (flags & MAS_VEL)
  1302.       {
  1303.       m_vxFull += dx;
  1304.       if (m_vxFull > m_psc->m_vFullMax)
  1305.         m_vxFull = m_psc->m_vFullMax;
  1306.       else if (m_vxFull < -m_psc->m_vFullMax)
  1307.         m_vxFull = -m_psc->m_vFullMax;
  1308.       }
  1309.     if (flags & MAS_ACCEL)
  1310.       {
  1311.       m_axFull += dx;
  1312.       if (m_axFull > m_psc->m_aFullMax)
  1313.         m_axFull = m_psc->m_aFullMax;
  1314.       else if (m_axFull < -m_psc->m_aFullMax)
  1315.         m_axFull = -m_psc->m_aFullMax;
  1316.       }
  1317.     if (!(flags & MAS_POS))
  1318.       dx = 0;
  1319.     }
  1320.   else 
  1321.     dx = 0;
  1322.  
  1323.   if (flags & MAS_Y)
  1324.     {
  1325.     if (flags & MAS_VEL)
  1326.       {
  1327.       m_vyFull += dy;
  1328.       if (m_vyFull > m_psc->m_vFullMax)
  1329.         m_vyFull = m_psc->m_vFullMax;
  1330.       else if (m_vyFull < -m_psc->m_vFullMax)
  1331.         m_vyFull = -m_psc->m_vFullMax;
  1332.       }
  1333.     if (flags & MAS_ACCEL)
  1334.       {
  1335.       m_ayFull += dy;
  1336.       if (m_ayFull > m_psc->m_aFullMax)
  1337.         m_ayFull = m_psc->m_aFullMax;
  1338.       else if (m_ayFull < -m_psc->m_aFullMax)
  1339.         m_ayFull = -m_psc->m_aFullMax;
  1340.       }
  1341.     if (!(flags & MAS_POS))
  1342.       dy = 0;
  1343.     }
  1344.   else 
  1345.     dy = 0;
  1346.  
  1347.   if (dx || dy)
  1348.     return this->MoveByFull(dx, dy, fCollide);
  1349.  
  1350.   return TRUE;
  1351.   }
  1352.  
  1353.  
  1354. //***************************************************************************
  1355. // IUnknown Interface
  1356. //***************************************************************************
  1357.  
  1358. //---------------------------------------------------------------------------
  1359. // 
  1360. //---------------------------------------------------------------------------
  1361. STDMETHODIMP CSprite::QueryInterface
  1362. (
  1363.   REFIID  iid,
  1364.   LPVOID* ppvObjOut
  1365. )
  1366. {
  1367.   if (!ppvObjOut)
  1368.     return E_INVALIDARG;
  1369.  
  1370.   *ppvObjOut = NULL;
  1371.  
  1372.   if (iid == IID_IUnknown)
  1373.     *ppvObjOut = this->GetUnknown();
  1374.   else if (iid == IID_IDispatch)
  1375.     *ppvObjOut = this->GetDispatch();
  1376.   else if (iid == IID_ISprite)
  1377.     *ppvObjOut = (ISprite *)this;
  1378.  
  1379.   if (*ppvObjOut)
  1380.     {
  1381.     this->AddRef();
  1382.     return S_OK;
  1383.     }
  1384.  
  1385.   return E_NOINTERFACE;
  1386. }
  1387.  
  1388.  
  1389. //---------------------------------------------------------------------------
  1390. // 
  1391. //---------------------------------------------------------------------------
  1392. STDMETHODIMP_(ULONG) CSprite::AddRef
  1393. (
  1394.   void 
  1395. )
  1396. {
  1397.   return ++m_cref;
  1398. }
  1399.  
  1400.  
  1401. //---------------------------------------------------------------------------
  1402. // 
  1403. //---------------------------------------------------------------------------
  1404. STDMETHODIMP_(ULONG) CSprite::Release
  1405. (
  1406.   void 
  1407. )
  1408. {
  1409.   ASSERT(m_cref, "bad m_cref");
  1410.   m_cref--;
  1411.   if (!m_cref)
  1412.     {
  1413.     delete this;
  1414.     return 0;
  1415.     }
  1416.   return m_cref;
  1417. }
  1418.  
  1419.  
  1420. //***************************************************************************
  1421. // IDispatch Interface
  1422. //***************************************************************************
  1423.  
  1424. //---------------------------------------------------------------------------
  1425. // Method needed by COleAuto, so it can implement IDispatch for us.
  1426. //---------------------------------------------------------------------------
  1427. HRESULT CSprite::GetTypeLibInfo
  1428. (
  1429.   HINSTANCE    *phinstOut,
  1430.   const GUID  **pplibidOut, 
  1431.   SHORT        *pwMajLib, 
  1432.   SHORT        *pwMinLib,
  1433.   const CLSID **ppclsidOut, 
  1434.   const IID   **ppiidOut, 
  1435.   ITypeLib   ***ppptlOut
  1436. )
  1437. {
  1438.   *phinstOut  = g_hinst;
  1439.   *pplibidOut = &LIBID_SPRUUIDS;
  1440.   *pwMajLib   = 1;
  1441.   *pwMinLib   = 0;
  1442.   *ppclsidOut = &CLSID_Sprite;
  1443.   *ppiidOut   = &IID_ISprite;
  1444.   *ppptlOut   = &g_ptlMain;
  1445.   return S_OK;
  1446. }
  1447.  
  1448. //--- EOF -------------------------------------------------------------------
  1449.  
  1450.  
  1451.