#include "Snake.h" #include "c_WinGUI.h" /* ------------------------------------------------------------------------------------------------------------------ */ /* */ #define WINDOW_CLASS_NAME SNAKE_MAIN_WINDOW_CLASS #define BORDERSIZE 15 #define MAXSECTIONS 1024 #define MAXPRIZES 512 typedef enum { Left, Right, Up, Down, TDir_Num }TDir; typedef struct { BOOL DirChange; TDir Dir; TDir OldDir; int SecNun; int Row; int Col; int OldRow; int OldCol; }TSectInfo; typedef struct { TDir Dir; BOOL SectChangeDir[256]; int TurnCol; int TurnRow; }TTurn; typedef struct { BOOL Exists; int Value; int Col; int Row; }TPrize; /* ------------------------------------------------------------------------------------------------------------------ */ /* */ static HWND hGameWindow; static SnakeApp_t SnakeApp; static BOOL NewSect; static int VK_P = 112; static unsigned int SnakeTimer = 1; static long TotalClicks = 0; static int Sections; static int NumPrizes; static TPrize Prizes[MAXPRIZES]; static TSectInfo SectInfo[MAXSECTIONS]; static TTurn TurnList[25]; static int NumTurns; /* ------------------------------------------------------------------------------------------------------------------ */ /* */ static BOOL SetupWindow(HWND hWindow) { } /* ------------------------------------------------------------------------------------------------------------------ */ /* Main Window */ c_WinGUI_EventHandlerDef(WM_DESTROY, Main_Destroy) { if (SnakeApp.hHeadBitmap) { DeleteObject(SnakeApp.hHeadBitmap); } if (SnakeApp.hBodyBitmap) { DeleteObject(SnakeApp.hBodyBitmap); } if (SnakeApp.hOneHundredBitmap) { DeleteObject(SnakeApp.hOneHundredBitmap); } PostQuitMessage(0); } c_WinGUI_EventHandlerDef(WM_CREATE, Main_Create) { memset(&SnakeApp, 0, sizeof(SnakeApp_t)); SnakeApp.Size = 32; SnakeApp.hHeadBitmap = LoadBitmap(WinApp.hInstance, "Head"); if (!SnakeApp.hHeadBitmap) { MessageBox(hwnd, "No head", "Fatal Error", MB_OK); return FALSE; } SnakeApp.hBodyBitmap = LoadBitmap(WinApp.hInstance, "Body"); if (!SnakeApp.hBodyBitmap) { MessageBox(hwnd, "No body", "Fatal Error", MB_OK); return FALSE; } SnakeApp.hOneHundredBitmap = LoadBitmap(WinApp.hInstance, "Hundred"); if (!SnakeApp.hOneHundredBitmap) { MessageBox(hwnd, "No hundred", "Fatal Error", MB_OK); return FALSE; } int CXFull = GetSystemMetrics(SM_CXSCREEN); int CYFull = GetSystemMetrics(SM_CYSCREEN); SnakeApp.NumXSects = div(CXFull, SnakeApp.Size); SnakeApp.MaxCols = (SnakeApp.NumXSects.quot-1)*SnakeApp.Size; int BoardWidth = CXFull - SnakeApp.MaxCols; div_t StartC = div(BoardWidth, 2); SnakeApp.StartCol = StartC.quot; SnakeApp.NumYSects = div(CYFull, SnakeApp.Size); SnakeApp.MaxRows = (SnakeApp.NumYSects.quot-1)*SnakeApp.Size; BoardWidth = CYFull - SnakeApp.MaxRows; StartC = div(BoardWidth, 2); SnakeApp.StartRow = StartC.quot; hGameWindow = CreateWindow(SNAKE_GAME_WINDOW_CLASS, "Game Window", WS_CHILD | WS_VISIBLE, SnakeApp.StartCol, SnakeApp.StartRow, SnakeApp.MaxCols, SnakeApp.MaxRows, hwnd, NULL, WinApp.hInstance, NULL); return TRUE; } c_WinGUI_EventHandlerDef(WM_SIZE, Main_Size) { if (hGameWindow) { MoveWindow(hGameWindow, 0, 0, cx, cy, TRUE); RECT Rect; GetClientRect(hGameWindow, &Rect); int CXFull = Rect.right - Rect.left; int CYFull = Rect.bottom - Rect.top; SnakeApp.NumXSects = div(CXFull, SnakeApp.Size); SnakeApp.MaxCols = (SnakeApp.NumXSects.quot-1)*SnakeApp.Size; int BoardWidth = CXFull - SnakeApp.MaxCols; div_t StartC = div(BoardWidth, 2); SnakeApp.StartCol = StartC.quot; SnakeApp.NumYSects = div(CYFull, SnakeApp.Size); SnakeApp.MaxRows = (SnakeApp.NumYSects.quot-1)*SnakeApp.Size; BoardWidth = CYFull - SnakeApp.MaxRows; StartC = div(BoardWidth, 2); SnakeApp.StartRow = StartC.quot; } } c_WinGUI_EventMapBegin(WndProc) c_WinGUI_EventMap(WM_DESTROY, Main_Destroy); c_WinGUI_EventMap(WM_CREATE, Main_Create); c_WinGUI_EventMap(WM_SIZE, Main_Size); c_WinGUI_EventMapEnd() /* ------------------------------------------------------------------------------------------------------------------ */ /* GAME */ static void InitializeSections(void); static void SetColRow(void) { int i; for (i=0; i<=Sections; i++) { SectInfo[i].OldCol = SectInfo[i].Col; SectInfo[i].OldRow = SectInfo[i].Row; switch (SectInfo[i].Dir) { case Up: { SectInfo[i].Row-=SnakeApp.Size; break; } case Down:{ SectInfo[i].Row+=SnakeApp.Size; break; } case Left: { SectInfo[i].Col-=SnakeApp.Size; break; } case Right: { SectInfo[i].Col+=SnakeApp.Size; break; } } } for (i = Sections; i>0; i--) { if (SectInfo[i-1].DirChange) { SectInfo[i].DirChange = TRUE; SectInfo[i].Dir = SectInfo[i-1].Dir; SectInfo[i-1].DirChange = FALSE; } } } static void SetNewTurnSection(void) { for (int i=1; i<=Sections; i++) { if (TurnList[NumTurns].SectChangeDir[i]==TRUE) { break; } TurnList[NumTurns].SectChangeDir[i] = FALSE; i++; TurnList[NumTurns].SectChangeDir[i] = TRUE; } } static void Boom(HWND hwnd) { memset(SectInfo, 0, sizeof(SectInfo)); Sections = 0; NumPrizes = 0; for (int i=0; i<10; i++) { MessageBeep(-1); } InitializeSections(); InvalidateRect(hwnd, NULL, TRUE); } static void WhiteOut(HWND hwnd, int i) { HDC PaintDC = GetDC(hwnd); HDC MemDC = CreateCompatibleDC(PaintDC); HBITMAP SaveBmp = SelectBitmap(MemDC, SnakeApp.hOneHundredBitmap); BitBlt(PaintDC, Prizes[i].Col, Prizes[i].Row, 32, 32, MemDC, 0, 0, SRCINVERT); SelectObject(MemDC, SaveBmp); DeleteDC(MemDC); ReleaseDC(hwnd, PaintDC); } static void CheckForCollision(HWND hwnd) { if (SectInfo[0].Col<0) Boom(hwnd); if (SectInfo[0].Row<0) Boom(hwnd); if (SectInfo[0].Col + SnakeApp.Size > SnakeApp.MaxCols) Boom(hwnd); if (SectInfo[0].Row + SnakeApp.Size > SnakeApp.MaxRows) Boom(hwnd); for (int i=1; i<=Sections; i++) { if (SectInfo[i].Col == SectInfo[0].Col && SectInfo[i].Row == SectInfo[0].Row) { Boom(hwnd); } } for (int i=0; i<=NumPrizes; i++) { if (Prizes[i].Exists) { if (((SectInfo[0].Row >= Prizes[i].Row) && (SectInfo[0].Row <=Prizes[i].Row + (SnakeApp.Size-1)))&& ((SectInfo[0].Col >=Prizes[i].Col) && (SectInfo[0].Col <=Prizes[i].Col + (SnakeApp.Size-1)))) { Prizes[i].Exists = FALSE; WhiteOut(hwnd, i); } } } } static void InitializeSections(void) { int i; int StartCol; int StartRow; Sections = 5; StartCol = SnakeApp.Size * 3; StartRow = SnakeApp.Size * 3; for (i=0; i<=Sections; i++) { SectInfo[i].Dir = Right; SectInfo[i].DirChange = FALSE; SectInfo[i].Col = StartCol - (SnakeApp.Size * i); SectInfo[i].Row = StartRow; SectInfo[i].OldCol = SectInfo[i].Col; SectInfo[i].OldRow = SectInfo[i].Row; } NewSect = FALSE; } static void GetOldDir(TDir NewDir) { TurnList[NumTurns].Dir = NewDir; TurnList[NumTurns].SectChangeDir[1] = TRUE; SectInfo[0].OldDir = SectInfo[0].Dir; SectInfo[0].Dir = NewDir; SectInfo[0].DirChange = TRUE; TurnList[0].TurnCol = SectInfo[0].Col; TurnList[0].TurnRow = SectInfo[0].Row; } static void MoveBitmap(HWND hwnd) { SetColRow(); HDC DC = GetDC(hwnd); HDC PicDC = CreateCompatibleDC(DC); CheckForCollision(hwnd); HBITMAP OldBmp = SelectBitmap(PicDC, SnakeApp.hHeadBitmap); BitBlt(DC, SectInfo[0].OldCol, SectInfo[0].OldRow, SnakeApp.Size, SnakeApp.Size, PicDC, 0, 0, SRCINVERT); BitBlt(DC, SectInfo[0].Col, SectInfo[0].Row, SnakeApp.Size, SnakeApp.Size, PicDC, 0, 0, SRCINVERT); SelectObject(PicDC, OldBmp); OldBmp = SelectBitmap(PicDC, SnakeApp.hBodyBitmap); BitBlt(DC, SectInfo[1].Col, SectInfo[1].Row, SnakeApp.Size, SnakeApp.Size, PicDC, 0, 0, SRCINVERT); BitBlt(DC, SectInfo[Sections].Col, SectInfo[Sections].Row, SnakeApp.Size, SnakeApp.Size, PicDC, 0, 0, SRCINVERT); if (NewSect) { BitBlt(DC, SectInfo[Sections].Col, SectInfo[Sections].Row, SnakeApp.Size, SnakeApp.Size, PicDC, 0, 0, SRCINVERT); NewSect = FALSE; } SelectObject(PicDC, OldBmp); SectInfo[0].DirChange = FALSE; DeleteDC(PicDC); ReleaseDC(hwnd, DC); SetNewTurnSection(); } static void SetSections(void) { Sections++; SectInfo[Sections].Dir = SectInfo[Sections-1].Dir; SectInfo[Sections].DirChange = FALSE; switch (SectInfo[Sections].Dir) { case Left: { SectInfo[Sections].Col = SectInfo[Sections-1].Col + SnakeApp.Size; SectInfo[Sections].Row = SectInfo[Sections-1].Row; break; } case Right: { SectInfo[Sections].Col = SectInfo[Sections-1].Col - SnakeApp.Size; SectInfo[Sections].Row = SectInfo[Sections-1].Row; break; } case Up: { SectInfo[Sections].Col = SectInfo[Sections-1].Col; SectInfo[Sections].Row = SectInfo[Sections-1].Row + SnakeApp.Size; break; } case Down: { SectInfo[Sections].Col = SectInfo[Sections-1].Col; SectInfo[Sections].Row = SectInfo[Sections-1].Row - SnakeApp.Size; break; } } SectInfo[Sections].OldCol = SectInfo[Sections-1].Col; SectInfo[Sections].OldRow = SectInfo[Sections-1].Row; } static void SetPrizes(void) { NumPrizes++; Prizes[NumPrizes].Exists = TRUE; Prizes[NumPrizes].Row = (rand() % SnakeApp.NumYSects.quot) * SnakeApp.Size; Prizes[NumPrizes].Col = (rand() % SnakeApp.NumXSects.quot) * SnakeApp.Size; } c_WinGUI_EventHandlerDef(WM_CREATE, Game_Create) { if (!SetTimer(hwnd, SnakeTimer, 125, NULL)) { MessageBox(hwnd, "No Timers Available", "Snake Info", MB_OK); return FALSE; } NumPrizes = 0; InitializeSections(); return TRUE; } c_WinGUI_EventHandlerDef(WM_DESTROY, Game_Destroy) { KillTimer(hwnd, SnakeTimer); } c_WinGUI_EventHandlerDef(WM_CHAR, Game_Char) { if (ch==VK_P) { KillTimer(hwnd, SnakeTimer); } } c_WinGUI_EventHandlerDef(WM_KEYDOWN, Game_Key) { switch (vk) { case VK_DOWN: { GetOldDir(Down); break; } case VK_UP: { GetOldDir(Up); break; } case VK_LEFT: { GetOldDir(Left); break; } case VK_RIGHT: { GetOldDir(Right); break; } } MoveBitmap(hwnd); } c_WinGUI_EventHandlerDef(WM_PAINT, Game_Paint) { PAINTSTRUCT PaintStruct; HDC DC = BeginPaint(hwnd, &PaintStruct); HDC PicDC = CreateCompatibleDC(DC); // Draw Head HBITMAP OldMap = SelectBitmap(PicDC, SnakeApp.hHeadBitmap); BitBlt(DC, SectInfo[0].Col, SectInfo[0].Row, SnakeApp.Size, SnakeApp.Size, PicDC, 0, 0, SRCINVERT); SelectObject(PicDC, OldMap); // Draw Body OldMap = SelectBitmap(PicDC, SnakeApp.hBodyBitmap); for (int i=1; i<=Sections; i++) { BitBlt(DC, SectInfo[i].Col, SectInfo[i].Row, SnakeApp.Size, SnakeApp.Size, PicDC, 0, 0, SRCINVERT); } SelectObject(PicDC, OldMap); DeleteDC(PicDC); EndPaint(hwnd, &PaintStruct); SectInfo[0].DirChange = FALSE; } c_WinGUI_EventHandlerDef(WM_TIMER, Game_Timer) { HBITMAP SaveBmp; SetFocus(hwnd); if (id==SnakeTimer) { MoveBitmap(hwnd); TotalClicks++; if ((TotalClicks%10)==0) { SetSections(); SetPrizes(); HDC PaintDC = GetDC(hwnd); HDC PicDC = CreateCompatibleDC(PaintDC); NewSect = TRUE; SaveBmp = SelectBitmap(PicDC, SnakeApp.hOneHundredBitmap); BitBlt(PaintDC, Prizes[NumPrizes].Col, Prizes[NumPrizes].Row, 32, 32, PicDC, 0, 0, SRCINVERT); SelectObject(PicDC, SaveBmp); DeleteDC(PicDC); ReleaseDC(hwnd, PaintDC); } } } c_WinGUI_EventMapBegin(GameWndProc) c_WinGUI_EventMap(WM_CREATE, Game_Create); c_WinGUI_EventMap(WM_DESTROY, Game_Destroy); c_WinGUI_EventMap(WM_CHAR, Game_Char); c_WinGUI_EventMap(WM_KEYDOWN, Game_Key); c_WinGUI_EventMap(WM_PAINT, Game_Paint); c_WinGUI_EventMap(WM_TIMER, Game_Timer); c_WinGUI_EventMapEnd() /* ------------------------------------------------------------------------------------------------------------------ */ /* */ static BOOL Register(HINSTANCE hInstance) { WNDCLASS WndClass; WndClass.style = CS_HREDRAW | CS_VREDRAW; WndClass.lpfnWndProc = WndProc; WndClass.cbClsExtra = 0; WndClass.cbWndExtra = 0; WndClass.hInstance = hInstance; WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); WndClass.hbrBackground = GetStockBrush(GRAY_BRUSH); WndClass.lpszMenuName = NULL; WndClass.lpszClassName = WINDOW_CLASS_NAME; RegisterClass(&WndClass); WndClass.style = CS_HREDRAW | CS_VREDRAW; WndClass.lpfnWndProc = GameWndProc; WndClass.hIcon = NULL; WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); WndClass.hbrBackground = GetStockBrush(WHITE_BRUSH); WndClass.lpszClassName = SNAKE_GAME_WINDOW_CLASS; return RegisterClass(&WndClass); } static HWND Create(HINSTANCE hInstance, int nCmdShow) { HWND hwnd = CreateWindow(WINDOW_CLASS_NAME, "A Snake and it's Tail", WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL ); if (hwnd == NULL) { return NULL; } nCmdShow = SW_SHOWMAXIMIZED; ShowWindow(hwnd, nCmdShow); UpdateWindow(hwnd); return hwnd; } /* ------------------------------------------------------------------------------------------------------------------ */ /* */ c_WinGUI_Main(){ MSG msg; if (!hPrevInstance) { if (!Register(hInstance)) { return FALSE; } } WinApp.hInstance = hInstance; HWND MainHwnd = Create(hInstance, nShowCmd); if (!MainHwnd) { return FALSE; } WinApp.hwnd = MainHwnd; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; }