JavaScript制作贪吃蛇游戏代码

JavaScript011

JavaScript制作贪吃蛇游戏代码,第1张

蛇的身体:数组

食物:在规定范围内生成的随机数

蛇的身体累加:数组元素个数增加

蛇碰墙死:数组首个元素的x值或y值小于0或者大于地图的宽度活高度

蛇咬自己死:数组首个元素的x值和y值和其他元素值重复

移动速度:在指定的时间内调用移动方法

开始:开始调用方法

暂停:暂停调用方法

积分:蛇没吃一个食物,全局变量加1

自己做吧,很简单,做完进步很大

// Snake.cpp

#include <windows.h>

#include <tchar.h>

#include <atlimage.h>

#include <deque>

using namespace std

#include <Mmsystem.h>

#pragma comment( lib,"winmm.lib" )

const UINT MAX_LOADSTRING = 40

TCHAR szTitle[MAX_LOADSTRING] = "贪吃蛇 js简化版1.1"

TCHAR szWindowClass[MAX_LOADSTRING] = "Snake"

ATOM MyRegisterClass(HINSTANCE hInstance)

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM)

const UINT BMP_WIDTH = 600

const UINT BMP_HEGITH = 600

HWND g_hWnd

HDC g_hDC

HDC g_hBufDC

HBITMAP g_hBufBmp

CImage g_Bg //背景图

CImage g_Snake //蛇图

CImage g_Food //食物图

CImage g_Head //蛇头图

CImage g_Rear //蛇尾图

CImage g_Shibai //死亡图

deque<POINT> g_SnakeDeque //蛇位置队列

POINT g_FoodPos //食物位置

int iSnakeDir //蛇位置方向

enum DIR_ENUM { DIR_UP,DIR_DN,DIR_LT,DIR_RT }  //枚举4个方向

int iKey  //记录玩家按下的按键值

int iLife = 3 //三条生命

bool bIsDie = false //是否死亡过

bool bAtc = false

POINT ptHead

void GameInit() //游戏初始化

void GameFrame() //游戏帧

void InputProcess() //输入处理

void LogicProcess() //逻辑处理

void WndDrawProcess() //窗口图形绘制

//判断pt点是否在蛇身

bool IsInSnake( POINT pt )

{

for (UINT i=0i<g_SnakeDeque.size()i++)

{

if (g_SnakeDeque[i].x == pt.x && g_SnakeDeque[i].y == pt.y)

{

return true

}

}

return false

}

//随机食物位置

void FoodRand()

{

do 

{

g_FoodPos.x = rand()%20*30  //宽600,最多有20个30,随机一下

g_FoodPos.y = rand()%20*30

} while (IsInSnake(g_FoodPos))

}

void GameInit()

{

g_hDC = GetDC(g_hWnd)

g_hBufDC = CreateCompatibleDC(g_hDC)

g_hBufBmp = CreateCompatibleBitmap(g_hDC,BMP_WIDTH,BMP_HEGITH)

SelectObject(g_hBufDC,g_hBufBmp)

ReleaseDC(g_hWnd,g_hDC)

g_Bg.Load("bg.png")

g_Snake.Load("snake.png")

g_Food.Load("food.png")

g_Head.Load("head.png")

g_Rear.Load("rear.png")

g_Shibai.Load("sbai.png")

POINT ptSnake = {300,300} //定义蛇位置

g_SnakeDeque.push_back(ptSnake)//位置加入队列中

iSnakeDir = rand()%4 //随机蛇运动方向

mciSendString( "open bg.mp3 alias bgMusic",NULL,0,NULL ) //发送MIC命令:打开bgMusic.mp3文件,并命名为 bgMusic 记住这名字很重要

mciSendString( "play bgMusic from 0 repeat",NULL,0,NULL )//从0开始播放bgMusic,并重复播放 其他的命令还算有stop,pause等

//以此类推,先读取了吃到食物和死亡的音乐,在指定位置播放

mciSendString( "open eat.wav alias eatMusic",NULL,0,NULL ) //同上(能支持CD,MP3,wav,midi,avi等格式,不支持rm或rmvb或ogg等)

mciSendString( "open die.wav alias dieMusic",NULL,0,NULL ) //同上

srand( timeGetTime() ) //随机种子,使得每次随机不一样

FoodRand()

}

void GameFrame()

{

static  int iStep = timeGetTime() //速度限制一下

if( timeGetTime()-iStep > 300 ) //300毫秒移动一次,想快点可以改,也可以作为难度递增,改小此值

{

iStep = timeGetTime()

InputProcess()

LogicProcess()

}

WndDrawProcess()

}

void InputProcess() //输入处理

{

//控制蛇运动

if( iKey == VK_UP ) //如果按下“上”键,其他按键可以自己改,VK_开头,如果是字母或数字按键,则对应ASCII码

{

if( iSnakeDir == DIR_LT || iSnakeDir == DIR_RT ) //若蛇正往左右走时才能改变

{

iSnakeDir = DIR_UP

}

}

else if(  iKey == VK_DOWN ) //以此类推

{

if( iSnakeDir == DIR_LT || iSnakeDir == DIR_RT )

{

iSnakeDir = DIR_DN

}

}

else if(  iKey == VK_LEFT )

{

if( iSnakeDir == DIR_UP || iSnakeDir == DIR_DN )

{

iSnakeDir = DIR_LT

}

}

else if(  iKey == VK_RIGHT )

{

if( iSnakeDir == DIR_UP || iSnakeDir == DIR_DN )

{

iSnakeDir = DIR_RT

}

}

//蛇运动,其实蛇的运动就是蛇头根据方向往前走一步,而蛇尾去掉一步,

//如果转化为算法就是在队列前根据方向加入一个节点,去掉队列最后一个节点,好好理解,算法的重要性

ptHead = g_SnakeDeque.front() //获取第一个节点

if( iSnakeDir == DIR_UP )

{

ptHead.y -= 30

}

else if( iSnakeDir == DIR_DN )

{

ptHead.y += 30

}

else if( iSnakeDir == DIR_LT )

{

ptHead.x -= 30

}

else if( iSnakeDir == DIR_RT )

{

ptHead.x += 30

}

}

void LogicProcess() //逻辑处理

{

//蛇出界了或者蛇吃到自己身体了,需要死掉

if( ptHead.x < 0 || ptHead.x >= 600 || ptHead.y <0 || ptHead.y >= 600 || IsInSnake(ptHead) )

{

mciSendString( "play dieMusic from 0",NULL,0,NULL ) //播放死亡音乐

g_SnakeDeque.clear() //全清

POINT ptSnake = {300,300} //定义蛇的位置

g_SnakeDeque.push_back( ptSnake ) //放入蛇的节点中

iSnakeDir = rand()%4 //随机蛇运动方向

iLife-- //死亡,生命减1

if( iLife <= 0 )

{

bIsDie = true

g_hDC = GetDC(g_hWnd)

g_Shibai.Draw(g_hDC,0,0)

ReleaseDC(g_hWnd,g_hDC)

int ret = MessageBox(g_hWnd,"3次生命已用完 \n 是否重新开始程序!","提示",MB_OKCANCEL)

if (ret == IDOK)

{

FoodRand()

return

}

DestroyWindow(g_hWnd) //摧毁关闭窗口

return

}

}

else if( ptHead.x==g_FoodPos.x && ptHead.y==g_FoodPos.y ) //蛇吃到食物

{

mciSendString( "play eatMusic from 0",NULL,0,NULL ) //播放吃到食物音乐

g_SnakeDeque.push_front( ptHead ) //新的位置加入蛇头,蛇头往前移动

//g_SnakeDeque.pop_back() //和正常行走最大的不同

FoodRand() //重新随机食物

}

else //无出界,无吃到自身,无吃到食物,正常行走

{

g_SnakeDeque.push_front( ptHead ) //新的位置加入蛇头,蛇头往前移动

g_SnakeDeque.pop_back() //删除最后节点,蛇尾往前收

}

}

void WndDrawProcess() //绘图处理

{

RECT rc = {0,0,BMP_WIDTH,BMP_HEGITH}

FillRect(g_hBufDC,&rc,(HBRUSH)GetStockObject(WHITE_BRUSH))

g_Bg.Draw(g_hBufDC,0,0)//绘制背景

g_hDC = GetDC(g_hWnd)

for( UINT i=0 i<g_SnakeDeque.size() i++ ) //遍历蛇的节点,绘画蛇的样子

{

if( i== 0 )

{

g_Head.Draw( g_hBufDC, g_SnakeDeque[i].x, g_SnakeDeque[i].y ) //绘画蛇头

}

else if( i == g_SnakeDeque.size()-1 )

{

g_Rear.Draw( g_hBufDC, g_SnakeDeque[i].x, g_SnakeDeque[i].y ) //绘画蛇尾

}

else

{

g_Snake.Draw( g_hBufDC, g_SnakeDeque[i].x, g_SnakeDeque[i].y ) //绘画蛇身,把蛇的样子画到指点位置节点上

}

}

//绘画食物

g_Food.Draw( g_hBufDC, g_FoodPos.x, g_FoodPos.y )

if (bIsDie)

{

iLife = 3

bIsDie = false

}

//绘画生命数

char sz[32] = {0}

for( int i=0 i<iLife i++ )

{

strcat_s( sz, " ★") //根据生命数,加入红心

}

SetTextColor( g_hBufDC, RGB(255,0,0) )//设置字体颜色为红色

SetBkMode( g_hBufDC,TRANSPARENT ) //设置字体背景颜色为透明

TextOut( g_hBufDC,0,0,sz,strlen(sz)) //输出字体

BitBlt(g_hDC,0,0,BMP_WIDTH,BMP_HEGITH,g_hBufDC,0,0,SRCCOPY)

ReleaseDC(g_hWnd,g_hDC)

}

int APIENTRY _tWinMain(HINSTANCE hInstance,

   HINSTANCE /*hPrevInstance*/,

   LPTSTR    /*lpCmdLine*/,

   int       nCmdShow)

{

MSG msg

MyRegisterClass(hInstance)

int iW = 600+GetSystemMetrics(SM_CXFIXEDFRAME)*2

int iH = 600+GetSystemMetrics(SM_CYFIXEDFRAME)*2+GetSystemMetrics(SM_CYCAPTION)

int iX = (GetSystemMetrics(SM_CXSCREEN)-iW)/2

int iY = (GetSystemMetrics(SM_CYSCREEN)-iH)/2

g_hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,

iX, iY, iW, iH, NULL, NULL, hInstance, NULL)

if (!g_hWnd)

{

return FALSE

}

GameInit()

ShowWindow(g_hWnd, nCmdShow)

UpdateWindow(g_hWnd)

ZeroMemory(&msg,sizeof(MSG))

while (msg.message != WM_QUIT)

{

if (PeekMessage(&msg, NULL, 0, 0,PM_REMOVE))

{

TranslateMessage(&msg)

DispatchMessage(&msg)

}

else if(!bAtc)

{

GameFrame()

}

else

{

::WaitMessage()

}

}

return (int) msg.wParam

}

ATOM MyRegisterClass(HINSTANCE hInstance)

{

WNDCLASSEX wcex

wcex.cbSize = sizeof(WNDCLASSEX)

wcex.style = CS_HREDRAW | CS_VREDRAW

wcex.lpfnWndProc = WndProc

wcex.cbClsExtra = 0

wcex.cbWndExtra = 0

wcex.hInstance = hInstance

wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SNAKE))

wcex.hCursor = LoadCursor(NULL, IDC_ARROW)

wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1)

wcex.lpszMenuName = NULL

wcex.lpszClassName = szWindowClass

wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL))

return RegisterClassEx(&wcex)

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)

{

switch (message)

{

case WM_KILLFOCUS:

bAtc = true

break

case WM_SETFOCUS:

bAtc = false

break

case WM_KEYDOWN:

iKey = wParam //玩家按下按键是捕获按键值

break

case WM_DESTROY:

DeleteObject(g_hBufBmp)

DeleteDC(g_hBufDC)

PostQuitMessage(0)

break

default:

return DefWindowProc(hWnd, message, wParam, lParam)

}

return 0

}