贪吃蛇1.0版本基础功能初步全部完成

================================

wid
This commit is contained in:
mrwid 2013-04-09 00:44:04 +08:00
parent be2d9e16cc
commit 60f6078638
17 changed files with 605 additions and 100 deletions

View File

@ -9,15 +9,14 @@ LRESULT DealBeginMenuMsg( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
static int menuID = 0;
static int oldMenuID = 0;
HDC hdc;
HDC hdc;
PAINTSTRUCT ps;
switch( message )
{
case WM_CREATE:
hInst = ((LPCREATESTRUCT)lParam)->hInstance;
PlaySound( MAKEINTRESOURCE( IDR_GAME_START ), hInst, SND_RESOURCE | SND_ASYNC | SND_LOOP );
SetTimer( hwnd, TMR_BEGIN, 60, NULL );
hInst =(HINSTANCE) GetWindowLong( hwnd, GWL_HINSTANCE );
PostMessage( hwnd, CM_GAME_READY, 0, 0 );
return 0;
case WM_PAINT:
@ -26,8 +25,14 @@ LRESULT DealBeginMenuMsg( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
EndPaint( hwnd, &ps );
return 0;
case CM_GAME_READY:
SetTimer( hwnd, TMR_BEGIN, 60, NULL );
PlaySound( MAKEINTRESOURCE( IDR_GAME_START ), (HINSTANCE)GetWindowLong( hwnd, GWL_HINSTANCE ), SND_RESOURCE | SND_ASYNC | SND_LOOP );
return 0;
case CM_START_GAME:
InvalidateRect( hwnd, NULL, TRUE );
SetWindowLong( hwnd, GWL_WNDPROC, (long)PlayingProc );
SetTimer( hwnd, TMR_PLAYING_READY, 500, NULL ); //开启游戏准备音效定时器
PlaySound( NULL, NULL, SND_FILENAME ); //终止当前音效
return CM_START_GAME;

View File

@ -7,6 +7,7 @@
#include "Init_Begin_UI.h"
#include "HelpDialogProc.h"
#include "MacroDefine.h"
#include "PlayingProc.h"
#include "resource.h"
//////////////////////////////////////////////////////////////////////////

46
GameOverDlgProc.c Normal file
View File

@ -0,0 +1,46 @@
#include "GameOverDlgProc.h"
#include "MacroDefine.h"
//////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK GameOverProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
{
HWND hStatic;
LOGFONT lf = {0};
HFONT hFont;
strcpy( lf.lfFaceName, "ËÎÌå" );
lf.lfWidth = 30;
lf.lfHeight = 50;
lf.lfWeight = FW_NORMAL;
lf.lfCharSet = GB2312_CHARSET;
lf.lfPitchAndFamily = 35;
hFont = CreateFontIndirect (&lf);
switch( message )
{
case WM_INITDIALOG:
hStatic = CreateWindow( TEXT("static"), TEXT("GAME OVER !"), WS_CHILD | WS_VISIBLE, 25, 50, 400, 50, hDlg, NULL, NULL, NULL );
SendMessage( hStatic, WM_SETFONT, (WPARAM)hFont, 0 );
return TRUE;
case WM_COMMAND:
switch( LOWORD(wParam) )
{
case IDC_EXIT_GAME:
EndDialog( hDlg, GAME_EXIT );
return TRUE;
case IDC_GAME_AGAIN:
EndDialog( hDlg, GAME_AGAIN );
return TRUE;
case IDC_RETURN_MAIN:
EndDialog( hDlg, GAME_MAIN );
return TRUE;
}
break;
}
return 0;
}

10
GameOverDlgProc.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
//////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include "resource.h"
//////////////////////////////////////////////////////////////////////////
LRESULT CALLBACK GameOverProc( HWND, UINT, WPARAM, LPARAM );

View File

@ -4,20 +4,16 @@
LRESULT CALLBACK WndProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
static int gameStatus = CM_UN_START;
LRESULT valReturn;
switch( gameStatus )
{
case CM_UN_START:
valReturn = DealBeginMenuMsg( hwnd, message, wParam, lParam );
if( valReturn == CM_START_GAME )
gameStatus = CM_START_ED;
SetWindowLong( hwnd, GWL_WNDPROC, (long)PlayingProc );
return valReturn;
case CM_START_ED:
return PlayingProc( hwnd, message, wParam, lParam );
}
return DefWindowProc( hwnd, message, wParam, lParam );

View File

@ -2,9 +2,22 @@
#include <stdio.h>
//////////////////////////////////////////////////////////////////////////
void InitPlayingMap( HWND hwnd, HDC hdc, HINSTANCE hInst )
void InitPlayingMap( HWND hwnd, HDC hdc, POINT ptFood, CMAP *gm_map, int level )
{
HPEN hPen;
HBRUSH hBrush;
hPen = CreatePen( PS_SOLID, 3, RGB(128, 128, 128) );
hBrush = CreateSolidBrush( RGB(192, 192, 192) );
SelectObject( hdc, hPen );
SelectObject( hdc, hBrush );
DrawBrickWall( hwnd, hdc );
DrawRandWall( hwnd, hdc, gm_map, level );
DrawRandomFood( hdc, ptFood );
DeleteObject( hPen );
DeleteObject( hBrush );
}
//////////////////////////////////////////////////////////////////////////
@ -62,16 +75,14 @@ void DrawRandWall( HWND hwnd, HDC hdc, CMAP *gm_map, int lev )
}
}
//////////////////////////////////////////////////////////////////////////
//绘制随机障碍物
void drawWallLine( HDC hdc, int x1, int y1, int x2, int y2 )
{
int i = 0;
int xPos = 0, yPos = 0;
FILE *fp;
fp = fopen( "D:\\a.txt", "a" );
fprintf( fp, "%d %d %d %d\n", x1, y1, x2, y2 );
fclose( fp );
if( x2-x1 == 0 )
{
yPos = y1;
@ -91,5 +102,25 @@ void drawWallLine( HDC hdc, int x1, int y1, int x2, int y2 )
xPos += 10;
}
}
}
}
//////////////////////////////////////////////////////////////////////////
//绘制食物
void DrawRandomFood( HDC hdc, POINT ptFood )
{
HPEN hPen;
HBRUSH hBrush;
hPen = GetStockObject( WHITE_PEN );
hBrush = CreateSolidBrush( RGB(255, 0, 0) );
SelectObject( hdc, hPen );
SelectObject( hdc, hBrush );
Ellipse( hdc, ptFood.x, ptFood.y, ptFood.x+10, ptFood.y+10 );
DeleteObject( hPen );
DeleteObject( hBrush );
}
//////////////////////////////////////////////////////////////////////////

View File

@ -12,10 +12,14 @@
//////////////////////////////////////////////////////////////////////////
void InitPlayingMap( HWND, HDC, HINSTANCE );
void InitPlayingMap( HWND, HDC, POINT, CMAP *, int );
//////////////////////////////////////////////////////////////////////////
void DrawBrickWall( HWND, HDC ); //画四周砖块
void DrawBrickWall( HWND, HDC ); //绘制四周砖块
void DrawRandWall( HWND, HDC, CMAP*, int ); //绘制随机障碍物
void DrawRandomFood( HDC, POINT ); //绘制食物
void DrawRandWall( HWND, HDC, CMAP*, int ); //随机墙壁

View File

@ -3,16 +3,37 @@
//////////////////////////////////////////////////////////////////////////
//游戏状态
#define CM_UN_START 0 //停留在起始界面
#define CM_START_ED 1 //正在进行游戏
#define CM_UN_START 0 //停留在起始界面
#define CM_START_ED 1 //正在进行游戏
//////////////////////////////////////////////////////////////////////////
#define CM_START_GAME (WM_USER + 100) //开始游戏消息
#define CM_READY_GAME (WM_USER + 100) //准备游戏消息
#define CM_START_GAME (WM_USER + 101) //开始游戏消息
#define CM_MOVE_SNAKE (WM_USER + 102) //移动蛇身
#define CM_GAME_OVER (WM_USER + 103) //游戏结束
#define CM_GAME_NEXT (WM_USER + 104) //下一关
#define CM_GAME_SUCCEED (WM_USER + 105) //全关成功
#define CM_GAME_READY (WM_USER + 106) //游戏准备
//////////////////////////////////////////////////////////////////////////
#define TMR_BEGIN 10000 //开始界面定时器
#define TMR_PLAYING_READY 10001 //播放准备音效
#define TMR_PLAYING_GO 10002 //播放开始音效
#define TMR_IMPACE_TEST 10003 //碰撞检测正确性测试
#define TMR_IMPACE_TEST 10003 //碰撞检测正确性测试
#define TMR_START_MOVE 10004 //移动蛇身
//////////////////////////////////////////////////////////////////////////
#define DR_UP 20000 //上移动
#define DR_DOWN 20001 //下移动
#define DR_LEFT 20002 //左移动
#define DR_RIGHT 20003 //右移动
//////////////////////////////////////////////////////////////////////////
#define GAME_AGAIN 30000 //再来一局
#define GAME_MAIN 30001 //回主菜单
#define GAME_EXIT 30003 //退出游戏

View File

@ -1,16 +1,19 @@
#include "PlayingProc.h"
#include "GameWndProc.h"
#include "map_data.h"
//////////////////////////////////////////////////////////////////////////
void testImpace( HWND hwnd );
void testFoodPlace( HWND hwnd );
static GM_STATUS APP = {
TEXT("贪吃蛇"),
0,
{0},
{0},
0,
{ {20, 20} },
{-10, -10},
DR_RIGHT,
5,
0
};
@ -20,8 +23,6 @@ LRESULT PlayingProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
HDC hdc;
PAINTSTRUCT ps;
HPEN hPen;
HBRUSH hBrush;
POINT pt = {0};
switch( message )
@ -30,48 +31,34 @@ LRESULT PlayingProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
switch( wParam )
{
case TMR_PLAYING_READY:
srand( (unsigned int)time(0) );
SetTimer( hwnd, TMR_PLAYING_READY, 1000*60, NULL ); //调整定时器为60秒
PlaySound( MAKEINTRESOURCE( IDR_READY ), (HINSTANCE)GetWindowLong( hwnd, GWL_HINSTANCE ), SND_RESOURCE | SND_ASYNC );
KillTimer( hwnd, TMR_PLAYING_READY );
SetTimer( hwnd, TMR_PLAYING_GO, 1500, NULL ); //启动游戏启动定时器
GetRandomFoodPlace( hwnd, &APP.food );
break;
case TMR_PLAYING_GO:
KillTimer( hwnd, TMR_PLAYING_GO );
PlaySound( MAKEINTRESOURCE( IDR_GO ), (HINSTANCE)GetWindowLong( hwnd, GWL_HINSTANCE ), SND_RESOURCE | SND_ASYNC );
//SetTimer( hwnd, TMR_IMPACE_TEST, 0, NULL ); //碰撞检测正确性测试
//MessageBox( hwnd, TEXT("游戏开始!"), TEXT("消息"), MB_OK );
//游戏开始
PostMessage( hwnd, CM_START_GAME, 0, 0 );
SetTimer( hwnd, TMR_START_MOVE, 200, 0 );
break;
//case TMR_IMPACE_TEST:
// testImpace( hwnd );
// break;
}
return 0;
case WM_PAINT:
hdc = BeginPaint( hwnd, &ps );
hPen = CreatePen( PS_SOLID, 3, RGB(128, 128, 128) );
hBrush = CreateSolidBrush( RGB(192, 192, 192) );
SelectObject( hdc, hPen );
SelectObject( hdc, hBrush );
InitPlayingMap( hwnd, hdc, (HINSTANCE)GetWindowLong( hwnd, GWL_HINSTANCE ) );
//APP.level = 7;
DrawRandWall( hwnd, hdc, gm_map, APP.level );
//APP.pt.x = 100;
//APP.pt.y = 100;
//PointImpaceTest( hwnd, APP.pt );
DeleteObject( hPen );
DeleteObject( hBrush );
InitPlayingMap( hwnd, hdc, APP.food, gm_map, APP.level );
EndPaint( hwnd, &ps );
return 0;
case CM_START_GAME:
SetWindowLong( hwnd, GWL_WNDPROC, (long)StartPlaying );
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
@ -82,11 +69,11 @@ LRESULT PlayingProc( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
//////////////////////////////////////////////////////////////////////////
void getWallLineRect( int, RECT *, RECT * ); //获取地图障碍物i在窗口中的实际位置
BOOL borderImpace( RECT, POINT ); //边缘碰撞检测
void getWallLineRect( int, RECT *, RECT *, int ); //获取地图障碍物i在窗口中的实际位置
BOOL borderImpace( RECT, POINT, int ); //边缘碰撞检测
//点障碍物的碰撞检测
BOOL PointImpaceTest( HWND hwnd, POINT pt )
BOOL PointImpaceTest( HWND hwnd, POINT pt, int exc )
{
int i = 0;
RECT rect = {0};
@ -94,26 +81,30 @@ BOOL PointImpaceTest( HWND hwnd, POINT pt )
GetClientRect( hwnd, &rect );
if( borderImpace(rect, pt) ) //边缘碰撞
if( borderImpace(rect, pt, exc) ) //边缘碰撞
return TRUE;
for( i; i < 5; i++ )
for( i = 0; i < 5; i++ )
{
getWallLineRect( i, &rect, &line );
getWallLineRect( i, &rect, &line, exc );
if( line.right - line.left == 0 ) //垂直障碍物
if( pt.x > line.left && pt.x < line.left + 10 && pt.y > line.top && pt.y < line.bottom )
if( pt.x >= line.left - exc && pt.x < line.left + 10 + exc && \
pt.y >= line.top - exc && pt.y < line.bottom + exc )
return TRUE;
if( line.bottom - line.top == 0 ) //水平障碍物
if( pt.x > line.left && pt.x < line.right && pt.y > line.top && pt.y < line.top + 10 )
if( pt.x >= line.left - exc && pt.x < line.right + exc && \
pt.y >= line.top - exc && pt.y < line.top + 10 + exc )
return TRUE;
}
return FALSE;
}
//////////////////////////////////////////////////////////////////////////
//获取地图障碍物i在窗口中的实际位置
void getWallLineRect( int i, RECT *rect, RECT *line )
void getWallLineRect( int i, RECT *rect, RECT *line, int exc )
{
//获取地图数据在窗口中的映射位置
line->left = (int)(gm_map[APP.level].line[i].x1 * rect->right); //x1
@ -122,53 +113,348 @@ void getWallLineRect( int i, RECT *rect, RECT *line )
line->bottom = (int)(gm_map[APP.level].line[i].y2 * rect->bottom); //y2
//添加偏移坐标
line->left += 10 - line->left % 10;
line->top += 10 - line->top % 10;
line->right += 10 - line->right % 10;
line->bottom += 10 - line->bottom % 10;
if( line->left )
{
line->left += (10 - line->left % 10);
line->top += (10 - line->top % 10);
line->right += (10 - line->right % 10);
line->bottom += (10 - line->bottom % 10);
}
}
//////////////////////////////////////////////////////////////////////////
//边缘碰撞检测
BOOL borderImpace( RECT rect, POINT pt )
BOOL borderImpace( RECT rect, POINT pt, int exc )
{
if( pt.x > rect.right-10 || pt.x < rect.left+10 )
if( pt.x > rect.right-20-exc || pt.x < rect.left+10 )
return TRUE;
if( pt.y > rect.bottom-10 || pt.y < rect.top+10 )
if( pt.y > rect.bottom-20-exc || pt.y < rect.top+10 )
return TRUE;
return FALSE;
}
/*
//检测碰撞正确性测试 - 测试结果: 正确
void testImpace( HWND hwnd )
//////////////////////////////////////////////////////////////////////////
//生成随机食物坐标
void GetRandomFoodPlace( HWND hwnd, POINT *ptFood )
{
int i = 0;
int i = 0, x = 0, y = 0;
RECT rect = {0}, line = {0};
POINT pt = {0};
HDC hdc;
TCHAR szBuffer[28] = {0};
wsprintf( szBuffer, "%s %i %s", TEXT(""), APP.level+1, TEXT("关障碍物碰撞检测") );
SetWindowText( hwnd, szBuffer );
ptFood->x = ptFood->y = 0;
SetTimer( hwnd, TMR_IMPACE_TEST, 0, NULL );
if( APP.level == 9 )
GetClientRect( hwnd, &rect );
while( PointImpaceTest( hwnd, *ptFood, 10 ) )
{
SetWindowText( hwnd, TEXT("贪吃蛇 - 碰撞检测正确性测试完毕") );
KillTimer( hwnd, TMR_IMPACE_TEST );
x = rand()%rect.right; y = rand()%rect.bottom;
ptFood->x = x - x%10; ptFood->y = y - y%10;
}
hdc = GetDC(hwnd);
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
int dealKeywordMsg( HWND hwnd, WPARAM ); //处理键盘消息
void moveSnake( ); //移动蛇身
void eraseNode( HWND, POINT ); //擦除一个蛇身节点
void drawSnakeBody( HWND ); //绘制蛇身
BOOL testEating( HWND ); //检测食物是否被吃掉
void updateGameInfo( HWND ); //更新游戏标题栏信息
void resetGameStatus(); //重置游戏状态
void nextLevel( HWND ); //下一关
BOOL testEatSelf( HWND ); //测试是否吃到自己
void gameOver( HWND ); //游戏结束
void gameAgain( HWND ); //再来一局
void startSnakeMove( HWND ); //蛇开始移动(封装移动方法)
//////////////////////////////////////////////////////////////////////////
//开始游戏
LRESULT CALLBACK StartPlaying( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam )
{
HDC hdc;
PAINTSTRUCT ps;
switch( message )
{
case WM_PAINT:
hdc = BeginPaint( hwnd, &ps );
InitPlayingMap( hwnd, hdc, APP.food, gm_map, APP.level );
EndPaint( hwnd, &ps );
return 0;
case WM_TIMER:
switch( wParam )
{
case TMR_START_MOVE:
startSnakeMove( hwnd );
break;
}
return 0;
case CM_GAME_OVER:
gameOver( hwnd );
break;
case CM_GAME_NEXT:
nextLevel( hwnd );
break;
case CM_GAME_SUCCEED:
MessageBox( NULL, "ok", "", 0 );
break;
case WM_KEYDOWN:
dealKeywordMsg( hwnd, wParam );
return 0;
for( pt.x = 0; pt.x < 800; pt.x++ )
for( pt.y = 0; pt.y < 600; pt.y++ )
if( !PointImpaceTest(hwnd, pt) )
SetPixel( hdc, pt.x, pt.y, RGB(0, 128, 0) );
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc( hwnd, message, wParam, lParam );
}
Sleep(2000);
APP.level ++;
InvalidateRect( hwnd, NULL, TRUE );
//////////////////////////////////////////////////////////////////////////
//处理键盘消息
int dealKeywordMsg( HWND hwnd, WPARAM wParam )
{
switch( wParam )
{
case VK_UP:
case 'W':
if(APP.direction != DR_DOWN) APP.direction = DR_UP; break;
case VK_DOWN:
case 'S':
if(APP.direction != DR_UP) APP.direction = DR_DOWN; break;
case VK_LEFT:
case 'A':
if(APP.direction != DR_RIGHT) APP.direction = DR_LEFT; break;
case VK_RIGHT:
case 'D':
if(APP.direction != DR_LEFT) APP.direction = DR_RIGHT; break;
case VK_CONTROL:
PostMessage( hwnd, WM_TIMER, TMR_START_MOVE, 0 );
break;
case VK_ESCAPE:
if ( MessageBox( NULL, TEXT("游戏正在运行, 确定退出吗?"), \
TEXT("确认"), MB_OKCANCEL | MB_ICONQUESTION ) == IDOK )
PostQuitMessage(0);
break;
}
return 0;
}
//移动蛇身
void moveSnake( )
{
int i = APP.len;
for( i; i > 0; i-- )
APP.body[i] = APP.body[i-1];
switch( APP.direction )
{
case DR_UP:
APP.body[0].y -= 10; break;
case DR_DOWN:
APP.body[0].y += 10; break;
case DR_LEFT:
APP.body[0].x -= 10; break;
case DR_RIGHT:
APP.body[0].x += 10; break;
}
}
//擦除蛇身的一个节点
void eraseNode( HWND hwnd, POINT ptNode )
{
HDC hdc;
HPEN hPen;
HBRUSH hBrush;
hdc = GetDC( hwnd );
hPen = CreatePen( PS_SOLID, 3, RGB(0, 0, 0) );
hBrush = CreateSolidBrush( RGB(0, 0, 0) );
SelectObject( hdc, hPen );
SelectObject( hdc, hBrush );
Rectangle( hdc, ptNode.x, ptNode.y, ptNode.x+10, ptNode.y+10 );
DeleteObject( hBrush );
ReleaseDC( hwnd, hdc );
}
*/
//绘制蛇身
void drawSnakeBody( HWND hwnd )
{
int i = 0;
HDC hdc;
HPEN hPen;
HBRUSH hBrush;
hdc = GetDC( hwnd );
hPen = CreatePen( PS_SOLID, 3, RGB(0, 128, 0) );
hBrush = CreateSolidBrush( RGB(0, 255, 0) );
SelectObject( hdc, hPen );
SelectObject( hdc, hBrush );
for( i; i <= APP.len; i++ )
RoundRect( hdc, APP.body[i].x, APP.body[i].y, APP.body[i].x+10, APP.body[i].y+10, 3, 3 );
eraseNode( hwnd, APP.body[APP.len] );
DeleteObject( hPen );
DeleteObject( hBrush );
ReleaseDC( hwnd, hdc );
}
//检测食物是否被吃掉
BOOL testEating( HWND hwnd )
{
if( APP.food.x == APP.body[0].x && APP.food.y == APP.body[0].y )
{
PlaySound( MAKEINTRESOURCE( IDR_EATING ), (HINSTANCE)GetWindowLong( hwnd, GWL_HINSTANCE ), SND_RESOURCE | SND_ASYNC );
APP.len += 2;
APP.score += 10;
if( (APP.level == APP.score / 100-1) && (APP.level < 9) )
{
APP.level++;
PostMessage( hwnd, CM_GAME_NEXT, 0, 0 );
}
GetRandomFoodPlace( hwnd, &APP.food );
return TRUE;
}
return FALSE;
}
//更新游戏信息
void updateGameInfo( HWND hwnd )
{
if( APP.score < 1000 )
wsprintf( APP.szGameTitle, "贪吃蛇 第 %d 关 得分: %d 进度: %d/10",
APP.level + 1, APP.score, APP.score/10%10 );
else //第十关以后的无尽模式统计方案
wsprintf( APP.szGameTitle, "贪吃蛇 第 %d 关 得分: %d 进度: %d/10",
APP.level + 1, APP.score, (APP.score-1000)/10 );
SetWindowText( hwnd, APP.szGameTitle );
}
//重置游戏状态
void resetGameStatus()
{
int i = APP.len;
APP.direction = DR_RIGHT;
APP.body[0].x = 10; APP.body[0].y = 20;
APP.food.x = -10; APP.food.y = -10;
for( i; i > 0; i-- )
{
APP.body[i].x = APP.body[0].x;
APP.body[i].y = APP.body[0].y;
}
}
//下一关
void nextLevel( HWND hwnd )
{
PlaySound( MAKEINTRESOURCE( IDR_NEXT ), (HINSTANCE)GetWindowLong( hwnd, GWL_HINSTANCE ), SND_RESOURCE | SND_ASYNC );
resetGameStatus();
InvalidateRect( hwnd, NULL, TRUE );
}
//测试是否吃到自己
BOOL testEatSelf( HWND hwnd )
{
int i = APP.len;
for( i; i > 0; i-- )
if( APP.body[0].x == APP.body[i].x && APP.body[0].y == APP.body[i].y )
{
PostMessage( hwnd, CM_GAME_OVER, 0, 0 );
return TRUE;
}
return FALSE;
}
//游戏结束
void gameOver( HWND hwnd )
{
int menuID = 0;
KillTimer( hwnd, TMR_START_MOVE );
PlaySound( MAKEINTRESOURCE( IDR_GAME_OVER ), (HINSTANCE)GetWindowLong( hwnd, GWL_HINSTANCE ), SND_RESOURCE );
InvalidateRect( hwnd, NULL, TRUE );
menuID = DialogBox(
(HINSTANCE)GetWindowLong( hwnd, GWL_HINSTANCE ),
MAKEINTRESOURCE(IDD_GAMEOVER_DLG),
hwnd, GameOverProc
);
switch( menuID )
{
case GAME_AGAIN:
gameAgain( hwnd );
break;
case GAME_MAIN:
SetWindowLong( hwnd, GWL_WNDPROC, (long)DealBeginMenuMsg );
PostMessage( hwnd, CM_GAME_READY, 0, 0 );
resetGameStatus();
APP.level = 0; APP.score = 0;
InvalidateRect( hwnd, NULL, TRUE );
SetWindowText( hwnd, TEXT("贪吃蛇") );
return ;
case GAME_EXIT:
PostMessage( hwnd, WM_DESTROY, 0, 0 );
return ;
}
}
//再来一局
void gameAgain( HWND hwnd )
{
resetGameStatus();
APP.level = 0;
APP.score = 0;
SetWindowLong( hwnd, GWL_WNDPROC, (long)PlayingProc );
PostMessage( hwnd, WM_TIMER, TMR_PLAYING_READY, 0 );
InvalidateRect( hwnd, NULL, TRUE );
}
//////////////////////////////////////////////////////////////////////////
//蛇开始移动 (封装移动方法)
void startSnakeMove( HWND hwnd )
{
if( PointImpaceTest(hwnd, APP.body[0], 0) )
{
PostMessage( hwnd, CM_GAME_OVER, 0, 0 );
return ;
}
testEating( hwnd );
drawSnakeBody( hwnd );
moveSnake( );
testEatSelf( hwnd );
updateGameInfo( hwnd );
InvalidateRect( hwnd, NULL, FALSE );
}

View File

@ -3,8 +3,12 @@
//////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#include "DealBeginMenuMsg.h"
#include "GameOverDlgProc.h"
#include "Init_Playing_Map.h"
#include "MacroDefine.h"
#include "cu_map.h"
@ -16,8 +20,9 @@ typedef struct GameStatus
{
TCHAR szGameTitle[256]; //标题栏内容
int level; //当前游戏关数
POINT head; //蛇头部所在坐标
POINT body[512]; //蛇身坐标
POINT food; //食物所在坐标
int direction; //当前行动方向
int len; //蛇身长度
int score; //游戏得分
}GM_STATUS;
@ -26,4 +31,9 @@ typedef struct GameStatus
LRESULT PlayingProc( HWND, UINT, WPARAM, LPARAM );
BOOL PointImpaceTest( HWND, POINT ); //点与障碍物的碰撞检测
BOOL PointImpaceTest( HWND, POINT, int ); //点与障碍物的碰撞检测
void GetRandomFoodPlace( HWND, POINT* ); //生成随机食物坐标
LRESULT CALLBACK StartPlaying( HWND, UINT, WPARAM, LPARAM ); //开始游戏

12
Snake.c
View File

@ -10,6 +10,7 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine
static TCHAR szGameName[] = TEXT( "Snake" );
HWND hwnd;
RECT rect;
MSG msg;
WNDCLASS wndclass;
@ -30,12 +31,17 @@ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine
return 0;
}
rect.left = 0; rect.top = 0;
rect.right = 800 + GetSystemMetrics(SM_CXFRAME);
rect.bottom = 600 + GetSystemMetrics(SM_CYCAPTION) + GetSystemMetrics(SM_CXFRAME);
AdjustWindowRect( &rect, WS_CAPTION, FALSE );
hwnd = CreateWindow(
szGameName, TEXT("̰³ÔÉß"),
WS_CAPTION | WS_SYSMENU,
(int)((GetSystemMetrics(SM_CXSCREEN)-800)/2),
(int)((GetSystemMetrics(SM_CYSCREEN)-600)/2),
800, 600,
(int)((GetSystemMetrics(SM_CXSCREEN)-rect.right) /2),
(int)((GetSystemMetrics(SM_CYSCREEN)-rect.bottom)/2),
rect.right, rect.bottom,
NULL, NULL, hInstance, NULL
);

View File

@ -43,7 +43,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /FR /YX /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x804 /d "NDEBUG"
@ -96,6 +96,10 @@ SOURCE=.\DealBeginMenuMsg.c
# End Source File
# Begin Source File
SOURCE=.\GameOverDlgProc.c
# End Source File
# Begin Source File
SOURCE=.\GameWndProc.c
# End Source File
# Begin Source File
@ -132,6 +136,10 @@ SOURCE=.\DealBeginMenuMsg.h
# End Source File
# Begin Source File
SOURCE=.\GameOverDlgProc.h
# End Source File
# Begin Source File
SOURCE=.\GameWndProc.h
# End Source File
# Begin Source File
@ -177,10 +185,18 @@ SOURCE=.\sounds\eating.wav
# End Source File
# Begin Source File
SOURCE=.\sounds\gameover.wav
# End Source File
# Begin Source File
SOURCE=.\sounds\go.wav
# End Source File
# Begin Source File
SOURCE=.\sounds\next.wav
# End Source File
# Begin Source File
SOURCE=.\sounds\ready.wav
# End Source File
# Begin Source File

View File

@ -8,15 +8,21 @@
#define IDR_EATING 103
#define IDR_READY 104
#define IDR_GO 105
#define IDR_NEXT 106
#define IDR_GAME_OVER 107
#define IDD_GAMEOVER_DLG 108
#define IDC_BTN_OK 1000
#define IDC_GAME_AGAIN 1001
#define IDC_RETURN_MAIN 1002
#define IDC_EXIT_GAME 1003
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 106
#define _APS_NEXT_RESOURCE_VALUE 109
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_CONTROL_VALUE 1004
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif

View File

@ -13,7 +13,7 @@
#undef APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
// Chinese (中国) resources
// Chinese (P.R.C.) resources
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
#ifdef _WIN32
@ -65,6 +65,8 @@ IDR_GAME_START WAVE DISCARDABLE "sounds\\start.wav"
IDR_EATING WAVE DISCARDABLE "sounds\\eating.wav"
IDR_READY WAVE DISCARDABLE "sounds\\ready.wav"
IDR_GO WAVE DISCARDABLE "sounds\\go.wav"
IDR_NEXT WAVE DISCARDABLE "sounds\\next.wav"
IDR_GAME_OVER WAVE DISCARDABLE "sounds\\gameover.wav"
/////////////////////////////////////////////////////////////////////////////
//
@ -79,6 +81,17 @@ BEGIN
DEFPUSHBUTTON "È·¶¨",IDC_BTN_OK,95,100,35,15,BS_CENTER
END
IDD_GAMEOVER_DLG DIALOG DISCARDABLE 0, 0, 187, 97
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP
FONT 10, "System"
BEGIN
PUSHBUTTON "再来一局",IDC_GAME_AGAIN,19,70,37,14,BS_CENTER |
BS_VCENTER
PUSHBUTTON "回主界面",IDC_RETURN_MAIN,74,70,37,14,BS_CENTER
PUSHBUTTON "退出游戏",IDC_EXIT_GAME,130,70,37,14,BS_CENTER |
BS_VCENTER
END
/////////////////////////////////////////////////////////////////////////////
//
@ -95,10 +108,64 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 120
END
IDD_GAMEOVER_DLG, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 180
TOPMARGIN, 7
BOTTOMMARGIN, 90
END
END
#endif // APSTUDIO_INVOKED
#endif // Chinese (中国) resources
#ifndef _MAC
/////////////////////////////////////////////////////////////////////////////
//
// Version
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,0,0,1
PRODUCTVERSION 1,0,0,1
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x1L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080404b0"
BEGIN
VALUE "Comments", "经典小游戏 - 贪吃蛇\0"
VALUE "CompanyName", "wid\0"
VALUE "FileDescription", "贪吃蛇 - 经典怀旧\0"
VALUE "FileVersion", "1, 0, 0, 1\0"
VALUE "InternalName", "Snake - 贪吃蛇\0"
VALUE "LegalCopyright", "Copyright 2013, wid\0"
VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "Snake.exe\0"
VALUE "PrivateBuild", "\0"
VALUE "ProductName", "null Snake\0"
VALUE "ProductVersion", "1, 0, 0, 1\0"
VALUE "SpecialBuild", "\0"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x804, 1200
END
END
#endif // !_MAC
#endif // Chinese (P.R.C.) resources
/////////////////////////////////////////////////////////////////////////////

Binary file not shown.

BIN
sounds/gameover.wav Normal file

Binary file not shown.

BIN
sounds/next.wav Normal file

Binary file not shown.