⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isohex19_2.cpp

📁 一個遊戲教程
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/*****************************************************************************
IsoHex19_2.cpp
Ernest S. Pazera
04OCT2000
Start a WIN32 Application Workspace, add in this file
Requires the following libs:
ddraw.lib, dxguid.lib
Requires the following files:
DDFuncs.h.cpp, GDICanvas.h/cpp, IsoMouseMap.h/cpp,
IsoScroller.h/cpp, IsoTilePlotter.h/cpp, IsoTileWalker.h/cpp
TileSet.h/cpp. IsoHexCore.h, IsoHexDefs.h
IsoRenderer.h/cpp
*****************************************************************************/

//////////////////////////////////////////////////////////////////////////////
//INCLUDES
//////////////////////////////////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN  

#include <windows.h>  
#include "DDFuncs.h"
#include "TileSet.h"
#include "IsoHexCore.h"
#include "IsoRenderer.h"
#include <list>
 
//////////////////////////////////////////////////////////////////////////////
//DEFINES
//////////////////////////////////////////////////////////////////////////////
//name for our window class
#define WINDOWCLASS "ISOHEX19"
//title of the application
#define WINDOWTITLE "IsoHex 19-2"

const int MAPWIDTH=40;
const int MAPHEIGHT=40;

//gamestates
const int GS_IDLE=0;//waits for a keypress
const int GS_STARTTURN=1;//starts a players turn
const int GS_ENDTURN=2;//ends a players turn
const int GS_NEXTUNIT=3;//finds the next unit to move
const int GS_STARTMOVE=4;//starts moving the unit
const int GS_DOMOVE=5;//moves the unit
const int GS_ENDMOVE=6;//ends a unit move
const int GS_NULLMOVE=7;//tells a unit to not move
const int GS_SKIPMOVE=8;//temporarily skip the move
const int GS_HOLDPOSITION=9;//fortify
const int GS_CLICKSELECT=10;//when a click occurs, this gamestate is selected
const int GS_CLICKCENTER=11;//click on a map location with none of the players units
const int GS_CLICKSTACK=12;//click on a map location with at least two of the players units
const int GS_PICKUNIT=13;//pick unit from the selection window

//////////////////////////////////////////////////////////////////////////////
//TYPEDEFS/STRUCTS
//////////////////////////////////////////////////////////////////////////////
struct UnitInfo//unit information structure
{
	int iType;//type of unit
	int iTeam;//team to which the unit belongs
	POINT ptPosition;//map location of the unit
	int iMovePoints;//number of movepoints left this turn
	bool bHolding;//true if holding position
};

typedef UnitInfo *PUNITINFO;//pointer type alias for unitinfo

typedef std::list<PUNITINFO> UNITLIST;//list of units
typedef std::list<PUNITINFO>::iterator UNITLISTITER;//iterator for unit list

//////////////////////////////////////////////////////////////////////////////
//PROTOTYPES
//////////////////////////////////////////////////////////////////////////////
bool Prog_Init();//game data initalizer
void Prog_Loop();//main game loop
void Prog_Done();//game clean up

//minimap functions
void SetupMiniMap();//does initial setup of the minimap
void UpdateMiniMap();//updates the minimap to reflect current game status
void RedrawMiniMap();//redraws the minimap to reflect current gamestate
void ShowMiniMap();//shows the minimap on-screen
void DestroyMiniMap();//cleans up the minimap

//////////////////////////////////////////////////////////////////////////////
//GLOBALS
//////////////////////////////////////////////////////////////////////////////
HINSTANCE hInstMain=NULL;//main application handle
HWND hWndMain=NULL;//handle to our main window

//game state
int iGameState=GS_IDLE;
int iCurrentTeam=0;//the team whose turn it currently is

//directdraw
LPDIRECTDRAW7 lpdd=NULL;
LPDIRECTDRAWSURFACE7 lpddsMain=NULL;
LPDIRECTDRAWSURFACE7 lpddsBack=NULL;
LPDIRECTDRAWSURFACE7 lpddsFrame=NULL;
LPDIRECTDRAWSURFACE7 lpddsMiniMap=NULL;//minimap surface

//tilesets
CTileSet tsBack;//background
CTileSet tsUnit;//unit
CTileSet tsShield;//shields
CTileSet tsPressEnter;//press enter text
CTileSet tsMiniMap;//minimap tileset

//offsets for the shields
POINT ptShieldOffset[2];//one for each unit

//isohexcore components
CTilePlotter TilePlotter;//plotter
CTileWalker TileWalker;//walker
CScroller Scroller;//scroller
CMouseMap MouseMap;//mousemap
CRenderer Renderer;//renderer

//minimap components
CTilePlotter MiniTilePlotter;
CScroller MiniScroller;

POINT ptScroll;//keep track of how quickly we scroll
POINT ptClick;//keep track of the clicked position

//map location structure
struct MapLocation
{
	UNITLIST ulUnitList;//list of units on this map location
};

MapLocation mlMap[MAPWIDTH][MAPHEIGHT];//map array
UNITLIST MainUnitList;//unit list for all units
UNITLIST TeamUnitList;//unit list for teams(Current Players Turn)
PUNITINFO pCurrentUnit;//current unit being moved
bool bFlash;//controls the flashing of the current unit
ISODIRECTION idMoveUnit;//direction in which the unit will be moved
bool bMovedUnit;//indicates whether or not a unit has been moved by the current player this turn

//unit selection variables(for selecting stacks of units)
RECT rcSelectWindow;//the selection window
POINT ptCellSize;//size of selection cell
PUNITINFO SelectUnitList[20];//unit selection list (max of 20 units)
POINT ptUnitOffset;//offset for placing units in the selection window
DWORD dwSelectWindowColor;//color for the selection window

//minimap array
int* MiniMap;//current minimap array

//rendering functionprototype
void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap);

//////////////////////////////////////////////////////////////////////////////
//WINDOWPROC
//////////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK TheWindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
{
	//which message did we get?
	switch(uMsg)
	{
	case WM_LBUTTONDOWN://beginning of click-select
		{
			//process differently, depending on gamestate
			switch(iGameState)
			{
			case GS_IDLE:
				{
					//grab the mouse position
					POINT ptCursor;
					ptCursor.x=LOWORD(lParam);
					ptCursor.y=HIWORD(lParam);
					//use the mousemap to get click position
					ptClick=MouseMap.MapMouse(ptCursor);
				}break;
			}
			return(0);//handled
		}break;
	case WM_LBUTTONUP://end of click-select
		{
			//process differently, depending on gamestate
			switch(iGameState)
			{
			case GS_IDLE:
				{
					//grab the mouse position
					POINT ptCursor;
					ptCursor.x=LOWORD(lParam);
					ptCursor.y=HIWORD(lParam);
					//use the mousemap to get click position
					POINT ptMap=MouseMap.MapMouse(ptCursor);
					//check map position against ptClick
					if(ptMap.x==ptClick.x && ptMap.y==ptClick.y)
					{
						//set gamestate to GS_CLICKSELECT
						iGameState=GS_CLICKSELECT;
					}
				}break;
			case GS_PICKUNIT:
				{
					//grab the mouse position
					POINT ptMouse;
					ptMouse.x=LOWORD(lParam);
					ptMouse.y=HIWORD(lParam);
					//check to see if the click was within the select window
					if(PtInRect(&rcSelectWindow,ptMouse))
					{
						//within the select window
						//determine which cell was clicked
						ptMouse.x-=rcSelectWindow.left;//subtract top left of the window
						ptMouse.y-=rcSelectWindow.top;
						ptMouse.x/=ptCellSize.x;//divide by cellsize
						ptMouse.y/=ptCellSize.y;
						int cellnum=ptMouse.x+5*ptMouse.y;//calc cell number
						//check for a NULL
						if(SelectUnitList[cellnum]==NULL)
						{
							//empty cell
							//do nothing
							return(0);
						}
						else
						{
							//non-empty cell
							//check if the unit has any movement points left
							if(SelectUnitList[cellnum]->iMovePoints==0)
							{
								//no movement points
								//do nothing
								return(0);
							}
							else
							{
								//check for holding position
								if(SelectUnitList[cellnum]->bHolding)
								{
									//set holding to false
									SelectUnitList[cellnum]->bHolding=false;
								}
								//remove this unit from the team list
								TeamUnitList.remove(SelectUnitList[cellnum]);
								//re-add this unit to the team list at the beginning
								TeamUnitList.push_front(SelectUnitList[cellnum]);
								//select next unit
								iGameState=GS_NEXTUNIT;
								//add entire screen to update rect
								Renderer.AddRect(Scroller.GetScreenSpace());
							}
						}
					}
					else
					{
						//outside of select window
						iGameState=GS_NEXTUNIT;
					}
				}break;
			}
			return(0);//handled
		}break;
	case WM_KEYDOWN:
		{
			switch(wParam)
			{
			case VK_ESCAPE:
				{
					DestroyWindow(hWndMain);
					return(0);
				}break;
			case VK_RETURN://at end of turn, if no unit has been moved
				{
					if(iGameState==GS_IDLE && pCurrentUnit==NULL) iGameState=GS_ENDTURN;
					return(0);
				}break;
			case VK_SPACE://do not move unit
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL) iGameState=GS_NULLMOVE;//only respond when gamestate is GS_IDLE;
					return(0);
				}break;
			case 'W'://wait to move this unit later
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL) iGameState=GS_SKIPMOVE;//skip this unit for now
				}break;
			case 'H'://tell unit to hold position
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL) iGameState=GS_HOLDPOSITION;//tell the unit to hold position
				}break;
			case 'C'://center on the current unit
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL)
					{
						//plot the current unit's world position
						POINT ptPlot=TilePlotter.PlotTile(pCurrentUnit->ptPosition);
						//adjust by half width and height of the screen
						ptPlot.x-=(Scroller.GetScreenSpaceWidth()/2);
						ptPlot.y-=(Scroller.GetScreenSpaceHeight()/2);
						//set the anchor
						Scroller.SetAnchor(&ptPlot);
						//add update rect to renderer
						Renderer.AddRect(Scroller.GetScreenSpace());
					}
				}break;
			case VK_NUMPAD8:
			case VK_UP:
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE
					{
						idMoveUnit=ISO_NORTH;//move to the north
						POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position
						if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking
						{
							if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty
							{
								iGameState=GS_STARTMOVE;//set the unit in motion
							}
							else
							{
								UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list
								PUNITINFO pUnitInfo=*iter;//get the unit from the list
								if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team
								{
									iGameState=GS_STARTMOVE;
								}
							}
						}
					}
				}break;
			case VK_NUMPAD9:
			case VK_PRIOR:
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE
					{
						idMoveUnit=ISO_NORTHEAST;//move to the north
						POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position
						if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking
						{
							if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty
							{
								iGameState=GS_STARTMOVE;//set the unit in motion
							}
							else
							{
								UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list
								PUNITINFO pUnitInfo=*iter;//get the unit from the list
								if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team
								{
									iGameState=GS_STARTMOVE;
								}
							}
						}
					}
				}break;
			case VK_NUMPAD6:
			case VK_RIGHT:
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE
					{
						idMoveUnit=ISO_EAST;//move to the north
						POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position
						if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking
						{
							if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty
							{
								iGameState=GS_STARTMOVE;//set the unit in motion
							}
							else
							{
								UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list
								PUNITINFO pUnitInfo=*iter;//get the unit from the list
								if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team
								{
									iGameState=GS_STARTMOVE;
								}
							}
						}
					}
				}break;
			case VK_NUMPAD3:
			case VK_NEXT:
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE
					{
						idMoveUnit=ISO_SOUTHEAST;//move to the north
						POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position
						if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking
						{
							if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty
							{
								iGameState=GS_STARTMOVE;//set the unit in motion
							}
							else
							{
								UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list
								PUNITINFO pUnitInfo=*iter;//get the unit from the list
								if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team
								{
									iGameState=GS_STARTMOVE;
								}
							}
						}
					}
				}break;
			case VK_NUMPAD2:
			case VK_DOWN:
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE
					{
						idMoveUnit=ISO_SOUTH;//move to the north
						POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position
						if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking
						{
							if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty
							{
								iGameState=GS_STARTMOVE;//set the unit in motion
							}
							else
							{
								UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list
								PUNITINFO pUnitInfo=*iter;//get the unit from the list
								if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team
								{
									iGameState=GS_STARTMOVE;
								}
							}
						}
					}
				}break;
			case VK_NUMPAD1:
			case VK_END:
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE
					{
						idMoveUnit=ISO_SOUTHWEST;//move to the north
						POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position
						if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking
						{
							if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty
							{
								iGameState=GS_STARTMOVE;//set the unit in motion
							}
							else
							{
								UNITLISTITER iter=mlMap[ptNext.x][ptNext.y].ulUnitList.begin();//get the first entry in the list
								PUNITINFO pUnitInfo=*iter;//get the unit from the list
								if(pUnitInfo->iTeam==pCurrentUnit->iTeam)//must be the same team
								{
									iGameState=GS_STARTMOVE;
								}
							}
						}
					}
				}break;
			case VK_NUMPAD4:
			case VK_LEFT:
				{
					if(iGameState==GS_IDLE && pCurrentUnit!=NULL)//gamestate must be GS_IDLE
					{
						idMoveUnit=ISO_WEST;//move to the north
						POINT ptNext=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);//check the next position
						if(ptNext.x>=0 && ptNext.y>=0 && ptNext.x<MAPWIDTH && ptNext.y<MAPWIDTH)//bounds checking
						{
							if(mlMap[ptNext.x][ptNext.y].ulUnitList.empty())//if the map location is empty
							{
								iGameState=GS_STARTMOVE;//set the unit in motion

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -