Skip to main content
gamedev.net
🔒 Locked

Sprite flip?

Started by Deciheximal Jan 10, 2004 at 8:33 PM 2 replies 400+ views
Original Post
Deciheximal
Deciheximal
I have a series of sprites that I need to draw with vertical and horizontal flips, using DirectX8. I can draw the sprites normally, but I have been unable to find any information about a command to draw them with a flip. I''d really prefer not to store mirror-imaged graphics to file and load twice (or 4x) as many sprites into memory in order to do this. Here is my current draw command: m_pSprite->draw(m_nCurrentFrame,playerX,playerY,surface) The current game programming book I have (Intro to Computer Game Programming w/ DirectX 8 - Ian Parberry) doesn''t cover this. I''m planning to buy a new book - can anybody suggest a good one that covers simple elements like the one above?
PlayGGY
PlayGGY
Well, what is in your draw command? We would need to know that first.

EDIT: Or is it sprite class in D3DX?

[edited by - PlayGGY on January 10, 2004 9:45:44 PM]
And the rockets' red glare, the bombs bursting in air,gave proof through the fight that our flag was still there.Oh say, does that star-spangled banner yet waveover the land of the free and the home of the brave?
Supernat02
Supernat02
I like his book, got me started!

I added these functions to my sprite's frame class (for animation):

void FlipHorizontally(void);
void FlipVertically(void);

I added these functions to my sprite base class:

void FlipAllFramesVertically(void);
void FlipAllFramesHorizontally(void);
void CopySprite(TDDSprite *fpSourceSprite);
unsigned char CopyFrame(unsigned char fpFrameIndex);

The copy sprite functions work like such:
Load up a sprite from file with one sprite class. Create a new sprite object, then from that object, call CopySprite(FirstSprite);
Then after the sprite is copied over, call FlipAllFramesVertically or horizontally. The CopyFrame is used as part of the CopySprite function, looping through all frames.

You are probably familiar with copying the memory over to the surface manually by now. I just copy it in reverse order. Here's the code:


void TDDSpriteFrame::FlipVertically(void)
{
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);

Surface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);

// For now, just assume 24 or 32 bit, must change though.

unsigned int RealWidth = Width << 2;
unsigned int BitmapSize = RealWidth*Height;
Byte *Dest = (Byte*)malloc(BitmapSize);
Byte *MemPtr = Dest;

// Copy the surface into a temporary memory space flipped.

Byte *Source = (Byte*)ddsd.lpSurface + RealWidth - 4;
for (int y=0; y < Height; y++)
{
for (int x=0; x < Width; x++)
{
memcpy(Dest, Source, 4);
Dest += 4;
Source -= 4;
}
Source += (ddsd.lPitch + RealWidth);
}

// Copy the temporary bits back to the surface.

Dest = (Byte*)ddsd.lpSurface;
Source = MemPtr;
for (int y=0; y < Height; y++)
{
memcpy(Dest, Source, RealWidth);
Dest += ddsd.lPitch;
Source += RealWidth;
}

// Free the memory.

free(MemPtr);

// Unlock the surface.

Surface->Unlock(ddsd.lpSurface);
}



You should only call this one time at initialization.

Here's all of my code since I won't be using it again, I decided to go D3D. It's messy and unfinished and in VCL, but it might give you some more ideas about other things anyway.

The DDraw.h File

#define KEY_DOWN(key) ((GetAsyncKeyState(key) & 0x8000) ? 1 : 0)
#define CLEAR(p,s) (memset(p,0,s))
#define GRID_MAX_COLS 200
#define GRID_MAX_ROWS 200
#define MAX_SEQUENCES 50
#define MAX_SEQUENCE_FRAMES 50

enum TDisplayResolutions {DR_640x480x8, DR_640x480x16, DR_640x480x24,
DR_640x480x32, DR_800x600x8, DR_800x600x16, DR_800x600x24,
DR_800x600x32, DR_1024x768x8, DR_1024x768x16, DR_1024x768x24,
DR_1024x768x32, DR_1152x864x8, DR_1152x864x16, DR_1152x864x24,
DR_1152x864x32, DR_1280x768x8, DR_1280x768x16, DR_1280x768x24,
DR_1280x768x32, DR_1280x1024x8, DR_1280x1024x16, DR_1280x1024x24,
DR_1280x1024x32, DR_KEEP_EXISTING};

enum TDisplayModes {DM_FULLSCREEN, DM_WINDOWED};

//---------------------------------------------------------------------------

class TDirectDraw;
class TDDSprite;
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

class TDDGrid : public TPersistent
{
private:
int FColumnCount;
int FRowCount;
int FCellWidth;
int FCellHeight;
int FWidth;
int FHeight;
int FXStart;
int FYStart;
int FXOffset;
int FYOffset;
void __fastcall fSetColumnCount(int fpColumnCount);
void __fastcall fSetRowCount(int fpRowCount);
int __fastcall fGetWidth(void);
int __fastcall fGetHeight(void);
int __fastcall fGetXStart(void);
int __fastcall fGetYStart(void);
int __fastcall fGetCell(int fpX, int fpY);
void __fastcall fSetXOffset(int fpXOffset);
void __fastcall fSetYOffset(int fpYOffset);
void __fastcall fSetCell(int fpX, int fpY, int fpCellValue);
bool FActive;
int FCells[GRID_MAX_COLS][GRID_MAX_ROWS];
public:
TDirectDraw *Parent;
void __fastcall Update(void);
__fastcall TDDGrid(TDirectDraw *fpParent);
__property int CellWidth = {read=FCellWidth};
__property int CellHeight = {read=FCellHeight};
__property int Cells[int x][int y] = {read=fGetCell, write=fSetCell};
bool __fastcall ShiftColumns(int fpDirection);
bool __fastcall ShiftRows(int fpDirection);
bool __fastcall FillRow(int fpRowIndex, int fpSpriteIndex);
bool __fastcall FillColumn(int fpColumnIndex, int fpSpriteIndex);
__published:
__property int XOffset = {read=FXOffset, write=fSetXOffset};
__property int YOffset = {read=FYOffset, write=fSetYOffset};
__property int XStart = {read=fGetXStart, write=FXStart};
__property int YStart = {read=fGetYStart, write=FYStart};
__property int Width = {read=fGetWidth, write=FWidth};
__property int Height = {read=fGetHeight, write=FHeight};
__property bool Active = {read=FActive, write=FActive};
__property int ColumnCount = {read=FColumnCount, write=fSetColumnCount, default=1};
__property int RowCount = {read=FRowCount, write=fSetRowCount, default=1};
};
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

//class TDirectDrawEditor : public TComponentEditor

//{

// public:

// void __fastcall Edit(void);

//};

//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

class TDDSpriteFrame : public TPersistent
{
public:
LPDIRECTDRAWSURFACE Surface;
int Width;
int Height;
TColor TransparentColor;
bool Transparent;
TDDSprite *Parent;
int Index;
void __fastcall FlipHorizontally(void);
void __fastcall FlipVertically(void);
__fastcall TDDSpriteFrame(TDDSprite *fpParent);
};
//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

class TDDSprite : public TPersistent
{
private:
TList *FFrames;
unsigned char FSequences[MAX_SEQUENCES][MAX_SEQUENCE_FRAMES];
TDDSpriteFrame* __fastcall fGetFrame(unsigned char fpIndex);
unsigned char __fastcall fGetFrameCount(void) {return (unsigned char)FFrames->Count;};
void __fastcall fSetXPos(unsigned short int fpXPos);
void __fastcall fSetYPos(unsigned short int fpYPos);
void __fastcall fSetCurrentFrameIndex(unsigned char fpIndex);
void __fastcall fSetSequence(unsigned char fpX, unsigned char fpY, unsigned char fpFrameIndex);
unsigned char __fastcall fGetSequence(unsigned char fpX, unsigned char fpY);
TDDSpriteFrame* __fastcall fGetCurrentFrame(void) {return Frames[CurrentFrameIndex];};
unsigned short int FXPos, FYPos;
bool FLockBounds;
bool FVisible;
unsigned char FCurrentSequenceIndex;
unsigned char FCurrentFrameIndex;
unsigned char FCurrentSequenceFrame;
unsigned char FFramesPerSecond;
unsigned char FSequenceFrameCounts[MAX_SEQUENCES];
unsigned long int FLastFrameTime;
public:
unsigned char Index;
TDirectDraw *Parent;
__fastcall TDDSprite(TDirectDraw *Owner);
void __fastcall FlipAllFramesVertically(void);
void __fastcall FlipAllFramesHorizontally(void);
void __fastcall FlipSequenceVertically(unsigned char fpSequenceIndex);
void __fastcall FlipSequenceHorizontally(unsigned char fpSequenceIndex);
void __fastcall NextFrame(void);
void __fastcall SetSequence(unsigned char fpSequenceIndex,
unsigned char *fpFrameIndeces,
unsigned char fpFrameCount);
void __fastcall SetSequence(unsigned char fpSequenceIndex,
unsigned char fpStartFrameIndex,
unsigned char fpStopFrameIndex);
void __fastcall AddFrame(AnsiString fpFileName, bool fpTransparent,
TColor fpTransparentColor, TRect *fpFrame);
void __fastcall LoadAnimation(AnsiString fpFileName, bool fpTransparent,
TColor fpTransparentColor, int fpColumns,
int fpRows, int fpWidth, int fpHeight);
void __fastcall CopySprite(TDDSprite *fpSourceSprite);
unsigned char __fastcall CopyFrame(unsigned char fpFrameIndex);
void __fastcall CopySequence(unsigned char fpSequenceIndex,
unsigned char fpNewSequenceIndex);
// __property unsigned char Sequences[unsigned char x][unsigned char y] = {read=fGetSequence, write=fSetSequence};

__property unsigned char CurrentSequenceIndex = {read=FCurrentSequenceIndex, write=FCurrentSequenceIndex};
__property unsigned char FramesPerSecond = {read=FFramesPerSecond, write=FFramesPerSecond};
__property unsigned char CurrentFrameIndex = {read=FCurrentFrameIndex, write=fSetCurrentFrameIndex};
__property bool Visible = {read=FVisible, write=FVisible};
__property bool LockBounds = {read=FLockBounds, write=FLockBounds};
__property TDDSpriteFrame* Frames[unsigned char Index] = {read=fGetFrame};
__property TDDSpriteFrame* CurrentFrame = {read=fGetCurrentFrame};
__property unsigned char FrameCount = {read=fGetFrameCount};
__property unsigned short int XPos = {read=FXPos, write=fSetXPos};
__property unsigned short int YPos = {read=FYPos, write=fSetYPos};
};

//---------------------------------------------------------------------------

//---------------------------------------------------------------------------

class PACKAGE TDirectDraw : public TCustomControl
{
private:
TDisplayResolutions FDisplayResolution;
TDisplayModes FDisplayMode;
LPDIRECTDRAW FDirectDrawObject;
LPDIRECTDRAWSURFACE FPrimarySurface;
LPDIRECTDRAWSURFACE FSecondarySurface;
LPDIRECTDRAWCLIPPER FClipper;
HWND FParentHandle;
TList *FSprites;
TList *FOverlaySprites;
TColor FTransparentColor;
int FDisplayWidth;
int FDisplayHeight;
int FDisplayBits;
int FPitch;
bool FActive;
TDDGrid *FGrid;
TComponent *FOwner;
TDDSprite* __fastcall fGetSprite(int Index);
TDDSprite* __fastcall fGetOverlaySprite(int Index);
void __fastcall fSetActive(bool Value);
void __fastcall fSetDisplayResolution(TDisplayResolutions Value);
void __fastcall fSetDisplayMode(TDisplayModes Value);
bool __fastcall fDDInitialize(void);
bool __fastcall fDDSetCooperativeLevel(void);
bool __fastcall fDDSetDisplayMode(void);
bool __fastcall fDDCreateSurfaces(void);
bool __fastcall fDDCreateClipper(void);
bool __fastcall fDDDestroyClipper(void);
bool __fastcall fDDDestroySurfaces(void);
bool __fastcall fDDDestroy(void);
int __fastcall fGetSpriteCount(void) {return FSprites->Count;};
int __fastcall fGetOverlaySpriteCount(void) {return FOverlaySprites->Count;};
protected:
public:
bool __fastcall LoadStandardPalette(void);
bool __fastcall FillSurface(int PaletteIndex);
bool __fastcall FillSurface(int Red, int Green, int Blue);
bool __fastcall Draw(void);
void __fastcall AllSpritesNextFrame(void);
void __fastcall AllOverlaySpritesNextFrame(void);
TDDSprite* __fastcall CreateSprite(unsigned char fpFramesPerSecond);
TDDSprite* __fastcall CreateOverlaySprite(unsigned char fpFramesPerSecond);
__fastcall TDirectDraw(TComponent* Owner);
__fastcall ~TDirectDraw(void);
void __fastcall AlignOverlayToGrid(int fpOverlaySpriteIndex,
int fpGridX, int fpGridY);
void __fastcall SetSpritesFramesPerSecond(unsigned char fpStartIndex,
unsigned char fpStopIndex, unsigned char fpFramesPerSecond);
void __fastcall SetOverlaySpritesFramesPerSecond(unsigned char fpStartIndex,
unsigned char fpStopIndex, unsigned char fpFramesPerSecond);
__property TDDSprite* Sprites[int Index] = {read=fGetSprite};
__property TDDSprite* OverlaySprites[int Index] = {read=fGetOverlaySprite};
__property int SpriteCount = {read=fGetSpriteCount};
__property int OverlaySpriteCount = {read=fGetOverlaySpriteCount};
__property LPDIRECTDRAW DDObject = {read=FDirectDrawObject};
__published:
__property Visible;
__property Color;
__property TDDGrid* Grid = {read=FGrid, write=FGrid};
__property int DisplayWidth = {read=FDisplayWidth};
__property int DisplayHeight = {read=FDisplayHeight};
__property TDisplayResolutions DisplayResolution = {read=FDisplayResolution, write=fSetDisplayResolution, stored=true};
__property TDisplayModes DisplayMode = {read=FDisplayMode, write=fSetDisplayMode, stored=true};
__property bool Active = {read=FActive, write=fSetActive, stored=true};
};


The implementation, DDraw.c file

#define RGB16BIT(r,g,b) (((b&31<<1)|((g&31)<<6)|((r&31)<<11)))
#define RGB24BIT(r,g,b) (((b&255)|((g&255)<<8)|((r&255)<<16)))

__fastcall TDDGrid::TDDGrid(TDirectDraw *fpParent)
: TPersistent()
{
Parent = fpParent;
FColumnCount = 1;
FRowCount = 1;
FCellWidth = Parent->DisplayWidth;
FCellHeight = Parent->DisplayHeight;
FWidth = Parent->DisplayWidth;
FHeight = Parent->DisplayHeight;
FXStart = 0;
FYStart = 0;
}

//---------------------------------------------------------------------------

int __fastcall TDDGrid::fGetWidth(void)
{
int ReturnVal = Parent->DisplayWidth;

if ((FWidth > 0) && (FWidth <= Parent->DisplayWidth))
{
ReturnVal = FWidth;
FCellWidth = FWidth/(FColumnCount - 2);
}

return ReturnVal;
}
//---------------------------------------------------------------------------

int __fastcall TDDGrid::fGetHeight(void)
{
int ReturnVal = Parent->DisplayHeight;

if ((FHeight > 0) && (FHeight <= Parent->DisplayHeight))
{
ReturnVal = FHeight;
FCellHeight = FHeight/(FRowCount - 2);
}

return ReturnVal;
}
//---------------------------------------------------------------------------

void __fastcall TDDGrid::fSetXOffset(int fpXOffset)
{
if ((fpXOffset > -CellWidth) && (fpXOffset < CellWidth))
FXOffset = fpXOffset;
}
//---------------------------------------------------------------------------

void __fastcall TDDGrid::fSetYOffset(int fpYOffset)
{
if ((fpYOffset > -CellHeight) && (fpYOffset < CellHeight))
FYOffset = fpYOffset;
}
//---------------------------------------------------------------------------

void __fastcall TDDGrid::fSetColumnCount(int fpColumnCount)
{
if ((fpColumnCount > 0) && (fpColumnCount < 200))
{
FColumnCount = fpColumnCount;
FCellHeight = Parent->DisplayHeight/(FColumnCount - 2);
}
}

//---------------------------------------------------------------------------

void __fastcall TDDGrid::fSetRowCount(int fpRowCount)
{
if ((fpRowCount > 0) && (fpRowCount < 200))
{
FRowCount = fpRowCount;
FCellWidth = Parent->DisplayWidth/(FRowCount - 2);
}
}
//---------------------------------------------------------------------------

int __fastcall TDDGrid::fGetXStart(void)
{
int ReturnVal = 0;

if (((FXStart + FWidth) < Parent->DisplayWidth) &&
(FXStart >= 0))
ReturnVal = FXStart;

return ReturnVal;
}
//---------------------------------------------------------------------------

int __fastcall TDDGrid::fGetYStart(void)
{
int ReturnVal = 0;

if (((FYStart + FHeight) < Parent->DisplayHeight) &&
(FYStart >= 0))
ReturnVal = FYStart;

return ReturnVal;
}
//---------------------------------------------------------------------------

void __fastcall TDDGrid::fSetCell(int fpX, int fpY, int fpCellValue)
{
if ((fpX < GRID_MAX_COLS) && (fpX >= 0) && (fpY < GRID_MAX_ROWS) && (fpY >= 0))
if ((fpCellValue >= 0) && (fpCellValue < Parent->SpriteCount))
FCells[fpX][fpY] = fpCellValue;
}
//---------------------------------------------------------------------------

int __fastcall TDDGrid::fGetCell(int fpX, int fpY)
{
int ReturnVal = 0;

if ((fpX < GRID_MAX_COLS) && (fpX >= 0) && (fpY < GRID_MAX_ROWS) && (fpY >= 0))
ReturnVal = FCells[fpX][fpY];

return ReturnVal;
}
//---------------------------------------------------------------------------

void __fastcall TDDGrid::Update(void)
{
FCellWidth = FWidth/(FRowCount - 2);
FCellHeight = FHeight/(FColumnCount - 2);
}
//---------------------------------------------------------------------------

bool __fastcall TDDGrid::ShiftColumns(int fpDirection)
{
bool ReturnVal = true;

if (fpDirection > 0)
{
for (int y=0; y < FRowCount; y++)
for (int x=(FColumnCount-1); (x - fpDirection) >= 0; x--)
FCells[x][y] = FCells[x-fpDirection][y];
}
else if (fpDirection < 0)
{
for (int y=0; y < FRowCount; y++)
for (int x=0; (x - fpDirection) < FColumnCount; x++)
FCells[x][y] = FCells[x-fpDirection][y];
}

return ReturnVal;
}
//---------------------------------------------------------------------------

bool __fastcall TDDGrid::ShiftRows(int fpDirection)
{
bool ReturnVal = true;

if (fpDirection > 0)
{
for (int x=0; x < FColumnCount; x++)
for (int y=(FRowCount-1); (y - fpDirection) >= 0; y--)
FCells[x][y] = FCells[x][y-fpDirection];
}
else if (fpDirection < 0)
{
for (int x=0; x < FColumnCount; x++)
for (int y=0; (y - fpDirection) < FRowCount; y++)
FCells[x][y] = FCells[x][y-fpDirection];
}

return ReturnVal;
}
//---------------------------------------------------------------------------

bool __fastcall TDDGrid::FillRow(int fpRowIndex, int fpSpriteIndex)
{
bool ReturnVal = true;

if ((fpRowIndex >= 0) && (fpRowIndex < FRowCount) && (fpSpriteIndex >= 0) &&
(fpSpriteIndex < Parent->SpriteCount))
{
for (int x=0; x < FColumnCount; x++)
FCells[x][fpRowIndex] = fpSpriteIndex;
}
else
ReturnVal = false;

return ReturnVal;
}
//---------------------------------------------------------------------------

bool __fastcall TDDGrid::FillColumn(int fpColumnIndex, int fpSpriteIndex)
{
bool ReturnVal = true;

if ((fpColumnIndex >= 0) && (fpColumnIndex < FColumnCount) &&
(fpSpriteIndex >= 0) && (fpSpriteIndex < Parent->SpriteCount))
{
for (int y=0; y < FRowCount; y++)
FCells[fpColumnIndex][y] = fpSpriteIndex;
}
else
ReturnVal = false;

return ReturnVal;
}
//---------------------------------------------------------------------------

//void __fastcall TDirectDrawEditor::Edit(void)

//{

// if (!frmDDEditor)

// frmDDEditor = new TfrmDDEditor(NULL);

// frmDDEditor->Show();

//}

//---------------------------------------------------------------------------

__fastcall TDDSpriteFrame::TDDSpriteFrame(TDDSprite *fpParent)
: TPersistent()
{
Parent = fpParent;
}
//---------------------------------------------------------------------------

void __fastcall TDDSpriteFrame::FlipVertically(void)
{
DDSURFACEDESC ddsd;
ddsd.dwSize = sizeof(ddsd);

Surface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);

// For now, just assume 24 or 32 bit, must change though.

unsigned int RealWidth = Width << 2;
unsigned int BitmapSize = RealWidth*Height;
Byte *Dest = (Byte*)malloc(BitmapSize);
Byte *MemPtr = Dest;

// Copy the surface into a temporary memory space flipped.

Byte *Source = (Byte*)ddsd.lpSurface + RealWidth - 4;
for (int y=0; y < Height; y++)
{
for (int x=0; x < Width; x++)
{
memcpy(Dest, Source, 4);
Dest += 4;
Source -= 4;
}
Source += (ddsd.lPitch + RealWidth);
}

// Copy the temporary bits back to the surface.

Dest = (Byte*)ddsd.lpSurface;
Source = MemPtr;
for (int y=0; y < Height; y++)
{
memcpy(Dest, Source, RealWidth);
Dest += ddsd.lPitch;
Source += RealWidth;
}

// Free the memory.

free(MemPtr);

// Unlock the surface.

Surface->Unlock(ddsd.lpSurface);
}
//---------------------------------------------------------------------------

void __fastcall TDDSpriteFrame::FlipHorizontally(void)
{
}
//---------------------------------------------------------------------------

__fastcall TDDSprite::TDDSprite(TDirectDraw *Owner)
: TPersistent()
{
FFrames = new TList();
Parent = Owner;
FXPos = 0;
FYPos = 0;
FLockBounds = false;
Visible = true;
FLastFrameTime = GetTickCount();
FCurrentFrameIndex = 0;
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::fSetSequence(unsigned char fpX, unsigned char fpY,
unsigned char fpFrameIndex)
{
if ((fpX < MAX_SEQUENCES) && (fpY < MAX_SEQUENCE_FRAMES) &&
(fpFrameIndex < FFrames->Count))
{
FSequences[fpX][fpY] = fpFrameIndex;
}
}
//---------------------------------------------------------------------------

unsigned char __fastcall TDDSprite::fGetSequence(unsigned char fpX,
unsigned char fpY)
{
unsigned char ReturnVal = 0;

if ((fpX < MAX_SEQUENCES) && (fpY < MAX_SEQUENCE_FRAMES))
{
ReturnVal = FSequences[fpX][fpY];
}

return ReturnVal;
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::SetSequence(unsigned char fpSequenceIndex,
unsigned char *fpFrameIndeces, unsigned char fpFrameCount)
{
if ((fpSequenceIndex < MAX_SEQUENCES) && (fpFrameIndeces != NULL))
{
for (int x=0; x < fpFrameCount; x++)
FSequences[fpSequenceIndex][x] = fpFrameIndeces[x];
FSequenceFrameCounts[fpSequenceIndex] = fpFrameCount;
}
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::SetSequence(unsigned char fpSequenceIndex,
unsigned char fpStartFrameIndex, unsigned char fpStopFrameIndex)
{
if ((fpSequenceIndex < MAX_SEQUENCES) &&
(fpStartFrameIndex < fpStopFrameIndex) &&
(fpStopFrameIndex < FFrames->Count) &&
((fpStopFrameIndex - fpStartFrameIndex) < MAX_SEQUENCE_FRAMES))
{
for (int x=0; x <= (fpStopFrameIndex - fpStartFrameIndex); x++)
FSequences[fpSequenceIndex][x] = fpStartFrameIndex + x;
FSequenceFrameCounts[fpSequenceIndex] = (fpStopFrameIndex + 1) - fpStartFrameIndex;
}
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::AddFrame(AnsiString fpFileName, bool fpTransparent,
TColor fpTransparentColor, TRect *fpFrame)
{
if ((fpFileName != NULL) && (!fpFileName.IsEmpty()) && FileExists(fpFileName))
{
TDDSpriteFrame *NewFrame = new TDDSpriteFrame(this);
Graphics::TBitmap *Bitmap = new Graphics::TBitmap();
Bitmap->LoadFromFile(fpFileName);

// Initialize the frame.

int RealXStart = 0;
int RealYStart = 0;
int RealWidth = Bitmap->Width;
int RealHeight = Bitmap->Height;

if (fpFrame != NULL)
{
RealXStart = fpFrame->Left;
RealYStart = fpFrame->Top;
RealWidth = fpFrame->Right - RealXStart;
RealHeight = fpFrame->Bottom - RealYStart;
}

NewFrame->Width = RealWidth;
NewFrame->Height = RealHeight;

// set to access caps, width, and height

DDSURFACEDESC ddsd;
CLEAR(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;

// Set Height and Width

ddsd.dwWidth = RealWidth;
ddsd.dwHeight = RealHeight;

// set surface to offscreen plain

ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

// create the new surface

Parent->DDObject->CreateSurface(&ddsd, &(NewFrame->Surface), NULL);

// Set Transparency

NewFrame->Transparent = fpTransparent;
NewFrame->TransparentColor = fpTransparentColor;
if (fpTransparent)
{
DDCOLORKEY ck;
ck.dwColorSpaceHighValue = (DWORD)(fpTransparentColor & 0x00FFFFFF);
ck.dwColorSpaceLowValue = (DWORD)(fpTransparentColor & 0x00FFFFFF);
NewFrame->Surface->SetColorKey(DDCKEY_SRCBLT, &ck);
}

// Set the true bitmap width for the memory copy.

int TrueBitmapWidth = RealWidth;
int BitmapSize = 0;
TPixelFormat pxFormat = Bitmap->PixelFormat;

// Adjust the true bitmap width for the memory copy.

if ((pxFormat == pf15bit) || (pxFormat == pf16bit))
TrueBitmapWidth = TrueBitmapWidth << 1;
else if ((pxFormat == pf24bit) || (pxFormat == pf32bit))
TrueBitmapWidth = TrueBitmapWidth << 2;

// Calculate the bitmap memory usage

BitmapSize = TrueBitmapWidth*RealHeight;

// Create memory and clear the buffer.

Byte *Buffer = (Byte*)malloc(BitmapSize);
CLEAR(Buffer, BitmapSize);

// Copy bitmap data to temporary buffer.

Byte *buffer = Buffer;
for (int y=RealYStart; y < (RealYStart + RealHeight); y++)
{
Byte *ScanLine = (Byte*)(Bitmap->ScanLine[y]) + RealXStart;
for (int x=RealXStart; x < (RealXStart + RealWidth); x++)
{
if ((pxFormat == pf24bit) || (pxFormat == pf32bit))
{
memcpy(buffer, ScanLine, 3);
buffer += 4;
if (pxFormat == pf24bit)
ScanLine += 3;
else
ScanLine += 4;
}
}
}

// Copy bitmap data to surface.

NewFrame->Surface->Lock(NULL, &ddsd, DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR, NULL);
Byte *dest = (Byte*)ddsd.lpSurface;
Byte *source = (Byte*)Buffer;
for (int y=0; y < RealHeight; y++)
{
memcpy(dest, source, TrueBitmapWidth);
dest += ddsd.lPitch;
source += TrueBitmapWidth;
}
NewFrame->Surface->Unlock(ddsd.lpSurface);

// Release memory

free(Buffer);
delete Bitmap;

// Set the new frame index.

NewFrame->Index = FFrames->Count;

// Add to the linked list.

FFrames->Add(NewFrame);
}
}
//---------------------------------------------------------------------------

unsigned char __fastcall TDDSprite::CopyFrame(unsigned char fpFrameIndex)
{
unsigned char ReturnVal = 0;

if (fpFrameIndex < FFrames->Count)
{
TDDSpriteFrame *Frame;
Frame = new TDDSpriteFrame(this);

// Add to the linked list.

ReturnVal = FFrames->Count;
FFrames->Add(Frame);

// Initialize the frame.

Frame->Width = ((TDDSpriteFrame*)FFrames->Items[fpFrameIndex])->Width;
Frame->Height = ((TDDSpriteFrame*)FFrames->Items[fpFrameIndex])->Height;

// set to access caps, width, and height

DDSURFACEDESC ddsd;
CLEAR(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;

// Set Height and Width

ddsd.dwWidth = Frame->Width;
ddsd.dwHeight = Frame->Height;

// set surface to offscreen plain

ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

// create the new surface

Parent->DDObject->CreateSurface(&ddsd, &(Frame->Surface), NULL);

// Set Transparency

Frame->Transparent = ((TDDSpriteFrame*)FFrames->Items[fpFrameIndex])->Transparent;
Frame->TransparentColor = ((TDDSpriteFrame*)FFrames->Items[fpFrameIndex])->TransparentColor;

if (Frame->Transparent)
{
DDCOLORKEY ck;
ck.dwColorSpaceHighValue = (DWORD)(Frame->TransparentColor & 0x00FFFFFF);
ck.dwColorSpaceLowValue = (DWORD)(Frame->TransparentColor & 0x00FFFFFF);
Frame->Surface->SetColorKey(DDCKEY_SRCBLT, &ck);
}

RECT Rect;
Rect.left = 0;
Rect.top = 0;
Rect.right = Frame->Width;
Rect.bottom = Frame->Height;

Frame->Surface->BltFast(0, 0, (((TDDSpriteFrame*)FFrames->Items[fpFrameIndex])->Surface),
&Rect, NULL);
}

return ReturnVal;
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::CopySequence(unsigned char fpSequenceIndex,
unsigned char fpNewSequenceIndex)
{
if ((fpSequenceIndex < MAX_SEQUENCES) && (fpNewSequenceIndex < MAX_SEQUENCES))
{
unsigned char NewSequence[MAX_SEQUENCE_FRAMES];

for (int x=0; x < FSequenceFrameCounts[fpSequenceIndex]; x++)
{
NewSequence[x] = CopyFrame(FSequences[fpSequenceIndex][x]);
}
SetSequence(fpNewSequenceIndex, (unsigned char*)NewSequence, FSequenceFrameCounts[fpSequenceIndex]);
}
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::FlipSequenceVertically(unsigned char fpSequenceIndex)
{
if (fpSequenceIndex < MAX_SEQUENCES)
{
for (int x=0; x < FSequenceFrameCounts[fpSequenceIndex]; x++)
((TDDSpriteFrame*)FFrames->Items[FSequences[fpSequenceIndex][x]])->FlipVertically();
}
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::FlipSequenceHorizontally(unsigned char fpSequenceIndex)
{
if (fpSequenceIndex < MAX_SEQUENCES)
{
for (int x=0; x < FSequenceFrameCounts[fpSequenceIndex]; x++)
((TDDSpriteFrame*)FFrames->Items[FSequences[fpSequenceIndex][x]])->FlipHorizontally();
}
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::LoadAnimation(AnsiString fpFileName,
bool fpTransparent, TColor fpTransparentColor,
int fpColumns, int fpRows, int fpWidth, int fpHeight)
{
TRect LoopRect;

for (int y=0; y < fpRows; y++)
for (int x=0; x < fpColumns; x++)
{
LoopRect = Rect(x*fpWidth, y*fpHeight, x*fpWidth + fpWidth, y*fpHeight + fpHeight);
AddFrame(fpFileName, fpTransparent, fpTransparentColor, &LoopRect);
}
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::FlipAllFramesVertically(void)
{
for (int x=0; x < FFrames->Count; x++)
Frames[x]->FlipVertically();
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::FlipAllFramesHorizontally(void)
{
for (int x=0; x < FFrames->Count; x++)
Frames[x]->FlipHorizontally();
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::CopySprite(TDDSprite *fpSourceSprite)
{
FFramesPerSecond = fpSourceSprite->FramesPerSecond;
for (int z=0; z < fpSourceSprite->FrameCount; z++)
{
TDDSpriteFrame *Frame;
if (FrameCount > z)
{
Frame = (TDDSpriteFrame*)FFrames->Items[z];
Frame->Surface->Release();
}
else
{
Frame = new TDDSpriteFrame(this);

// Add to the linked list.

FFrames->Add(Frame);
}

// Initialize the frame.

Frame->Width = fpSourceSprite->Frames[z]->Width;
Frame->Height = fpSourceSprite->Frames[z]->Height;

// set to access caps, width, and height

DDSURFACEDESC ddsd;
CLEAR(&ddsd, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;

// Set Height and Width

ddsd.dwWidth = Frame->Width;
ddsd.dwHeight = Frame->Height;

// set surface to offscreen plain

ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;

// create the new surface

Parent->DDObject->CreateSurface(&ddsd, &(Frame->Surface), NULL);

// Set Transparency

Frame->Transparent = fpSourceSprite->Frames[z]->Transparent;
Frame->TransparentColor = fpSourceSprite->Frames[z]->TransparentColor;

if (Frame->Transparent)
{
DDCOLORKEY ck;
ck.dwColorSpaceHighValue = (DWORD)(Frame->TransparentColor & 0x00FFFFFF);
ck.dwColorSpaceLowValue = (DWORD)(Frame->TransparentColor & 0x00FFFFFF);
Frame->Surface->SetColorKey(DDCKEY_SRCBLT, &ck);
}

RECT Rect;
Rect.left = 0;
Rect.top = 0;
Rect.right = Frame->Width;
Rect.bottom = Frame->Height;

Frame->Surface->BltFast(0, 0, (fpSourceSprite->Frames[z]->Surface),
&Rect, NULL);
}
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::fSetCurrentFrameIndex(unsigned char fpIndex)
{
if (fpIndex < (FrameCount-1))
FCurrentFrameIndex = fpIndex;
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::NextFrame(void)
{
if (FFramesPerSecond > 0)
{
unsigned long int TickCount = GetTickCount();
if ((TickCount - FLastFrameTime) > (unsigned long int)1000/(FFramesPerSecond))
{
if (++FCurrentSequenceFrame >= FSequenceFrameCounts[FCurrentSequenceIndex])
FCurrentSequenceFrame = 0;

FCurrentFrameIndex = FSequences[FCurrentSequenceIndex][FCurrentSequenceFrame];
FLastFrameTime = TickCount;

/* if (FCurrentFrameIndex == (FrameCount-1))
FCurrentFrameIndex = 0;
else
FCurrentFrameIndex++;

FLastFrameTime = TickCount; */

}
}
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::fSetXPos(unsigned short int fpXPos)
{
if (FLockBounds)
{ // NOTE TO SELF: Make DisplayHeight and DisplayWidth functions to retrieve different values, based on DisplayMode

if ((fpXPos <= (Parent->DisplayWidth - CurrentFrame->Width)) &&
(fpXPos > 0))
{
FXPos = fpXPos;
}
}
else
FXPos = fpXPos;
}
//---------------------------------------------------------------------------

void __fastcall TDDSprite::fSetYPos(unsigned short int fpYPos)
{
if (FLockBounds)
{ // NOTE TO SELF: Make DisplayHeight and DisplayWidth functions to retrieve different values, based on DisplayMode

if ((fpYPos <= (Parent->DisplayHeight - CurrentFrame->Height)) &&
(fpYPos > 0))
{
FYPos = fpYPos;
}
}
else
FYPos = fpYPos;
}
//---------------------------------------------------------------------------

TDDSpriteFrame* __fastcall TDDSprite::fGetFrame(unsigned char fpIndex)
{
TDDSpriteFrame *ReturnVal = NULL;

if (fpIndex < FFrames->Count)
ReturnVal = (TDDSpriteFrame*)FFrames->Items[fpIndex];

return ReturnVal;
}
//---------------------------------------------------------------------------

__fastcall TDirectDraw::TDirectDraw(TComponent* Owner)
: TCustomControl(Owner)
{
FDisplayWidth = 640;
FDisplayHeight = 480;
FDisplayBits = 8;
FDisplayResolution = DR_640x480x8;
FParentHandle = ((TWinControl*)Owner)->Handle;
FOwner = Owner;
Color = clBlue;
FGrid = new TDDGrid(this);

FSprites = new TList();
FOverlaySprites = new TList();
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::fDDInitialize(void)
{
if (DirectDrawCreate(NULL, &FDirectDrawObject, NULL) == DD_OK)
return true;
else
return false;
}
//---------------------------------------------------------------------------

void __fastcall TDirectDraw::fSetDisplayResolution(TDisplayResolutions Value)
{
if (Value >= DR_640x480x8)
FDisplayResolution = Value;
else
FDisplayResolution = DR_640x480x8;

switch (Value)
{
case DR_640x480x8:
case DR_640x480x16:
case DR_640x480x24:
case DR_640x480x32:
FDisplayWidth = 640;
FDisplayHeight = 480;
break;
case DR_800x600x8:
case DR_800x600x16:
case DR_800x600x24:
case DR_800x600x32:
FDisplayWidth = 800;
FDisplayHeight = 600;
break;
case DR_1024x768x8:
case DR_1024x768x16:
case DR_1024x768x24:
case DR_1024x768x32:
FDisplayWidth = 1024;
FDisplayHeight = 768;
break;
case DR_1152x864x8:
case DR_1152x864x16:
case DR_1152x864x24:
case DR_1152x864x32:
FDisplayWidth = 1152;
FDisplayHeight = 864;
break;
case DR_1280x768x8:
case DR_1280x768x16:
case DR_1280x768x24:
case DR_1280x768x32:
FDisplayWidth = 1280;
FDisplayHeight = 768;
break;
case DR_1280x1024x8:
case DR_1280x1024x16:
case DR_1280x1024x24:
case DR_1280x1024x32:
FDisplayWidth = 1280;
FDisplayHeight = 1024;
break;
default:
FDisplayWidth = 640;
FDisplayHeight = 480;
break;
}

switch (Value)
{
case DR_640x480x8:
case DR_800x600x8:
case DR_1024x768x8:
case DR_1152x864x8:
case DR_1280x768x8:
case DR_1280x1024x8:
FDisplayBits = 8;
break;
case DR_640x480x16:
case DR_800x600x16:
case DR_1024x768x16:
case DR_1152x864x16:
case DR_1280x768x16:
case DR_1280x1024x16:
FDisplayBits = 16;
break;
case DR_640x480x24:
case DR_800x600x24:
case DR_1024x768x24:
case DR_1152x864x24:
case DR_1280x768x24:
case DR_1280x1024x24:
FDisplayBits = 24;
break;
case DR_640x480x32:
case DR_800x600x32:
case DR_1024x768x32:
case DR_1152x864x32:
case DR_1280x768x32:
case DR_1280x1024x32:
FDisplayBits = 32;
break;
default:
FDisplayBits = 8;
break;
}

FGrid->Update();
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::fDDSetCooperativeLevel(void)
{
bool ReturnVal = true;
DWORD CooperativeFlags = 0;

switch (FDisplayMode)
{
case DM_FULLSCREEN:
CooperativeFlags = DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN;
break;
case DM_WINDOWED:
CooperativeFlags = DDSCL_NORMAL;
break;
default:
CooperativeFlags = DDSCL_NORMAL;
break;
}

if (FDirectDrawObject)
{
if (FDirectDrawObject->SetCooperativeLevel(FParentHandle, CooperativeFlags) != DD_OK)
ReturnVal = false;
}
else
ReturnVal = false;

return ReturnVal;
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::fDDSetDisplayMode(void)
{
if (FDisplayResolution == DR_KEEP_EXISTING)
{
DDSURFACEDESC ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
FDirectDrawObject->GetDisplayMode(&ddsd);
FDisplayWidth = ddsd.dwWidth;
FDisplayHeight = ddsd.dwHeight;
FDisplayBits = ddsd.ddpfPixelFormat.dwRGBBitCount;
}

if (FDirectDrawObject->SetDisplayMode(FDisplayWidth, FDisplayHeight, FDisplayBits) == DD_OK)
return true;
else
return false;
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::fDDCreateSurfaces(void)
{
bool ReturnVal = true;
DDSURFACEDESC ddsd;

memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
ddsd.dwFlags = DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;

if (FDisplayMode == DM_FULLSCREEN)
{
ddsd.dwFlags = DDSD_BACKBUFFERCOUNT | DDSD_CAPS;
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
ddsd.dwBackBufferCount = 1;
}

HRESULT Result = FDirectDrawObject->CreateSurface(&ddsd, &FPrimarySurface, NULL);
switch (Result)
{
case DDERR_INVALIDOBJECT:
case DDERR_INVALIDPARAMS:
case DDERR_OUTOFVIDEOMEMORY:
case DDERR_NODIRECTDRAWHW:
case DDERR_NOCOOPERATIVELEVELSET:
case DDERR_INVALIDCAPS:
case DDERR_INVALIDPIXELFORMAT:
case DDERR_NOALPHAHW:
case DDERR_NOFLIPHW:
case DDERR_NOZBUFFERHW:
case DDERR_NOEXCLUSIVEMODE:
case DDERR_OUTOFMEMORY:
case DDERR_PRIMARYSURFACEALREADYEXISTS:
case DDERR_NOEMULATION:
case DDERR_INCOMPATIBLEPRIMARY:
ReturnVal = false;
break;
}

if (FDisplayMode == DM_FULLSCREEN)
{
DDSCAPS ddscaps;
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
if (FPrimarySurface->GetAttachedSurface(&ddscaps, &FSecondarySurface) != DD_OK)
ReturnVal = false;
}

return ReturnVal;
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::fDDCreateClipper(void)
{
bool ReturnVal = true;

FDirectDrawObject->CreateClipper(0, &FClipper, NULL);
LPRGNDATA RegionData;
RegionData = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + sizeof(RECT));
RECT Rect;

if (FDisplayMode == DM_FULLSCREEN)
{
if (!FGrid->Active)
{
Rect.left = 0;
Rect.top = 0;
Rect.right = FDisplayWidth;
Rect.bottom = FDisplayHeight;
}
/* else
{
Rect.left = 0;
Rect.top = 0;
Rect.right = FGrid->Width;
Rect.bottom = FGrid->Height;
} */

}
else
{
Rect.left = ClientOrigin.x;
Rect.top = ClientOrigin.y;
Rect.right = ClientOrigin.x + Width;
Rect.bottom = ClientOrigin.y + Height;
}

memcpy(RegionData->Buffer, &Rect, sizeof(RECT));
RegionData->rdh.dwSize = sizeof(RGNDATAHEADER);
RegionData->rdh.iType = RDH_RECTANGLES;
RegionData->rdh.nCount = 1;
RegionData->rdh.nRgnSize = sizeof(RECT);

RegionData->rdh.rcBound.left = Rect.left;
RegionData->rdh.rcBound.top = Rect.top;
RegionData->rdh.rcBound.right = Rect.right;
RegionData->rdh.rcBound.bottom = Rect.bottom;

if (FClipper->SetClipList(RegionData, 0) != DD_OK)
ReturnVal = false;

// If displaymode == fullscreen else

if (FSecondarySurface->SetClipper(FClipper) != DD_OK)
ReturnVal = false;
if (FPrimarySurface->SetClipper(FClipper) != DD_OK)
ReturnVal = false;

free(RegionData);

return ReturnVal;
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::fDDDestroyClipper(void)
{
bool ReturnVal = true;

if (FClipper)
FClipper->Release();
else
ReturnVal = false;

return ReturnVal;
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::fDDDestroySurfaces(void)
{
bool ReturnVal = true;

if (FSecondarySurface)
{
FSecondarySurface->Release();
FSecondarySurface = NULL;
}

if (FPrimarySurface)
{
FPrimarySurface->Release();
FPrimarySurface = NULL;
}
else
ReturnVal = false;

return ReturnVal;
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::fDDDestroy(void)
{
if (FDirectDrawObject)
{
FDirectDrawObject->Release();
FDirectDrawObject = NULL;
return true;
}
else
return false;
}
//---------------------------------------------------------------------------

void __fastcall TDirectDraw::fSetActive(bool Value)
{
bool Success = true;
if (Value != FActive)
{
if (Value)
{
Success = Success && fDDInitialize();
Success = Success && fDDSetCooperativeLevel();
Success = Success && fDDSetDisplayMode();
Success = Success && fDDCreateSurfaces();
Success = Success && fDDCreateClipper();
FActive = true;
}
else
{
FActive = false;
Success = Success && fDDDestroyClipper();
Success = Success && fDDDestroySurfaces();
Success = Success && fDDDestroy();
Success = Success && (FDirectDrawObject->RestoreDisplayMode() == DD_OK);
}
}

// Throw a messagebox to tell the user that something is wrong.

if (!Success)
{
Application->MessageBox("Direct Draw could not initiate or shutdown.",
"Error", MB_OK);
}
}
//---------------------------------------------------------------------------

TDDSprite* __fastcall TDirectDraw::fGetSprite(int Index)
{
TDDSprite *ReturnVal = NULL;
if ((Index >= 0) && (Index < FSprites->Count))
ReturnVal = (TDDSprite*)FSprites->Items[Index];

return ReturnVal;
}
//---------------------------------------------------------------------------

TDDSprite* __fastcall TDirectDraw::fGetOverlaySprite(int Index)
{
TDDSprite *ReturnVal = NULL;
if ((Index >= 0) && (Index < FOverlaySprites->Count))
ReturnVal = (TDDSprite*)FOverlaySprites->Items[Index];

return ReturnVal;
}
//---------------------------------------------------------------------------

TDDSprite* __fastcall TDirectDraw::CreateSprite(unsigned char fpFramesPerSecond)
{
TDDSprite *NewDDSprite = NULL;

// Initialize the Sprite

NewDDSprite = new TDDSprite(this);
NewDDSprite->Visible = true;

// Set frame's index.

NewDDSprite->Index = FSprites->Count;

// Add the sprite to the linked list.

FSprites->Add(NewDDSprite);

// Set Frames Per Second if valid.

if (fpFramesPerSecond != NULL)
NewDDSprite->FramesPerSecond = fpFramesPerSecond;

return NewDDSprite;
}
//---------------------------------------------------------------------------

TDDSprite* __fastcall TDirectDraw::CreateOverlaySprite(unsigned char fpFramesPerSecond)
{
TDDSprite *NewDDSprite = NULL;

// Initialize the Sprite

NewDDSprite = new TDDSprite(this);
NewDDSprite->Visible = true;

// Set frame's index.

NewDDSprite->Index = FOverlaySprites->Count;

// Add the sprite to the linked list.

FOverlaySprites->Add(NewDDSprite);

// Set Frames Per Second if valid.

if (fpFramesPerSecond != NULL)
NewDDSprite->FramesPerSecond = fpFramesPerSecond;

return NewDDSprite;
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::LoadStandardPalette(void)
{
bool ReturnVal = true;
static PALETTEENTRY pePalette[256];
memset(pePalette, 0, 256*sizeof(PALETTEENTRY));
LPDIRECTDRAWPALETTE lpddpal;

if (FActive)
{
for (int x=0; x < 256; x++)
{
if (x < 64)
pePalette[x].peRed = x*4;
else if ((x >= 64) && (x < 128))
pePalette[x].peGreen = (x-64)*4;
else if ((x >= 128) && (x < 192))
pePalette[x].peBlue = (x-128)*4;
else if ((x >= 192) && (x < 256))
pePalette[x].peRed = pePalette[x].peGreen = pePalette[x].peBlue = (x-192)*4;

pePalette[x].peFlags = PC_NOCOLLAPSE;
}
}
else
ReturnVal = false;

if (FDirectDrawObject->CreatePalette(DDPCAPS_8BIT | DDPCAPS_INITIALIZE | DDPCAPS_ALLOW256, pePalette, &lpddpal, NULL) != DD_OK)
ReturnVal = false;
else
if (FPrimarySurface->SetPalette(lpddpal) != DD_OK)
ReturnVal = false;

return ReturnVal;
}
//---------------------------------------------------------------------------

void __fastcall TDirectDraw::AlignOverlayToGrid(int fpOverlaySpriteIndex,
int fpGridX, int fpGridY)
{
TDDSprite *Sprite = (TDDSprite*)FOverlaySprites->Items[fpOverlaySpriteIndex];
Sprite->XPos = fpGridX*FGrid->CellWidth + FGrid->XOffset;
Sprite->YPos = fpGridY*FGrid->CellHeight + FGrid->YOffset;


}
//---------------------------------------------------------------------------

void __fastcall TDirectDraw::SetSpritesFramesPerSecond(unsigned char fpStartIndex,
unsigned char fpStopIndex, unsigned char fpFramesPerSecond)
{
if ((fpStartIndex < FSprites->Count) && (fpStopIndex < FSprites->Count) &&
(fpStartIndex < fpStopIndex))
{
for (int x=fpStartIndex; x <= fpStopIndex; x++)
((TDDSprite*)FSprites->Items[x])->FramesPerSecond = fpFramesPerSecond;
}
}
//---------------------------------------------------------------------------

void __fastcall TDirectDraw::SetOverlaySpritesFramesPerSecond(unsigned char fpStartIndex,
unsigned char fpStopIndex, unsigned char fpFramesPerSecond)
{
if ((fpStartIndex < FOverlaySprites->Count) &&
(fpStopIndex < FOverlaySprites->Count) && (fpStartIndex < fpStopIndex))
{
for (int x=fpStartIndex; x <= fpStopIndex; x++)
((TDDSprite*)FOverlaySprites->Items[x])->FramesPerSecond = fpFramesPerSecond;
}
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::Draw(void)
{
bool ReturnVal = false;
RECT Source;
RECT Dest;

// Full screen render

if ((FDisplayMode == DM_FULLSCREEN) && (FPrimarySurface) && (FSecondarySurface))
{
LPRGNDATA RegionData;
RegionData = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + sizeof(RECT));

RECT Rect;
Rect.left = 0;
Rect.top = 0;
Rect.right = FDisplayWidth;
Rect.bottom = FDisplayHeight;

memcpy(RegionData->Buffer, &Rect, sizeof(RECT));
RegionData->rdh.dwSize = sizeof(RGNDATAHEADER);
RegionData->rdh.iType = RDH_RECTANGLES;
RegionData->rdh.nCount = 1;
RegionData->rdh.nRgnSize = sizeof(RECT);

RegionData->rdh.rcBound.left = Rect.left;
RegionData->rdh.rcBound.top = Rect.top;
RegionData->rdh.rcBound.right = Rect.right;
RegionData->rdh.rcBound.bottom = Rect.bottom;

FClipper->SetClipList(RegionData, 0);
FSecondarySurface->SetClipper(FClipper);

free(RegionData);

DDBLTFX ddbltfx;
CLEAR(&ddbltfx, sizeof(ddbltfx));
ddbltfx.dwSize = sizeof(ddbltfx);
ddbltfx.dwFillColor = 0;
FSecondarySurface->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT,
&ddbltfx);

// Render each sprite based on their position if Grid is NOT active.

if (!FGrid->Active)
{
// Render the normal sprites.

for (int z=0; z < FSprites->Count; z++)
{
TDDSprite *Sprite = ((TDDSprite*)FSprites->Items[z]);
if (Sprite->Visible)
{
TPoint ptStartPoint = Point(Sprite->XPos, Sprite->YPos);
TPoint ptEndPoint = Point(Sprite->XPos +
Sprite->CurrentFrame->Width,
Sprite->YPos + Sprite->CurrentFrame->Height);

if (Sprite->CurrentFrame->Transparent)
{
FSecondarySurface->BltFast(ptStartPoint.x, ptStartPoint.y,
Sprite->CurrentFrame->Surface, NULL,
DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY);
}
else
{
FSecondarySurface->BltFast(ptStartPoint.x, ptStartPoint.y,
Sprite->CurrentFrame->Surface, NULL,
DDBLTFAST_WAIT | DDBLTFAST_NOCOLORKEY);
}
}
}
}
else // Render each sprite based on Grid if it IS active.

{
// Render the normal grid.

// Only render the inner rows and columns. The outer ones are for

// animating a movement from one section to the next using Offsets.


LPRGNDATA RegionData;
RegionData = (LPRGNDATA)malloc(sizeof(RGNDATAHEADER) + sizeof(RECT));

RECT Rect;
Rect.left = 0;
Rect.top = 0;
Rect.right = FGrid->Width;
Rect.bottom = FGrid->Height;

memcpy(RegionData->Buffer, &Rect, sizeof(RECT));
RegionData->rdh.dwSize = sizeof(RGNDATAHEADER);
RegionData->rdh.iType = RDH_RECTANGLES;
RegionData->rdh.nCount = 1;
RegionData->rdh.nRgnSize = sizeof(RECT);

RegionData->rdh.rcBound.left = Rect.left;
RegionData->rdh.rcBound.top = Rect.top;
RegionData->rdh.rcBound.right = Rect.right;
RegionData->rdh.rcBound.bottom = Rect.bottom;

FClipper->SetClipList(RegionData, 0);
FSecondarySurface->SetClipper(FClipper);

free(RegionData);

for (int y=(FGrid->RowCount-1); y >= 0; y--)
{
for (int x=(FGrid->ColumnCount-1); x >= 0; x--)
{
TDDSprite *Sprite = ((TDDSprite*)FSprites->Items[FGrid->Cells[x][y]]);

if (Sprite->Visible)
{
TPoint ptStartPoint = Point(FGrid->CellWidth*(x-1) + FGrid->XStart + FGrid->XOffset,
FGrid->CellHeight*(y-1) + FGrid->YStart + FGrid->YOffset);
TPoint ptEndPoint = Point(ptStartPoint.x +
Sprite->CurrentFrame->Width, ptStartPoint.y +
Sprite->CurrentFrame->Height);

Source.left = 0;
Source.top = 0;
Source.right = Sprite->CurrentFrame->Width;
Source.bottom = Sprite->CurrentFrame->Height;
Dest.left = ptStartPoint.x;
Dest.top = ptStartPoint.y;
Dest.right = ptEndPoint.x;
Dest.bottom = ptEndPoint.y;

if (Sprite->CurrentFrame->Transparent)
{
FSecondarySurface->Blt(&Dest, Sprite->CurrentFrame->Surface,
&Source, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
}
else
{
FSecondarySurface->Blt(&Dest, Sprite->CurrentFrame->Surface,
&Source, DDBLT_WAIT, NULL);
}
}
}
}
}

// Render the overlay sprites.

for (int z=0; z < FOverlaySprites->Count; z++)
{
TDDSprite *Sprite = ((TDDSprite*)FOverlaySprites->Items[z]);
if (Sprite->Visible)
{

TPoint ptStartPoint = Point(Sprite->XPos, Sprite->YPos);
TPoint ptEndPoint = Point(Sprite->XPos +
Sprite->CurrentFrame->Width,
Sprite->YPos + Sprite->CurrentFrame->Height);

Source.left = 0;
Source.top = 0;
Source.right = Sprite->CurrentFrame->Width;
Source.bottom = Sprite->CurrentFrame->Height;
Dest.left = ptStartPoint.x;
Dest.top = ptStartPoint.y;
Dest.right = ptEndPoint.x;
Dest.bottom = ptEndPoint.y;

if (Sprite->CurrentFrame->Transparent)
{
FSecondarySurface->Blt(&Dest, Sprite->CurrentFrame->Surface,
&Source, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
}
else
{
FSecondarySurface->Blt(&Dest, Sprite->CurrentFrame->Surface,
&Source, DDBLT_WAIT, NULL);
}
}
}

// Flip the surfaces.

FPrimarySurface->Flip(NULL, DDFLIP_WAIT);
}
else if ((FDisplayMode == DM_WINDOWED) && (FPrimarySurface))
{
DDBLTFX ddbltfx;
CLEAR(&ddbltfx, sizeof(ddbltfx));
ddbltfx.dwFillColor = 0;
FPrimarySurface->Blt(NULL, NULL, NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx);

for (int z=0; z < FSprites->Count; z++)
{
TDDSprite *Sprite = ((TDDSprite*)FSprites->Items[z]);
if (Sprite->Visible)
{
TPoint ptStartPoint = ClientOrigin;
TPoint ptEndPoint = ClientOrigin;
ptStartPoint.x += Sprite->XPos;
ptStartPoint.y += Sprite->YPos;
ptEndPoint.x += (Sprite->XPos + Sprite->CurrentFrame->Width);
ptEndPoint.y += (Sprite->YPos + Sprite->CurrentFrame->Height);

FPrimarySurface->BltFast(ptStartPoint.x, ptStartPoint.y,
Sprite->CurrentFrame->Surface, NULL,
DDBLTFAST_WAIT | DDBLTFAST_NOCOLORKEY);
}
}
}

return ReturnVal;
}
//---------------------------------------------------------------------------

void __fastcall TDirectDraw::AllSpritesNextFrame(void)
{
for (int x=0; x < FSprites->Count; x++)
((TDDSprite*)FSprites->Items[x])->NextFrame();
}
//---------------------------------------------------------------------------

void __fastcall TDirectDraw::AllOverlaySpritesNextFrame(void)
{
for (int x=0; x < FOverlaySprites->Count; x++)
((TDDSprite*)FOverlaySprites->Items[x])->NextFrame();
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::FillSurface(int Red, int Green, int Blue)
{
bool ReturnVal = true;

if ((FDisplayBits >= 16) && FActive)
{
DDSURFACEDESC ddsd;
memset(&ddsd,0,sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
USHORT *psBuffer;
UINT *piBuffer;

TPoint ptStartPoint = Point(0,0);
TPoint ptEndPoint = Point(FDisplayWidth, FDisplayHeight);
if (FDisplayMode != DM_FULLSCREEN)
{
if (FPrimarySurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL) != DD_OK)
{
ptEndPoint = Point(0,0);
ReturnVal = false;
}
else
{
ptStartPoint = ClientOrigin;
if (ptStartPoint.x < 0)
ptStartPoint.x = 0;
if (ptStartPoint.y < 0)
ptStartPoint.y = 0;

ptEndPoint = Point(ClientOrigin.x + Width, ClientOrigin.y + Height);
if (ptEndPoint.x > FDisplayWidth)
ptEndPoint.x = FDisplayWidth-1;
if (ptEndPoint.x < 0)
ptEndPoint.x = 0;
if (ptEndPoint.y > FDisplayHeight)
ptEndPoint.y = FDisplayHeight-1;
if (ptEndPoint.y < 0)
ptEndPoint.y = 0;
}
}
else
{
if (FSecondarySurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL) != DD_OK)
ReturnVal = false;
}

psBuffer = (USHORT*)ddsd.lpSurface;
piBuffer = (UINT*)ddsd.lpSurface;
int pitch;

if (FDisplayBits >= 24)
{
pitch = (ddsd.lPitch >> 2) - FDisplayWidth;
for (int y=ptStartPoint.y; y < ptEndPoint.y; y++)
{
for (int x=ptStartPoint.x; x < ptEndPoint.x; x++)
{
*piBuffer = (UINT)RGB24BIT(Red, Green, Blue);
piBuffer++;
}
piBuffer += pitch;
}
}
else
{
pitch = (ddsd.lPitch >> 1) - FDisplayWidth;
for (int y=ptStartPoint.y; y < ptEndPoint.y; y++)
{
for (int x=ptStartPoint.x; x < ptEndPoint.x; x++)
{
*psBuffer = (USHORT)RGB16BIT(Red, Green, Blue);
psBuffer++;
}
psBuffer += pitch;
}
}

if (FDisplayMode != DM_FULLSCREEN)
{
if (FPrimarySurface->Unlock(ddsd.lpSurface) != DD_OK)
ReturnVal = false;
}
else
{
if (FSecondarySurface->Unlock(ddsd.lpSurface) != DD_OK)
ReturnVal = false;
else
if (FPrimarySurface->Flip(NULL, DDFLIP_WAIT) != DD_OK)
ReturnVal = false;
}
}
else
ReturnVal = false;

return ReturnVal;
}
//---------------------------------------------------------------------------

bool __fastcall TDirectDraw::FillSurface(int iPaletteIndex)
{
bool ReturnVal = true;

if ((FDisplayBits == 8) && FActive)
{
UCHAR *pVideoBuffer = NULL;
DDSURFACEDESC ddsd;
memset(&ddsd, 0, sizeof(ddsd));
ddsd.dwSize = sizeof(ddsd);
if (FSecondarySurface->Lock(NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL) != DD_OK)
ReturnVal = false;
else
{
pVideoBuffer = (UCHAR*) ddsd.lpSurface;
int pitch = ddsd.lPitch - FDisplayWidth;

for (int y=0; y < FDisplayHeight; y++)
{
for (int x=0; x < FDisplayWidth; x++)
{
*pVideoBuffer = iPaletteIndex;
pVideoBuffer++;
}
pVideoBuffer += pitch;
}

if (FSecondarySurface->Unlock(ddsd.lpSurface) != DD_OK)
ReturnVal = false;
else
FPrimarySurface->Flip(NULL, DDFLIP_WAIT);
}
}
else
ReturnVal = false;

return ReturnVal;
}
//---------------------------------------------------------------------------

void __fastcall TDirectDraw::fSetDisplayMode(TDisplayModes Value)
{
FDisplayMode = Value;

// if (FOwner->ClassNameIs("TCustomForm"))

{
TForm *MainForm = (TForm*)FOwner;
if (Value == DM_FULLSCREEN)
{
MainForm->WindowState = wsMaximized;
MainForm->BorderStyle = bsNone;
TBorderIcons EmptyIcons;
MainForm->BorderIcons = EmptyIcons ;
}
else
{
MainForm->WindowState = wsNormal;
MainForm->BorderStyle = bsSingle;
TBorderIcons Icons;
Icons << biSystemMenu << biMinimize << biMaximize << biHelp;
MainForm->BorderIcons = Icons;
}
}
}
//---------------------------------------------------------------------------

__fastcall TDirectDraw::~TDirectDraw(void)
{
fDDDestroySurfaces();
fDDDestroy();
}


Chris

[edited by - Supernat02 on January 10, 2004 11:51:23 PM]
Chris ByersMicrosoft DirectX MVP - 2005
Deciheximal
Deciheximal
Thanks for answering guys, sorry for the time gap. A follow up post will soon follow.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.