Click here to Skip to main content
15,894,128 members
Articles / Multimedia / DirectX

A DirectX Game: Quadrino

Rate me:
Please Sign up or sign in to vote.
4.89/5 (41 votes)
16 Oct 2008CPOL26 min read 397.6K   6.2K   125  
An interpretation of a popular falling block game implemented with DirectX that attempts to avoid any copyright infringement.
/* Tetrisview.h ***************************************************************
Author:		Paul Watt, Copyright (c) 2002
Date:		4/2/2002
Purpose:	
******************************************************************************/
#ifndef __TETRISVIEW_H
#define __TETRISVIEW_H

/* Include Files *************************************************************/
#include <atlcrack.h>
#include <atlmisc.h>

#include <ddraw.h>
#include "DDBuffer.h"
#include "DDFontSurface.h"
#include "DDrawWindow.h"
#include "DSSoundManager.h"

#include "Animation.h"
#include "TetrisGame.h"

#include <list>
#include <vector>

/* Constants / Defined / Typedefs ********************************************/
using std::list;
typedef list<Animation*>		listAnimation;
typedef listAnimation::iterator iterListAnimation;

#include "TetrisDefines.h"

const DWORD SCREEN_WIDTH  = 800;
const DWORD SCREEN_HEIGHT = 600;

const double MAX_DESCENT = 20 / 1000.0;

/* Global Functions **********************************************************/
HRESULT DrawPiece(DDSurface *pSurface, DDSurface *pBlock, PIECE_TYPE piece, UINT nDir, RECT &rLoc, DWORD dwFlags);
HRESULT GetRandomOrientation (DDBLTFX &fx);


/* Class **********************************************************************
Author:		Paul Watt
Date:		4/2/2002
Purpose:	
******************************************************************************/
class CTetrisView : public CWindowImpl<CTetrisView, DDrawWindow>
{
public:
	enum VIEW_STATE{OPTIONS = 0, NORMAL, PAUSE, GAMEOVER, CREDITS};

protected:
	/* Direct Draw interfaces ****************************************************/
	DDSurface		*m_pUpdateSurface;
	DDSurface		*m_pBoard;

	DDFontSurface	*m_pBreman32;

	DDSurface		*m_pBackground;
	DDSurface		*m_pTitle;
	DDSurface		*m_pPause;
	DDSurface		*m_pGameOver;
	DDSurface		*m_pOptionScreen;
	DDSurface		*m_pStartText;
	DDSurface		*m_pOptionsText;
	DDSurface		*m_pExitText;
	DDSurface		*m_pPieceImages[PT_COUNT+1];

	DDSURFACEDESC2   m_ddsd;

	listAnimation	m_lstAnimations;

	DSSoundManager	m_SoundManager;
	DSSound			*m_pSoundBang;
	DSSound			*m_pSoundDrop;
	DSSound			*m_pSoundFade;
	DSSound			*m_pSoundSetPiece;
	DSSound			*m_pSoundTumble;
	DSSound			*m_pSoundGameOver;

	/* Game data *****************************************************************/
	CTetrisGame		*m_pGame;
	double			 m_dDescentRate;
	DWORD			 m_dwStartTime;
	FLOAT			 m_fFPS;

	bool			m_isSwapWaiting;

	VIEW_STATE		m_state;
	/* Display parameters ********************************************************/
	RECT m_rStart;
	RECT m_rBoard;
	RECT m_rName;
	RECT m_rPreview[3];
	RECT m_rScore;
	RECT m_rStore;

	/* Display State *************************************************************/
	PIECE_TYPE	m_Store;
	PIECE_TYPE	m_Preview[3];
	DWORD		m_dwScore;
	bool		m_isBoardNeeded;
	bool		m_isBackgroundNeeded;
	DWORD		m_textDrawCount;

	enum EVENT_ID	{
					NO_EVENT			= 0,
					REFRESH_PREVIEW1	= 1,	
					REFRESH_PREVIEW2	= 2,
					REFRESH_PREVIEW3	= 4,
					REFRESH_STORE		= 8,
					REFRESH_BOARD		= 16,
					START_DESCENT		= 32,
					STOP_DESCENT		= 64
					};

			//C: Virtual overrides from DDrawWindow
	virtual HRESULT DestroyObjects();
	virtual HRESULT Init ();
	virtual HRESULT AdjustWindowForModeChange ();
public:
	enum ANIMATIONS{SWAP = 1};

	CTetrisView ();
	~CTetrisView();


	HRESULT SetGame (CTetrisGame *pGame);
	void	Flush();

	HRESULT UpdateFrame ();
	HRESULT	Animate		(DDSurface *pSurface);
	HRESULT TriggerEvents (DWORD dwEventID);

	DECLARE_WND_CLASS(NULL)

	BOOL PreTranslateMessage(MSG* pMsg)
	{
		pMsg;
		return FALSE;
	}

			//C: Use the BEGIN_MSG_MAP_EX macro to use WTL message cracking instead
			//   of the generic format function handler.
	BEGIN_MSG_MAP_EX(CTetrisView)
		MSG_WM_ERASEBKGND(OnEraseBkgnd)
		MSG_WM_PAINT(OnPaint)
		MSG_WM_SIZE(OnSize)
	END_MSG_MAP()

			//C: Message handlers
	LRESULT OnEraseBkgnd(HDC hdc);
	LRESULT OnPaint(HDC hdc);
	LRESULT OnSize(UINT nMode, CSize size);

	HRESULT OnStartGame ();
	HRESULT OnSetPiece	(RECT &rPos);
	HRESULT OnSwap		();
	HRESULT OnGameOver	();

	VIEW_STATE GetState ();
	void SetState	(VIEW_STATE state);

	void SetSoundFXVolume (FLOAT volume);

protected:
			//C: Initialization members.
	HRESULT LoadLayout(LPCTSTR pszLayout);
	HRESULT FreeImages();
			//C: Display helpers
	HRESULT DrawBackground (DDSurface *pSurface);
	HRESULT UpdateBoard (bool isForcePaint);
	HRESULT DrawBoard	(DDSurface *pSurface);
	HRESULT DrawLine	(DDSurface *pSurface, POINT &ptOffset, TetrisLine &top, TetrisLine &line, TetrisLine &bottom);
	HRESULT DrawPreview	(DDSurface *pSurface);
	HRESULT DrawScore	(DDSurface *pSurface);
	HRESULT DrawStore	(DDSurface *pSurface);

	HRESULT DrawMain    (DDSurface *pSurface);
	HRESULT DrawGameOver(DDSurface *pSurface);
	HRESULT DrawPause	(DDSurface *pSurface);

	/* Animation Sequences ***************************************************/
	HRESULT NewPieceAnimation (DWORD dwMilliSec, FLOAT fDelay);
	HRESULT CreateSetPiece(TETRIS_PIECE& piece, RECT& rPos, bool isSuper);
	HRESULT CreateCollapseBoard(setUINT sLines, FLOAT fDelay);
	HRESULT CreateLineDrop(UINT nStart, UINT nEnd, UINT nDropCount, FLOAT fDelay, bool isPaintBoard);
	HRESULT CreateLineExplosion(setUINT sLines, DDSurface *pBoard, FLOAT fDelay);
	HRESULT CreateStoreSwap();
	HRESULT CreateLineFade(setUINT sLines);
	HRESULT GameOverAnimation ();
	HRESULT PauseAnimation    ();
};


/******************************************************************************
	CTetrisView inline methods
******************************************************************************/
/* Private ********************************************************************
Author:		Paul Watt
Date:		4/2/2002
Purpose:	Handles the erasebkgnd message.  This handler will in fact defer the
			background preparation to the paint routine.
******************************************************************************/
inline LRESULT CTetrisView::OnEraseBkgnd(HDC hdc)
{
			//C: Indicate that the paint handler should erase the background.
	return 0;
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		10/18/2002
Purpose:	
Parameters:			
Return:		
******************************************************************************/
inline CTetrisView::VIEW_STATE CTetrisView::GetState () 
{
	return m_state;
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		10/18/2002f
Purpose:	
Parameters:			
Return:		
******************************************************************************/
inline void CTetrisView::SetState	(VIEW_STATE state)
{
	m_state = state;	
			//C: This will force all of the elements of the display to be repainted
			//   when the state of the game changes.
	m_isBackgroundNeeded= true;
	m_Store				= PT_EMPTY;
	m_Preview[0]		= PT_EMPTY;
	m_Preview[1]		= PT_EMPTY;
	m_Preview[2]		= PT_EMPTY;
	m_dwScore			= 0xFFFFFFFF;
	m_isBoardNeeded		= true;

	m_textDrawCount = 0;
}


/* Public *********************************************************************
Author:		Paul Watt
Date:		10/22/2002
Purpose:	Sets the volume level for the sound effects.
Parameters:	volume[in]: Volume level from 0 - 100
Return:		-
******************************************************************************/
inline void CTetrisView::SetSoundFXVolume (FLOAT volume)
{
			//C: Set the sound level for all of the sound effects.
	if (m_pSoundBang)
	{
		m_pSoundBang->SetVolume(volume);
	}
	if (m_pSoundDrop)
	{
		m_pSoundDrop->SetVolume(volume);
	}
	if (m_pSoundFade)
	{
		m_pSoundFade->SetVolume(volume);
	}
	if (m_pSoundSetPiece)
	{
		m_pSoundSetPiece->SetVolume(volume);
	}
	if (m_pSoundTumble)
	{
		m_pSoundTumble->SetVolume(volume);
	}
	if (m_pSoundGameOver)
	{
		m_pSoundGameOver->SetVolume(volume);
	}
}

#endif

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer
United States United States
I am a software architect and I have been developing software for nearly two decades. Over the years I have learned to value maintainable solutions first. This has allowed me to adapt my projects to meet the challenges that inevitably appear during development. I use the most beneficial short-term achievements to drive the software I develop towards a long-term vision.

C++ is my strongest language. However, I have also used x86 ASM, ARM ASM, C, C#, JAVA, Python, and JavaScript to solve programming problems. I have worked in a variety of industries throughout my career, which include:
• Manufacturing
• Consumer Products
• Virtualization
• Computer Infrastructure Management
• DoD Contracting

My experience spans these hardware types and operating systems:
• Desktop
o Windows (Full-stack: GUI, Application, Service, Kernel Driver)
o Linux (Application, Daemon)
• Mobile Devices
o Windows CE / Windows Phone
o Linux
• Embedded Devices
o VxWorks (RTOS)
o Greenhills Linux
o Embedded Windows XP

I am a Mentor and frequent contributor to CodeProject.com with tutorial articles that teach others about the inner workings of the Windows APIs.

I am the creator of an open source project on GitHub called Alchemy[^], which is an open-source compile-time data serialization library.

I maintain my own repository and blog at CodeOfTheDamned.com/[^], because code maintenance does not have to be a living hell.

Comments and Discussions