#include "UnitSnake.h"//---------------------------------------------------------------------------TSnakeBuf::TWall TSnakeBuf::Wall0[]={{-1}};TSnakeBuf::TWall TSnakeBuf::Wall1[]={{5,10,23,10},{-1}};TSnakeBuf::TWall TSnakeBuf::Wall2[]={{10,5,10,16},{18,5,18,16},{-1}};TSnakeBuf::TWall TSnakeBuf::Wall3[]={{10,5,10,16},{18,5,18,16},{ 5,10,23,10},{-1}};TSnakeBuf::TWall TSnakeBuf::Wall4[]={{ 5,6,23, 6},{5,14,23,14},{-1}};TSnakeBuf::TWall TSnakeBuf::Wall5[]={{ 5,6,23, 6},{5,14,23,14},{14, 7,14,13},{-1}};TSnakeBuf::TWall TSnakeBuf::Wall6[]={{10,0,10,16},{18,5,18,20},{-1}};TSnakeBuf::TWall TSnakeBuf::Wall7[]={{ 0,6,23, 6},{5,14,27,14},{-1}};TSnakeBuf::TWall TSnakeBuf::Wall8[]={{ 6,5, 6,20},{20,5,20,20},{13, 0,13,16},{-1}};TSnakeBuf::TWall TSnakeBuf::Wall9[]={{ 0,6,15, 6},{21,0,21, 9},{12,14,27,14},{6,12,6,20},{-1}};TSnakeBuf::TWall *TSnakeBuf::Walls[]={TSnakeBuf::Wall0,TSnakeBuf::Wall1,TSnakeBuf::Wall2,TSnakeBuf::Wall3,TSnakeBuf::Wall4,TSnakeBuf::Wall5,TSnakeBuf::Wall6,TSnakeBuf::Wall7,TSnakeBuf::Wall8,TSnakeBuf::Wall9};//---------------------------------------------------------------------------TSnakeBuf::TBmpPos TSnakeBuf::BmpPos[] ={ // Wall Bean Super Head Horz Vert CrnUL CrnUR CrnDL CrnDR TailU TailD TailL TailR Stage {{{4,1},{4,2},{5,2},{5,1},{4,0},{5,0},{0,1},{1,1},{0,2},{1,2},{3,1},{2,2},{2,1},{3,2},{5,2}}}, {{{0,0},{1,0},{3,0},{2,0},{2,0},{2,0},{2,0},{2,0},{2,0},{2,0},{2,0},{2,0},{2,0},{2,0},{3,0}}},};//---------------------------------------------------------------------------TSnakeBuf::TSnakeBuf(){ _Snake = 0; _iBeanNo = 0; _iStageBeans = 200; _iScore = 0; _bGameOver = false; _bEndStage = false; memset(_Units,0,sizeof(_Units)); memset(_DispBuf,0,sizeof(_DispBuf));}//---------------------------------------------------------------------------TSnakeBuf::~TSnakeBuf(){ ClearSnake();}//---------------------------------------------------------------------------void TSnakeBuf::ClearSnake(void){ if(_Snake) { TSnakeNode *toDel; _Snake->Prev->Next=0; while(_Snake) { toDel=_Snake; _Snake=_Snake->Next; delete toDel; } _Snake=0; }}//---------------------------------------------------------------------------void TSnakeBuf::InitSnake(void){ ClearSnake(); _Snake = new TSnakeNode; TSnakeNode *nd = new TSnakeNode; _Snake->x = UnitX/2; _Snake->y = UnitY-2; _Snake->Next = nd; _Snake->Prev = nd; nd->x = UnitX/2; nd->y = UnitY-1; nd->Next = _Snake; nd->Prev = _Snake;}//---------------------------------------------------------------------------void TSnakeBuf::StepMove(int d){ if((_Snake)&&(d)&&(!_bGameOver)&&(!_bEndStage)) { TSnakeNode NewPos = *_Snake; switch(d) { case sdUp : NewPos.y--; break; //up case sdDown : NewPos.y++; break; //down case sdLeft : NewPos.x--; break; //left case sdRight: NewPos.x++; break; //right default : return; //do nothing } if((NewPos.x<0)||(NewPos.y<0)||(NewPos.x>=UnitX)||(NewPos.y>=UnitY)) { _bGameOver = true; return; } if(GetDispBuf(NewPos.x,NewPos.y)==sbnWall) { _bGameOver = true; return; } if((GetDispBuf(NewPos.x,NewPos.y)>=sbnHead)&&(GetDispBuf(NewPos.x,NewPos.y)<sbnStage)) { _bGameOver = true; return; } bool bEat = GetUnit(NewPos.x,NewPos.y)==sbnBean || GetUnit(NewPos.x,NewPos.y)==sbnStage; SetUnit(NewPos.x,NewPos.y,sbnNone); if(bEat) { TSnakeNode *NewNode = new TSnakeNode; NewNode->x = NewPos.x; NewNode->y = NewPos.y; NewNode->Next = _Snake; NewNode->Prev = _Snake->Prev; _Snake->Prev->Next = NewNode; _Snake->Prev=NewNode; _Snake = NewNode; _iScore += ssEat; } else { _Snake = _Snake->Prev; _Snake->x = NewPos.x; _Snake->y = NewPos.y; } DrawSnake(); if(bEat) if(!GenBean()) { _bEndStage = true; _iScore += ssStage; } }}//---------------------------------------------------------------------------int TSnakeBuf::GetDispBuf(int x, int y){ if((x>=0) && (x<UnitX) && (y>=0) && (y<UnitY)) return _DispBuf[y][x]; return 0;}//---------------------------------------------------------------------------int TSnakeBuf::GetUnit(int x, int y){ if((x>=0) && (x<UnitX) && (y>=0) && (y<UnitY)) return _Units[y][x]; return 0;}//---------------------------------------------------------------------------void TSnakeBuf::SetUnit(int x, int y, int n){ if((x>=0) && (x<UnitX) && (y>=0) && (y<UnitY)) _Units[y][x] = n;}//---------------------------------------------------------------------------void TSnakeBuf::DrawSnake(void){ memcpy(_DispBuf,_Units,sizeof(_Units)); if(_Snake) { TSnakeNode *lpNode = _Snake->Next; _DispBuf[_Snake->y][_Snake->x]=sbnHead; while((lpNode)&&(lpNode!=_Snake)) { if(lpNode->Next==_Snake) { if(lpNode->y==lpNode->Prev->y) _DispBuf[lpNode->y][lpNode->x] = (lpNode->x<lpNode->Prev->x?sbnTailL:sbnTailR); else _DispBuf[lpNode->y][lpNode->x] = (lpNode->y<lpNode->Prev->y?sbnTailU:sbnTailD); } else if(lpNode->y==lpNode->Prev->y) { if(lpNode->y>lpNode->Next->y) _DispBuf[lpNode->y][lpNode->x]=(lpNode->x<lpNode->Prev->x)?sbnCornDL:sbnCornDR; else if(lpNode->y<lpNode->Next->y) _DispBuf[lpNode->y][lpNode->x]=(lpNode->x<lpNode->Prev->x)?sbnCornUL:sbnCornUR; else _DispBuf[lpNode->y][lpNode->x]=sbnHorz; } else { if(lpNode->x<lpNode->Next->x) _DispBuf[lpNode->y][lpNode->x]=(lpNode->y<lpNode->Prev->y)?sbnCornUL:sbnCornDL; else if(lpNode->x>lpNode->Next->x) _DispBuf[lpNode->y][lpNode->x]=(lpNode->y<lpNode->Prev->y)?sbnCornUR:sbnCornDR; else _DispBuf[lpNode->y][lpNode->x]=sbnVert; } lpNode = lpNode->Next; } }}//---------------------------------------------------------------------------void TSnakeBuf::InitStage(int StgNum){ _iBeanNo = 0; _bGameOver = false; _bEndStage = false; memset(_Units,0,sizeof(_Units)); memset(_DispBuf,0,sizeof(_DispBuf)); GenWalls(StgNum); InitSnake(); DrawSnake(); GenBean();}//---------------------------------------------------------------------------void TSnakeBuf::ClearScore(void){ _iScore = 0;}//---------------------------------------------------------------------------bool TSnakeBuf::GenBean(void){ if(++_iBeanNo<=_iStageBeans) { int x = random(UnitX); int y = random(UnitY); while(GetDispBuf(x,y)) { x = random(UnitX); y = random(UnitY); } SetUnit(x,y,_iBeanNo==_iStageBeans?sbnStage:sbnBean); return true; } return false;}//---------------------------------------------------------------------------void TSnakeBuf::GenWalls(int StgNum){ int StNo=StgNum%StageCount; TWall *lpWall = Walls[StNo]; for(int i=0; lpWall[i].x1>=0; i++) { if(lpWall[i].x1==lpWall[i].x2) { for(int y=lpWall[i].y1; y<=lpWall[i].y2; y++) { SetUnit(lpWall[i].x1,y,sbnWall); } } else { for(int x=lpWall[i].x1; x<=lpWall[i].x2; x++) { SetUnit(x,lpWall[i].y1,sbnWall); } } }}//---------------------------------------------------------------------------bool TSnakeBuf::fGetRunning(void){ return ((_Snake)&&(!_bGameOver)&&(!_bEndStage));}//---------------------------------------------------------------------------__fastcall TSnakeTimer::TSnakeTimer():TThread(false){ dwTimeToWait = 300; hTimer = NULL; OnTimer = NULL; iSkipUserEvent = 0; FreeOnTerminate = true;}//---------------------------------------------------------------------------void __fastcall TSnakeTimer::DestroyTimer(void){ OnTimer = NULL; Terminate(); SetEvent(hTimer);}//---------------------------------------------------------------------------void __fastcall TSnakeTimer::SyOnStart(void){ dwWaitTime = dwTimeToWait; iSkipUserEvent = 0; hTimer = CreateEvent(NULL, true, false, NULL);}//---------------------------------------------------------------------------void __fastcall TSnakeTimer::SyOnExit(void){ CloseHandle(hTimer);}//---------------------------------------------------------------------------void __fastcall TSnakeTimer::SyOnTimer(void){ if((OnTimer)&&(!iSkipUserEvent)) { try { OnTimer(this); } catch(Exception &e) { //ignore user's error } } if(iSkipUserEvent>0) iSkipUserEvent--; ResetEvent(hTimer);}//---------------------------------------------------------------------------void __fastcall TSnakeTimer::Execute(void){ Synchronize(SyOnStart); while(!Terminated) { WaitForSingleObject(hTimer,dwWaitTime); if(!Terminated) { Synchronize(SyOnTimer); } } Synchronize(SyOnExit);}//---------------------------------------------------------------------------void __fastcall TSnakeTimer::fSetInterval(DWORD dwIntv){ dwWaitTime = dwTimeToWait = dwIntv; iSkipUserEvent = 1; TriggerTimer();}//---------------------------------------------------------------------------void __fastcall TSnakeTimer::TriggerTimer(int iWait){ if(hTimer) { if(iWait>0) iSkipUserEvent = iWait+1; SetEvent(hTimer); }}//---------------------------------------------------------------------------

评论