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

📄 playzone.cpp

📁 一款战旗类的打飞机游戏源码
💻 CPP
字号:
/*
Copyright (c)  2005  william.
      Permission is granted to copy, distribute and/or modify this document
      under the terms of the GNU Free Documentation License, Version 1.2
      or any later version published by the Free Software Foundation;
      with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
	 Texts.  A copy of the license is included in the section entitled "GNU
      Free Documentation License".
*/
#include "stdafx.h"
#include "resource.h"

const CTagPos TagPosZero;
const COLORREF BLACK	=  RGB(0,0,0);
const COLORREF BLUE	=  RGB(136,174,255);
const CPen BlackPen(PS_SOLID,1,BLACK);
const CPen BluePen(PS_SOLID,1,BLUE);

//using for detect which direction a tail can put.
const UINT Cell_dir_x[14]={0,4,4,4,14,15,15,15,15,15,11,1,1,1};
const UINT Cell_dir_y[14]={0,2,2,2,7,15,15,15,15,15,13,8,8,8};
inline UINT GetCellPlaneDirect(UINT cell_x,UINT cell_y){
  return Cell_dir_x[cell_x] & Cell_dir_y[cell_y];
}

bool APlane::IsPlane(CTagPos pos) const
{
	CRect rect;
	GetPlaneRect(rect);
	CPoint pt(pos.x,pos.y);
	if(rect.PtInRect(pt))
	{
		CTagPos planePos;
		for(int i=1;i<14;++i)
		{
			GetNumPos(i,planePos);
			if(planePos == pos)return true;
		}

	}
	return false;
}

//if a plane across the other?
//at least One is no a GuessPlane
//GuessPlane & GuessPlane no need to test.
bool operator &(const APlane& plane1,const APlane& plane2)
{
	CTagPos pos1;
	CTagPos pos2;
	int Dir_x1 = Dir_x[D2N[plane1.Dir]];
	int Dir_y1 = Dir_y[D2N[plane1.Dir]];
	int Dir_x2 = Dir_x[D2N[plane2.Dir]];
	int Dir_y2 = Dir_y[D2N[plane2.Dir]];

	for(int i=1;i<14;++i)
	{

		int offset_r = HeadOffset[Dir_x1][i];
		int offset_b = HeadOffset[Dir_y1][i];
		pos1.x = plane1.Head.x + offset_r;
		pos1.y = plane1.Head.y + offset_b;

		for(int j=1;j<14;++j)
		{
         int offset_r = HeadOffset[Dir_x2][j];
         int offset_b = HeadOffset[Dir_y2][j];
         pos2.x = plane2.Head.x + offset_r;
         pos2.y = plane2.Head.y + offset_b;

         if(pos1 == pos2) return true;
		}
	}
	return false;
   
}


////////////////////////////////////////////////////////////////
//
//	CPlanes
//
//
//
void CPlanes::GetPlane(const CTagPos& pos,APlane& plane) const
{
	APlane pl;
	for(UINT i =1;i<=GetNum();++i)
	{
		GetPlane(i,pl);
		if(pl.IsPlane(pos))
		{
			plane.Head = pl.Head;
			plane.Dir = pl.Dir;
			return;
		}
	}
	plane.Head = CTagPos(0,0);
	plane.Dir = pdNO;
}

UINT CPlanes::AddPlane(const CTagPos& head,PlaneDirect dir)
{
	if(planes.GetCount()==(int)Max)return Max;
	//add it
	APlane plane(head,dir);
	//set the grid
	CTagPos posTure;
	for(int i=1;i<14;++i)
	{
		plane.GetNumPos(i,posTure);
		Grid4Plane[posTure.x][posTure.y] = true;
	}
   return (UINT)planes.Add(plane);
}

void CPlanes::RemovePlane(int num)
{
	ASSERT(num>0 && num<=(int)GetMaxNum());
	APlane plane;
	GetPlane(num,plane);
	//del it.
	planes.RemoveAt(num-1);

#ifdef _DEBUG
	//affirm no other same-head plane
	APlane pl;
	for(UINT i=1;i<GetNum();++i)
	{
		GetPlane(i,pl);
		ASSERT(pl.Head != plane.Head);
	}
#endif

	//clear the grid.
	CTagPos posTure;
	for(int i=1;i<14;++i)
	{
		plane.GetNumPos(i,posTure);
		Grid4Plane[posTure.x][posTure.y] = false;
	}

}

bool CPlanes::NoAnotherPlane(const CTagPos& pos) const
{
	bool retval = !Grid4Plane[pos.x][pos.y];

#ifdef _DEBUG
	//affirm
	bool val=true;
	APlane planeSetted;
	for(UINT i=1;i<=GetNum();++i)
	{
		GetPlane(i,planeSetted);
		if(planeSetted.IsPlane(pos)){
			val =  false;goto END;}
	}
END:
	ASSERT(val == retval);
#endif

	return retval;
}

bool CPlanes::NoAnotherPlane(const APlane& plane) const
{
	bool retval = true;
	CTagPos pos;
	//test every planes-cells(13)
	for(int i=1;i<14;++i)
	{
		plane.GetNumPos(i,pos);
		if(Grid4Plane[pos.x][pos.y]){
			retval = false;break;
		}
	}

#ifdef _DEBUG
	//affirm
	bool val =true;
	APlane planeSetted;
	for(UINT i=1;i<=GetNum();++i)
	{
		GetPlane(i,planeSetted);
		if(plane & planeSetted){
			val = false;goto END;}
	}
END:
	ASSERT(val == retval);
#endif
	return retval;
}



/////////////////////////////////////////////////////////
//
// 
//
//
//

IMPLEMENT_DYNAMIC(CPlayZone, CStatic)
BEGIN_MESSAGE_MAP(CPlayZone, CStatic)
	ON_WM_PAINT()
   ON_WM_ERASEBKGND()
END_MESSAGE_MAP()


HICON CPlayZone::HeadTag = 0;
HICON CPlayZone::BodyTag = 0;
HICON CPlayZone::GuessTag = 0;
HICON CPlayZone::NoneTag = 0;
CDC* CPlayZone::PlaneDC=0;
CSize* CPlayZone::PlaneSize=0;
HICON CPlayZone::TailTagHEAD = 0;
HICON CPlayZone::TailTagTAIL = 0;
CDC* CPlayZone::BackgroundDC = 0;
CSize* CPlayZone::BackgroundSize = 0;

void CPlayZone::OnInit()
{
	CRect rect;
	GetClientRect(&rect);
	Height = rect.bottom - rect.top;
	cell = Height/MaxCell;
	Height = MaxCell*cell;
	ClientRect.top = rect.top;
	ClientRect.left = rect.left;
	ClientRect.right  = rect.left+Height;
	ClientRect.bottom  = rect.top+Height;

	TargetSet.InitHashTable(MaxCell);


	CClientDC dc(this);

	CBitmap mem;
	mem.CreateCompatibleBitmap(&dc,ClientRect.Width(),ClientRect.Height());
	MemDC.CreateCompatibleDC(&dc);
	MemDC.SelectObject(mem);


	if(HeadTag==0){
		HeadTag = AfxGetApp()->LoadIcon(IDI_HEAD);
		BodyTag = AfxGetApp()->LoadIcon(IDI_BODY);
		GuessTag = AfxGetApp()->LoadIcon(IDI_GUESS);
      NoneTag = AfxGetApp()->LoadIcon(IDI_NONE);
	}

	//load put-test-tag
	if(TailTagHEAD==0){
		TailTagHEAD = AfxGetApp()->LoadIcon(IDI_TAIL);
		TailTagTAIL = AfxGetApp()->LoadIcon(IDI_TAILS);
	}


	if(PlaneDC != 0) return;
	PlaneDC = new CDC[4];
	PlaneSize = new CSize[4];

	CBitmap Plane[4];
	Plane[D2N[pdLEFT]].LoadBitmap(IDB_PLANE_LEFT);
	Plane[D2N[pdDOWN]].LoadBitmap(IDB_PLANE_DOWN);
	Plane[D2N[pdRIGHT]].LoadBitmap(IDB_PLANE_RIGHT);
	Plane[D2N[pdUP]].LoadBitmap(IDB_PLANE_UP);

	BITMAP bt;

	for(int i=0;i<4;++i)
	{
		Plane[i].GetBitmap(&bt);
		PlaneSize[i].cx = bt.bmWidth;
		PlaneSize[i].cy = bt.bmHeight;
		PlaneDC[i].CreateCompatibleDC(&dc);
		PlaneDC[i].SelectObject(&Plane[i]);
	}


   BackgroundDC = new CDC[2];
   BackgroundSize = new CSize[2];

	CBitmap bkgnd[2];
	bkgnd[0].LoadBitmap(IDB_BKGND_LIGHT);
	bkgnd[1].LoadBitmap(IDB_BKGND_DARK);
	for(int i=0;i<2;++i)
	{
		bkgnd[i].GetBitmap(&bt);
		BackgroundSize[i].cx = bt.bmWidth;
		BackgroundSize[i].cy = bt.bmHeight;
		BackgroundDC[i].CreateCompatibleDC(&dc);
		BackgroundDC[i].SelectObject(&bkgnd[i]);
	}

	//Test:
	//TargetSet[CTagPos(7,7)] = tagHEAD; 
	//TargetSet[CTagPos(6,6)] = tagBODY; 
	//TargetSet[CTagPos(6,8)] = tagNONE; 

}

bool CPlayZone::SetGuessPlane(const CTagPos& head,PlaneDirect dir)
{
	if(dir == pdNO) return false;
   int allDir = GetCellPlaneDirect(head.x,head.y);
	APlane plan;
	plan.Head = head;
	if(dir & allDir){
		plan.Dir = dir;
		if(Planes.NoAnotherPlane(plan))
		{
			Planes.AddPlane(plan);
			return true;
		}
	}
	return false;
}

//used for tell player where can put a plane 
//and where can't, need the player to set a head point,
bool CPlayZone::SetFourGuessPlaneTail(const CTagPos& head)
{
	int dir = GetCellPlaneDirect(head.x,head.y);
	if(dir == pdNO) return false;

	SetHeadPos = CTagPos(head.x,head.y);

	APlane plan;
	plan.Head = head;
	CTagPos TailPos;
	bool retval = false;
	for(int i=0;i<4;++i)
	{
		if(dir & N2D[i]){
			plan.Dir = N2D[i];
			if(Planes.NoAnotherPlane(plan))
			{
				plan.GetPlaneTailPos(TailPos);
				ShowTailTag[i] = TailPos;
				retval = true;
			}
		}
	}
	return retval;
}

void CPlayZone::DrawBkGroud()
{
	if(IsActive){
		MemDC.StretchBlt(ClientRect.left,ClientRect.top,
			ClientRect.Width(),ClientRect.Height(),&BackgroundDC[0],
			0,0,BackgroundSize[0].cx,BackgroundSize[0].cy,SRCCOPY);
	}else{
		MemDC.StretchBlt(ClientRect.left,ClientRect.top,
			ClientRect.Width(),ClientRect.Height(),&BackgroundDC[1],
			0,0,BackgroundSize[1].cx,BackgroundSize[1].cy,SRCCOPY);
	}
}

void CPlayZone::DrawMainGrid()
{
	if(!IsActive){
		MemDC.SelectObject(BluePen);
	}
	int step = 0;
	for(UINT i = 1;i<MaxCell;i+=2)
	{
		step += cell;
		MemDC.MoveTo(0,step);
		MemDC.LineTo(Height,step);
		MemDC.MoveTo(step,0);
		MemDC.LineTo(step,Height);
		step += cell;
		MemDC.MoveTo(0,step);
		MemDC.LineTo(Height,step);
		MemDC.MoveTo(step,0);
		MemDC.LineTo(step,Height);
	}
	if(!IsActive){
		MemDC.SelectObject(BlackPen);
	}

}

void CPlayZone::DrawPosiblePos()
{
	for(int i=0;i<4;++i)
	{
		if(ShowTailTag[i] != TagPosZero)
		{
			LONG x = ShowTailTag[i].x;
			LONG y = ShowTailTag[i].y;
			CellToUnit(x,y);
			DrawIconEx(MemDC.GetSafeHdc(),x,y,TailTagTAIL,cell,cell,0,0,DI_NORMAL);
		}
	}
	if(SetHeadPos!= TagPosZero)
	{
		LONG x = SetHeadPos.x;
		LONG y = SetHeadPos.y;
		CellToUnit(x,y);
		DrawIconEx(MemDC.GetSafeHdc(),x,y,TailTagHEAD,cell,cell,0,0,DI_NORMAL);
	}
}

void CPlayZone::DrawPlane()
{
	//put palnes under flag;
	APlane plane;
	for(UINT i =1;i<=Planes.GetNum();++i)
	{
		Planes.GetPlane(i,plane);
		CRect rect;
		plane.GetPlaneRect(rect);
		CellToUnit(rect);
		CDC* source = &PlaneDC[D2N[plane.Dir]];
		int PlaneWidth = PlaneSize[D2N[plane.Dir]].cx;
		int PlaneHeight = PlaneSize[D2N[plane.Dir]].cy;
		MemDC.TransparentBlt(rect.left,rect.top,rect.Width()+1,rect.Height()+1,source,0,0,PlaneWidth,PlaneHeight,RGB(255,0,255));
	}
}

void CPlayZone::DoDrawFlag(const CTagPos& pos,_tag flag) const
{
	LONG ix = pos.x,iy = pos.y;
	CellToUnit(ix,iy);
	HICON TheTag = 0;
	switch(flag)
	{
	case tagBODY:
		TheTag = BodyTag;
		break;
	case tagHEAD:
		TheTag = HeadTag;
		break;
	case tagTEST:
		TheTag = GuessTag;
		break;
	case tagNONE:
		TheTag = NoneTag;
		break;
	}
	ASSERT(TheTag!=0);
	DrawIconEx(MemDC.GetSafeHdc(),ix,iy,TheTag,cell,cell,0,0,DI_NORMAL);
	DUMP2(L"Draw flag",pos.x,pos.y);
}


void CPlayZone::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	DrawBkGroud();
	DrawPlane();
	DrawFlag();
	DrawPosiblePos();
	DrawMainGrid();
   
	dc.BitBlt(0,0,ClientRect.Width(),ClientRect.Height(),&MemDC,0,0,SRCCOPY);
}

PlaneDirect GetPlaneDir(const CTagPos& base,const CTagPos& offset)
{
	if(offset.x > base.x && offset.y == base.y)return pdRIGHT;
	if(offset.x < base.x && offset.y == base.y)return pdLEFT;
	if(offset.x == base.x && offset.y > base.y)return pdDOWN;
	if(offset.x == base.x && offset.y < base.y)return pdUP;
	return pdNO;
}

MBU CPlayZone::On1stMButtonUp(const CTagPos& HitPos)
{
	//if clicked on a plane,del it
	if(!Planes.NoAnotherPlane(HitPos))
	{
		UINT n = Planes.IsBody(HitPos);
		ASSERT(n>0 && n<=Planes.GetMaxNum());
		Planes.RemovePlane(n);
		InvalidateRect(0,false);
		return mbDEL;
	}

	//plane is use-out
	if(Planes.GetMaxNum() == Planes.GetNum()){
		return mbMax;
	}

	SetHeadPos = HitPos;
	if(SetFourGuessPlaneTail(HitPos)){
		//put a 1-4 tag means the tail pos
		InvalidateRect(0,false);
		return mbSEL;
	}else{
		//cannot set a plan here
		SetHeadPos = TagPosZero;
		return mbCANT;
	}

}

MBU CPlayZone::On2ndMButtonUp(const CTagPos& HitPos){
	MBU retval=mbCANCEL;
	if(Planes.NoAnotherPlane(HitPos)){
		PlaneDirect dir = GetPlaneDir(SetHeadPos,HitPos);
		if(dir != pdNO){
			SetGuessPlane(SetHeadPos,dir);
			if(Planes.GetMaxNum() == Planes.GetNum()){
				//reach the max num
				retval =mbOKMAX;
			}else{
				retval = mbNEXT;}
		}
	}
	ShowTailTag[0] = ShowTailTag[1] = ShowTailTag[2] = ShowTailTag[3] = TagPosZero;
	SetHeadPos = TagPosZero;
	InvalidateRect(0,false);
	
	return retval;
}

MBU CPlayZone::OnMButtonUp(CPoint point)
{
	if(!IsStart)return mbNONE;
	if(!GuessZone && !IsActive)return mbNONE;

	CTagPos HitPos(point.x,point.y);
	UnitToCell(HitPos);

	//please click the head wanted
	if(SetHeadPos == TagPosZero){
      return On1stMButtonUp(HitPos);
	//click the tail wanted
	}else{
		return On2ndMButtonUp(HitPos);
	}
}

void CPlayZone::OnGuessRButtonUp(CPoint point)
{
	if(!IsStart)return;
	//if(!GuessZone)return;
	ASSERT(GuessZone);
	//on other operator now.
	if(SetHeadPos != TagPosZero)return;

	CTagPos pos(point.x,point.y);
	UnitToCell(pos);
	_tag tagHere  = GetFlag(pos);
	UINT IDS_id = IDS_GU_NONE_FLAG;

	switch(tagHere)
	{
	case tagBLACK:
		SetFlag(pos,tagTEST);
		IDS_id=IDS_GU_TEST_FLAG;
		break;
	case tagBODY:
		//SetFlag(pos,tagHEAD);
		IDS_id=IDS_GU_HEAD_FLAG;
		break;
	case tagHEAD:
		//SetFlag(pos,tagBODY);
		IDS_id=IDS_GU_BODY_FLAG;
		break;
	case tagTEST:
		//SetFlag(pos,tagHEAD);
		TargetSet.RemoveKey(pos);
		IDS_id=IDS_GU_BLACK_FLAG;
		break;
	}
	SetGuide(IDS_id);
	InvalidateRect(0,false);
}


bool CPlayZone::OnGuessLButtonUp(CPoint point,int& cell_x,int& cell_y)
{
	if(!IsStart)return false;
	if(!IsActive)return false;

	if(SetHeadPos != TagPosZero){
      ShowTailTag[0] = ShowTailTag[1] = ShowTailTag[2] = ShowTailTag[3] = TagPosZero;
      SetHeadPos = TagPosZero;
	}

	//if(!GuessZone)return;
	ASSERT(GuessZone);

	CTagPos pos(point.x,point.y);
	UnitToCell(pos);

	_tag Tag;

	//clicked on a Tag?
	if(TargetSet.Lookup(pos,Tag))
	{
		if(Tag == tagBODY || Tag == tagHEAD){
			SetGuide(IDS_GU_AFFIRM);
			cell_x=cell_x=0;
			return false;
		}
		if(Tag == tagNONE){
			SetGuide(IDS_GU_AFFIRM_NO);
			cell_x=cell_x=0;
			return false;
		}
	}

	cell_x= pos.x; cell_y = pos.y;
	SetGuide(IDS_GU_SEND);
	return true;
	//CStatic::OnLButtonUp(nFlags, point);
}

_tag CPlayZone::IsBombed(int x,int y) const
{
#ifdef _DEBUG
	ASSERT_CELL_RANGE(x,y);
#endif
	CTagPos pos(x,y);
	int planeNum = Planes.IsBody(pos);
	if(planeNum !=0 )
		if(Planes.IsHead(planeNum,pos))
			return tagHEAD;
		else
			return tagBODY;
	else
		return tagNONE;

}

void CPlayZone::CellToUnit(LONG& x,LONG& y) const
{
	LONG min = 1;
	LONG max = MaxCell+1;
	if(x<min)x=min;
	if(y<min)y=min;
	if(x>max)x=max;
	if(y>max)y=max;
	x = (x-1)*cell;
	y = (y-1)*cell;

#ifdef _DEBUG
	ASSERT_UNIT_RANGE(x,y);
#endif
}

void CPlayZone::UnitToCell(LONG& x,LONG& y) const
{
	LONG min = 0;
	LONG max = Height;
   if(x<min)x=min;
	if(y<min)y=min;
	if(x>max)x=max;
	if(y>max)y=max;
	x = x/cell+1;
	y = y/cell+1;

#ifdef _DEBUG
	ASSERT_CELL_RANGE(x,y);
#endif
}

void CPlayZone::SetActive(bool act)
{
	if(IsActive != act)
	{
      IsActive = act;
      InvalidateRect(0,false);
	}
}

⌨️ 快捷键说明

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