diff --git a/Bitmaps/Shield.bmp b/Bitmaps/Shield.bmp new file mode 100644 index 0000000..0ae3ab9 Binary files /dev/null and b/Bitmaps/Shield.bmp differ diff --git a/Bitmaps/bullet.bmp b/Bitmaps/bullet.bmp new file mode 100644 index 0000000..5424e68 Binary files /dev/null and b/Bitmaps/bullet.bmp differ diff --git a/Bitmaps/bullet.bmp.ufo b/Bitmaps/bullet.bmp.ufo new file mode 100644 index 0000000..5b2ebcb Binary files /dev/null and b/Bitmaps/bullet.bmp.ufo differ diff --git a/Bitmaps/logo.bmp b/Bitmaps/logo.bmp new file mode 100644 index 0000000..96eb803 Binary files /dev/null and b/Bitmaps/logo.bmp differ diff --git a/Bitmaps/ship.bmp b/Bitmaps/ship.bmp new file mode 100644 index 0000000..cbe77ba Binary files /dev/null and b/Bitmaps/ship.bmp differ diff --git a/Bitmaps/si.bmp b/Bitmaps/si.bmp new file mode 100644 index 0000000..1c41573 Binary files /dev/null and b/Bitmaps/si.bmp differ diff --git a/Bitmaps/title.bmp b/Bitmaps/title.bmp new file mode 100644 index 0000000..f0dc85a Binary files /dev/null and b/Bitmaps/title.bmp differ diff --git a/Bitmaps/ufo.bmp b/Bitmaps/ufo.bmp new file mode 100644 index 0000000..6a0510f Binary files /dev/null and b/Bitmaps/ufo.bmp differ diff --git a/CDXAddons/CDXHPC/cdxhpc.cpp b/CDXAddons/CDXHPC/cdxhpc.cpp new file mode 100644 index 0000000..46488ee --- /dev/null +++ b/CDXAddons/CDXHPC/cdxhpc.cpp @@ -0,0 +1,101 @@ +///////////////////////////////////////////////////////////////////// +// Project Name: [ CDX Class Library - CDX.lib ] +// Source File: [ CDX High Performance Counter Implementation] +// Author: [ Bil Simser - bsimser@home.com ] +// Contributions: [ Michael Rich, Jimb Esser ] +// Revision: [ 2.0 ] +///////////////////////////////////////////////////////////////////// + +#include "cdxhpc.h" + + +///////////////////////////////////////////////////////////////////// +// constructor +///////////////////////////////////////////////////////////////////// +CDXHPC::CDXHPC() +{ + // init to zero + freq.QuadPart = 0; + restart.QuadPart = 0; + bPaused = FALSE; +} + +///////////////////////////////////////////////////////////////////// +// starts the counter +///////////////////////////////////////////////////////////////////// +BOOL CDXHPC::Start() +{ + QueryPerformanceCounter(&restart); + if (!QueryPerformanceFrequency(&freq)) return FALSE; + // convert it down to milliseconds + freq.QuadPart /= 1000; + return TRUE; +} + +///////////////////////////////////////////////////////////////////// +// returns the current # of ms since counter was started +///////////////////////////////////////////////////////////////////// +DWORD CDXHPC::GetValue() +{ + if (bPaused) + return (DWORD)((paused.QuadPart - restart.QuadPart) / freq.QuadPart); + LARGE_INTEGER timer; + QueryPerformanceCounter(&timer); + return (DWORD)((timer.QuadPart - restart.QuadPart) / freq.QuadPart); +} + +///////////////////////////////////////////////////////////////////// +// waits for a specified ms since the counter was started +// note that if its already been that long since it was started +// the function would exit immediately +///////////////////////////////////////////////////////////////////// +void CDXHPC::Wait(DWORD dwMilliSecs) +{ + while (TRUE) + { + if (GetValue()>=dwMilliSecs) break; + } +} + +///////////////////////////////////////////////////////////////////// +// waits for a specified ms after the function is called +///////////////////////////////////////////////////////////////////// +void CDXHPC::WaitFor(DWORD dwWaitTime) +{ + DWORD dwStart = GetValue(); + while (TRUE) + { + if (GetValue() - dwStart >= dwWaitTime) break; + } +} + + +///////////////////////////////////////////////////////////////////// +// resets the counter back to zero +///////////////////////////////////////////////////////////////////// +void CDXHPC::Reset() +{ + LARGE_INTEGER timer, excess; + QueryPerformanceCounter(&timer); + excess.QuadPart = (timer.QuadPart - restart.QuadPart) % freq.QuadPart; + QueryPerformanceCounter(&restart); + restart.QuadPart -= excess.QuadPart; +} + +void CDXHPC::Pause() +{ + if (!bPaused) { + QueryPerformanceCounter(&paused); + bPaused = TRUE; + } +} + +void CDXHPC::Resume() +{ + if (bPaused) { + LARGE_INTEGER timer; + QueryPerformanceCounter(&timer); + restart.QuadPart += timer.QuadPart - paused.QuadPart; + bPaused = FALSE; + } +} diff --git a/CDXAddons/CDXHPC/cdxhpc.h b/CDXAddons/CDXHPC/cdxhpc.h new file mode 100644 index 0000000..00d5015 --- /dev/null +++ b/CDXAddons/CDXHPC/cdxhpc.h @@ -0,0 +1,40 @@ +// CDXHPC class, with additional functions - Pause and Resume added by Jimb Esser + +#ifndef _H_CDXHPC +#define _H_CDXHPC + +#define WIN32_EXTRA_LEAN +#include + +class CDXHPC +{ +public: + // constructor + CDXHPC(); + // destructor + virtual ~CDXHPC() {}; + + // starts the counter + BOOL Start(); + // returns the current # of ms since counter was started + DWORD GetValue(); + // waits for a specified ms since the counter was started + // note that if its already been that long since it was started + // the function would exit immediately + void Wait(DWORD dwStopTime); + // waits for a specified ms after the function is called + void WaitFor(DWORD dwWaitTime); + + // resets the counter back to zero + void Reset(); + + void Pause(); + void Resume(); + +protected: + // counter variables + LARGE_INTEGER freq, restart, paused; + BOOL bPaused; +}; + +#endif /* #ifndef _H_CDXHPC */ diff --git a/CDXAddons/CDXMenu/CDXMENU.CPP b/CDXAddons/CDXMenu/CDXMENU.CPP new file mode 100644 index 0000000..3b9f80b --- /dev/null +++ b/CDXAddons/CDXMenu/CDXMENU.CPP @@ -0,0 +1,271 @@ +////////////////////////////////////////////////////////////////////////////////// +// $Source: /cvsroot/cdx/cdx3.0/addons/CDXMenu/CDXMENU.CPP,v $ +// $Author: mindcry $ +// +// $Log: CDXMENU.CPP,v $ +// Revision 1.2 2000/06/30 08:31:46 mindcry +// Some minor fixes from Mike +// +// Revision 1.1.1.1 2000/04/22 16:50:12 hebertjo +// Initial checkin of v3.0 to SourceForge CVS. +// +// Revision 1.1.1.1 1999/05/04 23:59:23 bsimser +// Imported addons +// +// $Revision: 1.2 $ +////////////////////////////////////////////////////////////////////////////////// +#include "CDX.h" +#include "CDXMenu.h" + +////////////////////////////////////////////////////////////////////////////////// +// CDXMenu Default Constructor +////////////////////////////////////////////////////////////////////////////////// +CDXMenu::CDXMenu() +{ +} + +////////////////////////////////////////////////////////////////////////////////// +// CDXMenu Constructor +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::Create(CDXSurface *pSurface, int Spacing) +{ + m_Spacing = Spacing; + m_ItemCount = 0; + m_CurrentItem = 0; + m_pSurface = pSurface; + m_bWrap = TRUE; + ZeroMemory(&m_Title, sizeof(m_Title)); +} + +////////////////////////////////////////////////////////////////////////////////// +// Sets the wrapping capabilities of the menu +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::SetWrap(BOOL bWrap) +{ + m_bWrap = bWrap; +} + +////////////////////////////////////////////////////////////////////////////////// +// Sets the title used by the menu (optional) +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::SetTitle(const char *szTitle, COLORREF color) +{ + strcpy(m_Title.m_szTitle, szTitle); + m_Title.m_color = color; + m_Title.m_bActive = TRUE; +} + +////////////////////////////////////////////////////////////////////////////////// +// Adds an item to the menu +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::AddItem(char *szString, COLORREF oncolor, COLORREF offcolor, COLORREF disabledcolor) +{ + strcpy(m_MenuItems[m_ItemCount].m_szString, szString); + m_MenuItems[m_ItemCount].m_OnColor = oncolor; + m_MenuItems[m_ItemCount].m_OffColor = offcolor; + m_MenuItems[m_ItemCount].m_DisabledColor = disabledcolor; + m_MenuItems[m_ItemCount].m_Enabled = TRUE; + m_ItemCount++; +} + +////////////////////////////////////////////////////////////////////////////////// +// Returns the current menu item +////////////////////////////////////////////////////////////////////////////////// +int CDXMenu::Enter() +{ + return m_CurrentItem; +} + +////////////////////////////////////////////////////////////////////////////////// +// Enables / Disables a menu item +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::EnableItem(int item, BOOL bEnable) +{ + m_MenuItems[item].m_Enabled = bEnable; +} + +////////////////////////////////////////////////////////////////////////////////// +// Sets the current item to the first on in the menu +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::Home() +{ + m_CurrentItem = 0; +} + +////////////////////////////////////////////////////////////////////////////////// +// Moves up one menu option. If wrapping is enabled, wraps to the last item +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::Up() +{ + m_CurrentItem--; + if(m_CurrentItem < 0) { + if(m_bWrap) { + End(); + } + else { + Home(); + } + } + if (!m_MenuItems[m_CurrentItem].m_Enabled) Up(); +} + +////////////////////////////////////////////////////////////////////////////////// +// Moves down one menu option. If wrapping is enabled, wraps to the first item +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::Down() +{ + m_CurrentItem++; + if(m_CurrentItem > (m_ItemCount-1)) { + if(m_bWrap) { + Home(); + } + else { + End(); + } + } + if (!m_MenuItems[m_CurrentItem].m_Enabled) Down(); +} + +////////////////////////////////////////////////////////////////////////////////// +// Sets the last menu item as the current one +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::End() +{ + m_CurrentItem = m_ItemCount - 1; +} + +////////////////////////////////////////////////////////////////////////////////// +// Draws the menu to the surface specified in the constructor. This method +// draws the menu centered on the screen and centers all the items in +// the menu. +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::DrawCentered(void) +{ + SIZE sz; + COLORREF col; + int X, Y, i; + HDC hdc; + + hdc = m_pSurface->GetDC(); + m_pSurface->SetFont(); + + // get the height and width of the title in the current font + GetTextExtentPoint32(hdc, m_Title.m_szTitle, + lstrlen(m_Title.m_szTitle), &sz); + + // calc the full height of the menu + int mh = (m_Spacing * (m_ItemCount)); + + // if the title is active add it to the height + if(m_Title.m_bActive) { + mh+=m_Spacing; + } + + // calc the vertical starting point + Y = (m_pSurface->GetHeight() - mh) / 2; + + // draw the title if its active + if(m_Title.m_bActive) { + // determine the X drawing for the title and draw it + X = (m_pSurface->GetWidth() - sz.cx) / 2; + m_pSurface->TextXY(X, Y, m_Title.m_color, m_Title.m_szTitle); + } + + // draw all the items + for(i=0; iGetWidth() - sz.cx) / 2; + + col = (i == m_CurrentItem) ? m_MenuItems[i].m_OnColor : m_MenuItems[i].m_OffColor; + if (!m_MenuItems[i].m_Enabled) col = m_MenuItems[i].m_DisabledColor; + if(m_Title.m_bActive) { + m_pSurface->TextXY(X, Y+((i+1)*m_Spacing), col, m_MenuItems[i].m_szString); + } + else { + m_pSurface->TextXY(X, Y+((i+1)*m_Spacing), col, m_MenuItems[i].m_szString); + } + } + + m_pSurface->ReleaseDC(); +} + +////////////////////////////////////////////////////////////////////////////////// +// Draws the menu to the surface specified in the constructor. This +// method figures out the X and Y values and places the menu in the +// center of the screen +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::Draw(void) +{ + SIZE sz; + int dwWidest, i; + HDC hdc; + + hdc = m_pSurface->GetDC(); + m_pSurface->SetFont(); + + // get the height and width of the title in the current font + GetTextExtentPoint32(hdc, m_Title.m_szTitle, + lstrlen(m_Title.m_szTitle), &sz); + + // calc the full height of the menu + int mh = (m_Spacing * (m_ItemCount)); + + // if the title is active, add it to the height also + if(m_Title.m_bActive) { + dwWidest = sz.cx; + mh+=m_Spacing; + } + else { + dwWidest = 0; + } + + // go through each item and figure out the widest one + for(i=0; iGetWidth() - dwWidest) / 2; + int Y = (m_pSurface->GetHeight() - mh) / 2; + + // release the handle and draw the menu + m_pSurface->ReleaseDC(); + + Draw(X, Y); +} + +////////////////////////////////////////////////////////////////////////////////// +// Draws the menu to the surface specified in the constructor. This +// uses the X and Y parameters passed to place the menu. +////////////////////////////////////////////////////////////////////////////////// +void CDXMenu::Draw(int X, int Y) +{ + COLORREF col; + int i; + + m_pSurface->GetDC(); + m_pSurface->SetFont(); + + if(m_Title.m_bActive) { + m_pSurface->TextXY(X, Y, m_Title.m_color, m_Title.m_szTitle); + } + + for(i=0; iTextXY(X, Y+((i+1)*m_Spacing), col, m_MenuItems[i].m_szString); + } + else { + m_pSurface->TextXY(X, Y+(i+1*m_Spacing), col, m_MenuItems[i].m_szString); + } + } + + m_pSurface->ReleaseDC(); +} diff --git a/CDXAddons/CDXMenu/Cdxmenu.h b/CDXAddons/CDXMenu/Cdxmenu.h new file mode 100644 index 0000000..46d4fd3 --- /dev/null +++ b/CDXAddons/CDXMenu/Cdxmenu.h @@ -0,0 +1,72 @@ +////////////////////////////////////////////////////////////////////////////////// +// $Source: /cvsroot/cdx/cdx3.0/addons/CDXMenu/CDXMENU.H,v $ +// $Author: mindcry $ +// +// $Log: CDXMENU.H,v $ +// Revision 1.2 2000/06/30 08:33:46 mindcry +// Some minor fixes from Mike +// +// Revision 1.1.1.1 2000/04/22 16:50:12 hebertjo +// Initial checkin of v3.0 to SourceForge CVS. +// +// Revision 1.1.1.1 1999/05/04 23:59:23 bsimser +// Imported addons +// +// $Revision: 1.2 $ +////////////////////////////////////////////////////////////////////////////////// + +#define MAX_MENU_ITEMS 21 //MIRZA +#define MAX_STRING_LENGTH 80 + +class CDXMenu +{ +public: + CDXMenu(); + void Create(CDXSurface *pSurface, int Spacing); + void SetTitle(const char *szTitle, COLORREF color); + void SetWrap(BOOL bWrap); + void AddItem(char *szString, COLORREF oncolor, COLORREF offcolor, COLORREF disabledcolor=RGB(0xaa,0xaa,0xaa)); + void EnableItem(int item, BOOL bEnable); + + // drawing related + void DrawCentered(void); + void Draw(void); + void Draw(int X, int Y); + + // selection modification + void Up(void); + void Down(void); + void Home(void); + void End(void); + int Enter(void); + + CDXSurface *GetSurface() { return m_pSurface; }; + //MIRZA + int GetCurrentItem() { return m_CurrentItem; } + void SetCurrentItem(int nNewValue) { m_CurrentItem = nNewValue; } + int GetItemCount() { return m_ItemCount; } + + + +private: + CDXSurface *m_pSurface; + + struct MenuItem { + char m_szString[MAX_STRING_LENGTH]; + COLORREF m_OnColor; + COLORREF m_OffColor; + COLORREF m_DisabledColor; + BOOL m_Enabled; + } m_MenuItems[MAX_MENU_ITEMS]; + + int m_ItemCount; + int m_Spacing; + int m_CurrentItem; + BOOL m_bWrap; + + struct Title { + char m_szTitle[MAX_STRING_LENGTH]; + COLORREF m_color; + BOOL m_bActive; + } m_Title; +}; diff --git a/CDXAddons/CDXStar/Cdxstar.cpp b/CDXAddons/CDXStar/Cdxstar.cpp new file mode 100644 index 0000000..1c16e8e --- /dev/null +++ b/CDXAddons/CDXStar/Cdxstar.cpp @@ -0,0 +1,200 @@ +////////////////////////////////////////////////////////////////////////////////// +// $Source: /cvsroot/cdx/cdx3.0/examples/vc/ex9/CDXSTAR.CPP,v $ +// $Author: istan $ +// +// $Log: CDXSTAR.CPP,v $ +// Revision 1.1 2001/02/17 18:19:30 istan +// Added to the repository +// +// Revision 1.1.1.1 1999/05/04 23:59:23 bsimser +// Imported addons +// +// $Revision: 1.1 $ +////////////////////////////////////////////////////////////////////////////////// +#include "CDX.h" +#include "CDXStar.h" +#include + +////////////////////////////////////////////////////////////////////////////////// +// CDXStarField Constructor +////////////////////////////////////////////////////////////////////////////////// +CDXStarField::CDXStarField(CDXScreen *pScreen) +{ + m_Screen = pScreen; + m_NumStars = 100; + m_StarVelocity = 1; + m_Top = 0; + m_Left = 0; + m_Width = m_Screen->GetWidth(); + m_Right = m_Width; + m_Height = m_Screen->GetHeight(); + m_Bottom = m_Height-32; + m_CenterX = m_Width / 2; + m_CenterY = m_Height / 2; + m_StarMode = THREED; + m_Towards = TRUE; + m_Colored = TRUE; +} + +////////////////////////////////////////////////////////////////////////////////// +// CDXStarField Destructor +////////////////////////////////////////////////////////////////////////////////// +CDXStarField::~CDXStarField() +{ +} + +////////////////////////////////////////////////////////////////////////////////// +// CDXStarField Create +////////////////////////////////////////////////////////////////////////////////// +void CDXStarField::Create() +{ + CreateStars(); + CalcPosition(); +} + +////////////////////////////////////////////////////////////////////////////////// +// CDXStarField Update +////////////////////////////////////////////////////////////////////////////////// +void CDXStarField::Update(BOOL bErase) +{ + if(bErase) + ClearStars(); + CalcPosition(); +} + +////////////////////////////////////////////////////////////////////////////////// +// CDXStarField CreateStars +////////////////////////////////////////////////////////////////////////////////// +void CDXStarField::CreateStars() +{ + srand((unsigned)time(NULL)); + for(int i=0; iGetBack()->Lock(); + + for(int i=0; i 0) && (m_Stars[i].m_Z < 256)) + { + newx = ((m_Stars[i].m_X << 7) / m_Stars[i].m_Z) + m_CenterX; + newy = ((m_Stars[i].m_Y << 7) / m_Stars[i].m_Z) + m_CenterY; + if((newx > m_Left) && (newx < m_Right) && + (newy > m_Top) && (newy < m_Bottom)) + { + /* if(!m_Colored) + { + if(m_Flashing) + m_Stars[i].m_Color = rand()%255; + else + { + if(m_Stars[i].m_Z >= 0 && m_Stars[i].m_Z < 50) + m_Stars[i].m_Color = 244; + else if(m_Stars[i].m_Z >= 50 && m_Stars[i].m_Z < 100) + m_Stars[i].m_Color = 243; + else if(m_Stars[i].m_Z >= 100 && m_Stars[i].m_Z < 150) + m_Stars[i].m_Color = 242; + else if(m_Stars[i].m_Z >= 150 && m_Stars[i].m_Z < 200) + m_Stars[i].m_Color = 241; + else + m_Stars[i].m_Color = 240; + } + } + + */ + + m_Screen->GetBack()->PutPixel(newx, newy, White);//m_Stars[i].m_Color); + m_Stars[i].m_OldX = newx; + m_Stars[i].m_OldY = newy; + if(m_Towards) + m_Stars[i].m_Z -= m_StarVelocity; + else + m_Stars[i].m_Z += m_StarVelocity; + } + else + { + m_Stars[i].m_X = rand()%m_Width - m_Width / 2; + m_Stars[i].m_Y = rand()%m_Height - m_Height / 2; + m_Stars[i].m_Color = rand()%255; + if(m_Towards) + m_Stars[i].m_Z = 255; + else + m_Stars[i].m_Z = rand()%255; + } + } +/* else + { + m_Stars[i].m_X = rand()%m_Width - m_Width / 2; + m_Stars[i].m_Y = rand()%m_Height - m_Height / 2; + m_Stars[i].m_Color = rand()%255; + if(m_Towards) + m_Stars[i].m_Z = 255; + else + m_Stars[i].m_Z = rand()%255; + } + +*/ + + + } + + m_Screen->GetBack()->UnLock(); +} + +////////////////////////////////////////////////////////////////////////////////// +// CDXStarField ClearStars +////////////////////////////////////////////////////////////////////////////////// +void CDXStarField::ClearStars() +{ + m_Screen->GetBack()->Fill(0); +} + +////////////////////////////////////////////////////////////////////////////////// +// CDXStarField SetNumberofStars +////////////////////////////////////////////////////////////////////////////////// +void CDXStarField::SetNumberofStars(int iStars) +{ + if(iStars != m_NumStars) + { + m_NumStars = iStars; + if(m_NumStars > MAXSTARS) + m_NumStars = MAXSTARS; + if(m_NumStars < 0) + m_NumStars = 0; + } +} + +//mirza +void CDXStarField::AllWhite( void ) +{ + for(int i=0; iGetBack()->Lock(); + for(int i=0; iGetBack()->PutPixel(m_Stars[i].m_OldX, m_Stars[i].m_OldY, White);//m_Stars[i].m_Color); + } + m_Screen->GetBack()->UnLock(); +} \ No newline at end of file diff --git a/CDXAddons/CDXStar/Cdxstar.h b/CDXAddons/CDXStar/Cdxstar.h new file mode 100644 index 0000000..3e66cb2 --- /dev/null +++ b/CDXAddons/CDXStar/Cdxstar.h @@ -0,0 +1,74 @@ +////////////////////////////////////////////////////////////////////////////////// +// $Source: /cvsroot/cdx/cdx3.0/examples/vc/ex9/CDXSTAR.H,v $ +// $Author: istan $ +// +// $Log: CDXSTAR.H,v $ +// Revision 1.1 2001/02/17 18:19:30 istan +// Added to the repository +// +// Revision 1.1.1.1 1999/05/04 23:59:23 bsimser +// Imported addons +// +// $Revision: 1.1 $ +////////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////////// +// CDXStarField Class +////////////////////////////////////////////////////////////////////////////////// +#include "cdxscreen.h" +#include "cdxsurface.h" + +#define MAXSTARS 100 +#define White RGB(255,255,255) +enum m_Mode { HORIZONTAL, VERTICAL, THREED }; + +class CDXStarFieldRecord +{ +public: + int m_X; + int m_Y; + int m_Z; + int m_OldX; + int m_OldY; + int m_Color; +}; + +class CDXStarField +{ +public: + CDXStarField(CDXScreen*); + ~CDXStarField(); + + void Create(); + void Update(BOOL bErase = TRUE); + void CreateStars(); + void CalcPosition(); + void ClearStars(); + void SetNumberofStars(int); + //mirza + void AllWhite( void ); + void DrawStars( void ); + +public: + CDXScreen* m_Screen; + CDXStarFieldRecord m_Stars[MAXSTARS]; + + int m_NumStars; + int m_StarVelocity; + int m_Width; + int m_Height; + int m_LWidth; + int m_LHeight; + int m_CenterX; + int m_CenterY; + int m_Left; + int m_Right; + int m_Top; + int m_Bottom; + + m_Mode m_StarMode; + + BOOL m_Towards; + BOOL m_Flashing; + BOOL m_Colored; +}; diff --git a/CDXAddons/CDXTextScrol/CDXBitmapFont.cpp b/CDXAddons/CDXTextScrol/CDXBitmapFont.cpp new file mode 100644 index 0000000..3a0a9f8 --- /dev/null +++ b/CDXAddons/CDXTextScrol/CDXBitmapFont.cpp @@ -0,0 +1,770 @@ +// Project Name: [ CDX BitmapFont ] +// Original Author: [ Ioannis Karagiorgos - karagior@pluto.fernuni-hagen.de ] +// Author: [ Jimb Esser - wasteland@writeme.com ] +// Date: [ 7.4.1999 ] +// Revision: [ 2.00 ] +// Updated to work with CDX 3.0 and other bug fixes by Jimb Esser +////////////////////////////////////////////////////////////////////////////////// + +#include "CDXBitmapFont.h" + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +CDXBitmapFont::CDXBitmapFont( CDXScreen * Scr , char * FontNam , int Height , + int Color , int ColKey, int BackColor , int Attributes , int SurfaceType ) +{ + TextSurface = NULL; + Create( Scr , FontNam , Height , Color , ColKey , BackColor , Attributes ); +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +CDXBitmapFont::CDXBitmapFont( CDXScreen * Scr ) +{ + TextSurface = NULL; + Create( Scr , "Courier" , 12 , RGB( 255 , 255 , 255 ) , RGB(0,0,0) , RGB(0,0,0) , + FW_NORMAL , CDXMEM_VIDTHENSYS); +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +CDXBitmapFont::~CDXBitmapFont( ) +{ + if( TextSurface != NULL ) delete TextSurface; +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +void CDXBitmapFont::Create( CDXScreen * Scr , char * FontNam , int Height , + int Color , int ColKey, int BackColor , int Attributes , int SurfaceType ) +{ + int X , Y , i; + char TextBuffer[ 2 ]; + SIZE size; + CDXSurface * TempSurface; + + FontName = FontNam; + FontColor = Color; + FontBackgroundColor = BackColor; + FontColorKey = ColKey; + FontHeight = Height; + FontAttributes = Attributes; + TextSurfaceType = SurfaceType; + Screen = Scr; + + if( TextSurface != NULL ) delete TextSurface; + + // create temporary surface in order to get the character widths + // surface can be created in system memory because it is only needed one time + TempSurface = new CDXSurface(); + // TODO: Errorcheck + TempSurface->Create( Screen , 100 , 100 , CDXMEM_SYSTEMONLY ); + + // the font surface will be width=320 and height as needed + // i chose width=320 because some video cards dont support surfaces wider + // than the actual resolution in video memory, so if you choose + // videomode 320x200 or 320x240 the surface would be allocated in system memory + // which would slow down output of fonts. + TempSurface->ChangeFont( FontName , 0 , FontHeight , FontAttributes ); + + // loop through all 256 characters and calculate position and size of every character + + X = Y = 0; + + for( i=0; i<128; i++ ) + { + TextBuffer[ 0 ] = i; + TextBuffer[ 1 ] = '\0'; + + HDC dc = TempSurface->GetDC( ); + TempSurface->SetFont( ); + SetBkMode( dc , OPAQUE ); + SetTextColor( dc, RGB( 255 , 255 , 255 ) ); + SetBkColor( dc, RGB( 0 , 0 , 0 ) ); + GetTextExtentPoint32( dc , TextBuffer , 1 , &size ); + TempSurface->ReleaseDC( ); + + // if x + character width exceed 310 then begin new line + if( X+size.cx >= 310 ) + { + X = 0; + Y += size.cy; + } + + CDXBitmapFontArray[ i ].Height = size.cy; + CDXBitmapFontArray[ i ].Width = size.cx; + + CDXBitmapFontArray[ i ].Rectangle.left = X; + CDXBitmapFontArray[ i ].Rectangle.top = Y; + CDXBitmapFontArray[ i ].Rectangle.right = X + size.cx; + CDXBitmapFontArray[ i ].Rectangle.bottom = Y + size.cy; + X += size.cx; + } + + + delete TempSurface; + + if( TextSurface != NULL ) + delete TextSurface; + + TextSurface = new CDXSurface(); + // TODO: Errorcheck + TextSurface->Create( Screen , 320 , Y+Height+5 , TextSurfaceType ); + PaintCharactersInSurface( ); +} + +void GetRGB(CDXScreen* Screen, DWORD c, long &r, long &g, long &b) +{ + int r2, g2, b2; + switch (Screen->GetBPP()) { + case 8: + Screen->GetColor(c, &r2, &g2, &b2); + r = r2; + g = g2; + b = b2; + break; + case 15: + b = c & 0x1f; + g = (c >> 5) & 0x1f; + r = (c >> 10) & 0x1f; + break; + case 16: + b = c & 0x1f; + g = (c >> 5) & 0x3f; + r = (c >> 11) & 0x1f; + break; + case 24: + b = c & 0xFF; + g = (c >> 8) & 0xFF; + r = (c >> 16) & 0xFF; + break; + case 32: + b = c & 0xFF; + g = (c >> 8) & 0xFF; + r = (c >> 16) & 0xFF; + break; + } +} +void MakeColor(CDXScreen* Screen, DWORD &c, long r, long g, long b) +{ + switch (Screen->GetBPP()) { + case 8: + c = (r) | (g << 8) | (b << 16); // Not Supported, return it as it was initially encoded... + break; + case 15: + c = (b) | (g << 5) | (r << 10); + break; + case 16: + c = (b) | (g << 5) | (r << 11); + break; + case 24: + case 32: + c = (b) | (g << 8) | (r << 16); + break; + } +} + + + +// -------------------------------------------------------------------------------------- +// rough draft of a anti-aliasing routine. Not currently used anyways +// @author Jimb Esser +// -------------------------------------------------------------------------------------- +void CDXBitmapFont::PaintCharactersInSurface2( void ) +{ + char TextBuffer[ 2 ]; + int i; + + TextSurface->ChangeFont( FontName , 0 , FontHeight, FontAttributes ); + TextSurface->SetColorKey( FontColorKey ); + + // create temporary surface in order to draw the fonts before + // antialiasing + CDXSurface *TempSurface = new CDXSurface(); + // TODO: Errorcheck + TempSurface->Create( Screen , 200 , 200 , CDXMEM_SYSTEMONLY ); + TempSurface->ChangeFont( FontName , 0 , FontHeight*2 , FontAttributes ); + TempSurface->Fill(FontBackgroundColor); + + // print all characters on surface + + HRGN Region; + HDC dc; + +// dc = TextSurface->GetDC( ); +// TextSurface->SetFont( ); +// TextSurface->ReleaseDC(); + + int iHeight, iWidth, x, y; + DWORD c; + long r, g, b; + long dr, dg, db; + + for( i=0; i<128; i++ ) + { + TextBuffer[ 0 ] = i; + TextBuffer[ 1 ] = '\0'; + + // Draw the text + TempSurface->Fill(0); + dc = TempSurface->GetDC( ); + TempSurface->SetFont( ); + SetBkMode( dc , OPAQUE ); + SetTextColor( dc, FontColor ); + SetBkColor( dc, FontBackgroundColor ); + + // select clip region because some characters like 'j' exceed the drawing rectangle + // and reach into other characters bitmaps + Region = CreateRectRgn( CDXBitmapFontArray[i].Rectangle.left , + CDXBitmapFontArray[i].Rectangle.top , + CDXBitmapFontArray[i].Rectangle.right , + CDXBitmapFontArray[i].Rectangle.bottom ); + // SelectClipRgn( dc, Region ); + TextOut( dc, 0, 0, TextBuffer , 1 ); + + TempSurface->ReleaseDC( ); + + // Sample down to half size... + iWidth = CDXBitmapFontArray[i].Rectangle.right - CDXBitmapFontArray[i].Rectangle.left; + iHeight = CDXBitmapFontArray[i].Rectangle.bottom - CDXBitmapFontArray[i].Rectangle.top; + for (x=0; xLock(); + c = TempSurface->GetPixel(x*2, y*2); + GetRGB(Screen, c, dr, dg, db); + r = dr; g = dg; b = db; + + c = TempSurface->GetPixel(x*2+1, y*2); + GetRGB(Screen, c, dr, dg, db); + r += dr; b += db; g += dg; + + c = TempSurface->GetPixel(x*2, y*2+1); + GetRGB(Screen, c, dr, dg, db); + r += dr; b += db; g += dg; + + c = TempSurface->GetPixel(x*2+1, y*2+1); + GetRGB(Screen, c, dr, dg, db); + r += dr; b += db; g += dg; /* */ + + TempSurface->UnLock(); + + r /=4; g /=4; b /=4; + MakeColor(Screen, c, r, g, b); + + TextSurface->Lock(); + TextSurface->PutPixel(x+CDXBitmapFontArray[i].Rectangle.left, y+CDXBitmapFontArray[i].Rectangle.top, c); + TextSurface->UnLock(); + } + + + DeleteObject( Region ); + } + + +// TextSurface->UnLock(); + TextSurface->SetColorKey( FontColorKey ); +} + + +void CDXBitmapFont::PaintCharactersInSurface( void ) +{ + char TextBuffer[ 2 ]; + int i; + + TextSurface->ChangeFont( FontName , 0 , FontHeight , FontAttributes ); + + // Convert the font color to what it should be for the + // bitdepth of the screen. If we're in 8-bit, nothing + // will be done with it, assume a palette color index + // is passed in. If MakeColor() in cdxscreen (or here) + // is implemented to handle 8-bit, we could process + // 8-bit like the others (taking an RGB() parameter). + int r, g, b; + r = FontColorKey & 0xFF; + g = (FontColorKey >> 8) & 0xFF; + b = (FontColorKey >> 16) & 0xFF; + DWORD c; + MakeColor(Screen, c, r, g, b); + TextSurface->SetColorKey( c ); + + // print all characters on surface + HDC dc = TextSurface->GetDC( ); + TextSurface->SetFont( ); + SetBkMode( dc , OPAQUE ); + SetTextColor( dc, FontColor ); + SetBkColor( dc, FontBackgroundColor ); + + HRGN Region; + + for( i=0; i<128; i++ ) + { + TextBuffer[ 0 ] = i; + TextBuffer[ 1 ] = '\0'; + + // select clip region because some characters like 'j' exceed the drawing rectangle + // and reach into other characters bitmaps + Region = CreateRectRgn( CDXBitmapFontArray[i].Rectangle.left , + CDXBitmapFontArray[i].Rectangle.top , + CDXBitmapFontArray[i].Rectangle.right , + CDXBitmapFontArray[i].Rectangle.bottom ); + SelectClipRgn( dc, Region ); + TextOut( dc, CDXBitmapFontArray[i].Rectangle.left , + CDXBitmapFontArray[i].Rectangle.top , TextBuffer , 1 ); + DeleteObject( Region ); + } + + + TextSurface->ReleaseDC( ); +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +HRESULT CDXBitmapFont::DrawAligned( int X , int Y , int Width , char * Text , CDXSurface * lpDDest , int Align ) +{ + int TWidth, Width2; + HRESULT rval; + char ch; + + TWidth = GetTextWidth( Text ); + + if( Align == CDX_CENTERJUSTIFY ) + { + // if text wider then output width do print only the fitting characters + if( TWidth < Width ) + { + X = X + ( Width - TWidth ) / 2; + + while( (ch = *Text++) != '\0' ) + { + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + if(rval == DDERR_SURFACELOST) + return rval; + } + X += CDXBitmapFontArray[ ch ].Width; + } + } + else + { + TWidth = 0; + while( (ch = *Text++) != '\0' ) + { + Width2 = CDXBitmapFontArray[ ch ].Width; + TWidth += Width2; + if( TWidth > Width ) + break; + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + if (rval == DDERR_SURFACELOST) + return rval; + } + X += Width2; + } + } + } + else + if( Align == CDX_RIGHTJUSTIFY ) + { + // if text wider then output width do print only the fitting characters + if( TWidth < Width ) + { + X = X + ( Width - TWidth ); + + while( (ch = *Text++) != '\0' ) + { + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + if (rval == DDERR_SURFACELOST) + return rval; + } + X += CDXBitmapFontArray[ ch ].Width; + } + } + else + { + TWidth = 0; + while( (ch = *Text++) != '\0' ) + { + Width2 = CDXBitmapFontArray[ ch ].Width; + TWidth += Width2; + if( TWidth > Width ) + break; + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + if (rval == DDERR_SURFACELOST) + return rval; + } + X += Width2; + } + } + } + + return rval; +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +HRESULT CDXBitmapFont::DrawAlignedTrans( int X , int Y , int Width , char * Text , CDXSurface * lpDDest , int Align ) +{ + int TWidth, Width2; + HRESULT rval; + char ch; + + TWidth = GetTextWidth( Text ); + + if( Align == CDX_CENTERJUSTIFY ) + { + // if text wider then output width do print only the fitting characters + if( TWidth < Width ) + { + X = X + ( Width - TWidth ) / 2; + + while( (ch = *Text++) != '\0' ) + { + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + if (rval == DDERR_SURFACELOST) + return rval; + } + X += CDXBitmapFontArray[ ch ].Width; + } + } + else + { + TWidth = 0; + while( (ch = *Text++) != '\0' ) + { + Width2 = CDXBitmapFontArray[ ch ].Width; + TWidth += Width2; + if( TWidth > Width ) + break; + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + if (rval == DDERR_SURFACELOST) + return rval; + } + X += Width2; + } + } + } + else + if( Align == CDX_RIGHTJUSTIFY ) + { + // if text wider then output width do print only the fitting characters + if( TWidth < Width ) + { + X = X + ( Width - TWidth ); + + while( (ch = *Text++) != '\0' ) + { + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + if (rval == DDERR_SURFACELOST) + return rval; + } + X += CDXBitmapFontArray[ ch ].Width; + } + } + else + { + TWidth = 0; + while( (ch = *Text++) != '\0' ) + { + Width2 = CDXBitmapFontArray[ ch ].Width; + TWidth += Width2; + if( TWidth > Width ) + break; + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + if (rval == DDERR_SURFACELOST) + return rval; + } + X += Width2; + } + } + } + + return rval; +} + + + +// -------------------------------------------------------------------------------------- +// Length = -1 means draw the complete string, else length characters +// -------------------------------------------------------------------------------------- +HRESULT CDXBitmapFont::Draw(int X, int Y, char * Text , CDXSurface* lpDDest , int Length ) +{ + HRESULT rval; + char ch; + + while( ( (ch = *Text++) != '\0' ) && + ( Length-- != 0 ) ) + { + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT); + if (rval == DDERR_SURFACELOST) + return rval; + } + X += CDXBitmapFontArray[ ch ].Width; + } + + return rval; +} + + + +// -------------------------------------------------------------------------------------- +// Length = -1 means draw the complete string, else length characters +// -------------------------------------------------------------------------------------- +/*HRESULT CDXBitmapFont::DrawClipped(int X, int Y, char * Text , CDXSurface* lpDDest, LPRECT ClipRect , int Length ) +{ + HRESULT rval; + RECT ModSrc; + int XSave , YSave; + char ch; + + while( ( (ch = *Text++) != '\0' ) && + ( Length-- != 0 ) ) + + { + ModSrc = CDXBitmapFontArray[ ch ].Rectangle; + XSave = X; YSave = Y; + Clip(&X, &Y, &ModSrc, ClipRect); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &ModSrc, + DDBLTFAST_WAIT); + + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &ModSrc, + DDBLTFAST_WAIT); + if (rval == DDERR_SURFACELOST) + return rval; + } + + X = XSave; + Y = YSave; + + X += CDXBitmapFontArray[ ch ].Width; + } + + return rval; + +} +*/ + + + +// -------------------------------------------------------------------------------------- +// Length = -1 means draw the complete string, else length characters +// -------------------------------------------------------------------------------------- +HRESULT CDXBitmapFont::DrawTrans(int X, int Y, char * Text , CDXSurface* lpDDest , int Length ) +{ + HRESULT rval; + char ch; + + while( ( (ch = *Text++) != '\0' ) && + ( Length-- != 0 ) ) + + { + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &CDXBitmapFontArray[ ch ].Rectangle, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + } + X += CDXBitmapFontArray[ ch ].Width; + } + + return rval; +} + + + +// -------------------------------------------------------------------------------------- +// Length = -1 means draw the complete string, else length characters +// -------------------------------------------------------------------------------------- +/*HRESULT CDXBitmapFont::DrawTransClipped(int X, int Y, char * Text , CDXSurface* lpDDest, LPRECT ClipRect , int Length ) +{ + HRESULT rval; + RECT ModSrc; + int XSave , YSave; + char ch; + + while( ( (ch = *Text++) != '\0' ) && + ( Length-- != 0 ) ) + + { + ModSrc = CDXBitmapFontArray[ ch ].Rectangle; + XSave = X; YSave = Y; + Clip(&X, &Y, &ModSrc, ClipRect); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &ModSrc, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + + if(rval == DDERR_SURFACELOST) + { + Restore( ); + rval = lpDDest->GetDDS()->BltFast(X, Y, TextSurface->GetDDS(), &ModSrc, + DDBLTFAST_WAIT| DDBLTFAST_SRCCOLORKEY); + if (rval == DDERR_SURFACELOST) + return rval; + } + X = XSave; + Y = YSave; + X += CDXBitmapFontArray[ ch ].Width; + } + + return rval; + +} +*/ + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +void CDXBitmapFont::SetFont( char * FontNam , int Height , int Color , int Attributes ) +{ + Create( Screen , FontNam , Height , Color , FontColorKey , FontBackgroundColor , Attributes ); +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +void CDXBitmapFont::SetColor( int Color ) +{ + FontColor = Color; + + PaintCharactersInSurface( ); +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +void CDXBitmapFont::SetColorKey( int ColorKey ) +{ + FontColorKey = ColorKey; + + TextSurface->SetColorKey( FontColorKey ); +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +void CDXBitmapFont::SetBackgroundColor( int Color ) +{ + FontBackgroundColor = Color; + + PaintCharactersInSurface( ); +} + + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +int CDXBitmapFont::GetCharacterWidth( char ch ) +{ + return CDXBitmapFontArray[ ch ].Width; +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +int CDXBitmapFont::GetCharacterHeight( char ch ) +{ + return CDXBitmapFontArray[ ch ].Height; +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +int CDXBitmapFont::GetTextWidth( char * Text ) +{ + int Result; + char ch; + + Result = 0; + + while( (ch = *Text++) != '\0' ) + { + Result += CDXBitmapFontArray[ ch ].Width; + } + + return Result; +} + + + +// -------------------------------------------------------------------------------------- +// -------------------------------------------------------------------------------------- +void CDXBitmapFont::Restore( void ) +{ + TextSurface->Restore(); + PaintCharactersInSurface( ); +} diff --git a/CDXAddons/CDXTextScrol/CDXBitmapFont.h b/CDXAddons/CDXTextScrol/CDXBitmapFont.h new file mode 100644 index 0000000..4dd9aa8 --- /dev/null +++ b/CDXAddons/CDXTextScrol/CDXBitmapFont.h @@ -0,0 +1,88 @@ +////////////////////////////////////////////////////////////////////////////////// +// Project Name: [ CDX BitmapFont ] +// Original Author: [ Ioannis Karagiorgos - karagior@pluto.fernuni-hagen.de ] +// Author: [ Jimb Esser - wasteland@writeme.com ] +// Date: [ 7.4.1999 ] +// Revision: [ 2.00 ] +// Updated to work with CDX 3.0 and other bug fixes by Jimb Esser +// Note: the draw clipped functions have not yet been updated +////////////////////////////////////////////////////////////////////////////////// + + +#ifndef __CDX_BITMAPFONT__ +#define __CDX_BITMAPFONT__ + +#define CDXINCLUDEALL +#include + + +#ifndef CDX_CENTERJUSTIFY +#define CDX_CENTERJUSTIFY 1 +#endif +#ifndef CDX_RIGHTJUSTIFY +#define CDX_RIGHTJUSTIFY 3 +#endif + +// Function used internally that makes a DWORD color value from a RGB triplet +void MakeColor(CDXScreen* Screen, DWORD &c, long r, long g, long b); + + +class CDXBitmapFont +{ +public: + + typedef struct + { + RECT Rectangle; + int Width , Height; + } CDXBITMAPFONT; + + CDXBITMAPFONT CDXBitmapFontArray[ 256 ]; + + int FontColor; + int FontBackgroundColor; + int FontColorKey; + int FontHeight; + int FontAttributes; + char * FontName; + int TextSurfaceType; + + CDXSurface * TextSurface; + CDXScreen * Screen; + + CDXBitmapFont( CDXScreen * Scr ); + // Note on ColorKey: + // if your screen is in 8bit mode, then this parameter must be + // the index of the color (dependant on palette), for any other + // bitdepth, pass in an RGB(r,g,b) macro parameter + CDXBitmapFont( CDXScreen * Scr , char * FontNam , int Height , int Color = RGB( 255 , 255 , 255 ), int ColKey = RGB(0,0,0), + int BackColor = RGB(0,0,0) , int Attributes = FW_NORMAL , int SurfaceType = CDXMEM_VIDTHENSYS ); + ~CDXBitmapFont(); + + void Create( CDXScreen * Scr , char * FontNam , int Height , int Color , int ColKey, + int BackColor , int Attributes = FW_NORMAL , int SurfaceType = CDXMEM_VIDTHENSYS ); + void PaintCharactersInSurface( void ); + void PaintCharactersInSurface2( void ); // Prototype of an antialiased version. Not currently used + + HRESULT Draw(int X, int Y, char * Text , CDXSurface* lpDDest , int Length = -1 ); +// HRESULT DrawClipped(int X, int Y, char * Text , CDXSurface* lpDDest, LPRECT ClipRect , int Length = -1); + HRESULT DrawTrans(int X, int Y, char * Text , CDXSurface* lpDDest , int Length = -1); +// HRESULT DrawTransClipped(int X, int Y, char * Text , CDXSurface* lpDDest, LPRECT ClipRect , int Length = -1); + + // iWidth is the width of the box in which the text should be aligned + HRESULT DrawAligned( int X , int Y , int Width , char * Text , CDXSurface * lpDDest , int Align ); + HRESULT DrawAlignedTrans( int X , int Y , int Width , char * Text , CDXSurface * lpDDest , int Align ); + + void SetFont( char * FontNam , int Height , int Color , int Attributes = FW_NORMAL ); + void SetColor( int Color ); + void SetColorKey( int ColorKey ); + void SetBackgroundColor( int Color ); + + int GetCharacterWidth( char ch ); + int GetCharacterHeight( char ch ); + int GetTextWidth( char * Text ); + + void Restore( ); +}; + +#endif \ No newline at end of file diff --git a/CDXAddons/CDXTextScrol/CDXBitmapFont.txt b/CDXAddons/CDXTextScrol/CDXBitmapFont.txt new file mode 100644 index 0000000..4f4da20 --- /dev/null +++ b/CDXAddons/CDXTextScrol/CDXBitmapFont.txt @@ -0,0 +1,197 @@ +Documentation file for class CDXBitmapfont + +Note: This is a version modified by Jimb Esser to support CDX 3.0 and to have +better lost surface recovery, along with some other minor bug fixes. + +(c) 4/1999 by Ioannis Karagiorgos + EMail: karagior@pluto.fernuni-hagen.de + + +contributions to the CDX project and to everyone who uses and extends it! + + + +Purpose of CDXBitmapFont class: +------------------------------- + The CDXBitmapfont class is intended to deliver a faster way of drawing text + using DirectX. CDXBitmapFont creates an offscreen surface with the selected + font on it and blits the characters to the desired CDXSurface. + This should be faster than using the standard windows text output routines. + You can select the font, size, Attributes, fore- and backgroundcolor and the + colorkey of each font. + Text can be output normal, with transparent background, clipped, + and left/right/center aligned. + There are alos functions to calculate the width and height of characters + or complete string widths. + + CAUTION: If you try to change the settings of a created font, e.g. you want to + change the font color from red to green, then you can do this but with a big + performance decrease because the class has to repaint its font surface to create + the new font with the desired color. + + So you should create a new font object for every font/style/color change you want. + The only change that does not force the font class to repaint its internal font + surface is the change of the colorkey! + + +Reference: +---------- + + CDXBitmapFont( CDXScreen * Scr ) + - Scr is a pointer to the CDXScreen object + + - This constructor creates a font "Courier" , height=12 , Color=RGB(255,255,255) , + backgroundcolor = RGB(0,0,0) , colorkey = RGB(0,0,0) , + Attributes = FW_NORMAL = standard font + surface is allocated in video memory first and then in system memory + if there is no space in video memory + + + CDXBitmapFont( CDXScreen * Scr , char * FontNam , int Height , int Color, int ColKey , + int BackColor , int Attributes , int SurfaceType ) + - Scr is a pointer to the CDXScreen object + - Fontnam = name of the font, e.g. Arial, Courier, etc. + - Height = font height + - Color [OPTIONAL] = font color, default = RGB(255,255,255) + - ColKey [OPTIONAL] = color key for transparent blits, default = RGB(0,0,0) + if your screen is in 8bit mode, then this parameter must be + the index of the color (dependant on palette), for any other + bitdepth, pass in an RGB(r,g,b) macro parameter + - BackColor [OPTIONAL] = background color of the text, default = RGB(0,0,0) + - Attributes [OPTIONAL] = font attributes, e.g. FW_NORMAL = normal font, FW_BOLD = bold font, ... , + default = FW_NORMAL + - SurfaceType [OPTIONAL] = where should the internal font surface be allocated ? default = CDXMEM_VIDTHENSYS + CDXMEM_VIDTHENSYS = surface is allocated in video memory first and then in system memory + if there is no space in video memory ( best performance ) + CDXMEM_VIDEOONLY = surface is allocated in video memory only, if no space then error ( best performance ) + CDXMEM_SYSTEMONLY = surface is allocated ion system memory only ( poorer performance ) + + - This constructor creates a font with the selected properties + + + HRESULT Draw( int X , int Y , char * Text , CDXSurface * lpDDest , int Length ) + - X = x-coord of the text + - Y = y-coord of the text + - Text = pointer to text string + - lpDDest = destination surface for text output + - length [OPTIONAL] = length of text string, default = -1 = draw complete string + if you choose e.g. 3 the function only draws the first 3 characters of the string + - HRSEULT = returns the last DirectDraw Blit error code + + - This function draws text at the specified location. + The text is drawn with its background color, for transparent draw look next function + + + HRESULT DrawTrans( int X , int Y , char * Text , CDXSurface * lpDDest , int Length ) + - X = x-coord of the text + - Y = y-coord of the text + - Text = pointer to text string + - lpDDest = destination surface for text output + - length [OPTIONAL] = length of text string, default = -1 = draw complete string + if you choose e.g. 3 the function only draws the first 3 characters of the string + + - This function draws text at the specified location transparent. + + + HRESULT DrawClipped( int X , int Y , char * Text , CDXSurface * lpDDest , LPRECT ClipRect , int Length ) + - X = x-coord of the text + - Y = y-coord of the text + - Text = pointer to text string + - lpDDest = destination surface for text output + - ClipRect = clip rectangle in which the text is clipped + - length [OPTIONAL] = length of text string, default = -1 = draw complete string + if you choose e.g. 3 the function only draws the first 3 characters of the string + - HRSEULT = returns the last DirectDraw Blit error code + + - This function draws text at the specified location clipped. + + + HRESULT DrawTransClipped( int X , int Y , char * Text , CDXSurface * lpDDest , LPRECT ClipRect , int Length ) + - X = x-coord of the text + - Y = y-coord of the text + - Text = pointer to text string + - lpDDest = destination surface for text output + - ClipRect = clip rectangle in which the text is clipped + - length [OPTIONAL] = length of text string, default = -1 = draw complete string + if you choose e.g. 3 the function only draws the first 3 characters of the string + - HRSEULT = returns the last DirectDraw Blit error code + + - This function draws text at the specified location transparent and clipped. + + + HRESULT DrawAligned( int X , int Y , int Width , char * Text , CDXSurface * lpDDest , int Align ) + - X = x-coord of the text + - Y = y-coord of the text + - Width = width of output area, text is aligned within this area + - Text = pointer to text string + - lpDDest = destination surface for text output + - Align = alignment of text + CDX_CENTERJUSTIFY = centered + CDX_RIGHTJUSTIFY = right aligned + - HRSEULT = returns the last DirectDraw Blit error code + + - This function draws text at the specified location and width middle/right aligned + + + HRESULT DrawAlignedTrans( int X , int Y , int Width , char * Text , CDXSurface * lpDDest , int Align ) + - X = x-coord of the text + - Y = y-coord of the text + - Width = width of output area, text is aligned within this area + - Text = pointer to text string + - lpDDest = destination surface for text output + - Align = alignment of text + CDX_CENTERJUSTIFY = centered + CDX_RIGHTJUSTIFY = right aligned + - HRSEULT = returns the last DirectDraw Blit error code + + - This function draws text at the specified location transparent and width center/right aligned + + + void SetFont( char * FontNam , int Height , int Color , int Attributes = FW_NORMAL ) + - Fontnam = name of the font + - Height = height of font + - Color = font color + - Attributes [OPTIONAL] = font attributes, default = FW_NORMAL + + - This function changes the font. CAUTION: time costly + + + void SetColor( int Color ) + - Color = font color + + - This function changes the font color. CAUTION: time costly + + + void SetBackgroundColor( int Color ) + - Color = font background color + + - This function changes the font background color. CAUTION: time costly + + + void SetColorKey( int ColorKey ) + - ColorKey = ColorKey for transparent text + + + int GetCharacterWidth( char ch ) + - ch = desired character + + - This function returns the width of charcter ch + + + int GetCharacterHeight( char ch ) + - ch = desired character + + - This function returns the height of charcter ch + + + int GetTextWidth( char * Text ) + - Text = text string + + - This function returns the width of the string Text + + + void Restore( ) + - This function restores the internal font surface. This could happen, when + surfaces are lost + + \ No newline at end of file diff --git a/CDXAddons/CDXTextScrol/CDXHorizTextScroller.cpp b/CDXAddons/CDXTextScrol/CDXHorizTextScroller.cpp new file mode 100644 index 0000000..910f200 --- /dev/null +++ b/CDXAddons/CDXTextScrol/CDXHorizTextScroller.cpp @@ -0,0 +1,946 @@ +// Project Name: [ CDXHorizTextScroller ] +// Author: [ Ioannis Karagiorgos - karagior@pluto.fernuni-hagen.de ] +// Date: [ 7.4.1999 ] +// Revision: [ 1.00 ] +////////////////////////////////////////////////////////////////////////////////// + +#include "CDXHorizTextScroller.h" + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +CDXHorizTextScroller::CDXHorizTextScroller( CDXScreen * Scr , RECT * ClipRectangle , + char * ScrollText , bool TextWrap , + CDXBitmapFont * Font ) +{ + Text = NULL; + TextSurface = NULL; + IXtoCharacter = NULL; + Screen = Scr; + + Wrap = TextWrap; + + + Text = new char [strlen( ScrollText )+1 ]; + strcpy( Text , ScrollText ); + + if( Font == NULL ) + { + TextSurface = new CDXBitmapFont( Screen ); + OwnFont = true; // class has to destroy font by herself + } + else + { + TextSurface = Font; + OwnFont = false; // font has to be destroyed by creator, not by this class + } + + ClipRect.left = ClipRectangle->left; + ClipRect.top = ClipRectangle->top; + ClipRect.right = ClipRectangle->right; + ClipRect.bottom = ClipRectangle->bottom; + + StartX = ClipRect.left; + StartY = ClipRect.top; + + TWidth = ClipRect.right - StartX; + + Create( ); + + ResetPosition( ); +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +void CDXHorizTextScroller::Create( void ) +{ + int i , j, Width; + int Count; + char ch; + char * Temp; + + IX = 0; + + TextLen = strlen( Text ); + if( TextLen == 0 ) + { + delete Text; + Text = new char[ 2 ]; + Text[ 0 ] = ' '; + Text[ 1 ] = '\0'; + TextLen = 1; + } + + // add spaces at the end of the string + if( Wrap == true ) + { + i = 0; + Count = 0; + while( i < TWidth ) + { + i += TextSurface->GetCharacterWidth( ' ' ); + ++ Count; + } + if( Count > 0 ) + { + Temp = new char[ TextLen + 1 ]; + strcpy( Temp , Text ); + delete Text; + TextLen += Count; + Text = new char[ TextLen + 1]; + strcpy( Text , Temp ); + for( i=0; iGetTextWidth( Text ); + CharsHeight = TextSurface->GetCharacterHeight( 'A' ); + + // Initialize IXtoCharacterArray + if( IXtoCharacter != NULL ) + delete IXtoCharacter; + + IXtoCharacter = new CDXHTS [TextWidth]; + + Count = 0; + + for( i=0; iGetCharacterWidth( ch ); + for( j=0; jCDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + X -= Offset; + + do + { + YSave = Y; + ClipXY( &X , &Y , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , &SrcRect , DDBLTFAST_WAIT ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + X += SrcRect.right - SrcRect.left; + Y = YSave; + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + CharPointer = Text; + ch = *CharPointer; + } + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + while( X < ClipRect.right ); + } + + } + else + { + Y = StartY; + X = StartX - IX; + + CharPointer = Text; + ch = *CharPointer; + + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + while( X+Width < StartX ) + { + X += Width; + ++ CharPointer; + if( *CharPointer == '\0' ) + CharPointer = Text; + ch = *CharPointer; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + + while( X < ClipRect.right ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + ClipX( &X , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , &SrcRect , DDBLTFAST_WAIT ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + X += SrcRect.right - SrcRect.left; + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + break; + } + } + } + + return Result; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CDXHorizTextScroller::DrawTrans( CDXSurface * lpDDS ) +{ + int X , Y , YSave; + int Width; + int Offset; + char * CharPointer; + RECT SrcRect; + char ch; + HRESULT Result; + + if( Wrap == true ) + { + X = StartX; + Y = StartY; + if( X < ClipRect.right ) + { + ch = IXtoCharacter[ IX ].Character; + Offset = IXtoCharacter[ IX ].Offset; + CharPointer = &Text[ IXtoCharacter[ IX ].PositionInText ]; + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + X -= Offset; + + do + { + if( ch != ' ' ) + { + YSave = Y; + ClipXY( &X , &Y , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY); + Y = YSave; + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + } + + X += SrcRect.right - SrcRect.left; + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + CharPointer = Text; + ch = *CharPointer; + } + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + while( X < ClipRect.right ); + } + + } + else + { + Y = StartY; + X = StartX - IX; + + CharPointer = Text; + ch = *CharPointer; + + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + while( X+Width < StartX ) + { + X += Width; + ++ CharPointer; + if( *CharPointer == '\0' ) + CharPointer = Text; + ch = *CharPointer; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + + while( X < ClipRect.right ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + if( ch != ' ' ) + { + ClipX( &X , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + } + + X += SrcRect.right - SrcRect.left; + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + break; + } + } + } + + return Result; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CDXHorizTextScroller::DrawOffset( CDXSurface * lpDDS , int * OffsetArray) +{ + int i; + int X , Y; + int Width, ClipWidth; + int Offset; + char * CharPointer; + RECT SrcRect; + char ch; + HRESULT Result; + + if( Wrap == true ) + { + X = StartX; + Y = StartY; + if( X < ClipRect.right ) + { + ch = IXtoCharacter[ IX ].Character; + Offset = IXtoCharacter[ IX ].Offset; + CharPointer = &Text[ IXtoCharacter[ IX ].PositionInText ]; + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + X -= Offset; + + do + { + ClipX( &X , &SrcRect , &ClipRect ); + ClipWidth = SrcRect.right - SrcRect.left; + for( i=ClipWidth; i>0; i-- ) + { + SrcRect.right = SrcRect.left + 1; + Result = lpDDS->GetDDS()->BltFast( X++ , Y+*OffsetArray++ , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + SrcRect.left++; + } + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + CharPointer = Text; + ch = *CharPointer; + } + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + while( X < ClipRect.right ); + } + + } + else + { + Y = StartY; + X = StartX - IX; + + CharPointer = Text; + ch = *CharPointer; + + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + while( X+Width < StartX ) + { + X += Width; + ++ CharPointer; + if( *CharPointer == '\0' ) + CharPointer = Text; + ch = *CharPointer; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + + if( X >= 0 ) + OffsetArray += X; + + + while( X < ClipRect.right ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + ClipX( &X , &SrcRect , &ClipRect ); + ClipWidth = SrcRect.right - SrcRect.left; + for( i=ClipWidth; i>0; i-- ) + { + SrcRect.right = SrcRect.left + 1; + Result = lpDDS->GetDDS()->BltFast( X++ , Y+*OffsetArray++ , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + SrcRect.left++; + } + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + break; + } + } + } + + return Result; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CDXHorizTextScroller::DrawOffsetTrans( CDXSurface * lpDDS , int * OffsetArray) +{ + int i; + int X , Y; + int Width, ClipWidth; + int Offset; + char * CharPointer; + RECT SrcRect; + char ch; + HRESULT Result; + + if( Wrap == true ) + { + X = StartX; + Y = StartY; + if( X < ClipRect.right ) + { + ch = IXtoCharacter[ IX ].Character; + Offset = IXtoCharacter[ IX ].Offset; + CharPointer = &Text[ IXtoCharacter[ IX ].PositionInText ]; + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + X -= Offset; + + do + { + ClipX( &X , &SrcRect , &ClipRect ); + ClipWidth = SrcRect.right - SrcRect.left; + for( i=ClipWidth; i>0; i-- ) + { + SrcRect.right = SrcRect.left + 1; + Result = lpDDS->GetDDS()->BltFast( X++ , Y+*OffsetArray++ , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + SrcRect.left++; + } + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + CharPointer = Text; + ch = *CharPointer; + } + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + while( X < ClipRect.right ); + } + + } + else + { + Y = StartY; + X = StartX - IX; + + CharPointer = Text; + ch = *CharPointer; + + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + while( X+Width < StartX ) + { + X += Width; + ++ CharPointer; + if( *CharPointer == '\0' ) + CharPointer = Text; + ch = *CharPointer; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + + if( X >= 0 ) + OffsetArray += X; + + + while( X < ClipRect.right ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + ClipX( &X , &SrcRect , &ClipRect ); + ClipWidth = SrcRect.right - SrcRect.left; + for( i=ClipWidth; i>0; i-- ) + { + SrcRect.right = SrcRect.left + 1; + Result = lpDDS->GetDDS()->BltFast( X++ , Y+*OffsetArray++ , TextSurface->TextSurface->GetDDS() , &SrcRect , + DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + SrcRect.left++; + } + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + break; + } + } + } + + return Result; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CDXHorizTextScroller::DrawStretch( CDXSurface * lpDDS , int * StretchArray) +{ + int i; + int X , Y; + int Height , Width, ClipWidth; + int Offset; + char * CharPointer; + RECT SrcRect, DstRect; + char ch; + HRESULT Result; + + if( Wrap == true ) + { + X = StartX; + Y = StartY; + if( X < ClipRect.right ) + { + ch = IXtoCharacter[ IX ].Character; + Offset = IXtoCharacter[ IX ].Offset; + CharPointer = &Text[ IXtoCharacter[ IX ].PositionInText ]; + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + Height = TextSurface->CDXBitmapFontArray[ ch ].Height; + + X -= Offset; + + do + { + ClipX( &X , &SrcRect , &ClipRect ); + ClipWidth = SrcRect.right - SrcRect.left; + for( i=ClipWidth; i>0; i-- ) + { + SrcRect.right = SrcRect.left + 1; + DstRect.left = X; + DstRect.right = X+1; + ++ X; + DstRect.top = Y; + DstRect.bottom = Y + Height + *StretchArray++; + + Result = lpDDS->GetDDS()->Blt( &DstRect , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLT_WAIT , NULL ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + SrcRect.left++; + } + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + CharPointer = Text; + ch = *CharPointer; + } + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + Height = TextSurface->CDXBitmapFontArray[ ch ].Height; + } + while( X < ClipRect.right ); + } + + } + else + { + Y = StartY; + X = StartX - IX; + + CharPointer = Text; + ch = *CharPointer; + + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + while( X+Width < StartX ) + { + X += Width; + ++ CharPointer; + if( *CharPointer == '\0' ) + CharPointer = Text; + ch = *CharPointer; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + + if( X >= 0 ) + StretchArray += X; + + + while( X < ClipRect.right ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + Height = TextSurface->CDXBitmapFontArray[ ch ].Height; + + ClipX( &X , &SrcRect , &ClipRect ); + ClipWidth = SrcRect.right - SrcRect.left; + for( i=ClipWidth; i>0; i-- ) + { + SrcRect.right = SrcRect.left + 1; + DstRect.left = X; + DstRect.right = X+1; + ++ X; + DstRect.top = Y; + DstRect.bottom = Y + Height + *StretchArray++; + + Result = lpDDS->GetDDS()->Blt( &DstRect , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLT_WAIT , NULL ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + SrcRect.left++; + } + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + break; + } + } + } + return Result; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CDXHorizTextScroller::DrawStretchTrans( CDXSurface * lpDDS , int * StretchArray) +{ + int i; + int X , Y; + int Height , Width, ClipWidth; + int Offset; + char * CharPointer; + RECT SrcRect, DstRect; + char ch; + HRESULT Result; + + if( Wrap == true ) + { + X = StartX; + Y = StartY; + if( X < ClipRect.right ) + { + ch = IXtoCharacter[ IX ].Character; + Offset = IXtoCharacter[ IX ].Offset; + CharPointer = &Text[ IXtoCharacter[ IX ].PositionInText ]; + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + Height = TextSurface->CDXBitmapFontArray[ ch ].Height; + + X -= Offset; + + do + { + ClipX( &X , &SrcRect , &ClipRect ); + ClipWidth = SrcRect.right - SrcRect.left; + for( i=ClipWidth; i>0; i-- ) + { + SrcRect.right = SrcRect.left + 1; + DstRect.left = X; + DstRect.right = X+1; + ++ X; + DstRect.top = Y; + DstRect.bottom = Y + Height + *StretchArray++; + + Result = lpDDS->GetDDS()->Blt( &DstRect , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLT_WAIT | DDBLT_KEYSRC , NULL ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + SrcRect.left++; + } + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + CharPointer = Text; + ch = *CharPointer; + } + + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + Height = TextSurface->CDXBitmapFontArray[ ch ].Height; + } + while( X < ClipRect.right ); + } + + } + else + { + Y = StartY; + X = StartX - IX; + + CharPointer = Text; + ch = *CharPointer; + + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + + while( X+Width < StartX ) + { + X += Width; + ++ CharPointer; + if( *CharPointer == '\0' ) + CharPointer = Text; + ch = *CharPointer; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + } + + if( X >= 0 ) + StretchArray += X; + + + while( X < ClipRect.right ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + Height = TextSurface->CDXBitmapFontArray[ ch ].Height; + + ClipX( &X , &SrcRect , &ClipRect ); + ClipWidth = SrcRect.right - SrcRect.left; + for( i=ClipWidth; i>0; i-- ) + { + SrcRect.right = SrcRect.left + 1; + DstRect.left = X; + DstRect.right = X+1; + ++ X; + DstRect.top = Y; + DstRect.bottom = Y + Height + *StretchArray++; + + Result = lpDDS->GetDDS()->Blt( &DstRect , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLT_WAIT | DDBLT_KEYSRC , NULL ); + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + SrcRect.left++; + } + + ++CharPointer; + ch = *CharPointer; + if( ch == '\0' ) + { + break; + } + } + } + return Result; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +void CDXHorizTextScroller::ScrollLeft( int Count ) +{ + if( Wrap == true ) + { + IX += Count; + if( IX >= TextWidth ) + IX -= TextWidth; + } + else + { + IX += Count; + if( IX > TextWidth ) + { + IX = TextWidth; + LeftEnd = TRUE; + RightEnd = FALSE; + } + else + { + LeftEnd = FALSE; + RightEnd = FALSE; + } + } +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +void CDXHorizTextScroller::ScrollRight( int Count ) +{ + if( Wrap == true ) + { + IX -= Count; + if( IX <= -1 ) + IX = TextWidth + IX; + } + else + { + IX -= Count; + if( IX <= -TWidth ) + { + IX = -TWidth; + LeftEnd = FALSE; + RightEnd = TRUE; + } + else + { + LeftEnd = FALSE; + RightEnd = FALSE; + } + } +} + + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +void CDXHorizTextScroller::ResetPosition( void ) +{ + if( Wrap == true ) + IX = TextWidth-TWidth; + else + IX = -TWidth; + + LeftEnd = FALSE; + RightEnd = TRUE; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +inline void CDXHorizTextScroller::ClipX(int *DestX, RECT *SrcRect, RECT *DestRect) +{ + // If it's partly off the right side of the screen + if(*DestX + (SrcRect->right - SrcRect->left) > DestRect->right) + SrcRect->right -= *DestX + (SrcRect->right-SrcRect->left) - DestRect->right; + + // Partly off the left side of the screen + if(*DestX < DestRect->left) + { + SrcRect->left += DestRect->left - *DestX; + *DestX = DestRect->left; + } + + return; +} + + + + + + + + +inline void CDXHorizTextScroller::ClipXY(int *DestX, int *DestY, RECT *SrcRect, RECT *DestRect) +{ + // If it's partly off the right side of the screen + if(*DestX + (SrcRect->right - SrcRect->left) > DestRect->right) + SrcRect->right -= *DestX + (SrcRect->right-SrcRect->left) - DestRect->right; + + // Partly off the left side of the screen + if(*DestX < DestRect->left) + { + SrcRect->left += DestRect->left - *DestX; + *DestX = DestRect->left; + } + + // Partly off the top of the screen + if(*DestY < DestRect->top) + { + SrcRect->top += DestRect->top - *DestY; + *DestY = DestRect->top; + } + + // If it's partly off the bottom side of the screen + if(*DestY + (SrcRect->bottom - SrcRect->top) > DestRect->bottom) + SrcRect->bottom -= ((SrcRect->bottom-SrcRect->top)+*DestY) - DestRect->bottom; + + return; +} diff --git a/CDXAddons/CDXTextScrol/CDXHorizTextScroller.h b/CDXAddons/CDXTextScrol/CDXHorizTextScroller.h new file mode 100644 index 0000000..cbb37c1 --- /dev/null +++ b/CDXAddons/CDXTextScrol/CDXHorizTextScroller.h @@ -0,0 +1,74 @@ +// Project Name: [ CDXHorizTextScroller ] +// Author: [ Ioannis Karagiorgos - karagior@pluto.fernuni-hagen.de ] +// Date: [ 7.4.1999 ] +// Revision: [ 1.00 ] +////////////////////////////////////////////////////////////////////////////////// +#ifndef __CDXHORIZTEXTSCROLLER__ +#define __CDXHORIZTEXTSCROLLER__ + +#define CDXINCLUDEALL +#include +#include "CDXBitmapFont.h" + + +class CDXHorizTextScroller +{ + typedef struct + { + WORD PositionInText; + char Character; + char Offset; + } CDXHTS; + + public: + + int CharsHeight; + int StartX , StartY; + int TWidth; + int IX; + char * Text; + int TextWidth; + int TextLen; + int Position; + + CDXHTS * IXtoCharacter; + + CDXBitmapFont * TextSurface; + CDXScreen * Screen; + + RECT ClipRect; + + bool OwnFont; + bool Wrap; + + BOOL LeftEnd, RightEnd; + + + CDXHorizTextScroller( CDXScreen * Scr , RECT * ClipRectangle , + char * ScrollText , bool TextWrap , CDXBitmapFont * Font = NULL ); + + void Create( void ); + ~CDXHorizTextScroller(); + + HRESULT Draw( CDXSurface * lpDDS ); + HRESULT DrawOffset( CDXSurface * lpDDS , int * OffsetArray); + HRESULT DrawStretch( CDXSurface * lpDDS , int * StretchArray); + HRESULT DrawTrans( CDXSurface * lpDDS ); + HRESULT DrawOffsetTrans( CDXSurface * lpDDS , int * OffsetArray); + HRESULT DrawStretchTrans( CDXSurface * lpDDS , int * StretchArray); + + void ScrollLeft( int Count = 1 ); + void ScrollRight( int Count = 1 ); + void ResetPosition( ); + + int GetPos( void ) { return IX; } + BOOL IsLeftEnd( void ) { return LeftEnd; }; + BOOL IsRightEnd( void ) { return RightEnd; }; + + + private: + inline void ClipX(int *DestX, RECT *SrcRect, RECT *DestRect); + inline void ClipXY(int *DestX, int *DestY , RECT *SrcRect, RECT *DestRect); +}; + +#endif \ No newline at end of file diff --git a/CDXAddons/CDXTextScrol/CDXHorizTextScroller.txt b/CDXAddons/CDXTextScrol/CDXHorizTextScroller.txt new file mode 100644 index 0000000..2fb3692 --- /dev/null +++ b/CDXAddons/CDXTextScrol/CDXHorizTextScroller.txt @@ -0,0 +1,108 @@ +Documentation file for class CDXHorizTextScoller + + +(c) 4/1999 by Ioannis Karagiorgos + EMail: karagior@pluto.fernuni-hagen.de + + +contributions to the CDX project and to everyone who uses and extends it! + + + +Purpose of CDXHorizTextScroller class: +------------------------------- + The CDXVertTextScroller class is able to display horizontal scrolling text. + You can also deform the scroll text vertical. + The text is displayed top aligned in the display rectangle. + You supply the class with a text and output rectangle and can display the + text in the output rectangle and scroll it left and right. + There are two ways of displaying the scrolltext. + TextWrap = true = text wraps around if it reaches its end, + TextWrap = false = text keeps invisible if it scrolls out of its display rectangle. + + +Reference: +---------- + + CDXHorizTextScroller( CDXScreen * Scr , RECT * ClipRectangle , + char * ScrollText , bool TextWrap, + CDXBitmapFont ) + - Scr = pointer to the CDXScreen object + - ClipRectabgle = output rectangle for the scroll text + - Scrolltext = text + - TextWrap = How is the text displayed? + true =tText wraps around if it leaves display rectangle + false = text is invisible if it leaves display rectangle + - Font [OPTIONAL] = CDXBitmapFont object for the scrolltext font, default = NULL + You can pass a CDXBitmapFont object, if you don't, the class + will create an own font, Courier, height=12, Color=RGB(255,255,255) + + - This constructor creates a CDXHorizTextScroller object + + + HRESULT Draw( CDXSurface * lpDDS ) + - lpDDS = destination surface for text output + - HRESULT = error code of the last blit + + - This function draws the text with its background color, for transparent drawing look next function + + + HRESULT DrawTrans( CDXSurface * lpDDS ) + - lpDDS = destination surface for text output + - HRESULT = error code of the last blit + + - This function draws the text transparent + + + HRESULT DrawOffset( CDXSurface * lpDDS , int * OffsetArray ) + - lpDDS = destination surface for text output + - OffsetArray = integer array with offset values for every text column + - HRESULT = error code of the last blit + + - This function draws the text deformed. To the y position of every displayed row of the text + an integer value from the offset array is added, so the text is deformed vertical. + The offset array has to have the same size as the display rectangle width. + For an example of how to use this effect, look into the demonstration code! + + + HRESULT DrawOffsetTrans( CDXSurface * lpDDS , int * OffsetArray ) + - lpDDS = destination surface for text output + - OffsetArray = integer array with offset values for every text column + - HRESULT = error code of the last blit + + - This function draws the text transparent deformed. + To the y position of every displayed row of the text + an integer value from the offset array is added, so the text is deformed vertical. + The offset array has to have the same size as the display rectangle width. + For an example of how to use this effect, look into the demonstration code! + + + + void ScrollLeft( int Count ) + - Count [OPTIONAL] = number of pixels to scroll the text left, default=1 + + - This function scrolls the scroll text Count lines up + + + void ScrollRight( int Count ) + - Count [OPTIONAL] = number of pixels to scroll the text down, default=1 + + - This function scrolls the scroll text Count lines down + + + void ResetPosition() + - This function resets the scrolltext position. + The scrolltext position is set to its rightmost position. + + BOOL IsLeftEnd() + - This function returns TRUE if the text runs out of the screen + while you scroll it to the left, else FALSE. + NOTE: This only works for texts which dont wrap around! + If the text wraps around, then it has no end ;-) + + BOOL IsRightEnd() + - This function returns TRUE if the text runs out of the screen + while you scroll it to the right, else FALSE. + NOTE: This only works for texts which dont wrap around! + If the text wraps around, then it has no end ;-) + \ No newline at end of file diff --git a/CDXAddons/CDXTextScrol/CDXVertTextScroller.cpp b/CDXAddons/CDXTextScrol/CDXVertTextScroller.cpp new file mode 100644 index 0000000..ca5cfcc --- /dev/null +++ b/CDXAddons/CDXTextScrol/CDXVertTextScroller.cpp @@ -0,0 +1,643 @@ +// Project Name: [ CDXVertTextScroller ] +// Author: [ Ioannis Karagiorgos - karagior@pluto.fernuni-hagen.de ] +// Date: [ 7.4.1999 ] +// Revision: [ 1.00 ] +////////////////////////////////////////////////////////////////////////////////// + +#include "CDXVertTextScroller.h" + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +CDXVertTextScroller::CDXVertTextScroller( CDXScreen * Scr , RECT * ClipRectangle , + char * ScrollText , int TextJustif , + int LineSpace , CDXBitmapFont * Font ) +{ + Text = NULL; + TextSurface = NULL; + Screen = Scr; + TextJustify = TextJustif; + LineSpacing = LineSpace; + LineHeight = 0; + TextHeight = 0; + IY = 0; + + + Text = new char [strlen( ScrollText )+1 ]; + if( strlen( ScrollText ) == 0 ) + strcpy( Text , " " ); + else + strcpy( Text , ScrollText ); + + if( Font == NULL ) + { + TextSurface = new CDXBitmapFont( Screen ); + OwnFont = true; // class has to destroy font by herself + } + else + { + TextSurface = Font; + OwnFont = false; // font has to be destroyed by creator, not by this class + } + + ClipRect.left = ClipRectangle->left; + ClipRect.top = ClipRectangle->top; + ClipRect.right = ClipRectangle->right; + ClipRect.bottom = ClipRectangle->bottom; + + StartX = ClipRect.left; + StartY = ClipRect.top; + + TWidth = ClipRect.right - StartX; + THeight = ClipRect.bottom - StartY; + + BottomEnd = FALSE; + TopEnd = FALSE; + + Create( ); + + ResetPosition( ); +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +void CDXVertTextScroller::Create( void ) +{ + int ChWidth , Width , Width2 , LineStart , Index , Index2, i , LineWidth; + bool found; + char ch; + char TextArray[ 1024 ]; + + LineCount = 1; + Index = 0; + Width = 0; + LineStart = 0; + + // now begin initializing lines array + for( i=0; iNumberOfChars = 0; + Lines[i]->LineWidth = 0; + Lines[i]->Characters = NULL; + Lines[i]->ExtraSpace = NULL; + } + + LineCount = 0; + Index = 0; + Width = 0; + LineStart = 0; + + for( ; ; ) + { + ch = Text[ Index ]; + + // test for linefeed + if( ( ch == '\n' ) || ( ch == '\0' ) ) + { + LineWidth = Index - LineStart; + for( i=0; iLineWidth = Width; + Lines[ LineCount ]->NumberOfChars = LineWidth; + Lines[ LineCount ]->Characters = new char[ LineWidth + 1 ]; + strcpy( Lines[ LineCount ]->Characters , TextArray ); + ++ Index; + LineStart = Index; + Width = 0; + ++ LineCount; + + if( ch == '\n' ) + continue; + else + break; + } + + ChWidth = TextSurface->GetCharacterWidth( ch ); + + // check if character fits in current line + if( Width + ChWidth > TWidth ) + { // no, go to next line + found = false; + // trace back to see, if we can break the whole word into the next line + Index2 = Index; + Width2 = Width; + while( Index >=LineStart ) + { + -- Index; + if( Text[Index] == ' ' ) + { + found = true; + break; + } + } + + if( found == true ) + { + -- Index; + } + else + { + Width = Width2; + Index = Index2; + } + + LineWidth = Index - LineStart + 1; + + for( i=0; iNumberOfChars = LineWidth; + Lines[ LineCount ]->Characters = new char[ LineWidth + 1 ]; + strcpy( Lines[ LineCount ]->Characters , TextArray ); + Lines[ LineCount ]->LineWidth = TextSurface->GetTextWidth( TextArray ); + + ++ LineCount; + ++ Index; + if( Text[ Index ] == ' ' ) + ++ Index; + LineStart = Index; + Width = 0; + } + else + { // yes, it fits + Width += ChWidth; + ++ Index; + } + + continue; + } + + + // output debug informations +/* FILE * Datei = fopen( "out.txt" , "w" ); + fprintf( Datei , "Lines: %i\n" , LineCount ); + for( i=0; iNumberOfChars , + Lines[i]->LineWidth , + Lines[i]->Characters ); + } + fclose( Datei ); +*/ + + LineHeight = TextSurface->GetCharacterHeight( 'A' ); + TextHeight = LineCount * ( LineHeight + LineSpacing ); +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +CDXVertTextScroller::~CDXVertTextScroller() +{ + int i; + + if( Text != NULL ) + delete Text; + + for( i=0; iCharacters != NULL ) + delete Lines[ i ]->Characters; + if( Lines[ i ]->ExtraSpace != NULL ) + delete Lines[ i ]->ExtraSpace; + delete Lines[ i ]; + } + + if( OwnFont == true ) + if( TextSurface != NULL ) + delete TextSurface; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CDXVertTextScroller::Draw( CDXSurface * lpDDS ) +{ + int X , Y , YSave, XSave; + int Row , Width , Width2; + char * CharPointer , ch; + RECT SrcRect; + HRESULT Result; + + Result = DD_OK; + + switch( TextJustify ) + { + case CDX_LEFTJUSTIFY: + + Row = 0; + Y = IY; + + while( Y + LineHeight + LineSpacing < 0 ) + { + Y += LineHeight + LineSpacing; + ++ Row; + } + + if( Row >= LineCount ) + break; + + while( Y < THeight ) + { + X = StartX; + CharPointer = Lines[ Row ]->Characters; + + while( ( ch = *CharPointer++ ) != '\0' ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + if( ch != ' ' ) + { + YSave = Y; + Y += StartY; + XSave = X; + ClipXY( &X , &Y , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT ); + Y = YSave; + X = XSave; + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + } + X += Width; + } + Y += LineHeight + LineSpacing; + ++ Row; + if( Row >= LineCount ) + break; + } + break; + + + case CDX_RIGHTJUSTIFY: + + Row = 0; + Y = IY; + + while( Y + LineHeight + LineSpacing < 0 ) + { + Y += LineHeight + LineSpacing; + ++ Row; + } + + if( Row >= LineCount ) + break; + + while( Y < THeight ) + { + CharPointer = Lines[ Row ]->Characters; + Width2 = Lines[ Row ]->LineWidth; + X = ClipRect.right - Width2; + + while( ( ch = *CharPointer++ ) != '\0' ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + if( ch != ' ' ) + { + YSave = Y; + Y += StartY; + XSave = X; + ClipXY( &X , &Y , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT ); + Y = YSave; + X = XSave; + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + } + X += Width; + } + Y += LineHeight + LineSpacing; + ++ Row; + if( Row >= LineCount ) + break; + } + break; + + + case CDX_CENTERJUSTIFY: + + Row = 0; + Y = IY; + + while( Y + LineHeight + LineSpacing < 0 ) + { + Y += LineHeight + LineSpacing; + ++ Row; + } + + if( Row >= LineCount ) + break; + + while( Y < THeight ) + { + CharPointer = Lines[ Row ]->Characters; + Width2 = Lines[ Row ]->LineWidth; + X = StartX + ( ( TWidth - Width2 ) / 2 ); + + while( ( ch = *CharPointer++ ) != '\0' ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + if( ch != ' ' ) + { + YSave = Y; + Y += StartY; + XSave = X; + ClipXY( &X , &Y , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT ); + Y = YSave; + X = XSave; + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + } + X += Width; + } + Y += LineHeight + LineSpacing; + ++ Row; + if( Row >= LineCount ) + break; + } + break; + + } + + return Result; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +HRESULT CDXVertTextScroller::DrawTrans( CDXSurface * lpDDS ) +{ + int X , Y , YSave, XSave; + int Row , Width , Width2; + char * CharPointer , ch; + RECT SrcRect; + HRESULT Result; + + Result = DD_OK; + + switch( TextJustify ) + { + case CDX_LEFTJUSTIFY: + + Row = 0; + Y = IY; + + while( Y + LineHeight + LineSpacing < 0 ) + { + Y += LineHeight + LineSpacing; + ++ Row; + } + + if( Row >= LineCount ) + break; + + while( Y < THeight ) + { + X = StartX; + CharPointer = Lines[ Row ]->Characters; + + while( ( ch = *CharPointer++ ) != '\0' ) + { + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + if( ch != ' ' ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + YSave = Y; + Y += StartY; + XSave = X; + ClipXY( &X , &Y , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY ); + Y = YSave; + X = XSave; + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + } + X += Width; + } + Y += LineHeight + LineSpacing; + ++ Row; + if( Row >= LineCount ) + break; + } + break; + + + case CDX_RIGHTJUSTIFY: + + Row = 0; + Y = IY; + + while( Y + LineHeight + LineSpacing < 0 ) + { + Y += LineHeight + LineSpacing; + ++ Row; + } + + if( Row >= LineCount ) + break; + + while( Y < THeight ) + { + CharPointer = Lines[ Row ]->Characters; + Width2 = Lines[ Row ]->LineWidth; + X = ClipRect.right - Width2; + + while( ( ch = *CharPointer++ ) != '\0' ) + { + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + if( ch != ' ' ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + YSave = Y; + Y += StartY; + XSave = X; + ClipXY( &X , &Y , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY ); + Y = YSave; + X = XSave; + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + } + X += Width; + } + Y += LineHeight + LineSpacing; + ++ Row; + if( Row >= LineCount ) + break; + } + break; + + + case CDX_CENTERJUSTIFY: + + Row = 0; + Y = IY; + + while( Y + LineHeight + LineSpacing < 0 ) + { + Y += LineHeight + LineSpacing; + ++ Row; + } + + if( Row >= LineCount ) + break; + + while( Y < THeight ) + { + CharPointer = Lines[ Row ]->Characters; + Width2 = Lines[ Row ]->LineWidth; + X = StartX + ( ( TWidth - Width2 ) / 2 ); + + while( ( ch = *CharPointer++ ) != '\0' ) + { + Width = TextSurface->CDXBitmapFontArray[ ch ].Width; + if( ch != ' ' ) + { + SrcRect = TextSurface->CDXBitmapFontArray[ ch ].Rectangle; + YSave = Y; + Y += StartY; + XSave = X; + ClipXY( &X , &Y , &SrcRect , &ClipRect ); + Result = lpDDS->GetDDS()->BltFast( X , Y , TextSurface->TextSurface->GetDDS() , + &SrcRect , DDBLTFAST_WAIT | DDBLTFAST_SRCCOLORKEY ); + Y = YSave; + X = XSave; + if( Result == DDERR_SURFACELOST ) + TextSurface->Restore( ); + } + X += Width; + } + Y += LineHeight + LineSpacing; + ++ Row; + if( Row >= LineCount ) + break; + } + break; + + } + + return Result; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +void CDXVertTextScroller::ScrollUp( int Count ) +{ + IY -= Count; + if( IY < -TextHeight ) + { + IY = -TextHeight; + BottomEnd = FALSE; + TopEnd = TRUE; + } + else + { + BottomEnd = FALSE; + TopEnd = FALSE; + } +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +void CDXVertTextScroller::ScrollDown( int Count ) +{ + IY += Count; + if( IY > THeight ) + { + IY = THeight; + BottomEnd = TRUE; + TopEnd = FALSE; + } + else + { + BottomEnd = FALSE; + TopEnd = FALSE; + } + +} + + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +void CDXVertTextScroller::ResetPosition( void ) +{ + IY = THeight; + //IY = 0; + BottomEnd = FALSE; + TopEnd = FALSE; +} + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +inline void CDXVertTextScroller::ClipX(int *DestX, RECT *SrcRect, RECT *DestRect) +{ + // If it's partly off the right side of the screen + if(*DestX + (SrcRect->right - SrcRect->left) > DestRect->right) + SrcRect->right -= *DestX + (SrcRect->right-SrcRect->left) - DestRect->right; + + // Partly off the left side of the screen + if(*DestX < DestRect->left) + { + SrcRect->left += DestRect->left - *DestX; + *DestX = DestRect->left; + } + + return; +} + + + + +////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////////////////// +inline void CDXVertTextScroller::ClipXY(int *DestX, int *DestY, RECT *SrcRect, RECT *DestRect) +{ + // If it's partly off the right side of the screen + if(*DestX + (SrcRect->right - SrcRect->left) > DestRect->right) + SrcRect->right -= *DestX + (SrcRect->right-SrcRect->left) - DestRect->right; + + // Partly off the left side of the screen + if(*DestX < DestRect->left) + { + SrcRect->left += DestRect->left - *DestX; + *DestX = DestRect->left; + } + + // Partly off the top of the screen + if(*DestY < DestRect->top) + { + SrcRect->top += DestRect->top - *DestY; + *DestY = DestRect->top; + } + + // If it's partly off the bottom side of the screen + if(*DestY + (SrcRect->bottom - SrcRect->top) > DestRect->bottom) + SrcRect->bottom -= ((SrcRect->bottom-SrcRect->top)+*DestY) - DestRect->bottom; + + return; +} diff --git a/CDXAddons/CDXTextScrol/CDXVertTextScroller.h b/CDXAddons/CDXTextScrol/CDXVertTextScroller.h new file mode 100644 index 0000000..5d0489f --- /dev/null +++ b/CDXAddons/CDXTextScrol/CDXVertTextScroller.h @@ -0,0 +1,75 @@ +// Project Name: [ CDXVertTextScroller ] +// Author: [ Ioannis Karagiorgos - karagior@pluto.fernuni-hagen.de ] +// Date: [ 7.4.1999 ] +// Revision: [ 1.00 ] +////////////////////////////////////////////////////////////////////////////////// + +#ifndef __CDXVERTTEXTSCROLLER__ +#define __CDXVERTTEXTSCROLLER__ + +#define CDXINCLUDEALL +#include +#include "CDXBitmapFont.h" + +#ifndef CDX_CENTERJUSTIFY +#define CDX_CENTERJUSTIFY 1 +#endif +#ifndef CDX_LEFTJUSTIFY +#define CDX_LEFTJUSTIFY 2 +#endif +#ifndef CDX_RIGHTJUSTIFY +#define CDX_RIGHTJUSTIFY 3 +#endif + +#define CDXVERTSCROLLERMAXLINES 500 + +class CDXVertTextScroller +{ + struct CDXVertScrollerStruct + { + int NumberOfChars; + int LineWidth; + char * Characters; + int * ExtraSpace; + }; + + public: + + CDXBitmapFont * TextSurface; + CDXScreen * Screen; + char * Text; + CDXVertScrollerStruct * Lines[ CDXVERTSCROLLERMAXLINES ]; + int LineCount; + int LineHeight; + int LineSpacing; + int IY; + RECT ClipRect; + int TextJustify; + int StartX , StartY; + int TWidth, THeight; + int TextHeight; + bool OwnFont; + BOOL BottomEnd, TopEnd; + + CDXVertTextScroller( CDXScreen * Scr , RECT * ClipRectangle , + char * ScrollText , int TextJustify = CDX_LEFTJUSTIFY, + int LineSpace=3 , CDXBitmapFont * Font = NULL ); + + void Create( void ); + ~CDXVertTextScroller(); + + HRESULT Draw( CDXSurface * lpDDS ); + HRESULT DrawTrans( CDXSurface * lpDDS ); + + void ScrollUp( int Count = 1 ); + void ScrollDown( int Count = 1 ); + void ResetPosition( ); + BOOL IsBottomEnd( void ) { return BottomEnd; }; + BOOL IsTopEnd( void ) { return TopEnd; }; + + private: + inline void ClipX(int *DestX, RECT *SrcRect, RECT *DestRect); + inline void ClipXY(int *DestX, int *DestY, RECT *SrcRect, RECT *DestRect); +}; + +#endif \ No newline at end of file diff --git a/CDXAddons/CDXTextScrol/CDXVertTextScroller.txt b/CDXAddons/CDXTextScrol/CDXVertTextScroller.txt new file mode 100644 index 0000000..c02a65e --- /dev/null +++ b/CDXAddons/CDXTextScrol/CDXVertTextScroller.txt @@ -0,0 +1,82 @@ +Documentation file for class CDXVertTextScoller + + +(c) 4/1999 by Ioannis Karagiorgos + EMail: karagior@pluto.fernuni-hagen.de + + +contributions to the CDX project and to everyone who uses and extends it! + + + +Purpose of CDXVertTextScroller class: +------------------------------- + The CDXVertTextScroller class is able to display vertical scrolling text. + You supply the class with a text and output rectangle and can display the + text in the output rectangle and scroll it up and down. + The text is formatted into separate lines automatically, you can support + this by inserting linefeeds (\n) in the text string. + + +Reference: +---------- + + CDXVertTextScroller( CDXScreen * Scr , RECT * ClipRectangle , + char * ScrollText , int TextJustify, + int LineSpace , CDXBitmapFont * Font ) + - Scr = pointer to the CDXScreen object + - ClipRectabgle = output rectangle for the scroll text + - Scrolltext = text, you can insert linefeeds in the text to control the way the + class breaks the text into lines + e.g. "Hello world\nThis is a scroll text\n....." + - TextJustify [OPTIONAL } = How is the text displayed? + CDX_CENTERJUSTIFY = each line is displayed centered + CDX_LEFTJUSTIFY = each line is displayed left justified + CDX_RIGHTJUSTIFY = each line is displayed right justified + - LineSpace [OPTIONAL] = space between the text lines, default = 3 + - Font [OPTIONAL] = CDXBitmapFont object for the scrolltext font, default = NULL + You can pass a CDXBitmapFont object, if you don't, the class + will create an own font, Courier, height=12, Color=RGB(255,255,255) + + - This constructor creates a CDXVertTextScroller object + + + HRESULT Draw( CDXSurface * lpDDS ) + - lpDDS = destination surface for text output + - HRESULT = error code of the last blit + + - This function draws the text with its background color, for transparent drawing look next function + + + HRESULT DrawTrans( CDXSurface * lpDDS ) + - lpDDS = destination surface for text output + - HRESULT = error code of the last blit + + - This function draws the text transparent + + + void ScrollUp( int Count ) + - Count [OPTIONAL] = number of pixels to scroll the text up, default=1 + + - This function scrolls the scroll text Count lines up + + + void ScrollDown( int Count ) + - Count [OPTIONAL] = number of pixels to scroll the text down, default=1 + + - This function scrolls the scroll text Count lines down + + + void ResetPosition() + - This function resets the scrolltext position. + The scrolltext is one pixel under the bottom of the display rectangle + If you scroll the text up it will become visible. + + BOOL IsTopEnd() + - This function returns TRUE if the text runs out of the screen + while you scroll it upwards, else FALSE. + + BOOL IsBottomEnd() + - This function returns TRUE if the text runs out of the screen + while you scroll it upwards, else FALSE. + \ No newline at end of file diff --git a/CHANGE_RECORD.txt b/CHANGE_RECORD.txt new file mode 100644 index 0000000..83b494d --- /dev/null +++ b/CHANGE_RECORD.txt @@ -0,0 +1,9 @@ +December 12 2001 + +1) TIME_TO_WAIT_INVADERS changed from 500ms to 100ms + +2) New state "NEXT_LEVEL" added (not yet implemented) + +3) ResetShip() function added so if hit ship will go to left corner and SI won't be restored. + +4) Pressing key "3" will toggle between single and 3-bullet fire. (must be level 3 at least?????) \ No newline at end of file diff --git a/DXVersion.h b/DXVersion.h new file mode 100644 index 0000000..2194757 --- /dev/null +++ b/DXVersion.h @@ -0,0 +1,150 @@ +/* =========================================================================== +// +// File: DXVersion.h +// +// Description: As soon as the application starts, we will read byte from +// "dx.bin" file. If that byte is equal to "1" (means the last +// time we ran this application it was shut down properly) write +// 0 byte to "dx.bin" file. Upon exiting application normaly we +// will write "1". In case we read "0" AND GetDXVersion < 7, at +// the start-up we will give user a warning to download the +// latest version of DirectX since that might be a reason +// application crashed. +// Note: The first time application is running on a given system, "dx.bin" should +// exist and have value "1" written in it ! +// +// Written by: Mirza King, April 2001 +// ======================================================================== */ + +#include +#include +#include + + + +typedef HRESULT(WINAPI * DIRECTDRAWCREATEEX)( GUID*, VOID**, REFIID, IUnknown* ); + + +/* --------------------------------------------------------------------------- +// +// Name: GetDXVersion() +// +// Function: Determine if DirectX 7.0 or higher is installed. +// +// Return value: DirectX Version 0 or 7 ( BYTE ) +// +// ------------------------------------------------------------------------ */ +BYTE GetDXVersion() +{ + + DIRECTDRAWCREATEEX DirectDrawCreateEx = NULL; + HINSTANCE hDDrawDLL = NULL; + BYTE dwDXVersion = 0; + + // First see if DDRAW.DLL even exists. + hDDrawDLL = LoadLibrary( "DDRAW.DLL" ); + if( hDDrawDLL == NULL ) + { + dwDXVersion = 0; + return dwDXVersion; + } + + //------------------------------------------------------------------------- + // DirectX 7.0 Check + //------------------------------------------------------------------------- + + // Check for DirectX 7 by creating a DDraw7 object + LPDIRECTDRAW7 pDD7; + DirectDrawCreateEx = (DIRECTDRAWCREATEEX)GetProcAddress( hDDrawDLL, + "DirectDrawCreateEx" ); + if( NULL == DirectDrawCreateEx ) + { + FreeLibrary( hDDrawDLL ); + return dwDXVersion; + } + + if( FAILED( DirectDrawCreateEx( NULL, (VOID**)&pDD7, IID_IDirectDraw7, + NULL ) ) ) + { + FreeLibrary( hDDrawDLL ); + return dwDXVersion; + } + + // DDraw7 was created successfully. We must be at least DX7.0 + dwDXVersion = 0x7; + pDD7->Release(); + + + //------------------------------------------------------------------------- + // End of checking for versions of DirectX + //------------------------------------------------------------------------- + + // Close open libraries and return + FreeLibrary( hDDrawDLL ); + + return dwDXVersion; +} + + + +/* --------------------------------------------------------------------------- +// +// Name: ReadExitStatus( void ) +// +// Function: Read BYTE binary from a file. +// +// Return value: BYTE +// +// ------------------------------------------------------------------------ */ +BYTE ReadExitStatus( void ) +{ + char Buffer[2]; + BYTE data = 0; + + int status_file = open( "dx.bin", O_RDONLY | O_BINARY ); + + if( status_file ) + { + read( status_file, Buffer, 1 ); + /*** + Here we want to make sure we operate on BYTE size data ! + ***/ + data = (Buffer[0] & 0xff); + close( status_file ); + } + + return data; +} + + + +/* --------------------------------------------------------------------------- +// +// Name: WriteExitStatus( BYTE data ) +// +// Function: Write BYTE binary to a file. +// +// +// Parameters: BYTE ( data ) +// +// Return value: none +// +// ------------------------------------------------------------------------ */ + +void WriteExitStatus( BYTE data ) +{ + char Buffer[2]; + + int status_file = open( "dx.bin", O_RDWR | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); + + if( status_file ) + { + Buffer[0] = data; + Buffer[1] = '\0'; + write( status_file, Buffer, sizeof(Buffer) ); + close( status_file ); + } +} + + +/* ================================ End ==================================== */ \ No newline at end of file diff --git a/Debug.h b/Debug.h new file mode 100644 index 0000000..f445148 --- /dev/null +++ b/Debug.h @@ -0,0 +1,75 @@ +/* =========================================================================== +// +// File: Debug.h +// +// Description: Prints debug info.. +// +// Written by: Mirza King, April 2001 +// ======================================================================== */ + +#define CDXINCLUDEALL +#include + + +/* --------------------------------------------------------------------------- +// +// Name: dprints +// +// Function: Prints debug info on the screen starting in the upper left +// corner. +// +// Remarks: Writes in red color. Screen object must exist. +// +// Usage: dprints("mirza king %d", 2001); +// +// ------------------------------------------------------------------------ */ +void dprints( char *fmt, ... ) +{ + char buf[256]; + + va_list args; + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); + + Screen->GetBack()->GetDC(); + Screen->GetBack()->TextXY(0, 0,RGB(255,0,0) , buf); + Screen->GetBack()->ReleaseDC(); + +} + + + + +/* --------------------------------------------------------------------------- +// +// Name: dprints +// +// Function: Prints debug info to a file. +// +// Remarks: File handle must exist. +// +// Usage: dprintf("mirza king %d \n", 2001); +// +// ------------------------------------------------------------------------ */ +void dprintf(FILE *fdebug, char *fmt, ... ) +{ + + char buf[256]; + + if (DebugFlag == 0) return; + + va_list args; + va_start(args, fmt); + vsprintf(buf, fmt, args); + va_end(args); + + if (fdebug != NULL) + { + fprintf(fdebug, buf); + } + +} + + +/* =============== End of file Debug.h ==================================== */ diff --git a/Options.h b/Options.h new file mode 100644 index 0000000..0219587 --- /dev/null +++ b/Options.h @@ -0,0 +1,85 @@ +/* =========================================================================== +// +// OptionsFile: Options.h +// +// Description: Game options - read/write to a file. +// +// Written by: Mirza King, April 2001 +// ======================================================================== */ + +#include +#include +#include + +#define OptionsFile "ops.bin" + +char OptionsBuffer[8]; + +/* --------------------------------------------------------------------------- +// +// Name: ReadOptions +// +// Function: Reads binary value from a file and converts it to DWORD. +// +// Return value: DWORD (High Score) +//dprints("data = %X first = %X second = %X", data, (data&0xff00)>>8, data&0xff); +// ------------------------------------------------------------------------ */ +DWORD ReadOptions( void ) +{ + DWORD data = 0; + + int file = open( OptionsFile, O_RDONLY | O_BINARY ); + + if( file ) + { + read( file, OptionsBuffer, 4 ); + /*** + Here we want to make sure we operate on BYTE size data ! + ***/ + data = data | (OptionsBuffer[0] & 0xff); + data = (data<<8) | (OptionsBuffer[1] & 0xff); + data = (data<<8) | (OptionsBuffer[2] & 0xff); + data = (data<<8) | (OptionsBuffer[3] & 0xff); + + close( file ); + } + + return data; +} + + + +/* --------------------------------------------------------------------------- +// +// Name: WriteOptions +// +// Function: Converts passed parameter to bytes and writes binary to a +// file. +// +// Parameters: DWORD +// +// Return value: none +//bool fisrst,second; +//WriteOptions( (((unsigned)first&0xff)<<8) | ((unsigned)second&0xff) ); +// +// +// ------------------------------------------------------------------------ */ + +void WriteOptions( DWORD data ) +{ + int file = open( OptionsFile, O_RDWR | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); + + if( file ) + { + for( int i=0,k=3; i<4; i++,k-- ) + OptionsBuffer[i] = (char) ( data >> 8*k ); + + write( file, OptionsBuffer, sizeof(OptionsBuffer) ); + + close( file ); + } +} + + + +/* =================================== End ================================ */ \ No newline at end of file diff --git a/ReadMe.txt b/ReadMe.txt new file mode 100644 index 0000000..7d6037b --- /dev/null +++ b/ReadMe.txt @@ -0,0 +1,50 @@ +======================================================================== + CDX 3.0 APPLICATION : SI +======================================================================== + + +AppWizard has created this SI application for you. + +This file contains a summary of what you will find in each of the files that +make up your SI application. + +SI.cpp + This is the main application source file. + +SI.dsp + This file (the project file) contains information at the project level and + is used to build a single project or subproject. Other users can share the + project (.dsp) file, but they should export the makefiles locally. + +///////////////////////////////////////////////////////////////////////////// +AppWizard has created the following resources: + +SI.rc + This is a listing of all of the Microsoft Windows resources that the + program uses. It includes the icons, bitmaps, and cursors that are stored + in the RES subdirectory. This file can be directly edited in Microsoft + Visual C++. + +res\SI.ico + This is an icon file, which is used as the application's icon (32x32). + This icon is included by the main resource file SI.rc. + +///////////////////////////////////////////////////////////////////////////// +Other standard files: + +StdAfx.h, StdAfx.cpp + These files are used to build a precompiled header (PCH) file + named SI.pch and a precompiled types file named StdAfx.obj. + +Resource.h + This is the standard header file, which defines new resource IDs. + Microsoft Visual C++ reads and updates this file. + +///////////////////////////////////////////////////////////////////////////// +Other notes: + +AppWizard uses "TODO:" to indicate parts of the source code you +should add to or customize. + + +///////////////////////////////////////////////////////////////////////////// diff --git a/Resource.h b/Resource.h new file mode 100644 index 0000000..8d6981b --- /dev/null +++ b/Resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by SI.RC +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS + +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 32771 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 110 +#endif +#endif diff --git a/SI.APS b/SI.APS new file mode 100644 index 0000000..802a893 Binary files /dev/null and b/SI.APS differ diff --git a/SI.cpp b/SI.cpp new file mode 100644 index 0000000..4fd1308 --- /dev/null +++ b/SI.cpp @@ -0,0 +1,2737 @@ +// =========================================================================== +// Project: Space Invaders +// File: SI.cpp +// Author: Mirza Kolakovic +// Date: April 6, 2001. +// =========================================================================== + +// =========================================================================== +// +// File: SI.CPP +// +// Description: This file is the main source file for Space InvaderZ. +// +// +// =========================================================================== + +#include "SI.h" +#include "debug.h" + +// --------------------------------------------------------------------------- +// +// Name: cdx_Init +// +// Function: handles initialization of the CDX objects +// +// +// Parameters: None. +// +// Return value: BOOL. +// +// --------------------------------------------------------------------------- +BOOL cdx_Init( void ) +{ + int i,j; + + /*** + Create the CDXSreen object + ***/ + Screen = new CDXScreen(); + if (Screen==NULL) + CDXError( NULL , "Could not create CDXScreen object" ); + + /*** + Enable triple buffering ? + ***/ + Screen->SetTripleBuffering(TripleBuffer); + /*** + Create Back buffer in Video RAM ? (too slow) + ***/ + Screen->CreateBackBufferInVRAM( BackBufferInVRAM ); + + /*** + Start app + ***/ + StartVideoMode(); + + /*** + Open Debug file? + ***/ + if (DebugFlag ) + fdebug = fopen("debug.txt","a+"); + + /*** + Create Sound Object + ***/ + Sound = new CDXSound; + Sound->Create(g_hWnd); + + /*** + Create Direct Input Object + ***/ + Input = new CDXInput(); + Input->Create(g_hInst, g_hWnd ); + + /*** + Load the tiles + ***/ + TitleT = new CDXTile(); + if( TitleT->Create( Screen , TITLE_BMP , 350 , 150 , 1 , CDXMEM_SYSTEMONLY ) == FALSE) + { + CDXError( Screen , "Could not load tiles from file TITLE.BMP" ); + } + UfoT = new CDXTile(); + if( UfoT->Create( Screen , UFO_BMP , 32 , 32 , 2 , CDXMEM_SYSTEMONLY ) == FALSE) + { + CDXError( Screen , "Could not load tiles from file UFO_BMP" ); + } + ShipT = new CDXTile(); + if( ShipT->Create( Screen , SHIP_BMP , 32 , 32 , 2 , CDXMEM_SYSTEMONLY ) == FALSE)// ??? ADD EXPLOSION + { + CDXError( Screen , "Could not load tiles from file SHIP_BMP" ); + } + SiT = new CDXTile(); + if( SiT->Create( Screen , SI_BMP , 32 , 32, 12 , CDXMEM_SYSTEMONLY ) == FALSE) + { + CDXError( Screen , "Could not load tiles from file SI_BMP" ); + } + BulletT= new CDXTile(); + if( BulletT->Create( Screen , BULLET_BMP , 16 , 16, 3 , CDXMEM_SYSTEMONLY ) == FALSE) // ??? ADD BOMB AND TORPEDO AND EXPLOSION + { + CDXError( Screen , "Could not load tiles from file BULLET_BMP" ); + } + + /*** + Create Sprites + ***/ + + Title = new CDXSprite(); + Title->Create(TitleT); + Title->SetColorKey(0); + UFO = new CDXSprite(); + UFO->Create(UfoT); + UFO->SetColorKey(0); + Ship = new CDXSprite(); + Ship->Create(ShipT); + SI = new CDXSprite(); + SI->Create(SiT); + SI->SetColorKey(0); + LivesSSprite = new CDXSprite(); + LivesSSprite->Create(ShipT); + LivesSSprite->SetScale ( 0.5 ); // SCALE IT + LivesSSprite->SetColorKey(0); + LivesSSprite->SetFrame(1); + + /*** + Create bullets + ***/ + for( i=0; i < MAX_BULLETS; i++) + { + Bullets[i] = 0; + Bullets[i] = new CDXSprite(); + Bullets[i]->Create(BulletT); + } + + /*** + Create bombs + ***/ + for( i=0; i < MAX_BOMBS; i++) + { + Bombs[i] = 0; + Bombs[i] = new CDXSprite(); + Bombs[i]->Create(BulletT); + } + + /*** + Create Invaders + ***/ + for( j=0; j < (HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS); j++) + { + SInvaders[j] = 0; + SInvaders[j] = new CDXSprite(); + SInvaders[j]->Create( SiT ); + } + + /*** + Create torpedos + ***/ + for( i=0; i < MAX_TORPEDOS; i++) + { + Torpedos[i] = 0; + Torpedos[i] = new CDXSprite(); + Torpedos[i]->Create(BulletT); + } + + /*** + Load Sounds + ***/ + BulletSound = new CDXSoundBuffer(); + BulletSound->Load( Sound, BULLET_WAV, 5 ); + Step1 = new CDXSoundBuffer(); + Step1->Load( Sound, STEP1_WAV, 5 ); + Step2 = new CDXSoundBuffer(); + Step2->Load( Sound, STEP2_WAV, 5 ); + Step3 = new CDXSoundBuffer(); + Step3->Load( Sound, STEP3_WAV, 5 ); + Step4 = new CDXSoundBuffer(); + Step4->Load( Sound, STEP4_WAV, 5 ); + UFOSound = new CDXSoundBuffer(); + UFOSound->Load( Sound, UFO_WAV, 5 ); + ExplodeSI = new CDXSoundBuffer(); + ExplodeSI->Load( Sound, SI_EXPLODE_WAV, 5 ); + ExplodeUFO = new CDXSoundBuffer(); + ExplodeUFO->Load( Sound, UFO_EXPLODE_WAV, 2 ); + ExplodeShip = new CDXSoundBuffer(); + ExplodeShip->Load( Sound, SHIP_EXPLODE_WAV,2 ); // ????????????????? + + /*** + Create Stars + ***/ + Stars = new CDXStarField(Screen); + Stars->m_Towards = TRUE; + Stars->m_Flashing = FALSE; + Stars->m_Colored = FALSE; + Stars->Create(); + + /*** + Create Menus + ***/ + CreateMenus(); + // Set active menu + CurrentMenu = MainMenu; + + /*** + Create Credits Scroll Text + ***/ + CreditsFont = new CDXBitmapFont( Screen , "Westminster" , 22 , YELLOW ); + CreditsScroll = new CDXVertTextScroller( Screen , &CreditsClipRect ,ScrollText, CDX_CENTERJUSTIFY , 4 , CreditsFont ); + + /*** + Get default Screen Palette + ***/ + Screen->GetPalette(0, 256, pe); //???????????????????? + + /*** + Create Timers + ***/ + PCScrollTimer = new CDXHPC(); + PCFrameDuration = new CDXHPC(); + PCShip = new CDXHPC(); + PCFireBullet = new CDXHPC(); + PCBullet = new CDXHPC(); + PCSIMove = new CDXHPC(); + PCSIExplosion = new CDXHPC(); + PCUFOExplosion = new CDXHPC(); + PCBulletExplode = new CDXHPC(); + PCShipExplode = new CDXHPC(); + PCStars = new CDXHPC(); + PCGameOver = new CDXHPC(); //????????????????????? + PCNextLevel = new CDXHPC(); + + /*** + Start counters + ***/ + PCShip->Start(); + PCStars->Start(); + PCBullet->Start(); + PCSIMove->Start(); + PCNextLevel->Start(); + PCGameOver->Start(); + PCFireBullet->Start(); + PCSIExplosion->Start(); + PCShipExplode->Start(); + PCScrollTimer->Start(); + PCUFOExplosion->Start(); + PCFrameDuration->Start(); + PCBulletExplode->Start(); + + /*** + Load HiScore from a file. + ***/ + HiScore = ReadHighScore(); + + bPlayThunder = true; // Play Thunder ??????????????? + bRestorePalette = true; // Show stars and restore palette + + // Seed the random-number generator with current time + srand( (unsigned)time( NULL ) ); + + /*** + Set GameState & GO !!!!!!!!!!! + ***/ + GameState = SPLASH; + + return TRUE; + +}/* ==== End of: void cdx_Init( void ) =================================== */ + + +// --------------------------------------------------------------------------- +// +// Name: cdx_DeInit +// +// Function: handles cleanup of CDX objects +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void cdx_DeInit( void ) +{ + int i; + + if( BulletSound ) + { + BulletSound->Stop(); + delete BulletSound; + } + else + if(Step1) + { + Step1->Stop(); + delete Step1; + } + else + if(Step2) + { + Step2->Stop(); + delete Step2; + } + else + if(Step3) + { + Step3->Stop(); + delete Step3; + } + else + if(Step4) + { + Step4->Stop(); + delete Step4; + } + else + if(ExplodeSI) + { + ExplodeSI->Stop(); + delete ExplodeSI; + } + else + if(ExplodeUFO) + { + ExplodeUFO->Stop(); + delete ExplodeUFO; + } + else + if(ExplodeShip) + { + ExplodeShip->Stop(); + delete ExplodeShip; + } + else + if(UFOSound) + { + UFOSound->Stop(); + delete UFOSound; + } + + + for( i=0; i < MAX_BULLETS; i++) + delete Bullets[i]; + + for( i=0; i < MAX_BOMBS; i++) + delete Bombs[i]; + + for( i=0; i < MAX_TORPEDOS; i++) + delete Torpedos[i]; + + for( i=0; i < (HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS); i++ ) + delete SInvaders[i]; + + SAFEDELETE( PCScrollTimer ); + SAFEDELETE( LivesSSprite ); + SAFEDELETE( BulletT ); + SAFEDELETE( Ship ); + SAFEDELETE( SI ); + SAFEDELETE( Title ); + SAFEDELETE( TitleT ); + SAFEDELETE( SiT ); + SAFEDELETE( ShipT ); + SAFEDELETE( UfoT ); + SAFEDELETE( PCBulletExplode); + SAFEDELETE( PCUFOExplosion ); + SAFEDELETE( PCSIExplosion ); + SAFEDELETE( PCSIMove ); + SAFEDELETE( PCBullet ); + SAFEDELETE( PCFireBullet ); + SAFEDELETE( PCAppTiming ); + SAFEDELETE( PCFrameDuration); + SAFEDELETE( PCShip ); + SAFEDELETE( PCShipExplode ); + SAFEDELETE( PCGameOver ); + SAFEDELETE( PCStars ); + SAFEDELETE( Sound ); + SAFEDELETE( Stars ); + SAFEDELETE( Input ); + SAFEDELETE( CreditsFont ); + SAFEDELETE( CreditsScroll ); + SAFEDELETE( MainMenu ); + SAFEDELETE( OptionsMenu ); + SAFEDELETE( Screen ); + + // Close the Debug file + if (DebugFlag) + fclose(fdebug); + + // Save Options + WriteOptions( (((unsigned)g_bFullScreen&0xff)<<8) | ((unsigned)SoundFlag&0xff) ); + + // Write Exir status 1 = "Success" + WriteExitStatus( 0x1 ); + +}/* ==== End of: void cdx_DeInit( void ) ================================= */ + + +// --------------------------------------------------------------------------- +// +// Name: cdx_DoFrame +// +// Function: Main game loop! Here we decide what part of the game we want +// to show, depending on the GameState variable. (State Machine) +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void cdx_DoFrame() +{ + // Get background surface + Back = Screen->GetBack(); + + switch( GameState ) + { + case SPLASH: + DisplaySplash(); + break; + + case INTRO: + GameIntro(); + break; + + case SETUP: + DisplaySetup(); + break; + + case RESET: + ResetGame(); + break; + + case PLAY_GAME: + PlayGame(); + break; + + case PAUSE: + PauseGame(); + break; + + case NEXT_LEVEL: + NextLevel(); + break; + + case GAME_OVER: + GameOver(); + break; + + default: + break; + + } + +}/* ==== End of: void cdx_DoFrame( void ) ================================ */ + + +// --------------------------------------------------------------------------- +// +// Name: DisplaySplash +// +// Function: Displays Logo and Plays Thunder Sound. This is a +// GameState function. GameState = SPLASH +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void DisplaySplash( void ) +{ + if ( !g_bFullScreen ) + GameState = INTRO; + else + GameState = INTRO; //should be SPLASH ???????????? + +}/* ==== End of: void DisplaySplash( void ) ============================== */ + + + +// --------------------------------------------------------------------------- +// +// Name: GameIntro +// +// Function: Displays Intro screen with points and Title. This is a +// GameState function. GameState = INTRO +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void GameIntro( void ) +{ + HDC dc; + UINT DefaultMode; + + Back->Fill(0); // Clear background + + /*** + Put some Stars + ***/ + if( bRestorePalette ) // Only the first time afer the Logo scene ! + { + bRestorePalette = false; + Screen->Flip(); +// Screen->SetPalette(0, 256, pe); // Restore our palette. + } + if( PCStars->GetValue() >= STAR_DELAY ) + { + Stars->Update(); // Update stars + PCStars->Reset(); + } + else + { + Stars->DrawStars(); + } + + /*** + Display Text + ***/ + dc = Back->GetDC(); + DefaultMode = GetTextAlign(dc); + SetTextAlign(dc, TA_CENTER | VTA_CENTER); +// Back->SetFont(); //??????????????????????????????????? what font + Back->TextXY(ScreenWidth/2, ScreenHeight-20, WHITE, MirzaKingText); // TextXY(x, y, color, string) + + int startatY = ScreenHeight/2-100; + for( int i=0; i<4; i++ ) + { + Back->TextXY(ScreenWidth/2, startatY, WHITE, PointsText[i]); + startatY += 50; + } + + /*** + Draw menu + ***/ + CurrentMenu->Draw(ScreenWidth/2, ScreenHeight-140); //X,Y + SetTextAlign(dc, DefaultMode); + Back->ReleaseDC(); + + /*** + Draw Title + ***/ + Title->SetPosX(ScreenWidth/2-175); + Title->SetPosY(0); + Title->Draw(Back , 0 , 0 , CDXBLT_TRANS ); + + /*** + Draw Invaders & ufo + ***/ + SI->SetFrame( 8 ); // Green Invader + SI->SetPos(ScreenWidth/2-85,ScreenHeight/2+45); + SI->Draw(Back , 0 , 0 , CDXBLT_TRANS ); + SI->SetFrame( 4 ); + SI->SetPos(ScreenWidth/2-85,ScreenHeight/2-5); + SI->Draw(Back , 0 , 0 , CDXBLT_TRANS ); + SI->SetFrame( 9 ); //Red Invader + SI->SetPos(ScreenWidth/2-85,ScreenHeight/2-55); + SI->Draw(Back , 0 , 0 , CDXBLT_TRANS ); + SI->SetFrame( 10 );//UFO + SI->SetPos(ScreenWidth/2-85,ScreenHeight/2-105); + SI->Draw(Back , 0 , 0 , CDXBLT_TRANS ); + + Screen->Flip(); + +}/* ==== End of: void GameIntro( void ) ================================== */ + + + +// --------------------------------------------------------------------------- +// +// Name: DisplaySetup +// +// Function: Video mode setup menu. This is a GameState function. +// GameState = SETUP +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void DisplaySetup( void ) +{ + Back->Fill(0); + + CurrentMenu->DrawCentered(); + + Screen->Flip(); + +}/* ==== End of: void DisplaySetup( void ) =============================== */ + + +// --------------------------------------------------------------------------- +// +// Name: ResetShip +// +// Function: Rest ship's state and position. +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void ResetShip(void) +{ + Ship->SetPosY( SHIP_Y ); //Position the Ship on Y-axis (constant) + Ship->SetPosX( 0 ); + Ship->SetFrame(1); + Ship->SetColorKey(0); + Ship->SetState( SHIP_ACTIVE ); + Ship->SetDelay(0); + +}/* ==== End of: void ResetShip( void ) =============================== */ + + +// --------------------------------------------------------------------------- +// +// Name: ResetGame +// +// Function: Sets all the variables and objects in their starting position. +// This is a GameState function. GameState = RESET +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void ResetGame( void ) +{ + /*** + Reset all game variables + ***/ + if(GameLevel > 20) + GameLevel=0; + BulletsToFire = 1; + SIMoveDelay = 1000 - GameLevel*25; + NumberOfLiveSI = HEAD_INVADERS + ANTENA_INVADERS + CONE_INVADERS; + BulletsSinceLastUFO = NoActiveBombs = 0; + ShipdX = UFOdX = BombdY = 0.0; + SIPlayStep = 0; + SINewFrame = 1; + MoveDown = false; + + /*** + Set colors for collision detection ! + Well, this didn't work when dispay was set for 32-bit colors + so we'll have to change startegy! We'll draw sprites and call GetPixel(x,y) + to determine color hex number. + CDX_LPDIRECTDRAWSURFACE surface = Screen->GetBack()->GetDDS(); + WhitePixel = DDColorMatch( surface, WHITE ); + RedPixel = DDColorMatch( surface, RED ); + GreenPixel = DDColorMatch( surface, GREEN ); + YellowPixel = DDColorMatch( surface, YELLOW ); + ***/ + // Ufo + UFOSound->Stop(); + UFO->SetFrame( 1 ); + UFO->SetPos( 0, 0 ); + UFO->Draw(Back, 0,0, CDXBLT_TRANS ); + Back->Lock(); + RedPixel=Back->GetPixel(10,10);//xy + Back->UnLock(); + // Invader + SI->SetFrame( 1 ); + SI->SetPos(0,0); + SI->Draw(Back, 0,0, CDXBLT_TRANS ); + Back->Lock(); + WhitePixel=Back->GetPixel(10,10);//xy + Back->UnLock(); + // Shield + SI->SetFrame( 11 );//shield block + SI->SetPos(0,0); + SI->Draw(Back , 0 , 0 , CDXBLT_TRANS ); + Back->Lock(); + ShieldPixel=Back->GetPixel(10,10);//xy + Back->UnLock(); + // Ship + Ship->SetFrame(1); + Ship->SetPos(0,0); + Ship->Draw(Back , 0 , 0 , CDXBLT_TRANS ); + Back->Lock(); + ShipPixel=Back->GetPixel(15,15);//xy + Back->UnLock(); + + /*** + Reset Ship + ***/ + ResetShip(); + + /*** + Reset UFO + ***/ + UFO->SetState( UFO_NOT_ACTIVE ); + UFO->SetFrame( 1 ); + UFO->SetPos( UFO_X, UFO_Y ); + + /*** + Reset Bullets + ***/ + for( int i=0; i < MAX_BULLETS; i++) + { + Bullets[i]->SetFrame(1); + Bullets[i]->SetState( BULLET_NOT_ACTIVE ); + Bullets[i]->SetColorKey(0); + } + + /*** + Reset Bombs + ***/ + for( i=0; i < MAX_BOMBS; i++) + { + Bombs[i]->SetState( BOMB_NOT_ACTIVE ); + Bombs[i]->SetColorKey(0); + } + + /*** + Reset Invaders + ***/ + SIStartMoveOnX = 5; + SIStopMoveOnX = ScreenWidth-37; // limits when moving when to stop and change direction + SIStopMoveOnY = SHIP_Y; + + SIStartDrawOnX = 75; // for initial drawing and line up + SIStartDrawOnY = 205; + SIDrawStep = 30; + + int posX = 0; + for( int j=0; j < (HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS); j++, posX++) + { + if( posX == CONE_INVADERS ) posX = 0; //CONE_INVADERS is max number per row + + SInvaders[j]->SetState( SI_ACTIVE ); + SInvaders[j]->SetVelX( SIVelocityRight ); + SInvaders[j]->SetVelY( SIVelocityDown ); + + if( j < HEAD_INVADERS/2 ) + { + SInvaders[j]->SetPos( SIStartDrawOnX + SIDrawStep*posX, SIStartDrawOnY ); //x,y Head Invaders 1st row + SInvaders[j]->SetFrame( 1 ); + SInvaders[j]->SetType( SI_HEAD ); + } + else + if( j >= HEAD_INVADERS/2 && j < HEAD_INVADERS ) + { + SInvaders[j]->SetPos( SIStartDrawOnX + SIDrawStep*posX, SIStartDrawOnY-35 ); //x,y Head Invaders 2nd row (from the bottom ) + SInvaders[j]->SetFrame( 1 ); + SInvaders[j]->SetType( SI_HEAD ); + } + else + if( j >= HEAD_INVADERS && j < HEAD_INVADERS+ANTENA_INVADERS/2) + { + SInvaders[j]->SetPos(SIStartDrawOnX + SIDrawStep*posX, SIStartDrawOnY - 70 ); //x,y Antenas, 3rd row + SInvaders[j]->SetFrame( 3 ); + SInvaders[j]->SetType( SI_ANTENA ); + } + else + if( j >= HEAD_INVADERS+ANTENA_INVADERS/2 && j < HEAD_INVADERS+ANTENA_INVADERS ) + { + SInvaders[j]->SetPos(SIStartDrawOnX + SIDrawStep*posX, SIStartDrawOnY - 105 ); //x,y Antenas, 4th row + SInvaders[j]->SetFrame( 3 ); + SInvaders[j]->SetType( SI_ANTENA ); + } + else + if( j >= HEAD_INVADERS+ANTENA_INVADERS ) + { + SInvaders[j]->SetPos(SIStartDrawOnX + SIDrawStep*posX, SIStartDrawOnY - 140 ); //x,y Cones, 5th row + SInvaders[j]->SetFrame( 5 ); + SInvaders[j]->SetType( SI_CONE ); + } + + SInvaders[j]->SetColorKey( 0 ); + } + + /*** + Reset Shields + ***/ + for(i=0; iReset(); + PCNextLevel->Reset(); + + GameState = NEXT_LEVEL; + +}/* ==== End of: void ResetGame( void ) ================================== */ + + +// --------------------------------------------------------------------------- +// +// Name: PlayGame +// +// Function: Function that moves the game. It will first check for the inputs, +// then move objects based on time it took to render previous frame. +// After "collision detection", background buffer will be cleared +// and updated game will be drawn. +// This is a GameState function. GameState = PLAY_GAME +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void PlayGame( void ) +{ + CheckInput(); // Check to see if ship is moving or bullets are fired ? + + MoveObjects(); // Move still active objects to the new positions ! + + Back->Fill(0); // Clear background before drawing new scene ! + + DrawObjects(); // Draw new scene ! + + DisplayStatistics( ); // Display score, hi-score and number of lives ! + + if( DebugFlag ) + Screen->Flip(TRUE,TRUE,TRUE); + else + Screen->Flip(); + + CollisionDetection(); // Detect collisions in the previous frame and update game ! + +}/* ==== End of: void PlayGame( void ) =================================== */ + + + +// --------------------------------------------------------------------------- +// +// Name: CheckInput +// +// Function: Check if keyboard pressed: update ship position, fire bullet +// or quit. +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void CheckInput( void ) +{ + /*** + Get the time it took to render last frame + ***/ + DurationOfTheFrame = PCFrameDuration->GetValue(); + PCFrameDuration->Reset(); + + /*** + Update keyboard input + ***/ + Input->Update(); + + /*** + Quit ? + ***/ + if (Input->GetKeyState(CDXKEY_ESCAPE)==CDXKEY_PRESS) // Quit playing + { + UFOSound->Stop(); + // Save HiScore + if( Score > HiScore ) + { + WriteHighScore( Score ); + } + GameState = INTRO; + GameLevel = 0; + Score = 0; + Lives = 3; + + // return out as the code below is invalid now + return; + } + + /*** + Move Ship if arrow key pressed and ship is still active and we are in the game + ***/ + if( (Ship->GetState() == SHIP_ACTIVE) && (GameState == PLAY_GAME) ) + { + double MoveShipNoPixelsThisFrame = ShipVelocityX * (double)DurationOfTheFrame; + // error correction + ShipdX += MoveShipNoPixelsThisFrame - (int)MoveShipNoPixelsThisFrame; + if( ShipdX >= 1.0 ) + { + MoveShipNoPixelsThisFrame++; + ShipdX -= 1.0; + } + + if(Input->GetKeyState(CDXKEY_RIGHTARROW) ) // go right + { + Ship->SetPosX( Ship->GetPosX() + (int)MoveShipNoPixelsThisFrame); + if(Ship->GetPosX() > (ScreenWidth-40) ) + Ship->SetPosX(ScreenWidth-40); + } + if(Input->GetKeyState(CDXKEY_LEFTARROW) ) // go left + { + Ship->SetPosX( Ship->GetPosX() - (int)MoveShipNoPixelsThisFrame ); + if(Ship->GetPosX() < 0) + Ship->SetPosX(0); + } + }// if( Ship->GetState() == SHIP_ACTIVE ) + + /*** + Fire bullets is 'space' key pressed and ship is still active + ***/ + int BulletsFired = 0; + if (Input->GetKeyState(CDXKEY_SPACE) && ( Ship->GetState() == SHIP_ACTIVE ) && (GameState == PLAY_GAME)) // Fire the bulet + { + if( PCFireBullet->GetValue() >= BULLET_DELAY ) + { + for( int i=0; (i < MAX_BULLETS) ; i++) + { + if( Bullets[i]->GetState() == BULLET_NOT_ACTIVE ) //find a bullet that is currently inactive + { + Bullets[i]->SetState( BULLET_ACTIVE ); + Bullets[i]->SetFrame(1); + BulletsFired++; + BulletsSinceLastUFO++; + + if( BulletsFired == 1 ) + { + Bullets[i]->SetPosX(Ship->GetPosX() + 8 ); + Bullets[i]->SetPosY(Ship->GetPosY() - 8 ); + Bullets[i]->SetFrame(1); + } + else + if( BulletsFired == 2 ) + { + Bullets[i]->SetPosX(Ship->GetPosX() - 6 ); + Bullets[i]->SetPosY(Ship->GetPosY() + 6 ); + Bullets[i]->SetFrame(1); + } + else + if( BulletsFired == 3 ) + { + Bullets[i]->SetPosX(Ship->GetPosX() + 22 ); + Bullets[i]->SetPosY(Ship->GetPosY() + 6 ); + Bullets[i]->SetFrame(1); + } + + if( SoundFlag && (BulletsFired == 1)) + { + BulletSound->Stop(); + BulletSound->Play(); + } + + if( BulletsFired == BulletsToFire ) break; + } + }//for( int i=0; (i < MAX_BULLETS) .... + + PCFireBullet->Reset(); + // Move UFO if time to... + if( (BulletsToFire == 1 && BulletsSinceLastUFO >= ACTIVATE_UFO_ON) || + (BulletsToFire == 3 && BulletsSinceLastUFO >= 2*ACTIVATE_UFO_ON)) + { + BulletsSinceLastUFO = 0; + UFO->SetPos( UFO_X, UFO_Y ); + UFO->SetState( UFO_ACTIVE ); + if( SoundFlag ) + { UFOSound->Stop(); + UFOSound->Play(); + } + } + + }//if( PCFireBullet->GetValue() >= BULLET_DELAY ) + }//if (Input->GetKeyState(CDXKEY_SPACE) ) // Fire the bulet + + /*** + Flash Keyboard buffer + ***/ + Input->FlushKeyboardData(); + +}/* ==== End of: void CheckInput( void ) ================================= */ + + + +// --------------------------------------------------------------------------- +// +// Name: MoveObjects +// +// Function: Move all the sprites (except Ship). +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void MoveObjects( void ) +{ + int i,j; + bool bFireBombs = false; + + /*** + Move Bullets + ***/ + for( i=0; i < MAX_BULLETS; i++) + { + if( Bullets[i]->GetState() == BULLET_ACTIVE ) //find active bullet + { + Bullets[i]->SetPosY( Bullets[i]->GetPosY() - (int)(BulletVelocityY * (double)DurationOfTheFrame) ); + if( Bullets[i]->GetPosY() <= 0 ) + Bullets[i]->SetState( BULLET_NOT_ACTIVE ); + } + } + + + /*** + Move Invaders + ***/ + if( SIMoveDelay > 1000 ) SIMoveDelay = 1000; + else + if( SIMoveDelay < 15 ) SIMoveDelay = 15; + + // Check if its time to move invaders + if( (PCSIMove->GetValue()>=(DWORD)SIMoveDelay)&&(NumberOfLiveSI>0)&&(Ship->GetState()==SHIP_ACTIVE)) + { + bFireBombs = true; + if( !MoveDown ) + { + for( j=0; j < (HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS); j++ ) // Then move invaders + { + if( SInvaders[j]->GetState() == SI_ACTIVE ) + SInvaders[j]->SetFrame( SInvaders[j]->GetFrame() + SINewFrame ); + + SInvaders[j]->SetPosX( SInvaders[j]->GetPosX() + SInvaders[j]->GetVelX() ); //set X position + + if( SInvaders[j]->GetState() == SI_ACTIVE && SInvaders[j]->GetPosX() > SIStopMoveOnX ) + MoveDown = true; + else + if( SInvaders[j]->GetState() == SI_ACTIVE && SInvaders[j]->GetPosX() < SIStartMoveOnX ) + MoveDown = true; + } + if( MoveDown ) //check if we really want to go down one row + { + for(j=0; j<(HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS); j++ ) + if( SInvaders[j]->GetPosY() >= SIStopMoveOnY && SInvaders[j]->GetState() == SI_ACTIVE ) + MoveDown = false; // don't move down cause one or more is already at the bottom + + if( !MoveDown ) //but instead change the direction + for(j=0; j<(HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS); j++ ) + SInvaders[j]->SetVelX( SInvaders[j]->GetVelX() * (-1) ); + } + } + else // move 'em down + { + for( int k=0; k < (HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS); k++ ) + { + if( MoveDown ) + SInvaders[k]->SetPosY( SInvaders[k]->GetPosY() + SInvaders[k]->GetVelY() ); + SInvaders[k]->SetVelX( SInvaders[k]->GetVelX() * (-1) ); + } + MoveDown = false; + } + + PCSIMove->Reset(); + + if( !MoveDown ) + SINewFrame = SINewFrame * (-1); //alternate between two frames + + // Play sound + if( SoundFlag ) + { + if( SIPlayStep == STEP1 ) + { + Step4->Stop(); + Step1->Play(); + SIPlayStep = STEP2; + } + else + if( SIPlayStep == STEP2 ) + { + Step1->Stop(); + Step2->Play(); + SIPlayStep = STEP3; + } + else + if( SIPlayStep == STEP3 ) + { + Step2->Stop(); + Step3->Play(); + SIPlayStep = STEP4; + } + else + if( SIPlayStep == STEP4 ) + { + Step3->Stop(); + Step4->Play(); + SIPlayStep = STEP1; + } + } + + } + + /*** + Move UFO + ***/ + if( UFO->GetState() == UFO_ACTIVE ) + { + double MoveUFOPixelsThisFrame = UFOVelocityX * (double)DurationOfTheFrame; + UFOdX += MoveUFOPixelsThisFrame - (int)MoveUFOPixelsThisFrame; + // A little bit of correction + if( UFOdX >= 1.0) + { + MoveUFOPixelsThisFrame++; + UFOdX -= 1.0; + } + + UFO->SetPosX( UFO->GetPosX() + (int)MoveUFOPixelsThisFrame ); + + if( UFO->GetPosX() > ScreenWidth ) + { + UFO->SetState( UFO_NOT_ACTIVE ); + UFO->SetPos( UFO_X, UFO_Y ); + UFOSound->Stop(); + } + } + + /*** + Move Bombs & Fire new ones, a little bit of AI + ***/ + double MoveBombPixelsThisFrame = BombVelocityY * (double)DurationOfTheFrame; + BombdY += MoveBombPixelsThisFrame - (int)MoveBombPixelsThisFrame; + // A little bit of correction + if( BombdY >= 1.0) + { + MoveBombPixelsThisFrame++; + BombdY -= 1.0; + } + for( i=0; iGetState() == BOMB_ACTIVE ) + { + Bombs[i]->SetPosY( Bombs[i]->GetPosY() + (int)MoveBombPixelsThisFrame); + if( Bombs[i]->GetPosY() >= ScreenHeight ) + { + Bombs[i]->SetState( BOMB_NOT_ACTIVE ); + NoActiveBombs--; + } + } + } + /*** + Now, Fire Bombs + ***/ + if( bFireBombs && (NoActiveBombs < (3+GameLevel))) // now, fire new ones if time for it. + { + if( NumberOfLiveSI <= 2 ) + { + for(i=0; iGetState() == SI_ACTIVE ) + { + for(j=0; jGetState() == BOMB_NOT_ACTIVE ) + { + Bombs[j]->SetState( BOMB_ACTIVE ); + NoActiveBombs++; + Bombs[j]->SetFrame(3); + Bombs[j]->SetPos( SInvaders[i]->GetPosX()+7, SInvaders[i]->GetPosY()+25 ); + break; // go find next invader to shot + } + } + } + } + } + else + { + int BombsToFire; + int fired = 0; + if( NumberOfLiveSI >= (HEAD_INVADERS + ANTENA_INVADERS + CONE_INVADERS)/2 ) BombsToFire=3+GameLevel; + else BombsToFire = 2+GameLevel; + if( BombsToFire > NumberOfLiveSI ) BombsToFire = NumberOfLiveSI; + // Find if any invader is positioned above the ship + int ShipX = Ship->GetPosX(); + for(i=0; (iGetPosX(); + if( (SIPositionX < (ShipX+32+SIDrawStep) && SIPositionX > (ShipX-(32+SIDrawStep))) && SInvaders[i]->GetState() == SI_ACTIVE ) + { + for(j=0; jGetState() == BOMB_NOT_ACTIVE ) + { + Bombs[j]->SetState( BOMB_ACTIVE ); + NoActiveBombs++; + Bombs[j]->SetFrame(3); + Bombs[j]->SetPos( SInvaders[i]->GetPosX()+7, SInvaders[i]->GetPosY()+25 ); + fired++; + break; // go find next invader to shot + } + } + } + } + + while( fired < BombsToFire ) // If we still have to fire some bombs, than do it random + { + int num = (HEAD_INVADERS + ANTENA_INVADERS + CONE_INVADERS -1) * rand() / (RAND_MAX + 1); // get random number in the range + + if( num >= 0 && num < HEAD_INVADERS + ANTENA_INVADERS + CONE_INVADERS ) //just to make sure we are in the range of SInvaders array + { + if( SInvaders[num]->GetState() == SI_ACTIVE ) + { + for(j=0; jGetState() == BOMB_NOT_ACTIVE ) + { + Bombs[j]->SetState( BOMB_ACTIVE ); + NoActiveBombs++; + Bombs[j]->SetFrame(3); + Bombs[j]->SetPos( SInvaders[num]->GetPosX()+7, SInvaders[num]->GetPosY()+25 ); + fired++; + break; // go find next invader to shot + } + } + } + } + } + } + }// end if( bFireBombs ) + + /*** + Move Torpedos + ***/ + + +}/* ==== End of: void MoveObjects( void ) ================================ */ + + +// --------------------------------------------------------------------------- +// +// Name: DrawObjects +// +// Function: Draw all of the game objects to the back buffer in the following +// order: bullets, bombs, torpedos, ship, shield, invaders, ufo. +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void DrawObjects( void ) +{ + int i,j; + /*** + Draw Bullets First + ***/ + for( i=0; i < MAX_BULLETS; i++) + { + if( Bullets[i]->GetState() != BULLET_NOT_ACTIVE ) //find an unused spot in the array + { + Bullets[i]->Draw(Back, 0,0, CDXBLT_TRANS ); + + if( (Bullets[i]->GetState() == BULLET_EXPLODE )&&(PCBulletExplode->GetValue()-Bullets[i]->GetDelay() >= BULLET_EXPLODE_DELAY) ) + Bullets[i]->SetState( BULLET_NOT_ACTIVE ); + + } + } + + /*** + Draw Bombs + ***/ + for( i=0; iGetState() != BOMB_NOT_ACTIVE ) + { + Bombs[i]->Draw(Back,0,0,CDXBLT_TRANS); + + if( (Bombs[i]->GetState() == BOMB_EXPLODE )&&(PCBulletExplode->GetValue()-Bombs[i]->GetDelay() >= BOMB_EXPLODE_DELAY) ) + { + Bombs[i]->SetState( BOMB_NOT_ACTIVE ); + NoActiveBombs--; + } + } + + /*** + Draw Torpedos + ***/ + + /*** + Draw Ship + ***/ + if( (Ship->GetState()==SHIP_EXPLODE)&&(PCShipExplode->GetValue()-Ship->GetDelay() >= SHIP_EXPLODE_DELAY) ) + { + + if( Ship->GetFrame() < SHIP_LAST_FRAME ) + { + Ship->SetFrame( Ship->GetFrame() + 1 ); + Ship->SetDelay( PCShipExplode->GetValue() ); + } + else + { + UFOSound->Stop(); + Ship->SetFrame( 0 ); + Ship->SetState(SHIP_NOT_ACTIVE); + + if( Lives > 0 ) + { + ResetShip(); + } + else + { + GameState = GAME_OVER; + CreditsScroll->ResetPosition(); + } + } + } + Ship->Draw(Back, 0,0, CDXBLT_TRANS ); + + /*** + Draw UFO + ***/ + if( UFO->GetState() != UFO_NOT_ACTIVE ) + { + if( UFO->GetState() == UFO_ACTIVE ) + { + UFO->Draw(Back, 0,0, CDXBLT_TRANS ); + } + else // Display points + { + Back->GetDC(); + Back->TextXY( UFO->GetPosX(), UFO->GetPosY(), RED, strUFOScore); + Back->ReleaseDC(); + if( PCUFOExplosion->GetValue() >= UFO_EXPLODE_DELAY ) + { + UFO->SetState( UFO_NOT_ACTIVE ); + ExplodeUFO->Stop(); + } + } + } + + + /*** + Draw Shields + ***/ + int a,b,c,d; + Back->Lock(); + for(i=0; iPutPixel( SHIELD_1_X+a, SHIELD_Y+i, ShieldPixel); + + for(b=0; bPutPixel( SHIELD_2_X+b, SHIELD_Y+i, ShieldPixel); + + for(c=0; cPutPixel( SHIELD_3_X+c, SHIELD_Y+i, ShieldPixel); + + for(d=0; dPutPixel( SHIELD_4_X+d, SHIELD_Y+i, ShieldPixel); + + } + Back->UnLock(); + + /*** + Draw invaders + ***/ + for( j=0; j < (HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS); j++ ) + { + if( SInvaders[j]->GetState() != SI_NOT_ACTIVE ) + { + SInvaders[j]->Draw(Back, 0,0, CDXBLT_TRANS ); + + if ( SInvaders[j]->GetState() == SI_EXPLODE ) //If just hit + { + SInvaders[j]->SetState( SI_EXPLODE_DELAY ); //show explosion frame number of millisec + SInvaders[j]->SetDelay(PCSIExplosion->GetValue()); + if( SoundFlag ) + { + ExplodeSI->Stop(); + ExplodeSI->Play(); + } + } + else + if( (PCSIExplosion->GetValue()-SInvaders[j]->GetDelay() >= EXPLODE_DELAY)&&(SInvaders[j]->GetState() == SI_EXPLODE_DELAY) ) + { + SInvaders[j]->SetState( SI_NOT_ACTIVE ); + SIMoveDelay-=10; + if( NumberOfLiveSI <= 0 ) + { + UFOSound->Stop(); + GameLevel++; + GameState = RESET;// No more invaders to kill, so bring 'em back + PCSIExplosion->WaitFor(TIME_TO_WAIT_INVADERS); + + } + } + } + + } + + +}/* ==== End of: void DrawObjects( void ) ================================ */ + + +// --------------------------------------------------------------------------- +// +// Name: CollisionDetection +// +// Function: This function handles all collision detection between the sprites. +// Possible collisions: Bullet -> Shield, Torpedo, Bomb, Invader, UFO +// Bomb,Torpedo -> Bullet, Shield, Ship +// The goal is to minimize number of comparisons, so if we have already +// search for Bullet-Bomb collision we won't do it again as Bomb-Bullet +// detection. +// +// Search patterns: +// 1 - Bullet->Shield->Invader,Bomb,Torpedo->UFO +// 2 - Bomb->Shield->Ship +// 3 - Torpedo->Shield->Ship +// 4 - Invader->Shield->Ship +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void CollisionDetection( void ) +{ + int i,j; + bool BulletHit = true; + bool BulletHasRedPixel = false; + bool BulletHasWhitePixel = false; + bool BulletHasShieldPixel = false; + bool BombHasShieldPixel = false; + bool BombHasShipPixel = false; + RECT ShipRect = { Ship->GetPosX()+1, Ship->GetPosY()+1, Ship->GetPosX()+30, Ship->GetPosY()+30 }; + + /*** + First test all the bullets for collision with: Shield, Invader, Bomb, Torpedo or UFO + ***/ + for( int BulletCounter = 0; BulletCounter < MAX_BULLETS; BulletCounter++) + { + if( Bullets[BulletCounter]->GetState() == BULLET_ACTIVE ) + { + // Get bullet rectangle + RECT BulletRect = { Bullets[BulletCounter]->GetPosX()+7, Bullets[BulletCounter]->GetPosY(), + Bullets[BulletCounter]->GetPosX() + 8, // make it narrow + Bullets[BulletCounter]->GetPosY() + 15 }; + + // Get bullet Pixel colors and set color flags + Back->Lock(); + for( i=0; i<2; i++ ) + for( j=0; j<16; j++ ) + { + if( Bullets[BulletCounter]->GetPosY() > 35 ) + { + DWORD Temp = Back->GetPixel( Bullets[BulletCounter]->GetPosX() + i+7, Bullets[BulletCounter]->GetPosY()+ j); + if( Temp == ShieldPixel ) BulletHasShieldPixel = true; + else + if( Temp == WhitePixel ) BulletHasWhitePixel = true; + else + if( Temp == RedPixel ) BulletHasRedPixel = true; + } + } + Back->UnLock(); + + // First Check if the shield has been hit + if( BulletHasShieldPixel ) + { + int x,y,a,b,k; + int Xdir = 1; + int PixelsOff = 250; + int Radius = 15; + + for(k=0; k= (SHIELD_1_X-1) && BulletRect.right <= (SHIELD_1_X+SHIELD_WIDTH) ) + { + // FIND THAT PIXEL IN THE BITMAP AND TURN IT OFF + if( ((x-SHIELD_1_X) >= 0) && ((x-SHIELD_1_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield1[ y-SHIELD_Y ][ x-SHIELD_1_X ] = 0; + } + + // Second ? + if ( BulletRect.left >= (SHIELD_2_X-1) && BulletRect.right <= (SHIELD_2_X+SHIELD_WIDTH) ) + { + if( ((x-SHIELD_2_X) >= 0) && ((x-SHIELD_2_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield2[ y-SHIELD_Y ][ x-SHIELD_2_X ] = 0; + } + + // Third ? + if ( BulletRect.left >= (SHIELD_3_X-1) && BulletRect.right <= (SHIELD_3_X+SHIELD_WIDTH) ) + { + if( ((x-SHIELD_3_X) >= 0) && ((x-SHIELD_3_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield3[ y-SHIELD_Y ][ x-SHIELD_3_X ] = 0; + } + + // Fourth ? + if ( BulletRect.left >= (SHIELD_4_X-1) && BulletRect.right <= (SHIELD_4_X+SHIELD_WIDTH) ) + { + if( ((x-SHIELD_4_X) >= 0) && ((x-SHIELD_4_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield4[ y-SHIELD_Y ][ x-SHIELD_4_X ] = 0; + } + + Xdir*=(-1); // Center of explosion is close to the center of the bullet so we want to turn pixels off + } // to the left and right equaly. + }// end of for(k=0; kSetState( BULLET_EXPLODE ); + Bullets[BulletCounter]->SetFrame(2); + Bullets[BulletCounter]->SetPosY( Bullets[BulletCounter]->GetPosY()-6 ); + Bullets[BulletCounter]->SetDelay( PCBulletExplode->GetValue() ); + + }// end if( BulletHasShieldPixel ) + + // If bullet is still active, Invader,Bullet,Torpedo is white so check if any of bullet pixel is turned to be white too. + if( BulletHasWhitePixel && Bullets[BulletCounter]->GetState() == BULLET_ACTIVE ) + { + // Now find out which Invader got hit? + for( j=0; j < HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS; j++ ) + { + if( SInvaders[j]->GetState() == SI_ACTIVE ) //if active check if that is the one that got hit + { // MAKE SI Rectangle + RECT SIRect = { SInvaders[j]->GetPosX() + 4, SInvaders[j]->GetPosY()+7, + SInvaders[j]->GetPosX() + 27, // make it smaller + SInvaders[j]->GetPosY() + 22 }; + // Perform rectangle collision test + if(SIRect.top > BulletRect.bottom) BulletHit = false; + else if(SIRect.bottom < BulletRect.top) BulletHit = false; + else if(SIRect.right < BulletRect.left) BulletHit = false; + else if(SIRect.left > BulletRect.right) BulletHit = false; + + if( BulletHit ) // If that is the one ..... + { + Bullets[BulletCounter]->SetState( BULLET_NOT_ACTIVE ); // we got hit, so return this bullet to the pool + SInvaders[j]->SetState( SI_EXPLODE ); + SInvaders[j]->SetFrame( 7 ); + NumberOfLiveSI--; + assert( NumberOfLiveSI >=0 ); + int WhichSI = SInvaders[j]->GetType(); + if( WhichSI == SI_HEAD ) Score+=10; + else + if( WhichSI == SI_ANTENA ) Score+=20; + else + if( WhichSI == SI_CONE ) Score+=30; + break; //... stop looking + } + + BulletHit = true; + }// if( SInvaders[j]->GetState() == SI_ACTIVE ) + }//for( int j=0; j < HEAD_INVADERS+ANTENA_INVADERS+CONE_INVADERS; j++ ) + + if( Bullets[BulletCounter]->GetState() == BULLET_ACTIVE ) //so, this one didn't hit Invader - maybe bomb ? + { + // check all active bombs for rectangle test + for(i=0; iGetState() == BOMB_ACTIVE ) + { + // Get Bomb rectangle + RECT BombRect = { Bombs[i]->GetPosX()+7, Bombs[i]->GetPosY()+3, + Bombs[i]->GetPosX() + 9, // make it narrow + Bombs[i]->GetPosY() + 12 }; + + // Perform rectangle collision test + if(BombRect.top > BulletRect.bottom) BulletHit = false; + else if(BombRect.bottom < BulletRect.top) BulletHit = false; + else if(BombRect.right < BulletRect.left) BulletHit = false; + else if(BombRect.left > BulletRect.right) BulletHit = false; + + if( BulletHit ) // If that is the one ..... + { + Bullets[BulletCounter]->SetState( BULLET_EXPLODE ); + Bullets[BulletCounter]->SetFrame(2); + Bullets[BulletCounter]->SetPosY( Bullets[BulletCounter]->GetPosY()-6 ); + Bullets[BulletCounter]->SetDelay( PCBulletExplode->GetValue() ); + Bombs[i]->SetState( BOMB_EXPLODE ); + Bombs[i]->SetFrame( 2 ); + Bombs[i]->SetDelay( PCBulletExplode->GetValue() ); + break; //... stop looking + } + + BulletHit = true; + } + } + + } + + if( Bullets[BulletCounter]->GetState() == BULLET_ACTIVE ) //so, this one didn't hit bomb - maybe torpedo ? + { + // check all active bombs for rectangle test + } + + }//if( (Pixel1 == WhitePixel ||....... + + // If at this point bullet is still active, check the UFO + if( Bullets[BulletCounter]->GetState() == BULLET_ACTIVE && UFO->GetState() == UFO_ACTIVE && BulletHasRedPixel) + { + Bullets[BulletCounter]->SetState( BULLET_NOT_ACTIVE );// UFO is down !!! + UFO->SetState( UFO_EXPLODE ); + PCUFOExplosion->Reset(); + UFOSound->Stop(); + if( SoundFlag ) + ExplodeUFO->Play(); + if( BulletsSinceLastUFO == 0 ) + { + Score+=500; + sprintf(strUFOScore, "%d", 500); + } + else + if( BulletsSinceLastUFO == 1 ) + { + Score+=300; + sprintf(strUFOScore, "%d", 300); + } + else + if( BulletsSinceLastUFO == 2 ) + { + Score+=150; + sprintf(strUFOScore, "%d", 150); + } + else + if( BulletsSinceLastUFO >= 2 ) + { + Score+=50; + sprintf(strUFOScore, "%d", 50); + } + } + + }//if( Bullets[BulletCounter]->GetState() == BULLET_ACTIVE ) + + BulletHasWhitePixel=BulletHasShieldPixel=BulletHasRedPixel=false; + + }//for( int i=0; i < MAX_BULLETS; i++) + + + /*** + Second test all the bombs for collision with: Shield or Ship (first ship, if true don't need to search shield array) + ***/ + for( int BombCounter = 0; BombCounter < MAX_BOMBS; BombCounter++) + { + if( Bombs[BombCounter]->GetState() == BOMB_ACTIVE ) + { + // Get Bomb rectangle + RECT BombRect = { Bombs[BombCounter]->GetPosX()+7, Bombs[BombCounter]->GetPosY()+3, + Bombs[BombCounter]->GetPosX() + 9, // make it narrow + Bombs[BombCounter]->GetPosY() + 12 }; + + // Get Bomb Pixel colors and set color flags + Back->Lock(); + for( i=7; i<10; i++ ) + for( j=3; j<13; j++ ) + { + if( (Bombs[BombCounter]->GetPosY()+ j) < ScreenHeight ) // !!! Danger - Make sure you are not reading not existing pixels ! + { + DWORD Temp = Back->GetPixel( Bombs[BombCounter]->GetPosX() + i, Bombs[BombCounter]->GetPosY()+ j); + if( Temp == ShieldPixel ) BombHasShieldPixel = true; + else + if( Temp == ShipPixel ) BombHasShipPixel = true; + } + } + Back->UnLock(); + + // First Check if the shield has been hit + if( BombHasShieldPixel ) + { + int x,y,a,b,k; + int Xdir = 1; + int PixelsOff = 250; + int Radius = 15; + + for(k=0; k= (SHIELD_1_X-1) && BombRect.right <= (SHIELD_1_X+SHIELD_WIDTH) ) + { + // FIND THAT PIXEL IN THE BITMAP AND TURN IT OFF + if( ((x-SHIELD_1_X) >= 0) && ((x-SHIELD_1_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield1[ y-SHIELD_Y ][ x-SHIELD_1_X ] = 0; + } + + // Second ? + if ( BombRect.left >= (SHIELD_2_X-1) && BombRect.right <= (SHIELD_2_X+SHIELD_WIDTH) ) + { + if( ((x-SHIELD_2_X) >= 0) && ((x-SHIELD_2_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield2[ y-SHIELD_Y ][ x-SHIELD_2_X ] = 0; + } + + // Third ? + if ( BombRect.left >= (SHIELD_3_X-1) && BombRect.right <= (SHIELD_3_X+SHIELD_WIDTH) ) + { + if( ((x-SHIELD_3_X) >= 0) && ((x-SHIELD_3_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield3[ y-SHIELD_Y ][ x-SHIELD_3_X ] = 0; + } + + // Fourth ? + if ( BombRect.left >= (SHIELD_4_X-1) && BombRect.right <= (SHIELD_4_X+SHIELD_WIDTH) ) + { + if( ((x-SHIELD_4_X) >= 0) && ((x-SHIELD_4_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield4[ y-SHIELD_Y ][ x-SHIELD_4_X ] = 0; + } + + Xdir*=(-1); // Center of explosion is close to the center of the Bomb so we want to turn pixels off + } // to the left and right equaly. + }// end of for(k=0; kSetState( BOMB_EXPLODE ); + Bombs[BombCounter]->SetFrame(2); + Bombs[BombCounter]->SetDelay( PCBulletExplode->GetValue() ); + + }// end if( BombHasShieldPixel ) + + if( (Bombs[BombCounter]->GetState()==BOMB_ACTIVE) && BombHasShipPixel ) + { + if( Ship->GetState()==SHIP_ACTIVE ) + { + Ship->SetState( SHIP_EXPLODE ); + Lives--; + if( SoundFlag ) + ExplodeShip->Play(); + } + Bombs[BombCounter]->SetState( BOMB_EXPLODE ); + Bombs[BombCounter]->SetFrame(2); + Bombs[BombCounter]->SetDelay( PCBulletExplode->GetValue() ); + return; + } + + }// end if( Bombs[BombCounter]->GetState() == BOMB_ACTIVE ) + BombHasShieldPixel = BombHasShipPixel = false; + }// end for( int BombCounter = 0; + + /*** + Third test all the torpedos for collision with: Shield or Ship + ***/ + + /*** + Fourth test all the active Invaders for collision with: Shield, Ship + ***/ + for(int SICounter=0; SICounterGetState() == SI_ACTIVE ) //if active check if that is the one that got hit + { // MAKE SI Rectangle with exact height + RECT SIRect = { SInvaders[SICounter]->GetPosX() + 4, SInvaders[SICounter]->GetPosY() + 7, + SInvaders[SICounter]->GetPosX() + 27, SInvaders[SICounter]->GetPosY() + 22 }; + + // Perform rectangle collision test with shield + if( SIRect.bottom > SHIELD_Y && SIRect.top < (SHIELD_Y+SHIELD_HEIGHT-15) ) + { + //First ? + if ( SIRect.left >= (SHIELD_1_X-1) || SIRect.right <= (SHIELD_1_X+SHIELD_WIDTH) ) + { + // FIND THAT PIXEL IN THE BITMAP AND TURN IT OFF + for(int y=SIRect.top; y= 0) && ((x-SHIELD_1_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield1[ y-SHIELD_Y ][ x-SHIELD_1_X ] = 0; + } + + // Second ? + if ( SIRect.left >= (SHIELD_2_X-1) || SIRect.right <= (SHIELD_2_X+SHIELD_WIDTH) ) + { + for(int y=SIRect.top; y= 0) && ((x-SHIELD_2_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield2[ y-SHIELD_Y ][ x-SHIELD_2_X ] = 0; + } + + // Third ? + if ( SIRect.left >= (SHIELD_3_X-1) || SIRect.right <= (SHIELD_3_X+SHIELD_WIDTH) ) + { + for(int y=SIRect.top; y= 0) && ((x-SHIELD_3_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield3[ y-SHIELD_Y ][ x-SHIELD_3_X ] = 0; + } + + // Fourth ? + if ( SIRect.left >= (SHIELD_4_X-1) || SIRect.right <= (SHIELD_4_X+SHIELD_WIDTH) ) + { + for(int y=SIRect.top; y= 0) && ((x-SHIELD_4_X) < SHIELD_WIDTH) && ((y-SHIELD_Y) >= 0) && ((y-SHIELD_Y) < SHIELD_HEIGHT ) ) + Shield4[ y-SHIELD_Y ][ x-SHIELD_4_X ] = 0; + } + } + + // Perform rectangle collision test with ship + if( (SIRect.bottom > SHIP_Y) && (Ship->GetState() == SHIP_ACTIVE) ) + { + bool RectCollision = true; + + if( SIRect.bottom > (SHIP_Y+20) ) + { + // Perform rectangle collision test with full ship rect + if(SIRect.top > ShipRect.bottom) RectCollision = false; + else if(SIRect.bottom < ShipRect.top) RectCollision = false; + else if(SIRect.right < ShipRect.left) RectCollision = false; + else if(SIRect.left > ShipRect.right) RectCollision = false; + } + else + { + // Perform rectangle collision test narrowing ship rect + if(SIRect.top > ShipRect.bottom) RectCollision = false; + else if(SIRect.bottom < ShipRect.top) RectCollision = false; + else if(SIRect.right < ShipRect.left+10) RectCollision = false; + else if(SIRect.left > ShipRect.right-10) RectCollision = false; + } + + if(RectCollision) + { + Ship->SetState( SHIP_EXPLODE ); + Lives--; + if( SoundFlag ) + ExplodeShip->Play(); + return; + } + + } + + } + } + +}/* ==== End of: void CollisionDetection( void ) ========================= */ + + + + +// --------------------------------------------------------------------------- +// +// Name: DisplayStatistics +// +// Function: Displays Score, Hi-Score and number of lives. +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void DisplayStatistics( void ) +{ + static char strScore[80]; + static char strHiScore[80]; + + assert( Lives > -1 ); + assert( Lives <= 3 ); + assert( Score >= 0 ); + assert( HiScore >= 0 ); + + sprintf(strScore, "Score: %lu", Score); + sprintf(strHiScore, "Hi-Score < %lu >", HiScore); + + + HDC dc = Back->GetDC(); + UINT Default = GetTextAlign(dc); // Get default text alignment + + Back->TextXY(0, 0, SCORE_COLOR, strScore); //Display score on the far left + + SetTextAlign(dc, TA_CENTER | VTA_TOP); + Back->TextXY( ScreenWidth/2, 0, HI_SCORE_COLOR, strHiScore); //Display HiScore in the middle + + SetTextAlign(dc, Default); //Restore default + + Back->ReleaseDC(); + + if( Lives >= 1) + { + LivesSSprite->SetPos( ScreenWidth-25, -5 ); + LivesSSprite->Draw( Back , 0 , 0, CDXBLT_TRANSSCALED ); + } + + if( Lives >= 2) + { + LivesSSprite->SetPos( ScreenWidth-41, -5 ); + LivesSSprite->Draw( Back , 0 , 0, CDXBLT_TRANSSCALED ); + } + + if( Lives ==3 ) + { + LivesSSprite->SetPos( ScreenWidth-57, -5 ); + LivesSSprite->Draw( Back , 0 , 0, CDXBLT_TRANSSCALED ); + } + +}/* ==== End of: void DisplayStatistics( void ) ========================== */ + + + +// --------------------------------------------------------------------------- +// +// Name: PauseGame +// +// Function: Freeze game! +// GameState function. GameState = PAUSE +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void PauseGame( void ) +{ + Back->Fill(0); + DrawObjects(); + DisplayStatistics(); + + HDC dc = Back->GetDC(); + UINT DefaultMode = GetTextAlign(dc); + SetTextAlign(dc, TA_CENTER | VTA_CENTER); + Back->SetFont(); //??????????????????????????????????? what font + Back->TextXY(ScreenWidth/2, ScreenHeight/2, RED, "P A U S E D"); // TextXY(x, y, color, string) + SetTextAlign(dc, DefaultMode); + Back->ReleaseDC(); + + Screen->Flip(); + +}/* ==== End of: void PauseGame( void ) ============================== */ + + +// --------------------------------------------------------------------------- +// +// Name: NextLevel +// +// Function: Display game leve and get player ready. This is a GameState function. +// GameState = NEXT_LEVEL +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void NextLevel( void ) +{ + + char strLevel[24]; + char strTime[16]; + int ElapsedTime = 3; + DWORD PC; + + Back->Fill(0); + + /*** + Fire the Sky !!!!! + ***/ + if( PCNextLevel->GetValue() >= NEXT_LEVEL_DELAY ) + { + PCShip->Reset(); // Reset Ship counter + PCStars->Reset(); + PCFireBullet->Reset(); + PCBullet->Reset(); + PCSIMove->Reset(); + PCSIExplosion->Reset(); + PCShipExplode->Reset(); + PCUFOExplosion->Reset(); + PCBulletExplode->Reset(); + + GameState = PLAY_GAME; + return; + } + + // setup variables + PC = PCNextLevel->GetValue(); + if( PC >= 1000 && PC < 2000) + ElapsedTime = 2; + else + if( PC >= 2000 ) + ElapsedTime = 1; + + sprintf(strTime, "%d", ElapsedTime); + sprintf(strLevel, "L e v e l %d", GameLevel); + + // draw text + HDC dc = Back->GetDC(); + UINT DefaultMode = GetTextAlign(dc); + SetTextAlign(dc, TA_CENTER | VTA_CENTER); + Back->TextXY(ScreenWidth/2, ScreenHeight/2, GREEN, strLevel); // TextXY(x, y, color, string) + Back->TextXY(ScreenWidth/2, ScreenHeight/2+40, YELLOW, strTime); + SetTextAlign(dc, DefaultMode); + Back->ReleaseDC(); + + Screen->Flip(); + + +}/* ==== End of: void NextLevel( void ) =============================== */ + + +// --------------------------------------------------------------------------- +// +// Name: GameOver +// +// Function: Displays Game Over text, stars, statistics and credits! +// GameState function. GameState = GAME_OVER +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void GameOver( void ) // change to this state when Lives == 0 +{ + Back->Fill( 0 ); + + if( PCStars->GetValue() >= STAR_DELAY ) + { + Stars->Update(); // Update stars + PCStars->Reset(); + } + else + { + Stars->DrawStars(); + } + + DisplayStatistics(); + + // Draw the rest of the shields + int a,b,c,d; + Back->Lock(); + for(int i=0; iPutPixel( SHIELD_1_X+a, SHIELD_Y+i, ShieldPixel); + + for(b=0; bPutPixel( SHIELD_2_X+b, SHIELD_Y+i, ShieldPixel); + + for(c=0; cPutPixel( SHIELD_3_X+c, SHIELD_Y+i, ShieldPixel); + + for(d=0; dPutPixel( SHIELD_4_X+d, SHIELD_Y+i, ShieldPixel); + + } + Back->UnLock(); + + CreditsFont->DrawAligned( 0 , 110 , 640 , "Credits:" , Back , CDX_CENTERJUSTIFY ); + CreditsScroll->DrawTrans( Back ); + if( PCScrollTimer->GetValue() >= SCROLL_DELAY ) + { + CreditsScroll->ScrollUp(); + PCScrollTimer->Reset(); + } + if( CreditsScroll->IsTopEnd() ) + CreditsScroll->ResetPosition(); + + + HDC dc = Back->GetDC(); + UINT DefaultMode = GetTextAlign(dc); + SetTextAlign(dc, TA_CENTER | VTA_CENTER); +// Back->SetFont(); //??????????????????????????????????? what font + Back->TextXY(ScreenWidth/2, 60, RED, "G A M E O V E R"); // TextXY(x, y, color, string) + SetTextAlign(dc, DefaultMode); + Back->ReleaseDC(); + + Screen->Flip(); + + +}/* ==== End of: void GameOver( void ) ============================== */ + + + +// --------------------------------------------------------------------------- +// +// Name: CreateMenus() +// +// Function: Create Menus here because they have to be destroyed and +// recreated upon display switch. +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void CreateMenus( void ) +{ + /*** + Create OptionsMenu + ***/ + OptionsMenu = new CDXMenu( ); + OptionsMenu->Create( Screen->GetBack( ) , 40 ); + OptionsMenu->SetTitle( "...[Esc] to Exit" , RGB( 0 , 255 , 0 ) ); + + /*** + Set up the OptionsMenu + ***/ + OptionsMenu->AddItem( "Switch to Full Screen Mode" , RGB( 255 , 0 , 0 ) , RGB( 255 , 255 , 255 ) ); + if(g_bFullScreen) OptionsMenu->EnableItem(0,FALSE); + OptionsMenu->AddItem( "Switch to Window Mode" , RGB( 255 , 0 , 0 ) , RGB( 255 , 255 , 255 ) ); + if(!g_bFullScreen) OptionsMenu->EnableItem(1,FALSE); + OptionsMenu->AddItem( "Sound OFF" , RGB( 255 , 0 , 0 ) , RGB( 255 , 255 , 255 ) ); + if( !SoundFlag ) OptionsMenu->EnableItem(2,FALSE); + OptionsMenu->AddItem( "Sound ON" , RGB( 255 , 0 , 0 ) , RGB( 255 , 255 , 255 ) ); + if( SoundFlag ) OptionsMenu->EnableItem(3,FALSE); + + if(g_bFullScreen) + OptionsMenu->SetCurrentItem(1); + else + OptionsMenu->SetCurrentItem(0); + + /*** + Create the main menu + ***/ + MainMenu = new CDXMenu(); + MainMenu->Create(Screen->GetBack(), MENU_ITEM_HEIGHT); + // Set the title of the menu to nothing + MainMenu->SetTitle("", RGB(0, 0, 0)); + // Add some options to the menu + MainMenu->AddItem("Start Game", RGB(255, 255, 0), RGB(255, 255, 255)); + MainMenu->AddItem("Options", RGB(255, 255, 0), RGB(255, 255, 255)); + MainMenu->AddItem("Quit", RGB(255, 255, 0), RGB(255, 255, 255)); + MainMenu->Home(); + + /*** + Change the screen font ??????????????? + ***/ +// if( ScreenHeight == 480 ) +// Screen->GetBack()->ChangeFont("Arial", 0, 18, FW_BOLD); +// else +// if( ScreenHeight == 600 ) +// Screen->GetBack()->ChangeFont("Arial", 0, 20, FW_BOLD); + + // ????????? do we have to set this font like Screen->GetBack()->SetFont(); + + +} /* ==== End of: void CreateMenus( void ) =============================== */ + + + + + +// =========================================================================== +// Following block of functions is window setup and +// video mode setup +// =========================================================================== + + +// --------------------------------------------------------------------------- +// +// Name: StartVideoMode +// +// Function: Sets Up video mode regarding to g_bFullScreen flag and try to start +// default full screen 640x480 ? +// If that fails, then start app in windowed mode +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void StartVideoMode( void ) +{ + AdjustWinStyle(); + Screen->CreateBackBufferInVRAM( BackBufferInVRAM ); + + if(g_bFullScreen) + { + // start app fullscreen with default ScreenWidth , ScreenHeight , ScreenBPP + if( Screen->CheckIfVideoModeExists( ScreenWidth , ScreenHeight , ScreenBPP ) == TRUE ) + { + if(FAILED(Screen->CreateFullScreen(g_hWnd, ScreenWidth, ScreenHeight, ScreenBPP))) + { + g_bFullScreen = !g_bFullScreen; + Screen->GetDD()->RestoreDisplayMode(); + AdjustWinStyle(); + if (FAILED(Screen->CreateWindowed(g_hWnd, ScreenWidth, ScreenHeight))) + CDXError( Screen , "Could not start default video mode " ); + } + + } + else + { + g_bFullScreen = !g_bFullScreen; + Screen->GetDD()->RestoreDisplayMode(); + AdjustWinStyle(); + if(FAILED(Screen->CreateWindowed(g_hWnd, ScreenWidth, ScreenHeight))) + CDXError( Screen , "Could not start default video mode " ); + } + } + else + { + // start app in a window + if (FAILED(Screen->CreateWindowed(g_hWnd, ScreenWidth, ScreenHeight))) + CDXError( Screen , "Could not start windowed mode " ); + } +} + + + +// --------------------------------------------------------------------------- +// +// Name: ChangeVideoMode +// +// Function: Switch to selected video mode +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void ChangeVideoMode( void ) +{ + // before the video mode is changed, we have to destroy all surfaces + CurrentMenu = 0; + SAFEDELETE( MainMenu ); + SAFEDELETE( OptionsMenu ); + SAFEDELETE( CreditsFont ); + SAFEDELETE( CreditsScroll); + + /*** + Set the new video mode + ***/ + if( g_bFullScreen ) + { + AdjustWinStyle(); + Screen->CreateBackBufferInVRAM( BackBufferInVRAM ); + Screen->SetTripleBuffering( TripleBuffer ); + if (FAILED(Screen->ChangeVideoMode(ScreenWidth , ScreenHeight , ScreenBPP ))) + CDXError (Screen, "Could not change to Full Screen"); + CDXLOG (">>> Full screen done <<<"); + } + else + { + Screen->GetDD()->RestoreDisplayMode(); + AdjustWinStyle(); + Screen->CreateBackBufferInVRAM( BackBufferInVRAM ); + Screen->SetTripleBuffering( TripleBuffer ); + if (FAILED(Screen->ChangeVideoMode(ScreenWidth , ScreenHeight, 0 ))) + CDXError (Screen, "Could not set window mode"); + CenterWindow(); + } + + /*** + Recreate the surfaces we destroyed before + ***/ + CreateMenus( ); + CurrentMenu = OptionsMenu; + CreditsFont = new CDXBitmapFont( Screen , "Westminster" , 22 , YELLOW ); + CreditsScroll = new CDXVertTextScroller( Screen , &CreditsClipRect ,ScrollText, CDX_CENTERJUSTIFY , 4 , CreditsFont ); + + /*** + Set up the OptionsMenu + ***/ + if( g_bFullScreen ) OptionsMenu->EnableItem(0,FALSE); + if( !g_bFullScreen ) OptionsMenu->EnableItem(1,FALSE); + if( !SoundFlag ) OptionsMenu->EnableItem(2,FALSE); + if( SoundFlag ) OptionsMenu->EnableItem(3,FALSE); + + if(g_bFullScreen) + OptionsMenu->SetCurrentItem(1); + else + OptionsMenu->SetCurrentItem(0); + + GameState = SETUP; +} + + +// --------------------------------------------------------------------------- +// +// Name: CenterWindow +// +// Function: centers the window on the screen +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void CenterWindow() +{ + RECT r; + int sx, sy; + + GetWindowRect(g_hWnd, &r); + + sx = GetSystemMetrics(SM_CXFULLSCREEN); + sy = GetSystemMetrics(SM_CYFULLSCREEN); + + SetWindowPos(g_hWnd, NULL, (sx-(r.right-r.left))/2, (sy-(r.bottom-r.top))/2, 0, + 0, SWP_NOSIZE | SWP_NOZORDER | + SWP_NOACTIVATE); +} + + +// --------------------------------------------------------------------------- +// +// Name: AdjustWinStyle +// +// Function: adjusts the window style according to the mode +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- + void AdjustWinStyle() +{ + if (g_bFullScreen) // In fullscreen mode the window must cover the whole desktop + { + DWORD dwStyle; + + // Change window attributes + + dwStyle = WS_POPUP | WS_VISIBLE; + + SetWindowLong(g_hWnd, GWL_STYLE, dwStyle); + + SetWindowPos(g_hWnd, HWND_TOPMOST, 0, 0, GetSystemMetrics(SM_CXFULLSCREEN), + GetSystemMetrics(SM_CYFULLSCREEN), SWP_NOACTIVATE | + SWP_NOZORDER); + } + else + { + RECT rect = {0, 0, ScreenWidth, ScreenHeight}; + DWORD dwStyle; + + // Change window attributes + + dwStyle = GetWindowStyle(g_hWnd); + dwStyle &= ~WS_POPUP; + dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU; + + SetWindowLong(g_hWnd, GWL_STYLE, dwStyle); + + // Resize the window so that the client area is 640x480 + + AdjustWindowRectEx(&rect, GetWindowStyle(g_hWnd), GetMenu(g_hWnd) != NULL, + GetWindowExStyle(g_hWnd)); + + // Just in case the window was moved off the visible area of the + // screen. + + SetWindowPos(g_hWnd, NULL, 0, 0, rect.right-rect.left, + rect.bottom-rect.top, SWP_NOMOVE | SWP_NOZORDER | + SWP_NOACTIVATE); + + SetWindowPos(g_hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + + CenterWindow(); + } +} + + + +// --------------------------------------------------------------------------- +// +// Name: WinProc +// +// Function: handles application messages +// +// --------------------------------------------------------------------------- + +DWORD PauseDelay; + +static long PASCAL WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + + switch(message) + { + case WM_ACTIVATEAPP: g_IsAppActive = wParam; // set if app is active or not + return 0; + + case WM_CHAR: + if(wParam == (int) '3' ) + { + if( BulletsToFire==1 ) + { + if(GameLevel>= 3 || DebugFlag ) + BulletsToFire = 3; + } + else + BulletsToFire = 1; + } + return 0; + + + case WM_KEYDOWN: switch(wParam) + { + case VK_PAUSE: + if( GameState == PLAY_GAME ) + { + UFOSound->Stop(); + GameState = PAUSE; + PCShip->Pause(); + PCStars->Pause(); + PCBullet->Pause(); + PCSIMove->Pause(); + PCGameOver->Pause(); + PCFireBullet->Pause(); + PCSIExplosion->Pause(); + PCShipExplode->Pause(); + PCUFOExplosion->Pause(); + PCFrameDuration->Pause(); + PCBulletExplode->Pause(); + PauseDelay = timeGetTime(); + } + if( (GameState == PAUSE) && ((timeGetTime()-PauseDelay)>1000)) + { + PCShip->Resume(); + PCStars->Resume(); + PCBullet->Resume(); + PCSIMove->Resume(); + PCGameOver->Resume(); + PCFireBullet->Resume(); + PCSIExplosion->Resume(); + PCShipExplode->Resume(); + PCUFOExplosion->Resume(); + PCFrameDuration->Resume(); + PCBulletExplode->Resume(); + GameState = PLAY_GAME; + } + break; + + case VK_ESCAPE: // if ESC key is hit, quit program + if( GameState == INTRO ) + SendMessage(hWnd, WM_CLOSE, 0, 0); + else + if( GameState == SPLASH ) + GameState = INTRO; + else + if( GameState == SETUP ) + { + CurrentMenu = MainMenu; + GameState = INTRO; + } + break; + + case VK_UP: + if( GameState == INTRO || GameState == SETUP ) + CurrentMenu->Up(); + break; + + case VK_DOWN: + if( GameState == INTRO || GameState == SETUP ) + CurrentMenu->Down(); + break; + + case VK_RETURN: + if( GameState == INTRO || GameState == SETUP ) + { + if( GameState == SETUP ) + { + switch(CurrentMenu->Enter()) + { + case 0: //Full screen + g_bFullScreen = TRUE; + ChangeVideoMode(); + break; + + case 1: //Window mode + g_bFullScreen = FALSE; + ChangeVideoMode(); + break; + + case 2: //sound off + { + SoundFlag = FALSE; + OptionsMenu->EnableItem(2,FALSE); + OptionsMenu->EnableItem(3,TRUE); + OptionsMenu->SetCurrentItem(3); + } + break; + + case 3: //sound oN + { + SoundFlag = TRUE; + OptionsMenu->EnableItem(2,TRUE); + OptionsMenu->EnableItem(3,FALSE); + OptionsMenu->SetCurrentItem(2); + } + break; + + default: + break; + } + } + else + switch(CurrentMenu->Enter()) + { + case 0: //Play + if( GameState == INTRO ) + GameState = RESET; + break; + + case 1: //setup + CurrentMenu = OptionsMenu; + GameState = SETUP; + break; + + case 2: //Quit + PostMessage(hWnd, WM_CLOSE, 0, 0); + break; + + default: + break; + } + } + + }// end switch(wParam) + + if( GameState == GAME_OVER ) + { + GameState = INTRO; + // Save HiScore + if( Score > HiScore ) + { + WriteHighScore( Score ); + } + + GameLevel = 0; + Score = 0; + Lives = 3; + } + return 0; + + case WM_SYSKEYUP: if (wParam == VK_RETURN) // Alt+Enter switches modes + { + if( GameState == SETUP ) + { + g_bFullScreen = !g_bFullScreen; + ChangeVideoMode(); + return 0; + } + } + return 1; + + case WM_SETCURSOR: SetCursor(NULL); // hide the mouse cursor + return 1; + case WM_CLOSE: cdx_DeInit(); + + case WM_DESTROY: PostQuitMessage(0); + return 0; + + default: return DefWindowProc(hWnd, message, wParam, lParam); + } +} + + + +// --------------------------------------------------------------------------- +// +// Name: ChangeToEXEDir +// +// Function: sets CWD to the DIR the EXE is in +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +static void ChangeToEXEDir() +{ + char buf[MAX_PATH]; + char *cptr; + + //now change the directory + //to make sure were accessing the proper file + GetModuleFileName(NULL, buf, MAX_PATH); + + //move pointer to end of string + cptr = buf + lstrlen(buf); + + //find the end of the path + do + { + cptr--; + } while (*cptr != '\\'); + cptr++; + *cptr='\0'; + + //change directory + SetCurrentDirectory(buf); + +} + + + +// --------------------------------------------------------------------------- +// +// Name: InitApp +// +// Function: Create the window and the CDX objects +// +// +// Parameters: int nCmdShow +// +// Return value: BOOL. +// +// --------------------------------------------------------------------------- +static BOOL InitApp(int nCmdShow) +{ + WNDCLASS WndClass; + + WndClass.style = CS_HREDRAW | CS_VREDRAW; + WndClass.lpfnWndProc = WinProc; + WndClass.cbClsExtra = 0; + WndClass.cbWndExtra = 0; + WndClass.hInstance = g_hInst; + WndClass.hIcon = LoadIcon(g_hInst, "APPICON"); + WndClass.hCursor = LoadCursor(0, IDC_ARROW); + WndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); + WndClass.lpszMenuName = 0; + WndClass.lpszClassName = szClassName; + RegisterClass(&WndClass); + + g_hWnd = CreateWindowEx( + WS_EX_TOPMOST, + szClassName, + szAppName, + WS_POPUP, + 0, + 0, + GetSystemMetrics(SM_CXFULLSCREEN), + GetSystemMetrics(SM_CYFULLSCREEN), + NULL, + NULL, + g_hInst, + NULL); + + // when hWnd = -1 there was an error creating the main window + // CDXError needs a CDXScreen object, if there is none at this early + // program stage, pass it NULL + if( !g_hWnd ) + CDXError( NULL , "could not create the main window" ); + + if (!g_bFullScreen) + AdjustWinStyle(); + + ShowWindow(g_hWnd, nCmdShow); + UpdateWindow(g_hWnd); + + return TRUE; +} + + +// --------------------------------------------------------------------------- +// +// Name: WinMain +// +// Function: inital function called by windows +// +// --------------------------------------------------------------------------- +int PASCAL WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) +{ + MSG msg; + + // save the app instance + g_hInst = hInstance; + + // Set current directory. + ChangeToEXEDir(); + + // Check last exit status + if( ReadExitStatus() != 0x1 ) + { + if( GetDXVersion() < 0x7 ) + MessageBox(NULL, "If you are experiencing problems with this game, get\nDirectX 7 or better from Microsoft web page !", "Space Invaderz", MB_OK | MB_ICONERROR | MB_APPLMODAL); + else + MessageBox(NULL, "If you are experiencing problems with this game,\ntry changing your display settings to 640x480 256 Colors !", "Space Invaderz", MB_OK | MB_ICONERROR | MB_APPLMODAL); + } + + // Write Exit status = "FAILED" + WriteExitStatus( 0x0 ); + + // Read options + DWORD options = ReadOptions(); + g_bFullScreen = (options & 0xff00)>>8; //first byte + SoundFlag = options & 0xff; + + if(!InitApp(nCmdShow)) + CDXError( NULL , "could not initialize application" ); + + if(!cdx_Init()) + { + PostQuitMessage(0); + return FALSE; + } + + PCAppTiming = new CDXHPC(); + PCAppTiming->Start(); + + while(1) + { + if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) + { + if(!GetMessage(&msg, NULL, 0, 0 )) return msg.wParam; + TranslateMessage(&msg); + DispatchMessage(&msg); + } + else + if( g_IsAppActive && ( PCAppTiming->GetValue() >= MIN_FRAME_TIME ) ) + { + PCAppTiming->Reset(); + cdx_DoFrame(); + } + else + if( ! g_IsAppActive ) + { + WaitMessage(); + } + } +} + + + + +/* ==== End of file _SI_C_ ==================================== */ + diff --git a/SI.dsp b/SI.dsp new file mode 100644 index 0000000..23e3664 --- /dev/null +++ b/SI.dsp @@ -0,0 +1,197 @@ +# Microsoft Developer Studio Project File - Name="SI" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=SI - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "SI.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "SI.mak" CFG="SI - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "SI - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "SI - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "SI - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "STRICT" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "STRICT" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ddraw.lib dsound.lib dxguid.lib dinput.lib winmm.lib cdx.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 +# ADD LINK32 ddraw.lib dsound.lib dxguid.lib dinput.lib winmm.lib cdx.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /machine:I386 + +!ELSEIF "$(CFG)" == "SI - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "STRICT" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "STRICT" /FR /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 ddraw.lib dsound.lib dxguid.lib dinput.lib winmm.lib cdxd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept +# ADD LINK32 ddraw.lib dsound.lib dxguid.lib dinput.lib winmm.lib cdxd.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept + +!ENDIF + +# Begin Target + +# Name "SI - Win32 Release" +# Name "SI - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Group "CDX" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\CDXAddons\CDXTextScrol\CDXBitmapFont.cpp +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\CDXTextScrol\CDXHorizTextScroller.cpp +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\Cdxhpc\cdxhpc.cpp +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\CDXMenu\Cdxmenu.cpp +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\CDXStar\Cdxstar.cpp +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\CDXTextScrol\CDXVertTextScroller.cpp +# End Source File +# End Group +# Begin Source File + +SOURCE=.\SI.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Group "CDX No. 1" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\CDXAddons\CDXTextScrol\CDXBitmapFont.h +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\CDXTextScrol\CDXHorizTextScroller.h +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\Cdxhpc\cdxhpc.h +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\CDXMenu\Cdxmenu.h +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\CDXStar\Cdxstar.h +# End Source File +# Begin Source File + +SOURCE=.\CDXAddons\CDXTextScrol\CDXVertTextScroller.h +# End Source File +# End Group +# Begin Source File + +SOURCE=.\Debug.h +# End Source File +# Begin Source File + +SOURCE=.\DXVersion.h +# End Source File +# Begin Source File + +SOURCE=.\Options.h +# End Source File +# Begin Source File + +SOURCE=.\ScoreIO.h +# End Source File +# Begin Source File + +SOURCE=.\SI.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\ReadMe.txt +# End Source File +# Begin Source File + +SOURCE=.\Resource.h +# End Source File +# Begin Source File + +SOURCE=.\SI.ico +# End Source File +# Begin Source File + +SOURCE=.\SI.rc +# End Source File +# End Group +# End Target +# End Project diff --git a/SI.dsw b/SI.dsw new file mode 100644 index 0000000..0794074 --- /dev/null +++ b/SI.dsw @@ -0,0 +1,29 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "SI"=.\SI.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/SI.h b/SI.h new file mode 100644 index 0000000..a5f7731 --- /dev/null +++ b/SI.h @@ -0,0 +1,512 @@ +// =========================================================================== +// Project: Space Invaders +// File: SI.h +// Author: Mirza Kolakovic +// Date: April 6, 2001. +// =========================================================================== + +// =========================================================================== +// +// File: SI.h +// +// Description: This file is the main header file for space invaders. +// +// +// =========================================================================== + +#define WIN32_LEAN_AND_MEAN + +#include +#include "resource.h" +#include +#include + +//#define NDEBUG //Uncomment this for release ! +#include + +#define CDXINCLUDEALL // this define includes all headers, otherwise include one by one +#include + +// CDX add-ons +#include ".\CDXAddons\CDXStar\CDXStar.h" +#include ".\CDXAddons\CDXTextScrol\CDXVertTextScroller.h" +#include ".\CDXAddons\CDXMenu\CDXMenu.h" +#include ".\CDXAddons\CDXHPC\CDXHPC.h" + +// SI includes +#include "ScoreIO.h" // Writes hi-score to a file +#include "DXVersion.h" //Checks app exit status and checks DirectX version no. +#include "Options.h" // Write options to a file + +// =========================================================================== +// Defines +// =========================================================================== +/*** + Do 1 frame (at least) every 1 milliseconds or 1000 FPS (1000(ms/s)/1(ms/Frame) = 1000 FPS ) + +Note: Since all game movements are based on FrameTime and calculated as Velocity*FrameTime, we have + to force frame time to be greater than or equal to 1. This is not important now but as the + processors are getting faster we want to limit frame rate to 1000FPS which is more than we will + never need. +***/ +#define MIN_FRAME_TIME 1 //milliseconds + +/*** +Game States +***/ +#define SPLASH 0 +#define INTRO 1 +#define SETUP 2 +#define RESET 3 +#define PLAY_GAME 4 +#define PAUSE 5 +#define NEXT_LEVEL 6 +#define GAME_OVER 7 + +/*** +Sound +***/ +//#define THUNDER_WAV ".\\DAS\\Thunder.das" +#define BULLET_WAV ".\\DAS\\B.das" +#define STEP1_WAV ".\\DAS\\S1.das" +#define STEP2_WAV ".\\DAS\\S2.das" +#define STEP3_WAV ".\\DAS\\S3.das" +#define STEP4_WAV ".\\DAS\\S4.das" +#define SI_EXPLODE_WAV ".\\DAS\\ESI.das" +#define UFO_EXPLODE_WAV ".\\DAS\\EFO.das" +#define UFO_WAV ".\\DAS\\F.das" +#define SHIP_EXPLODE_WAV ".\\DAS\\ESP.das" +//#define BOMB_EXPLODE_WAV ".\\DAS\\EBB.das" + +/*** +Bitmaps +***/ +//#define LOGO_BMP ".\\Bitmaps\\Logo.bmp" +#define TITLE_BMP ".\\DAB\\T.dab" +#define SI_BMP ".\\DAB\\S.dab" +#define UFO_BMP ".\\DAB\\F.dab" +#define SHIP_BMP ".\\DAB\\P.dab" +#define BULLET_BMP ".\\DAB\\B.dab" // bomb & torpedo here too. +//#define G_OVER_BMP ".\\DAB\\GOver.dab" + +/*** +Menu Items +***/ +#define MENU_ITEM_HEIGHT 28 // height of each menu item and spacing between items + +/*** +Number of Bullets, Bombs and Torpedos +***/ +#define MAX_BULLETS 50 +#define MAX_BOMBS 50 +#define MAX_TORPEDOS 10 + +/*** +Invaders Stuff +***/ +#define HEAD_INVADERS 32 // Number of Head Invaders +#define ANTENA_INVADERS 32 +#define CONE_INVADERS 16 + +/*** +Some Colors +***/ +#define WHITE RGB(255, 255, 255) +#define RED RGB(255, 0, 0) +#define GREEN RGB( 0, 255, 0) +#define YELLOW RGB(255, 255, 0) + +DWORD WhitePixel, // We will set these at run time using DDColorMatch() + RedPixel, // They will have different values regarding to color + ShipPixel, // depth.(256 colors, 16 bit or 32 bit colors ) + YellowPixel, // This is important for collision detection. + ShieldPixel; + +/*** +Stuff +***/ +#define NEXT_LEVEL_DELAY 3000 //millisec + +// =========================================================================== +// Global Variables +// =========================================================================== +char szAppName[] = "Space Invaderz"; +char szClassName[] = "SIWndClass"; + +HINSTANCE g_hInst; // instance handle +HWND g_hWnd; // window handle + +/*** +Flags for the DirectDraw object, Sounds & Debug +***/ +BOOL g_bFullScreen = TRUE; // running full screen? +BOOL g_IsAppActive = TRUE; // is the app active +BOOL TripleBuffer = FALSE; // triple buffering on/off +BOOL BackBufferInVRAM = FALSE; // backbuffer in vram/sysram +BOOL SoundFlag = TRUE; + +#ifdef NDEBUG +BOOL DebugFlag = FALSE; +#endif + +#ifndef NDEBUG +BOOL DebugFlag = TRUE; +#endif + +DWORD DurationOfTheFrame = 0; // in milliseconds + +/*** +Debug File Ptr +***/ +FILE *fdebug = 0; + +/*** +Screen resolution and color depth +***/ +int ScreenWidth = 640; +int ScreenHeight = 480; +int ScreenBPP = 8; + +/*** +Flags +***/ +bool bPlayThunder; +bool bRestorePalette; + +/*** +Palette +***/ +PALETTEENTRY pe[256]; //??????????????????????? what if more than 256 colors + +/*** +Game Data +***/ +int Lives = 3; +int GameState = 0; +int GameLevel = 0; +DWORD Score = 0; +DWORD HiScore = 0; + +#define HI_SCORE_COLOR RGB(255,255,255) // White +#define SCORE_COLOR RGB(255,255, 0) // Yellow + +#define STAR_DELAY 30 + +/*** +Ship stuff +***/ +#define SHIP_NOT_ACTIVE 0 +#define SHIP_ACTIVE 1 +#define SHIP_EXPLODE 2 +#define SHIP_LAST_FRAME 8 +#define SHIP_Y ScreenHeight-35 +#define SHIP_EXPLODE_DELAY 150 + + +double ShipdX; +const double ShipVelocityX = 200.0/1000.0;// 200 pixels per second + +/*** +Shields +***/ +#define SHIELD_HEIGHT 48 +#define SHIELD_WIDTH 72 +#define SHIELD_Y (SHIP_Y - 68) +#define SHIELD_1_X 40 +#define SHIELD_2_X 200 +#define SHIELD_3_X 360 +#define SHIELD_4_X 520 +// This 2D array is a shield bitmap. Positions within array +// set to one will be painted green while positions set to zero +// will not be painted +BYTE Shield1[SHIELD_HEIGHT][SHIELD_WIDTH]; +BYTE Shield2[SHIELD_HEIGHT][SHIELD_WIDTH]; +BYTE Shield3[SHIELD_HEIGHT][SHIELD_WIDTH]; +BYTE Shield4[SHIELD_HEIGHT][SHIELD_WIDTH]; + +/*** +UFO Stuff +***/ +double UFOdX; +char strUFOScore[20]; +int BulletsSinceLastUFO; +const double UFOVelocityX = 100.0/1000.0; //100 pixels per second + +#define UFO_X -32 // strat drawing it here +#define UFO_Y 30 +#define UFO_NOT_ACTIVE 0 +#define UFO_ACTIVE 1 +#define UFO_EXPLODE 2 +#define UFO_EXPLODE_DELAY 400 // in millisec +#define ACTIVATE_UFO_ON 32 //We will activate ufo after 32 bullets have been fired + +/*** +Bullet Stuff +***/ +CDXSprite * Bullets[ MAX_BULLETS ]; //Array to hold bullets +const double BulletVelocityY = 700.0/1000.0; + +int BulletsToFire = 1; // 1 or 3 + +#define BULLET_NOT_ACTIVE 0 +#define BULLET_ACTIVE 1 +#define BULLET_EXPLODE 2 +#define BULLET_EXPLODE_DELAY 100 +#define BULLET_DELAY 500 //delay in milliseconds between fire + +/*** +Bomb Stuff +***/ +CDXSprite * Bombs[ MAX_BOMBS ]; + +const double BombVelocityY = 70.0/1000.0; // 70 pixels per second +double BombdY; +int NoActiveBombs; +#define BOMB_NOT_ACTIVE 0 +#define BOMB_ACTIVE 1 +#define BOMB_EXPLODE 2 +#define BOMB_EXPLODE_DELAY 100 + +/*** +Torpedo Stuff +***/ +CDXSprite * Torpedos[ MAX_TORPEDOS ]; + +const double TorpedoVelocityY = 700.0/1000.0; // 700 pixels per second + +#define TORPEDO_NOT_ACTIVE 0 +#define TORPEDO_ACTIVE 1 + +/*** +SI Arrays and stuff +***/ +CDXSprite * SInvaders[ HEAD_INVADERS + ANTENA_INVADERS + CONE_INVADERS ]; + +bool MoveDown; +int SIStartMoveOnX, + SIStopMoveOnX, + SIStopMoveOnY, + SIStartDrawOnX, + SIStartDrawOnY, + SIDrawStep, + SINewFrame, + SIPlayStep, //defines what sound to play while moving Invaders + NumberOfLiveSI; + +int SIMoveDelay; //in milliseconds + +#define SI_HEAD 0 // Sprite stuff +#define SI_ANTENA 1 +#define SI_CONE 2 + +#define SI_ACTIVE 0 +#define SI_EXPLODE 1 +#define SI_NOT_ACTIVE 2 +#define SI_EXPLODE_DELAY 3 // transition state so we can see eplosion of the invader + +int SIVelocityLeft = -10; +int SIVelocityRight = 10; +int SIVelocityDown = 20; + +#define STEP1 0 //Sound states +#define STEP2 1 +#define STEP3 2 +#define STEP4 3 + +#define EXPLODE_DELAY 200 //in milliseconds +#define TIME_TO_WAIT_INVADERS 50 + +/*** +Credits +***/ +#define SCROLL_DELAY 25 +RECT CreditsClipRect = { 0 , 140 , 640 , SHIELD_Y }; + +// =========================================================================== +// CDX Objects +// =========================================================================== + +CDXScreen * Screen = 0;// The screen object, every program must have one +CDXSurface * Back = 0;// Global pointer to background surface; Used instead: Screen->GetBack() +CDXSound * Sound = 0;// Sound object +CDXStarField * Stars = 0; +CDXInput * Input = 0; +CDXBitmapFont * CreditsFont = 0; +CDXVertTextScroller * CreditsScroll = 0; +CDXMenu * MainMenu = 0; +CDXMenu * OptionsMenu = 0; +CDXMenu * CurrentMenu = 0; +CDXTile * SiT = 0; +CDXTile * TitleT = 0; +CDXTile * ShipT = 0; +CDXTile * UfoT = 0; +CDXTile * BulletT = 0; +CDXSprite * SI = 0; +CDXSprite * Ship = 0; +CDXSprite * UFO = 0; +CDXSprite * Title = 0; +CDXSprite * Bullet = 0; +CDXSprite * LivesSSprite = 0; +CDXSoundBuffer * Step1 = 0; +CDXSoundBuffer * Step2 = 0; +CDXSoundBuffer * Step3 = 0; +CDXSoundBuffer * Step4 = 0; +CDXSoundBuffer * BulletSound = 0; +CDXSoundBuffer * ExplodeSI = 0; +CDXSoundBuffer * UFOSound = 0; +CDXSoundBuffer * ExplodeUFO = 0; +CDXSoundBuffer * ExplodeShip = 0; +CDXHPC * PCScrollTimer = 0; +CDXHPC * PCShip = 0; +CDXHPC * PCStars = 0; +CDXHPC * PCShipExplode = 0; +CDXHPC * PCFireBullet = 0; +CDXHPC * PCBullet = 0; +CDXHPC * PCBulletExplode = 0; +CDXHPC * PCSIMove = 0; +CDXHPC * PCSIExplosion = 0; +CDXHPC * PCAppTiming = 0; +CDXHPC * PCUFOExplosion= 0; +CDXHPC * PCGameOver = 0; +CDXHPC * PCNextLevel = 0; +CDXHPC * PCFrameDuration = 0; +// ============================================================================ +// Forward declarations +// =========================================================================== + +void +AdjustWinStyle( void ); + +void +CenterWindow( void ); + +void +StartVideoMode( void ); + +void +ChangeVideoMode(void ); + +void +DisplaySplash( void ); + +void +GameIntro( void ); + +void +PlayGame( void ); + +void +DisplaySetup( void ); + +void +CreateMenus( void ); + +void +CheckInput( void ); + +void +MoveObjects( void ); + +void +CollisionDetection( void); + +void +DrawObjects( void ); + +void +DisplayStatistics( void ); + +void +ResetGame( void ); + +void +ResetShip(void); + +void +GameOver( void ); + +void +PauseGame( void ); + +void +NextLevel( void ); + +// ============================================================================ +// Global Text & Data +// =========================================================================== + +static char MirzaKingText[50] = "Space Invaderz - by Mirza King, 2001"; + +static char PointsText[4][80]= + { + {" = ? MYSTERY"}, + {" = 30 POINTS "}, + {" = 20 POINTS "}, + {" = 10 POINTS "} + }; + + +static char *ScrollText = "Space Invaderz\n\nWritten by Mirza King.\n\n\nThanks:\nPatricia Kolakovic for supporting me and creating bitmaps.\nNedzad Kolakovic for getting me TI-99/4A and Space Invaders ROM cartridge.\nAll of you who helped testing this game.\n\nSpecial thanks to CDX community.\nwww.cdxlib.com\n\nVisit us at:\nwww.mirzaking.freeservers.com\nsinvaderz@hotmail.com\n\nCopyright (c) MirzaKing, 2001\n\n\n"; + + + +BYTE ShieldBitMap[SHIELD_HEIGHT][SHIELD_WIDTH] = { \ +{0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0},\ +{0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0},\ +{0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0},\ +{0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0},\ +{0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0},\ +{0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0},\ +{0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0},\ +{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1},\ +{1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1} \ +}; + + + + + + + + + +/* ========== End of file _SI_H_ =================================== */ diff --git a/SI.ico b/SI.ico new file mode 100644 index 0000000..53d3149 Binary files /dev/null and b/SI.ico differ diff --git a/SI.ncb b/SI.ncb new file mode 100644 index 0000000..29950c9 Binary files /dev/null and b/SI.ncb differ diff --git a/SI.opt b/SI.opt new file mode 100644 index 0000000..3b2a6ad Binary files /dev/null and b/SI.opt differ diff --git a/SI.plg b/SI.plg new file mode 100644 index 0000000..7cd531b --- /dev/null +++ b/SI.plg @@ -0,0 +1,39 @@ + + +
+

Build Log

+

+--------------------Configuration: SI - Win32 Release-------------------- +

+

Command Lines

+Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP47.tmp" with contents +[ +/nologo /ML /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "STRICT" /Fp"Release/SI.pch" /YX /Fo"Release/" /Fd"Release/" /FD /c +"C:\Documents and Settings\Administrator\My Documents\Development\SI\SI.cpp" +] +Creating command line "cl.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP47.tmp" +Creating temporary file "C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP48.tmp" with contents +[ +ddraw.lib dsound.lib dxguid.lib dinput.lib winmm.lib cdx.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:windows /incremental:no /pdb:"Release/SI.pdb" /machine:I386 /out:"Release/SI.exe" +".\Release\CDXBitmapFont.obj" +".\Release\CDXHorizTextScroller.obj" +".\Release\cdxhpc.obj" +".\Release\Cdxmenu.obj" +".\Release\Cdxstar.obj" +".\Release\CDXVertTextScroller.obj" +".\Release\SI.obj" +".\Release\SI.res" +] +Creating command line "link.exe @C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\RSP48.tmp" +

Output Window

+Compiling... +SI.cpp +Linking... + + + +

Results

+SI.exe - 0 error(s), 0 warning(s) +
+ + diff --git a/SI.rc b/SI.rc new file mode 100644 index 0000000..93cc922 --- /dev/null +++ b/SI.rc @@ -0,0 +1,72 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +APPICON ICON DISCARDABLE "SI.ICO" +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/ScoreIO.h b/ScoreIO.h new file mode 100644 index 0000000..a8677f1 --- /dev/null +++ b/ScoreIO.h @@ -0,0 +1,82 @@ +/* =========================================================================== +// +// File: ScoreIO.h +// +// Description: High Score read/write to a file. +// +// Written by: Mirza King, April 2001 +// ======================================================================== */ + +#include +#include +#include + +#define File "hs.bin" + +char Buffer[8]; + +/* --------------------------------------------------------------------------- +// +// Name: ReadHighScore +// +// Function: Reads binary value from a file and converts it to DWORD. +// +// Return value: DWORD (High Score) +// +// ------------------------------------------------------------------------ */ +DWORD ReadHighScore( void ) +{ + DWORD data = 0; + + int hs_file = open( File, O_RDONLY | O_BINARY ); + + if( hs_file ) + { + read( hs_file, Buffer, 4 ); + /*** + Here we want to make sure we operate on BYTE size data ! + ***/ + data = data | (Buffer[0] & 0xff); + data = (data<<8) | (Buffer[1] & 0xff); + data = (data<<8) | (Buffer[2] & 0xff); + data = (data<<8) | (Buffer[3] & 0xff); + + close( hs_file ); + } + + return data; +} + + + +/* --------------------------------------------------------------------------- +// +// Name: WriteHighScore +// +// Function: Converts passed parameter to bytes and writes binary to a +// file. +// +// Parameters: DWORD (High Score) +// +// Return value: none +// +// ------------------------------------------------------------------------ */ + +void WriteHighScore( DWORD data ) +{ + int hs_file = open( File, O_RDWR | O_BINARY | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE); + + if( hs_file ) + { + for( int i=0,k=3; i<4; i++,k-- ) + Buffer[i] = (char) ( data >> 8*k ); + + write( hs_file, Buffer, sizeof(Buffer) ); + + close( hs_file ); + } +} + + + +/* =================================== End ================================ */ \ No newline at end of file diff --git a/Sound/Bullet.wav b/Sound/Bullet.wav new file mode 100644 index 0000000..f98c573 Binary files /dev/null and b/Sound/Bullet.wav differ diff --git a/Sound/ExplodeSI.wav b/Sound/ExplodeSI.wav new file mode 100644 index 0000000..7b66a1a Binary files /dev/null and b/Sound/ExplodeSI.wav differ diff --git a/Sound/ExplodeShip.wav b/Sound/ExplodeShip.wav new file mode 100644 index 0000000..3606c6d Binary files /dev/null and b/Sound/ExplodeShip.wav differ diff --git a/Sound/ExplodeUFO.wav b/Sound/ExplodeUFO.wav new file mode 100644 index 0000000..71abe1d Binary files /dev/null and b/Sound/ExplodeUFO.wav differ diff --git a/Sound/Step1.wav b/Sound/Step1.wav new file mode 100644 index 0000000..9d7dfdc Binary files /dev/null and b/Sound/Step1.wav differ diff --git a/Sound/Step2.wav b/Sound/Step2.wav new file mode 100644 index 0000000..505a749 Binary files /dev/null and b/Sound/Step2.wav differ diff --git a/Sound/Step3.wav b/Sound/Step3.wav new file mode 100644 index 0000000..87dd372 Binary files /dev/null and b/Sound/Step3.wav differ diff --git a/Sound/Step4.wav b/Sound/Step4.wav new file mode 100644 index 0000000..7e8e543 Binary files /dev/null and b/Sound/Step4.wav differ diff --git a/Sound/Thunder.wav b/Sound/Thunder.wav new file mode 100644 index 0000000..a707caa Binary files /dev/null and b/Sound/Thunder.wav differ diff --git a/Sound/old_ufo.wav b/Sound/old_ufo.wav new file mode 100644 index 0000000..56b3983 Binary files /dev/null and b/Sound/old_ufo.wav differ diff --git a/Sound/ufobbit.wav b/Sound/ufobbit.wav new file mode 100644 index 0000000..dfd0551 Binary files /dev/null and b/Sound/ufobbit.wav differ diff --git a/Stuff/func.txt b/Stuff/func.txt new file mode 100644 index 0000000..d04f977 --- /dev/null +++ b/Stuff/func.txt @@ -0,0 +1,165 @@ +BOOL cdx_Init( void ) +{ + // Create the CDXSreen object + Screen = new CDXScreen(); + if (Screen==NULL) + CDXError( NULL , "Could not create CDXScreen object" ); + + // enable triple buffering + Screen->SetTripleBuffering(TripleBuffer); + + // start app + StartVideoMode(); + +// LoadResources(); +// CreateObjects(); + + + return TRUE; +} + + +// --------------------------------------------------------------------------- +// +// Name: cdx_DeInit +// +// Function: handles cleanup of CDX objects +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void cdx_DeInit( void ) +{ + SAFEDELETE( Ship ); + SAFEDELETE( SI ); + SAFEDELETE( Resource ); + SAFEDELETE( Sound ); + SAFEDELETE( Thunder ); + SAFEDELETE( LogoT ); + SAFEDELETE( TitleT ); + SAFEDELETE( SiT ); + SAFEDELETE( ShipT ); + SAFEDELETE( Screen ); +} + + +// --------------------------------------------------------------------------- +// +// Name: cdx_DoFrame +// +// Function: performs drawing of the current frame +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +void cdx_DoFrame() +{ + Back = Screen->GetBack(); + // clear the current frame + Back->Fill(0); + + + Screen->Flip(TRUE, FALSE, TRUE); // Flip the back buffer to the front +} + + +// --------------------------------------------------------------------------- +// +// Name: LoadResources +// +// Function: Loads all bitmaps and .wav files from DATA_FILE +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +static void LoadResources( void ) +{ + /*** + Load the WAD file and get all the data. + ***/ + Resource = new CDXResource(); + if(FAILED(Resource->Open( DATA_FILE ))) + CDXError( Screen , "could not open Data file" ); + +char *ShipR = ""; +// LogoR = Resource->GetFile("l1.bmp" ); +// TitleR = Resource->GetFile("title.bmp"); +// if(FAILED(ShipR = Resource->GetFile("ship.bmp" ))) +// CDXError( Screen , "could not load SHIP.BMP" ); +// SiR = Resource->GetFile("si.bmp" ); +// ThunderR= Resource->GetFile("g.bmp" ); +// UfoR = Resource->GetFile("ufo.bmp" ); + + Resource->Close(); + + /*** + Now create their CDX objects + ***/ + + //Sound +/* Sound = new CDXSound; + Sound->Create(g_hWnd); + Sound->Enable3d(); + + Thunder = new CDXSoundBuffer(); + Thunder->Load( Sound, ThunderR ); + + //Tiles + LogoT = new CDXTile(); + if( LogoT->Create( Screen, LogoR, 350, 150, 1 ) == FALSE ) + CDXError( Screen , "could not load LOGO" ); + TitleT = new CDXTile(); + if( LogoT->Create( Screen, TitleR, 350, 150, 1) == FALSE ) + CDXError( Screen , "could not load TITLE" ); + ShipT = new CDXTile(); + if( ShipT->Create( Screen , ShipR , 64 , 32 , 2 ) == FALSE ) + CDXError( Screen , "could not load the Ship" ); + SiT = new CDXTile(); + if( SiT->Create( Screen , SiR , 352 , 32 , 11 ) == FALSE ) + CDXError( Screen , "could not load Invaders" ); + UfoT = new CDXTile(); + if( UfoT->Create( Screen , UfoR , 64 , 32 , 2 ) == FALSE ) + CDXError( Screen , "could not load UFO" ); +*/ +} + + +// --------------------------------------------------------------------------- +// +// Name: CreateObjects +// +// Function: Creates CDX objects from resources. +// +// +// Parameters: None. +// +// Return value: None. +// +// --------------------------------------------------------------------------- +/* void CreateObjects( void ) +{ + /*** + Create Sprites + ***/ +/* Ship = new CDXSprite(); + Ship->Create(ShipT); + Ship->SetPosY(440); + Ship->SetColorKey(0); + + SI = new CDXSprite(); + SI->Create( SiT ); + SI->SetColorKey(0); + + + +} +*/ \ No newline at end of file diff --git a/Stuff/res.txt b/Stuff/res.txt new file mode 100644 index 0000000..3ae9deb --- /dev/null +++ b/Stuff/res.txt @@ -0,0 +1,43 @@ +> I havn't ever tried to use it, but eventually i'm going to want to wrap all +> my stuff up into a single file to avoid having to worry about N number of +> files lying around. How does this work? + +> How will I load the resources out of the single file later? Say I was +> wanting to load the "SPLASH.BMP" into a surface, I just can't tell it to +> create a surface and load ("SPLASH") into it can i? + +This code should help: + +// create our CDX objects +CDXScreen *screen; +CDXSurface *surface; +CDXResource *res; + +// create our screen +screen = new CDXScreen(); + +// create our resource object +res = new CDXResource(); + +// open a resource file +res->Open("MYRES.WAD"); + +// create a CDXSurface from a bitmap resource in the file +surface = new CDXSurface(screen, res->GetFile("MYBITMAP.BMP"), +CDXMEM_VIDTHENSYS); + +// draw the new surface to the screen and flip +screen->GetBack()->Draw(surface); +screen->Flip(); + +The drawback is that CDXResource kinda sucks. It writes out a temporary file +called +CDX.TMP each time you call GetFile so it's a bit of a hog if you have large +files +you're extracting. CDXResource needs someone to look after it and make it a +little +better but it does the job. It would be nice if someone fixed it up to load the +files directly in memory but since CDX uses disk files, what's the point? Also, +the resouce builder program isn't very good in that it needs to be able to open +resource files and move things around in them. A good weekend project for +someone. diff --git a/Stuff/si-title.bmp b/Stuff/si-title.bmp new file mode 100644 index 0000000..e9e3c86 Binary files /dev/null and b/Stuff/si-title.bmp differ diff --git a/Tools/CDXResource.exe b/Tools/CDXResource.exe new file mode 100644 index 0000000..ca3c42d Binary files /dev/null and b/Tools/CDXResource.exe differ diff --git a/cdx3.0.zip b/cdx3.0.zip new file mode 100644 index 0000000..fc32141 Binary files /dev/null and b/cdx3.0.zip differ diff --git a/hs.bin b/hs.bin new file mode 100644 index 0000000..d2d9509 Binary files /dev/null and b/hs.bin differ