home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 1996 December / PCWKCD1296.iso / vjplusb / activex / inetsdk / samples / axscript / spruuids / src / spr.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-15  |  36.9 KB  |  1,450 lines

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