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

📄 isohex19_2.cpp

📁 一個遊戲教程
💻 CPP
📖 第 1 页 / 共 3 页
字号:
			pCurrentUnit->iMovePoints=0;
			//don't really do anything, just go to the next unit
			pCurrentUnit=NULL;
			iGameState=GS_NEXTUNIT;
		}break;
	case GS_SKIPMOVE://skip this unit for now
		{
			//put unit at end of team unit list
			TeamUnitList.push_back(pCurrentUnit);
			pCurrentUnit=NULL;//set current unit to NULL
			iGameState=GS_NEXTUNIT;//select the next unit
		}break;
	case GS_HOLDPOSITION://tell unit to hold position
		{
			//set holding flag
			pCurrentUnit->bHolding=true;
			//show the holding unit
			Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y);
			pCurrentUnit=NULL;
			bFlash=true;
			//set next gamestate
			iGameState=GS_NEXTUNIT;
			DWORD dwTimeStart=GetTickCount();//get the frame start time
			//scroll the frame (0,0)
			Renderer.ScrollFrame(0,0);
			//update the frame
			Renderer.UpdateFrame();
			//flip to show the back buffer
			lpddsMain->Flip(0,DDFLIP_WAIT);
			//wait until 500 ms have passed
			while(GetTickCount()-dwTimeStart<500);
		}break;
	case GS_STARTMOVE:
		{
			//set the moved flag to true
			bMovedUnit=true;
			//remove the unit from the map location
			mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.remove(pCurrentUnit);
			Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y);
			//set next gamestate
			iGameState=GS_DOMOVE;
		}break;
	case GS_DOMOVE:
		{
			//move the unit
			pCurrentUnit->ptPosition=TileWalker.TileWalk(pCurrentUnit->ptPosition,idMoveUnit);
			//set next gamestate
			iGameState=GS_ENDMOVE;
		}break;
	case GS_ENDMOVE:
		{
			//place the unit on its new map location
			mlMap[pCurrentUnit->ptPosition.x][pCurrentUnit->ptPosition.y].ulUnitList.push_front(pCurrentUnit);
			Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y);
			//subtract a movement point
			pCurrentUnit->iMovePoints--;
			//check to see if this unit is finished moving
			if(pCurrentUnit->iMovePoints==0)
			{
				//done moving
				pCurrentUnit=NULL;
				//set next gamestate
				iGameState=GS_NEXTUNIT;
			}
			else
			{
				//not done moving
				iGameState=GS_IDLE;
			}
			bFlash=true;
			DWORD dwTimeStart=GetTickCount();//get the frame start time
			//scroll the frame (0,0)
			Renderer.ScrollFrame(0,0);
			//update the frame
			Renderer.UpdateFrame();
			//flip to show the back buffer
			lpddsMain->Flip(0,DDFLIP_WAIT);
			//wait until 500 ms have passed
			while(GetTickCount()-dwTimeStart<500);
		}break;
	case GS_IDLE://the game is idling, update the frame, but thats about it.
		{
			DWORD dwTimeStart=GetTickCount();//get the frame start time
			//scroll the frame (0,0)
			Renderer.ScrollFrame(0,0);

			//toggle unit flash
			bFlash=!bFlash;

			//if the current unit is not null
			if(pCurrentUnit!=NULL)
			{
				//add the tile in which the current unit lives
				Renderer.AddTile(pCurrentUnit->ptPosition.x,pCurrentUnit->ptPosition.y);
			}

			//update the frame
			Renderer.UpdateFrame();

			//if the current unit IS null
			if(pCurrentUnit==NULL)
			{
				//show the end of turn marker if bflash is true
				if(bFlash) tsPressEnter.PutTile(lpddsBack,0,0,iCurrentTeam);
			}

			//redo the minimap
			UpdateMiniMap();
			RedrawMiniMap();
			ShowMiniMap();

			//flip to show the back buffer
			lpddsMain->Flip(0,DDFLIP_WAIT);
			//wait until 200 ms have passed
			while(GetTickCount()-dwTimeStart<200);
		}break;
	case GS_CLICKSELECT:
		{
			//check map location for emptiness
			if(mlMap[ptClick.x][ptClick.y].ulUnitList.empty())
			{
				//map location is empty
				iGameState=GS_CLICKCENTER;//we want to center on this map location
			}
			else
			{
				//map location is not empty
				//look at top of list
				UNITLISTITER iter=mlMap[ptClick.x][ptClick.y].ulUnitList.begin();
				PUNITINFO pUnitInfo=*iter;
				//check that if this unit belongs to the current team
				if(pUnitInfo->iTeam==iCurrentTeam)
				{
					//belongs to current team
					//one unit?
					if(mlMap[ptClick.x][ptClick.y].ulUnitList.size()==1)
					{
						//a single unit(already contained in pUnitInfo)
						//is this the current unit?
						if(pUnitInfo==pCurrentUnit)
						{
							//this is the current unit
							iGameState=GS_IDLE;//return to the neutral gamestate
						}
						else
						{
							//this is not the current unit
							//does this unit have any movement points left?
							if(pUnitInfo->iMovePoints>0)
							{
								//has movement points left
								//push the current unit to front of team list
								if(pCurrentUnit) TeamUnitList.push_front(pCurrentUnit);
								pCurrentUnit=NULL;
								//set holding to false for the new unit
								pUnitInfo->bHolding=false;
								//remove new unit from team list
								TeamUnitList.remove(pUnitInfo);
								//put new unit in front of team list
								TeamUnitList.push_front(pUnitInfo);
								//go to gs_nextunit
								iGameState=GS_NEXTUNIT;
							}
							else
							{
								//does not have movement points left
								//go back to gs_idle
								iGameState=GS_IDLE;
							}
						}
					}
					else
					{
						//place the current unit at the front of the list
						if(pCurrentUnit) TeamUnitList.push_front(pCurrentUnit);
						//a stack of units
						iGameState=GS_CLICKSTACK;
					}
				}
				else
				{
					//does not belong to current team
					iGameState=GS_CLICKCENTER;//we want to center on this map location
				}
			}
		}break;
	case GS_CLICKCENTER:
		{
			//center on clicked tile
			POINT ptPlot=TilePlotter.PlotTile(ptClick);//plot tile
			ptPlot.x-=(Scroller.GetScreenSpaceWidth()/2);//adjust by half screenspace
			ptPlot.y-=(Scroller.GetScreenSpaceHeight()/2);
			Scroller.SetAnchor(&ptPlot);//set anchor
			Renderer.AddRect(Scroller.GetScreenSpace());
			//return to GS_IDLE
			iGameState=GS_IDLE;
		}break;
	case GS_CLICKSTACK:
		{
			//prepare the stack
			int count;
			for(count=0;count<20;count++)//clear out the list
				SelectUnitList[count]=NULL;
			//reset count to 0
			count=0;
			//iterate through the list of units at the current map location
			UNITLISTITER iter;//iterator
			PUNITINFO pUnitInfo;//unit info
			for(iter=mlMap[ptClick.x][ptClick.y].ulUnitList.begin();count<20 && iter!=mlMap[ptClick.x][ptClick.y].ulUnitList.end();iter++)//iterate through list
			{
				pUnitInfo=*iter;//grab the unit
				//place unit in list
				SelectUnitList[count]=pUnitInfo;
				//add 1 to count
				count++;
			}
			//send to next gamestate
			iGameState=GS_PICKUNIT;
		}break;
	case GS_PICKUNIT:
		{
			//no scrolling
			Renderer.ScrollFrame(0,0);
			//update frame
			Renderer.UpdateFrame();
			//place select window onto display
			DDBLTFX ddbltfx;
			DDBLTFX_Clear(&ddbltfx);
			ddbltfx.dwFillColor=dwSelectWindowColor;
			lpddsBack->Blt(&rcSelectWindow,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&ddbltfx);
			//show the units
			int cellx,celly;//cell position
			int cellnum;//number of the cell
			int pixelx,pixely;//pixel position
			for(celly=0;celly<4;celly++)
			{
				for(cellx=0;cellx<5;cellx++)
				{
					cellnum=cellx+celly*5;//calculate the cell number
					//check that the unit exists
					if(SelectUnitList[cellnum])
					{
						//calculate pixel position
						pixelx=rcSelectWindow.left+ptCellSize.x*cellx;
						pixely=rcSelectWindow.top+ptCellSize.y*celly;
						//plot the units position
						pixelx+=ptUnitOffset.x;
						pixely+=ptUnitOffset.y;
						//put the unit
						tsUnit.PutTile(lpddsBack,pixelx,pixely,SelectUnitList[cellnum]->iType);
						//move the pixel to place shielf
						pixelx+=ptShieldOffset[SelectUnitList[cellnum]->iType].x;
						pixely+=ptShieldOffset[SelectUnitList[cellnum]->iType].y;
						//place appropriate shield
						if(SelectUnitList[cellnum]->bHolding)
						{
							//unit is holding
							tsShield.PutTile(lpddsBack,pixelx,pixely,iCurrentTeam*2+4);
						}
						else
						{
							//unit is not holding
							if(SelectUnitList[cellnum]->iMovePoints)
							{
								//unit has movement points left
								tsShield.PutTile(lpddsBack,pixelx,pixely,iCurrentTeam*2);
							}
							else
							{
								//unit does not have movememtn points left
								tsShield.PutTile(lpddsBack,pixelx,pixely,iCurrentTeam*2+8);
							}
						}
					}
				}
			}
			//flip
			lpddsMain->Flip(0,DDFLIP_WAIT);
		}break;
	}
}

void RenderFunc(LPDIRECTDRAWSURFACE7 lpddsDst,RECT* rcClip,int xDst,int yDst,int xMap,int yMap)
{
	//put background tile
	tsBack.ClipTile(lpddsDst,rcClip,xDst,yDst,0);
	//check for an empty list
	if(!mlMap[xMap][yMap].ulUnitList.empty())
	{
		//list is not empty
		UNITLISTITER iter=mlMap[xMap][yMap].ulUnitList.begin();//get iterator to beginning of list
		PUNITINFO pUnitInfo=*iter;//grab the item
		//if this is the current unit
		if(pUnitInfo==pCurrentUnit)
		{
			//this is the current unit
			if(!bFlash) return;//if flash is "off" dont render
		}
		tsUnit.ClipTile(lpddsDst,rcClip,xDst,yDst,pUnitInfo->iType);//place the unit
		iter++;//move to the next item in the list
		if(iter==mlMap[xMap][yMap].ulUnitList.end())//if the end of the list, this is a single unit
		{
			if(pUnitInfo->bHolding)//if holding position
			{//holding
				tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2+4);//place the shield
			}
			else
			{//not holding
				tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2);//place the shield
			}
		}
		else//more than one unit... this is a stack
		{
			if(pUnitInfo->bHolding)//if holding position
			{//holding
				tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2+5);//place the shield
			}
			else
			{//not holding
				tsShield.ClipTile(lpddsDst,rcClip,xDst+ptShieldOffset[pUnitInfo->iType].x,yDst+ptShieldOffset[pUnitInfo->iType].y,pUnitInfo->iTeam*2+1);//place the shield
			}
		}
	}
}

void SetupMiniMap()//does initial setup of the minimap
{
	//create the surface
	lpddsMiniMap=LPDDS_CreateOffscreen(lpdd,160,80);
	//load in the tileset
	tsMiniMap.Load(lpdd,"minimapts.bmp");
	//initialize the minimap arrays
	MiniMap=new int[MAPWIDTH*MAPHEIGHT];
	for(int count=0;count<MAPWIDTH*MAPHEIGHT;count++)
	{
		MiniMap[count]=0;
	}
	//initialize iso components
	//tile plotter
	MiniTilePlotter.SetMapType(ISOMAP_DIAMOND);
	MiniTilePlotter.SetTileSize(4,2);
	//scroller
	//calc worldspace
	MiniScroller.CalcWorldSpace(&MiniTilePlotter,&tsMiniMap.GetTileList()[0].rcDstExt,MAPWIDTH,MAPHEIGHT);
	//set screen-space
	RECT rcMiniScreenSpace;
	SetRect(&rcMiniScreenSpace,0,0,160,80);
	MiniScroller.SetScreenSpace(&rcMiniScreenSpace);
	//set the anchor
	POINT ptAnchor;
	ptAnchor.x=MiniScroller.GetWorldSpace()->left;
	ptAnchor.y=MiniScroller.GetWorldSpace()->top;
	MiniScroller.SetAnchor(&ptAnchor);

}

void UpdateMiniMap()//updates the minimap array
{
	//upate the minimap array to reflect game status
	for(int y=0;y<MAPHEIGHT;y++)//loop through rows
	{
		for(int x=0;x<MAPWIDTH;x++)//loop through columns
		{
			MiniMap[y*MAPWIDTH+x]=0;
			//if empty, place a zero
			if(mlMap[x][y].ulUnitList.empty())
			{
				MiniMap[y*MAPWIDTH+x]=0;
			}
			else
			{
				//occupied by a player
				UNITLISTITER iter=mlMap[x][y].ulUnitList.begin();
				PUNITINFO pUnitInfo=*iter;
				if(pUnitInfo!=pCurrentUnit || bFlash) MiniMap[y*MAPWIDTH+x]=1+pUnitInfo->iTeam;//put team info into minimap array
			}
		}
	}
}

void RedrawMiniMap()//redraws the minimap to reflect current gamestate
{
	//redraw the entire minimap
	//in real code, you can keep two arrays
	//one valid this frame and one valid last frame
	//and then only blit the changes from last frame to this one
	//thus reducing the number of blits
	//clear out the minimap surface
	DDBLTFX ddbltfx;
	DDBLTFX_ColorFill(&ddbltfx,0);
	lpddsMiniMap->Blt(NULL,NULL,NULL,DDBLT_WAIT | DDBLT_COLORFILL,&ddbltfx);
	POINT ptPlot;//plotting point
	for(int y=0;y<MAPHEIGHT;y++)//loop through rows
	{
		for(int x=0;x<MAPWIDTH;x++)//loop through columns
		{
			//put the mini-tile
			ptPlot.x=x;
			ptPlot.y=y;
			//plot map position
			ptPlot=MiniTilePlotter.PlotTile(ptPlot);
			//convert to screen coords
			ptPlot=MiniScroller.WorldToScreen(ptPlot);
			tsMiniMap.PutTile(lpddsMiniMap,ptPlot.x,ptPlot.y,MiniMap[y*MAPWIDTH+x]);
		}
	}
	//show a rectangle around viewable area on minimap
	HDC hdc;
	lpddsMiniMap->GetDC(&hdc);//borrow the dc from the minimap surface

	//get the anchor point from the main scroller
	POINT ptAnchor;
	ptAnchor.x=Scroller.GetAnchor()->x;
	ptAnchor.y=Scroller.GetAnchor()->y;

	//scale down by a factor of 16(to go from a 64x32 tile to 4x2)
	ptAnchor.x/=16;
	ptAnchor.y/=16;

	//subtract the mini-scroller's upper left
	ptAnchor.x-=MiniScroller.GetWorldSpace()->left;
	ptAnchor.y-=MiniScroller.GetWorldSpace()->top;

	//move to position in minimap
	MoveToEx(hdc,ptAnchor.x,ptAnchor.y,NULL);
	//draw box, one line at a time
	LineTo(hdc,ptAnchor.x+30,ptAnchor.y);//30 is 480/16
	LineTo(hdc,ptAnchor.x+30,ptAnchor.y+30);
	LineTo(hdc,ptAnchor.x,ptAnchor.y+30);
	LineTo(hdc,ptAnchor.x,ptAnchor.y);

	lpddsMiniMap->ReleaseDC(hdc);//restore the dc to the minimap
}

void ShowMiniMap()//shows the minimap on-screen
{
	RECT rcSrc;//src blitting rect
	RECT rcDst;//destination blitting rect
	//set src rect
	SetRect(&rcSrc,0,0,160,80);
	//set dest rect
	CopyRect(&rcDst,&rcSrc);
	OffsetRect(&rcDst,480,0);
	//do the blit
	lpddsBack->Blt(&rcDst,lpddsMiniMap,&rcSrc,DDBLT_WAIT,NULL);
}

void DestroyMiniMap()//cleans up the minimap
{
	//delete minimap array
	delete[] MiniMap;
	//destroy minimap surface
	if(lpddsMiniMap)
	{
		lpddsMiniMap->Release();
		lpddsMiniMap=NULL;
	}
	//destroy minimap tileset
	tsMiniMap.Unload();
}

⌨️ 快捷键说明

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