root/week1oplossing/GameEngine.h

User picture

Author: machiel.sleeuwaert

Revision: 13 («Previous)

(Oct 08 15:33 2008 UTC) Over 3 years ago


  

 
Show/hide line numbers
//-----------------------------------------------------------------
// Game Engine Object
// C++ Header - GameEngine.h - version 2008 v3_02
// Copyright Kevin Hoefman - kevin.hoefman@howest.be
// http://www.digitalartsandentertainment.be/
//
// New features: 
//		- v3 Engine uses tstring instead of String
//-----------------------------------------------------------------

#pragma once

//-----------------------------------------------------------------
// Include Files
//-----------------------------------------------------------------
#define _WIN32_WINNT 0x0600 // changed 25 sept 2008 to avoid conflict with Vista definition in other (system) header
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <tchar.h>
#include <Mmsystem.h>	// winmm.lib header, used for playing sound
#undef MessageBox

#include "AbstractGame.h" // needed to use abstract class as basis for all games

#include "GameDefines.h"  // common header files and defines / macros

#include <vector>			// using std::vector for tab control logic
#include <queue>			// using std::queue for event system
#include <algorithm>
using namespace std;

//-----------------------------------------------------------------
// Pragma Library includes
//-----------------------------------------------------------------
#pragma comment(lib, "msimg32.lib")		// used for transparency
#pragma comment(lib, "winmm.lib")		// used for sound

//-----------------------------------------------------------------
// GameEngine Defines
//-----------------------------------------------------------------
#define KEYBCHECKRATE 60

//-----------------------------------------------------------------
// GameEngine Forward Declarations
//-----------------------------------------------------------------
class Bitmap;
class SoundWave;
class Midi;
class HitRegion;

//-----------------------------------------------------------------
// GameEngine Class
//-----------------------------------------------------------------
class GameEngine
{
private:
	// singleton implementation : private constructor + static pointer to game engine
	GameEngine();
	static GameEngine*  m_GameEnginePtr;

public:
	// Destructor
	virtual ~GameEngine();

	// Static methods
	static GameEngine*  GetSingleton();

	// General Methods
	void		SetGame(AbstractGame* gamePtr);
	bool		Run(HINSTANCE hInstance, int iCmdShow);
	bool        ClassRegister(int iCmdShow);
	bool		SetGameValues(const tstring& titleRef, WORD wIcon, WORD wSmallIcon, int iWidth, int iHeight);
	bool		SetWindowRegion(const HitRegion* regionPtr); 
	bool		HasWindowRegion() const; 
	bool		GoFullscreen();		
	bool		GoWindowedMode();		
	bool		IsFullscreen() const;		
	void		ShowMousePointer(bool value) const;	

	LRESULT     HandleEvent(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
	bool		IsKeyDown(int vKey) const;
	void		QuitGame(void) const;
	void		MessageBox(double value) const;
	void		MessageBox(int value) const;
	void		MessageBox(size_t value) const;
	void		MessageBox(const tstring& textRef) const;
	void		RunGameLoop(bool value);
	void		TabNext(HWND ChildWindow) const;
	void		TabPrevious(HWND ChildWindow) const;

	// Draw Methods
	bool		DrawLine(int x1, int y1, int x2, int y2) const;
	bool		DrawLine(int x1, int y1, int x2, int y2, HDC hDC) const;
	bool		DrawPolygon(const POINT ptsArr[], int count) const;
	bool		DrawPolygon(const POINT ptsArr[], int count, bool close) const;
	bool		DrawPolygon(const POINT ptsArr[], int count, bool close, HDC hDC) const;
	bool		FillPolygon(const POINT ptsArr[], int count) const;
	bool		FillPolygon(const POINT ptsArr[], int count, bool close) const;
	bool		FillPolygon(const POINT ptsArr[], int count, bool close, HDC hDC) const;
	bool		DrawRect(int x, int y, int width, int height) const;
	bool		DrawRect(int x, int y, int width, int height, HDC hDC) const;
	bool		FillRect(int x, int y, int width, int height) const;
	bool		FillRect(int x, int y, int width, int height, HDC hDC) const;
	bool		DrawRoundRect(int x, int y, int width, int height, int radius) const;
	bool		DrawRoundRect(int x, int y, int width, int height, int radius, HDC hDC) const;
	bool		FillRoundRect(int x, int y, int width, int height, int radius) const;
	bool		FillRoundRect(int x, int y, int width, int height, int radius, HDC hDC) const;
	bool		DrawOval(int x, int y, int width, int height) const;
	bool		DrawOval(int x, int y, int width, int height, HDC hDC) const;
	bool		FillOval(int x, int y, int width, int height) const;
	bool		FillOval(int x, int y, int width, int height, HDC hDC) const;
	bool		DrawArc(int x, int y, int width, int height, int startDegree, int angle) const;
	bool		DrawArc(int x, int y, int width, int height, int startDegree, int angle, HDC hDC) const;
	bool		FillArc(int x, int y, int width, int height, int startDegree, int angle) const;
	bool		FillArc(int x, int y, int width, int height, int startDegree, int angle, HDC hDC) const;
	int			DrawString(const tstring& textRef, int x, int y) const;
	int			DrawString(const tstring& textRef, int x, int y, HDC hDC) const;
	int			DrawString(const tstring& textRef, int x, int y, int width, int height) const;
	int			DrawString(const tstring& textRef, int x, int y, int width, int height, HDC hDC) const;
	bool		DrawBitmap(Bitmap* bitmapPtr, int x, int y) const;
	bool		DrawBitmap(Bitmap* bitmapPtr, int x, int y, HDC hDC) const;
	bool		DrawBitmap(Bitmap* bitmapPtr, int x, int y, RECT rect) const;
	bool		DrawBitmap(Bitmap* bitmapPtr, int x, int y, RECT rect, HDC hDC) const;
	bool		DrawSolidBackground(COLORREF color);
	bool		DrawSolidBackground(COLORREF color, HDC hDC, RECT rect);
	void		SetColor(COLORREF color) {m_colDraw = color;}
	COLORREF	GetDrawColor() const {return m_colDraw;}
	void		SetFont(const tstring& fontNameRef, bool bold, bool italic, bool underline, int size);
	bool		Repaint() const;

	// Accessor Methods
	HINSTANCE	GetInstance() const { return m_hInstance; }
	HWND		GetWindow() const { return m_hWindow; }
	tstring&	GetTitle() const { return *m_TitlePtr; }
	WORD		GetIcon() const { return m_wIcon; }
	WORD		GetSmallIcon() const { return m_wSmallIcon; }
	int			GetWidth() const { return m_iWidth; }
	int			GetHeight() const { return m_iHeight; }
	int			GetFrameDelay() const { return m_iFrameDelay; }
	bool		GetSleep() const { return m_bSleep?true:false; }
	POINT		GetLocation() const;

	// Public Mutator Methods	
	void		SetTitle(const tstring& titleRef); // SetTitle automatically sets the window class name to the same name as the title - easier for students 
	void		SetIcon(WORD wIcon) { m_wIcon = wIcon; }
	void		SetSmallIcon(WORD wSmallIcon) { m_wSmallIcon = wSmallIcon; }
	void		SetWidth(int iWidth) { m_iWidth = iWidth; }
	void		SetHeight(int iHeight) { m_iHeight = iHeight; }
	void		SetFrameRate(double iFrameRate) { m_iFrameDelay = (int) (1000 / iFrameRate); }
	void		SetSleep(bool bSleep) { m_bSleep = bSleep; }
	void		SetKeyList(const tstring& keyListRef);
	void		SetPaintDoublebuffered() { m_PaintDoublebuffered = true; }	
	void		SetLocation(int x, int y);

	// Keyboard monitoring thread method
	virtual DWORD		KeybThreadProc();
	
private:
	// Private Mutator Methods	
	void		SetInstance(HINSTANCE hInstance) { m_hInstance = hInstance; };
	void		SetWindow(HWND hWindow) { m_hWindow = hWindow; };

	// Private Draw Methods
	void FormPolygon(const POINT ptsArr[], int count, bool close, HDC hDC) const;
	POINT AngleToPoint(int x, int y, int width, int height, int angle) const;

	// Member Variables
	HINSTANCE           m_hInstance;
	HWND                m_hWindow;
	tstring*            m_TitlePtr;
	WORD                m_wIcon, m_wSmallIcon;
	int                 m_iWidth, m_iHeight;
	int                 m_iFrameDelay;
	bool                m_bSleep;
	bool				m_bRunGameLoop;
	HANDLE				m_hKeybThread;
	DWORD				m_dKeybThreadID;
	bool				m_bKeybRunning;
	TCHAR*				m_KeyListPtr;
	unsigned int		m_KeybMonitor;
	AbstractGame*		m_GamePtr;
	bool				m_PaintDoublebuffered;
	bool				m_Fullscreen;

	// Draw assistance variables
	HDC m_HdcDraw;
	RECT m_RectDraw;
	bool m_isPainting, m_isDoublebuffering;
	COLORREF m_colDraw;
	HFONT m_FontDraw;

	// Fullscreen assistance variable
	POINT m_oldLoc;

	// Window Region assistance variable
	HitRegion* m_WindowRegionPtr;
		
	// -------------------------
	// Disabling default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, the declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	GameEngine(const GameEngine& gRef);
	GameEngine& operator=(const GameEngine& gRef);
};

//------------------------------------------------------------------------------------------------
// Callable Interface
//
// Interface implementation for classes that can be called by "caller" objects
//------------------------------------------------------------------------------------------------
class Caller;	// forward declaration

class Callable
{
public:
	virtual ~Callable() {}						// virtual destructor for polymorphism
	virtual void CallAction(Caller* callerPtr) = 0;
};

//------------------------------------------------------------------------------------------------
// Caller Base Class
//
// Base Clase implementation for up- and downcasting of "caller" objects: TextBox, Button, Timer, Audio and Video
//------------------------------------------------------------------------------------------------
class Caller
{
public:
	virtual ~Caller() {}				// do not delete the targets!

	static const int TextBox = 0;
	static const int Button = 1;
	static const int Timer = 2;
	static const int Audio = 3;
	static const int Video = 4;

	virtual int GetType() const = 0;

	virtual bool AddActionListener(Callable* targetPtr);		// public interface method, call is passed on to private method
	virtual bool RemoveActionListener(const Callable* targetPtr);	// public interface method, call is passed on to private method

protected:
	Caller() {}								// constructor only for derived classes
	vector<Callable*> m_TargetList;

	virtual bool CallListeners();			// placing the event code in a separate method instead of directly in the windows messaging
											// function allows inheriting classes to override the event code. 

private:
	bool AddListenerObject(Callable* targetPtr);
	bool RemoveListenerObject(const Callable* targetPtr);

	// -------------------------
	// Disabling default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, the declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	Caller(const Caller& tRef);
	Caller& operator=(const Caller& tRef);
};

//--------------------------------------------------------------------------
// Timer Class
//
// This timer is a queue timer, it will only work on Windows 2000 and higher
//--------------------------------------------------------------------------

class Timer : public Caller
{
public:
	Timer(int msec, Callable* targetPtr); // constructor automatically adds 2nd parameter to the list of listener objects

	virtual ~Timer();

	int GetType() const {return Caller::Timer;}
	void Start();
	void Stop();
	bool IsRunning() const;
	void SetDelay(int msec);
	int GetDelay() const;

private:	
	// -------------------------
	// Datamembers
	// -------------------------
	HANDLE m_TimerHandle;
	bool m_IsRunning;
	int m_Delay;

	// -------------------------
	// Handler functions
	// -------------------------	
	static void CALLBACK TimerProcStatic(void* lpParameter, BOOLEAN TimerOrWaitFired); // proc will call CallListeners()
		
	// -------------------------
	// Disabling default constructor, default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	Timer();
	Timer(const Timer& tRef);
	Timer& operator=(const Timer& tRef);
};

//-----------------------------------------------------------------
// TextBox Class
//-----------------------------------------------------------------

class TextBox : public Caller
{
public:
	TextBox(const tstring& textRef);
	TextBox();

	virtual ~TextBox();

	int GetType() const {return Caller::TextBox;}
	void SetBounds(int x, int y, int width, int height);
	tstring GetText() const;
	void SetText(const tstring& textRef);
	void SetFont(const tstring& fontNameRef, bool bold, bool italic, bool underline, int size);
	void SetBackcolor(COLORREF color);
	void SetForecolor(COLORREF color);
	COLORREF GetForecolor() const;
	COLORREF GetBackcolor() const;
	HBRUSH GetBackcolorBrush() const;
	RECT GetRect() const;
	void SetEnabled(bool bEnable);
	void Update(void) const;
	void Show() const;
	void Hide() const;

private:
	// -------------------------
	// Datamembers
	// -------------------------
	int m_x, m_y;
	HWND m_hWndEdit;
	WNDPROC m_procOldEdit;
	COLORREF m_BgColor, m_ForeColor;
	HBRUSH m_BgColorBrush;
	HFONT m_Font, m_OldFont;

	// -------------------------
	// Handler functions
	// -------------------------	
	static LRESULT CALLBACK EditProcStatic(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
	LRESULT EditProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
		
	// -------------------------
	// Disabling default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	TextBox(const TextBox& tRef);
	TextBox& operator=(const TextBox& tRef);
};

//-----------------------------------------------------------------
// Button Class
//-----------------------------------------------------------------
class Button : public Caller
{
public:
	Button(const tstring& textRef);
	Button();

	virtual ~Button();

	int GetType() const {return Caller::Button;}
	void SetBounds(int x, int y, int width, int height);
	tstring GetText() const;
	void SetText(const tstring& textRef);
	void SetFont(const tstring& fontNameRef, bool bold, bool italic, bool underline, int size);
	RECT GetRect() const;
	void SetEnabled(bool bEnable);
	void Update(void) const;
	void Show() const;
	void Hide() const;

private:
	// -------------------------
	// Datamembers
	// -------------------------
	int m_x, m_y;
	HWND m_hWndButton;
	WNDPROC m_procOldButton;
	bool m_Armed;
	COLORREF m_BgColor, m_ForeColor;
	HFONT m_Font, m_OldFont;

	// -------------------------
	// Handler functions
	// -------------------------	
	static LRESULT CALLBACK ButtonProcStatic(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
	LRESULT ButtonProc(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
		
	// -------------------------
	// Disabling default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	Button(const Button& bRef);
	Button& operator=(const Button& bRef);
};

//-----------------------------------------------------------------
// Audio Class
//-----------------------------------------------------------------
class Audio : public Caller
{
	// Static Proc function has to be able to call SwitchPlayingOff(), but nobody else should
	friend LRESULT Audio::AudioProcStatic(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

public:
	Audio(const tstring& nameRef);
	Audio(int IDAudio, const tstring& typeRef);

	virtual ~Audio();

	const tstring& GetName() const;
	const tstring& GetAlias() const;
	int GetDuration() const;
	bool IsPlaying() const;
	bool IsPaused() const;
	void SetRepeat(bool repeat);
	bool GetRepeat() const;
	bool Exists() const;
	int GetVolume() const;
	int GetType() const;

	// these methods are called to instruct the object. The methods that perform the actual sendstrings are private.
	void Play(int msecStart = 0, int msecStop = -1);
	void Pause();
	void Stop();
	void SetVolume(int volume);

	// commands are queued and sent through a Tick() which should be called by the main thread (mcisendstring isn't thread safe) 
	// has the additional benefit of creating a delay between mcisendstring commands
	void Tick();

private:	
	// -------------------------
	// Datamembers
	// -------------------------
	static int m_nr;
	tstring m_FileName;
	tstring m_Alias;
	bool m_Playing, m_Paused;
	bool m_MustRepeat;
	HWND m_hWnd;
	int m_Duration;
	int m_Volume;

	// -------------------------
	// Member functions
	// -------------------------			
	void Create(const tstring& nameRef);
	void Extract(WORD id , const tstring& typeRef, const tstring& fileNameRef) const;
	void SwitchPlayingOff();		

	// private mcisendstring command methods and command queue datamember
	queue<tstring> m_CommandQueue;
	void QueuePlayCommand(int msecStart);
	void QueuePlayCommand(int msecStart, int msecStop);
	void QueuePauseCommand();
	void QueueResumeCommand();
	void QueueStopCommand();
	void QueueVolumeCommand(int volume);		// add a m_Volume datamember? What volume does the video start on by default?
	void QueuePositionCommand(int x, int y);
	void QueueCommand(const tstring& commandRef);
	void SendMCICommand(const tstring& commandRef) const;
			
	// -------------------------
	// Handler functions
	// -------------------------	
	static LRESULT CALLBACK AudioProcStatic(HWND hWindow, UINT msg, WPARAM wParam, LPARAM lParam);
	
	// -------------------------
	// Disabling default constructor, default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	Audio();
	Audio(const Audio& aRef);
	Audio& operator=(const Audio& aRef);
};

//-----------------------------------------------------------------
// Bitmap Class
//-----------------------------------------------------------------

class Bitmap
{
public:
	Bitmap(const tstring& nameRef, bool createAlphaChannel = true);						
	Bitmap(int IDBitmap, const tstring& typeRef, bool createAlphaChannel = true);

	virtual ~Bitmap();

	bool Exists() const;
	HBITMAP GetHandle() const;
	int GetWidth() const;
	int GetHeight() const;
	void SetTransparencyColor(COLORREF color);
	COLORREF GetTransparencyColor() const;
	void SetOpacity(int);
	int GetOpacity() const;
	bool IsTarga() const;
	bool HasAlphaChannel() const;
	
private:	
	// -------------------------
	// Datamembers
	// -------------------------
	static int m_nr;
	HBITMAP m_Handle;
	COLORREF m_TransparencyKey;
	int m_Opacity;
	bool m_IsTarga;
	unsigned char* m_PixelsPtr; 
	bool m_Exists;
	bool m_HasAlphaChannel;

	// -------------------------
	// Methods
	// -------------------------
	void LoadBitInfo(); 
	void Extract(WORD id, tstring sType, tstring fileName) const;
		
	// -------------------------
	// Disabling default constructor, default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	Bitmap();
	Bitmap(const Bitmap& tRef);
	Bitmap& operator=(const Bitmap& tRef);
};

//-----------------------------------------------------------------
// TGA Loader Class - 16/11/04 Codehead - original name TGAImg
//-----------------------------------------------------------------
class TargaLoader
{
public:
	TargaLoader();
	~TargaLoader();
	int Load(const TCHAR* fileNamePtr);
	int GetBPP() const;
	int GetWidth() const;
	int GetHeight() const;
	const unsigned char* GetImg() const;       // Return a pointer to image data
	const unsigned char* GetPalette() const;   // Return a pointer to VGA palette
 
private:
	short int iWidth,iHeight,iBPP;
	unsigned long lImageSize;
	char bEnc;
	unsigned char *pImage, *pPalette, *pData;
   
	// Internal workers
	int ReadHeader();
	int LoadRawData();
	int LoadTgaRLEData();
	int LoadTgaPalette();
	void BGRtoRGB();
	void FlipImg();
};

//-----------------------------------------------------------------
// Extra OutputDebugString functions
//-----------------------------------------------------------------
void OutputDebugString(const tstring& textRef);

//-----------------------------------------------------------------
// Windows Procedure Declarations
//-----------------------------------------------------------------
DWORD WINAPI		KeybThreadProc (GameEngine* gamePtr);
LRESULT CALLBACK	WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

//-----------------------------------------------------------------
// HitRegion Class								
//-----------------------------------------------------------------
class HitRegion
{
public: 
	//---------------------------
	// Constructor(s)
	//---------------------------
	HitRegion();						// Default constructor. Geef de waarden van de nieuwe region op via de Create( ) methode.

	//---------------------------
	// Destructor
	//---------------------------
	virtual ~HitRegion();			

	//---------------------------
	// General Methods
	//---------------------------
	bool Create(int type, int x, int y, int width, int height);	// Gebruik deze create om een rechthoekige of elliptische hitregion te vormen

	bool Create(int type, const POINT* pointsArr, int numberOfPoints);	// Gebruik deze create om een polygonregion te vormen
	
	bool Create(int type, const Bitmap* bmpPtr, COLORREF cTransparent = RGB(255, 0, 255), COLORREF cTolerance = 0); // Gebruik deze create om een region uit een bitmap te maken

	HitRegion* Clone() const;											// Maakt een nieuw HitRegion object met dezelfde data als dit hitregion object, en returnt een pointerwaarde ernaartoe

	bool HitTest(HitRegion* regPtr) const;			// Returnt true als de regions overlappen, false als ze niet overlappen
	bool HitTest(int x, int y) const;				// Returnt true als het punt dat overeenkomt met de opgegeven x- en y-waarden in de region ligt, false indien niet.

	POINT CollisionTest(HitRegion* regPtr) const;	// Returnt {-1000000, -1000000} als de regions niet overlappen, en het middelpunt van de overlappende regio als ze wel overlappen.
													//		CollisionTest is handig om het raakpunt te bepalen van twee vormen die elkaar net raken.
	
	RECT GetDimension() const;					// Geeft de positie + breedte en hoogte terug van de kleinste rechthoek die deze region omhult (bij rechthoekige regions: de region zelf) 			

	HRGN GetHandle() const;						// Geeft de handle van de region weer (Win32 stuff)

	void Move(int x, int y);				// Verplaatst de volledige region volgens de opgegeven verplaatsing over x en y 

	static const int Ellipse = 0;			// Klasse-constanten om te kunnen opgeven welke soort region er moet gemaakt worden (analoog aan enum)
	static const int Rectangle = 1;
	static const int Polygon = 2;
	static const int FromBitmap = 3;

private:
	//---------------------------
	// Datamembers
	//---------------------------
	HRGN m_HitRegion;						// De region data wordt bijgehouden door middel van een Win32 "region" resource (niet kennen 1e semester).

	//---------------------------
	// Private methods
	//---------------------------
	HRGN BitmapToRegion(HBITMAP hBmp, COLORREF cTransparentColor, COLORREF cTolerance) const;

	// -------------------------
	// Disabling default copy constructor and default assignment operator.
	// If you get a linker error from one of these functions, your class is internally trying to use them. This is
	// an error in your class, these declarations are deliberately made without implementation because they should never be used.
	// -------------------------
	HitRegion(const HitRegion& sRef);				
	HitRegion& operator=(const HitRegion& sRef);	
};