📄 isohex19_2.cpp
字号:
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 + -