225 lines
6 KiB
C++
225 lines
6 KiB
C++
|
|
/*************************************************
|
|
* phsprite.cpp *
|
|
* *
|
|
* Copyright (C) 1995-1999 Microsoft Inc. *
|
|
* *
|
|
*************************************************/
|
|
|
|
// phsprite.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "dib.h"
|
|
#include "spriteno.h"
|
|
#include "sprite.h"
|
|
#include "phsprite.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPhasedSprite
|
|
|
|
IMPLEMENT_SERIAL(CPhasedSprite, CSprite, 0 /* schema number*/ )
|
|
|
|
CPhasedSprite::CPhasedSprite()
|
|
{
|
|
m_iNumCellRows = 1;
|
|
m_iNumCellColumns = 1;
|
|
m_iCellRow = 0;
|
|
m_iCellColumn = 0;
|
|
m_iCellHeight = CSprite::GetHeight();
|
|
m_iCellWidth = CSprite::GetWidth();
|
|
}
|
|
|
|
CPhasedSprite::~CPhasedSprite()
|
|
{
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPhasedSprite serialization
|
|
|
|
void CPhasedSprite::Serialize(CArchive& ar)
|
|
{
|
|
CSprite::Serialize(ar);
|
|
if (ar.IsStoring())
|
|
{
|
|
ar << (DWORD) m_iNumCellRows;
|
|
ar << (DWORD) m_iNumCellColumns;
|
|
ar << (DWORD) m_iCellRow;
|
|
ar << (DWORD) m_iCellColumn;
|
|
}
|
|
else
|
|
{
|
|
DWORD dw;
|
|
ar >> dw;
|
|
SetNumCellRows(dw);
|
|
ar >> dw;
|
|
SetNumCellColumns(dw);
|
|
ar >> dw;
|
|
SetCellRow(dw);
|
|
ar >> dw;
|
|
SetCellColumn(dw);
|
|
}
|
|
}
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CPhasedSprite commands
|
|
|
|
// Do any initialization after file load of a new image etc.
|
|
void CPhasedSprite::Initialize()
|
|
{
|
|
CSprite::Initialize();
|
|
m_iNumCellRows = 1;
|
|
m_iNumCellColumns = 1;
|
|
m_iCellRow = 0;
|
|
m_iCellColumn = 0;
|
|
m_iCellHeight = CSprite::GetHeight();
|
|
m_iCellWidth = CSprite::GetWidth();
|
|
}
|
|
|
|
// Divide the image into a given number of rows
|
|
BOOL CPhasedSprite::SetNumCellRows(int iRows)
|
|
{
|
|
if (iRows < 1) {
|
|
TRACE("Invalid number of rows");
|
|
return FALSE;
|
|
}
|
|
// compute the height of each row
|
|
int iCellHeight = CSprite::GetHeight() / iRows;
|
|
if (iCellHeight < 1) {
|
|
TRACE("Can't make them that small");
|
|
return FALSE;
|
|
}
|
|
// set the new height and row count
|
|
m_iNumCellRows = iRows;
|
|
m_iCellRow = 0;
|
|
m_iCellHeight = iCellHeight;
|
|
return TRUE;
|
|
}
|
|
|
|
// Divide the image into a given number of columns
|
|
BOOL CPhasedSprite::SetNumCellColumns(int iColumns)
|
|
{
|
|
if (iColumns < 1) {
|
|
TRACE("Invalid number of columns");
|
|
return FALSE;
|
|
}
|
|
// compute the width of each column
|
|
int iCellWidth = CSprite::GetWidth() / iColumns;
|
|
if (iCellWidth < 1) {
|
|
TRACE("Can't make them that small");
|
|
return FALSE;
|
|
}
|
|
// set the new width and column count
|
|
m_iNumCellColumns = iColumns;
|
|
m_iCellColumn = 0;
|
|
m_iCellWidth = iCellWidth;
|
|
return TRUE;
|
|
}
|
|
|
|
// set the current row
|
|
BOOL CPhasedSprite::SetCellRow(int iRow)
|
|
{
|
|
if ((iRow >= m_iNumCellRows)
|
|
|| (iRow < 0)) {
|
|
TRACE("Invalid row");
|
|
return FALSE;
|
|
}
|
|
if (iRow == m_iCellRow) return FALSE; // nothing to do
|
|
m_iCellRow = iRow;
|
|
// send a notification to redraw
|
|
if (m_pNotifyObj) {
|
|
CRect rcPos;
|
|
GetRect(&rcPos);
|
|
m_pNotifyObj->Change(this,
|
|
CSpriteNotifyObj::IMAGE,
|
|
&rcPos);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// set the current column
|
|
BOOL CPhasedSprite::SetCellColumn(int iColumn)
|
|
{
|
|
if ((iColumn >= m_iNumCellColumns)
|
|
|| (iColumn < 0)) {
|
|
TRACE("Invalid column");
|
|
return FALSE;
|
|
}
|
|
if (iColumn == m_iCellColumn) return FALSE; // nothing to do
|
|
m_iCellColumn = iColumn;
|
|
// send a notification to redraw
|
|
if (m_pNotifyObj) {
|
|
CRect rcPos;
|
|
GetRect(&rcPos);
|
|
m_pNotifyObj->Change(this,
|
|
CSpriteNotifyObj::IMAGE,
|
|
&rcPos);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
// get the bounding rectangle
|
|
void CPhasedSprite::GetRect(CRect* pRect)
|
|
{
|
|
ASSERT(pRect);
|
|
pRect->left = m_x;
|
|
pRect->top = m_y;
|
|
pRect->right = m_x + GetWidth();
|
|
pRect->bottom = m_y + GetHeight();
|
|
}
|
|
|
|
// Test for a hit in a non-transparent area
|
|
BOOL CPhasedSprite::HitTest(CPoint point)
|
|
{
|
|
// Test if the point is inside the sprite rectangle
|
|
if ((point.x > m_x)
|
|
&& (point.x < m_x + GetWidth())
|
|
&& (point.y > m_y)
|
|
&& (point.y < m_y + GetHeight())) {
|
|
// Hit is in sprite rect
|
|
// See if this point is transparent by testing to
|
|
// see if the pixel value is the same as the top
|
|
// left corner value. Note that top left of the
|
|
// image is bottom left in the DIB.
|
|
// Get the address of the top, left pixel
|
|
BYTE* p = (BYTE*)GetPixelAddress(point.x - m_x, point.y - m_y);
|
|
ASSERT(p);
|
|
|
|
if ( ( p != NULL) && (*p != m_bTransIndex) ) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
// Render a sprite to a DIB
|
|
void CPhasedSprite::Render(CDIB *pDIB, CRect* pClipRect)
|
|
{
|
|
ASSERT(pDIB);
|
|
ASSERT(pClipRect);
|
|
// Get the sprite rect and see if it's visible
|
|
CRect rcDraw;
|
|
GetRect(&rcDraw);
|
|
if (!rcDraw.IntersectRect(pClipRect, &rcDraw)) {
|
|
return; // not visible
|
|
}
|
|
// modify the source x and y values for the current phase of the sprite
|
|
int xs = rcDraw.left - m_x + m_iCellColumn * m_iCellWidth;
|
|
int ys = rcDraw.top - m_y + m_iCellRow * m_iCellHeight;
|
|
ASSERT(xs >= 0 && xs < CSprite::GetWidth());
|
|
ASSERT(ys >= 0 && ys < CSprite::GetHeight());
|
|
CopyBits(pDIB, // dest DIB
|
|
rcDraw.left, // dest x
|
|
rcDraw.top, // dest y
|
|
rcDraw.right - rcDraw.left, // width
|
|
rcDraw.bottom - rcDraw.top, // height
|
|
xs, // source x
|
|
ys, // source y
|
|
PALETTEINDEX(m_bTransIndex)); // trans color index
|
|
}
|