SPR.H

//--------------------------------------------------------------------------- 
// Spr.h
//---------------------------------------------------------------------------
// Sprite handler
//---------------------------------------------------------------------------
// (C) Copyright 1992-1997 by Microsoft Corporation. All rights reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
// Constants
//---------------------------------------------------------------------------
#define SPR_brdINLEFT 0x0001
#define SPR_brdINTOP 0x0002
#define SPR_brdINRIGHT 0x0004
#define SPR_brdINBOTTOM 0x0008
#define SPR_brdIN 0x000F
#define SPR_brdOUTLEFT 0x0010
#define SPR_brdOUTTOP 0x0020
#define SPR_brdOUTRIGHT 0x0040
#define SPR_brdOUTBOTTOM 0x0080
#define SPR_brdOUT 0x00F0
#define SPR_brdALL 0x00FF
#define SPR_brdLEFT 0x0011
#define SPR_brdTOP 0x0022
#define SPR_brdRIGHT 0x0044
#define SPR_brdBOTTOM 0x0088

#define MAS_X 0x0001
#define MAS_Y 0x0002
#define MAS_POS 0x0004
#define MAS_VEL 0x0008
#define MAS_ACCEL 0x0010
#define MAS_RECIPDIST 0x0020
#define MAS_REMEMBER 0x0080


//---------------------------------------------------------------------------
// Macros
//---------------------------------------------------------------------------
#define tickOFSEC(sec) ((int)(20*(sec)))
#define PuserDEREF(type, pspr) ((type)((pspr)->m_bUser))
#define SPRITEOFI(psprite) ((CSprite *)(void *)(psprite))


//---------------------------------------------------------------------------
// Typedefs
//---------------------------------------------------------------------------
class CDisplay;
class CSpriteClass;
class CSprite;
typedef UINT BRD;
typedef WORD IDBMP;
typedef struct tagIMG *PIMG;
typedef void (*PFNCOLLIDE)(CSprite *, CSprite *, int);
#define FLOAT float
#define FULLOFFLOAT(r8) ((long)((r8) * (FLOAT)0x10000))
#define FLOATOFFULL(i4) ((FLOAT)(i4) / (FLOAT)0x10000)
#define FIXED(full, sub, super) \
union \
{ \
long full; \
struct \
{ \
USHORT sub; \
SHORT super; \
}; \
}


//---------------------------------------------------------------------------
// Image description
//---------------------------------------------------------------------------
typedef struct tagIMG
{
int iimgNext;
int x, y;
int cx, cy;
PIMG pimgNext;
} IMG;
#define iimgNONE (-1)
#define iimgREMOVE (-2)


//---------------------------------------------------------------------------
// Display surface for sprites
//---------------------------------------------------------------------------
class CDisplay
{
friend class CSprite;
friend class CSpriteClass;

public:
CDisplay(HINSTANCE hinst, HWND hwnd, HDC hdc, IUnknown *pparent, PFNCOLLIDE pfncollide, int cimg, PIMG prgimg, UINT idbmp);
~CDisplay(void);

void DestroyAll(void);
void Timer(void);
void Paint(HDC hdc);
void Refresh(void);
void SetBackColor(COLORREF c);
void FireCollide(CSprite *psprLowId, CSprite *psprHighId, int);

HINSTANCE m_hinst;
HWND m_hwnd;
HDC m_hdc;
int m_cx, m_cy;
PFNCOLLIDE m_pfnCollide; // Routine to handle spr collisions
CSprite *m_psprFirst;
CSprite *m_psprLast;
IUnknown *m_punkParent; // For get_Parent() on SpriteClass
COLORREF m_colorBack;
HBRUSH m_hbrushBack;

protected:
int m_cimg;
int m_csc;
PIMG m_prgimg;
IDBMP m_idbmp;
HBITMAP m_hbmp;

// DEBUG info
#define SIG_Display 'Disp'
DECLARE_SIGNATURE(SIG_Display);
};


//---------------------------------------------------------------------------
// Class description of different types of sprites
//---------------------------------------------------------------------------
class CSpriteClass : public ISpriteClass, public COleAuto,
public IProvideClassInfo, public IConnectionPointContainer
{
friend class CDisplay;
friend class CSprite;

public:
// *** Constructor/Destructor methods ***
static HRESULT Create(CDisplay *pdisp, CSpriteClass **ppscOut);
CSpriteClass(CDisplay *pdisp);
~CSpriteClass(void);
void Close(void);

// *** Event methods ***
void FireInit( CSprite *pspr, VARIANT *pvarUser);
void FireTick( CSprite *pspr);
void FireBorder(CSprite *pspr, BRD brd);
void FireTerm( CSprite *pspr);
void FireLastTerm(void);

// *** IUnknown methods ***
STDMETHOD(QueryInterface)(REFIID iid, void** ppvObjOut);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
inline IUnknown *GetUnknown(void) {return (ISpriteClass *)this;};
inline IDispatch *GetDispatch(void) {return (ISpriteClass *)this;};

// *** IDispatch methods ***
DECLARE_STANDARD_DISPATCH();
// Override required by COleAuto:
virtual ITypeInfo **GetTinfoClsAddr(void) { return &g_ptinfoClsSpriteClass; };
virtual ITypeInfo **GetTinfoIntAddr(void) { return &g_ptinfoIntSpriteClass; };
virtual HRESULT GetTypeLibInfo(HINSTANCE *phinstOut, const GUID **pplibidOut,
SHORT *pwMajLibOut, SHORT *pwMinLibOut,
const CLSID **ppclsidOut, const IID **ppiidOut,
ITypeLib ***ppptlOut);
virtual IDispatch *GetPrimary() {return this->GetDispatch(); };

// *** ISpriteClass methods ***
STDMETHOD(get_Application)(ISpruuidsApp** ppRet);
STDMETHOD(get_Parent)(IGame** ppRet);
STDMETHOD(CreateSprite)(int x, int y, VARIANT arg, ISprite** ppRet);
STDMETHOD(get_Tag)(VARIANT* pRet);
STDMETHOD(put_Tag)(VARIANT val);
STDMETHOD(get_Image)(int* pRet);
STDMETHOD(put_Image)(int val);
STDMETHOD(get_Border)(int* pRet);
STDMETHOD(put_Border)(int val);
STDMETHOD(get_Collide)(int* pRet);
STDMETHOD(put_Collide)(int val);
STDMETHOD(get_MaximumVelocity)(float* pRet);
STDMETHOD(put_MaximumVelocity)(float val);
STDMETHOD(get_Friction)(float* pRet);
STDMETHOD(put_Friction)(float val);
STDMETHOD(get_MaximumAcceleration)(float* pRet);
STDMETHOD(put_MaximumAcceleration)(float val);
STDMETHOD(get_AccelerationFriction)(float* pRet);
STDMETHOD(put_AccelerationFriction)(float val);
STDMETHOD(get_SpriteCount)(int* pRet);

// *** IProvideClassInfo methods ***
STDMETHOD(GetClassInfo)(ITypeInfo** pptinfoOut);
// *** IProvideClassInfo2 methods ***
STDMETHOD(GetGUID)(DWORD dwGuidKind, GUID* pGUID);

// *** IConnectionPointContainer methods ***
STDMETHOD(EnumConnectionPoints)(LPENUMCONNECTIONPOINTS* ppEnum);
STDMETHOD(FindConnectionPoint)(REFIID iid, LPCONNECTIONPOINT* ppCP);

class XCP : public IConnectionPoint
{
public:
XCP();
void Close(void);

// *** IUnknown methods ***
STDMETHOD(QueryInterface)(REFIID iid, void** ppvObjOut);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
inline IUnknown *GetUnknown(void) {return (IConnectionPoint *)this;};

// *** IConnectionPoint methods ***
STDMETHOD(GetConnectionInterface)(IID* piid);
STDMETHOD(GetConnectionPointContainer)(IConnectionPointContainer** ppCPC);
STDMETHOD(Advise)(IUnknown* punkSink, DWORD* pdwCookie);
STDMETHOD(Unadvise)(DWORD dwCookie);
STDMETHOD(EnumConnections)(LPENUMCONNECTIONS* ppEnum);

// *** Member Variables ***
ULONG m_cref;
#define SC_cADVISE 5
IDispatch *m_rgpdisp[SC_cADVISE]; // Array of pdisps to call.
} m_cp;

// *** Member Variables ***
CDisplay *m_pdisp;
int m_id;
int m_brd; // Mask indicates which borders to check collision with
int m_maskCollide; // Mask indicates which other sprites can collide with
int m_iimg;
int m_cspr;
VARIANT m_varTag;
FLOAT m_friction;
FLOAT m_frictionAccel;
BOOL m_fFrictionAccel;
ULONG m_cref;
FIXED( m_vFullMax, m_vSubMax, m_vMax);
FIXED( m_aFullMax, m_aSubMax, m_aMax);

private:
// DEBUG info
static HRESULT s_hr;
#define SIG_SpriteClass 'SCls'
DECLARE_SIGNATURE(SIG_SpriteClass);
};


//---------------------------------------------------------------------------
// Definition of sprite
//---------------------------------------------------------------------------
class CSprite : ISprite, COleAuto
{
friend class CDisplay;
friend class CSpriteClass;

public:
// *** Constructor/Destructor methods ***
CSprite(CSpriteClass *psc, int x, int y, CSprite *psprPrev, VARIANT *pvarUser);
~CSprite();

// *** General Routines ***
CSprite *PsprMutate(CSpriteClass *psc, VARIANT *pvarUser);
void MarkFree();
BOOL MoveToFull(long xFull, long yFull, BOOL fCollide);
BOOL MoveByFull(long dxFull, long dyFull, BOOL fCollide);
BOOL DoMoveAt(CSprite *psprAt, float dMax, float scale, long flags, BOOL fCollide);

// *** IUnknown methods ***
STDMETHOD(QueryInterface)(REFIID riid, void** ppvObj);
STDMETHOD_(ULONG, AddRef)(void);
STDMETHOD_(ULONG, Release)(void);
inline IUnknown *GetUnknown(void) {return (ISprite *)this;};
inline IDispatch *GetDispatch(void) {return (ISprite *)this;};

// *** IDispatch methods ***
DECLARE_STANDARD_DISPATCH();
// Override required by COleAuto:
virtual ITypeInfo **GetTinfoClsAddr(void) { return &g_ptinfoClsSprite; };
virtual ITypeInfo **GetTinfoIntAddr(void) { return &g_ptinfoIntSprite; };
virtual HRESULT GetTypeLibInfo(HINSTANCE *phinstOut, const GUID **pplibidOut,
SHORT *pwMajLibOut, SHORT *pwMinLibOut,
const CLSID **ppclsidOut, const IID **ppiidOut,
ITypeLib ***ppptlOut);
virtual IDispatch *GetPrimary() {return this->GetDispatch(); };

// *** ISprite methods ***
STDMETHOD(get_Application)(ISpruuidsApp** ppRet);
STDMETHOD(get_Parent)(ISpriteClass** ppRet);
STDMETHOD(MoveTo)(FLOAT x, FLOAT y);
STDMETHOD(MoveBy)(FLOAT dx, FLOAT dy);
STDMETHOD(MoveAtSprite)(ISprite *sprite, FLOAT dMax, FLOAT scale, long flags);
STDMETHOD(Remove)(void);
STDMETHOD(Refresh)(void);
STDMETHOD(IgnoreMove)(void);
STDMETHOD(get_Left)(FLOAT* pRet);
STDMETHOD(put_Left)(FLOAT val);
STDMETHOD(get_Top)(FLOAT* pRet);
STDMETHOD(put_Top)(FLOAT val);
STDMETHOD(get_Vx)(FLOAT* pRet);
STDMETHOD(put_Vx)(FLOAT val);
STDMETHOD(get_Vy)(FLOAT* pRet);
STDMETHOD(put_Vy)(FLOAT val);
STDMETHOD(get_Ax)(FLOAT* pRet);
STDMETHOD(put_Ax)(FLOAT val);
STDMETHOD(get_Ay)(FLOAT* pRet);
STDMETHOD(put_Ay)(FLOAT val);
STDMETHOD(get_FrictionX)(FLOAT* pRet);
STDMETHOD(put_FrictionX)(FLOAT val);
STDMETHOD(get_FrictionY)(FLOAT* pRet);
STDMETHOD(put_FrictionY)(FLOAT val);
STDMETHOD(get_Image)(int* pRet);
STDMETHOD(put_Image)(int val);
STDMETHOD(get_TickMove)(int* pRet);
STDMETHOD(put_TickMove)(int val);
STDMETHOD(get_TickEvent)(int* pRet);
STDMETHOD(put_TickEvent)(int val);
STDMETHOD(get_Visible)(VARIANT_BOOL* pRet);
STDMETHOD(put_Visible)(VARIANT_BOOL val);
STDMETHOD(get_Tag)(VARIANT* pRet);
STDMETHOD(put_Tag)(VARIANT val);
STDMETHOD(get_Width)(int* pRet);
STDMETHOD(get_Height)(int* pRet);

// *** Member Variables ***
CDisplay *m_pdisp;
CSpriteClass *m_psc;
CSprite *m_psprNext;
CSprite *m_psprPrev;
FIXED( m_xFull, m_xSub, m_x);
FIXED( m_yFull, m_ySub, m_y);
FIXED( m_vxFull, m_vxSub, m_vx);
FIXED( m_vyFull, m_vySub, m_vy);
FIXED( m_axFull, m_axSub, m_ax);
FIXED( m_ayFull, m_aySub, m_ay);
BOOL m_fFriction;
FLOAT m_fx; // Friction
FLOAT m_fy;
long m_tickEvt, m_tickEvtMax, m_tickMove, m_tickMoveMax;
int m_iimg;
PIMG m_pimg;
VARIANT m_varTag;

// Support for MoveAtSprite()
CSprite *m_psprAt;
float m_dMaxAt;
float m_scaleAt;
long m_flagsAt;


protected:
// *** Internal Routines ***
BOOL _FDraw(BOOL fCollide);
void _Erase();
void _Link();
void _Unlink(BOOL fFireEvt);

// *** Member Variables ***
BOOL m_fNeedRefresh:1;
BOOL m_fFree:1;
BOOL m_fIgnoreMove:1;
BOOL m_fLinked:1;
BOOL m_fHidden; // 2 = Implicitly hidden for _Init event
ULONG m_cref;

// DEBUG info
#define SIG_Sprite 'Spr '
DECLARE_SIGNATURE(SIG_Sprite);
};

//--- EOF -------------------------------------------------------------------