zoukankan      html  css  js  c++  java
  • 游戏编程笔记-起步(三)-贪吃蛇游戏实现

    游戏编程笔记-起步


    3.贪吃蛇游戏实现





    代码下载:http://download.csdn.net/detail/you_lan_hai/3738025

    核心代码实现如下,算法描述见 “起步(一)”:

    #include "app.h"
    #include <string.h>
    #include <stdlib.h>
    
    int g_map[100][100];//2维地图
    
    int g_nWidth = 610; //窗口宽度
    int g_nHeight = 514;//窗口高度
    
    int g_rows = 0;     //地图行数
    int g_cols = 0;     //地图列数
    int g_nSize = 30;   //地图方格尺寸
    
    struct Point//二维点
    {
        int r;//行
        int c;//列
    };
    
    Point   g_snake[1000];  //蛇
    int     g_nLength = 0;  //蛇的长度
    int     g_nSpeed;
    bool    g_bLive = true; //是否存活
    int     g_nSnakeDir = 0;    //蛇的当前移动方向。0-左,1-右,2-上,3-下
    
    const Point g_direction[4] = {{0,-1},{0,1},{-1,0},{1,0}};//四个方向运动增量。
    
    Point g_prizePos;       //奖子坐标
    
    bool g_bPause = true;   //是否暂停
    
    HBRUSH g_brushs[4];     //背景画刷
    
    
    void setSnakeDir(int dir)//设置蛇的运动方向。
    {
        if ((dir==0 && g_nSnakeDir==1)
            || (dir==1 && g_nSnakeDir==0)
            || (dir==2 && g_nSnakeDir==3)
            || (dir==3 && g_nSnakeDir==2))//反方向移动则令他暂停
        {
            g_bPause = true;
            return;//直接返回,什么也不做。
        }
        else
        {
            g_bPause = false;
            g_nSnakeDir = dir;
        }
    }
    
    void resetLevel()//重置关卡
    {
        /*初始化地图。将四边初始为障碍,即不可通过。
        * 0-可通过,1-障碍,2-奖子,3-蛇
        */
        memset(g_map,0,sizeof(g_map));
        for (int r=0; r<g_rows; ++r)
        {
            g_map[r][0] = 1;
            g_map[r][g_cols-1] = 1;
        }
        for (int c=0; c<g_cols; ++c)
        {
            g_map[0][c] = 1;
            g_map[g_rows-1][c] = 1;
        }
    
        g_nSpeed = 500;
    
        g_bPause = true;//暂停
        g_nSnakeDir = 1;//向右。
        g_bLive = true;
        g_nLength = 3;//蛇初始有3个结点
        g_snake[0].r = 1;//蛇头
        g_snake[0].c = 3;
        g_snake[1].r = 1;
        g_snake[1].c = 2;
        g_snake[2].r = 1;
        g_snake[2].c = 1;
        //把初始状态写入地图
        for (int i=0; i<g_nLength; ++i)
        {
            g_map[g_snake[i].r][g_snake[i].c] = 3;
        }
    
        //初始化奖子坐标
        g_prizePos.r = 1;
        g_prizePos.c = g_cols-2;
    }
    
    void init()//游戏初始化
    {
        g_brushs[0] = CreateSolidBrush(RGB(255,255,255));//白色画刷
        g_brushs[1] = CreateSolidBrush(RGB(0,0,255));//绘制障碍画刷
        g_brushs[2] = CreateSolidBrush(RGB(255,0,0));//绘制奖子画刷
        g_brushs[3] = CreateSolidBrush(RGB(0,255,0));//绘制蛇画刷
    
        srand(GetTickCount());
    
        //矫正窗口高度、宽度数据
        RECT rc;
        GetClientRect(getHWnd(),&rc);
        g_nWidth = rc.right - rc.left;
        g_nHeight = rc.bottom - rc.top;
    
        //计算行列值
        g_rows = g_nHeight / g_nSize;
        g_cols = g_nWidth / g_nSize;
    
        resetLevel();
    }
    
    void update()//逻辑更新
    {
        //时钟控制
        static int oldTime = 0;
        int curTime = GetTickCount();
        if (curTime - oldTime < g_nSpeed)
        {
            return ;
        }
        oldTime = curTime;
        //////////////////////////////////////////////////////////////////////////
        static int lastOcurTime = 0;//奖子上次出现的时间
    
        if(curTime - lastOcurTime > 10000)//每隔10s更新一次位置。
        {
            //lastOcurTime不为-1表示,没有被吃掉,则将原来位置的奖子从地图擦掉。
            if (lastOcurTime != -1)
            {
                g_map[g_prizePos.r][g_prizePos.c] = 0;
            }
            lastOcurTime = curTime;
    
            //随机产生奖子位置。
            bool flag = true;
            while(flag)
            {
                g_prizePos.r = rand()%(g_rows-2)+1;
                g_prizePos.c = rand()%(g_cols-2)+1;
                if (g_map[g_prizePos.r][g_prizePos.c] == 0)//符合条件
                {
                    flag = false;
                    g_map[g_prizePos.r][g_prizePos.c] = 2;
                }
            }
        }
    
        if (!g_bLive || g_bPause)//死亡或暂停
        {
            return ;
        }
    
        //先判断是否可走,即是否撞死。
        Point newHead;
        newHead.r = g_snake[0].r + g_direction[g_nSnakeDir].r;
        newHead.c = g_snake[0].c + g_direction[g_nSnakeDir].c;
        if (g_map[newHead.r][newHead.c]==1 || g_map[newHead.r][newHead.c]==3)
        {
            g_bLive = false;
            if(IDYES == MessageBox(getHWnd(),L"你撞死啦!是否重新来过?",
                L"撞死提示",MB_YESNO))
            {
                resetLevel();
            }
            else
            {
                PostQuitMessage(0);
            }
            return ;
        }
        else if (g_map[newHead.r][newHead.c] == 2)//遇到奖子
        {
            ++g_nLength ;
            lastOcurTime = -1;
            g_nSpeed -= 10;
        }
        else
        {
            //撤销尾部在地图上遗留数据
            g_map[g_snake[g_nLength-1].r][g_snake[g_nLength-1].c] = 0;
        }
        
        memmove(g_snake+1,g_snake,sizeof(Point)*(g_nLength-1));//移动蛇的中间数据
        g_snake[0].r = newHead.r;
        g_snake[0].c = newHead.c;
        
        //添加蛇头数据
        g_map[g_snake[0].r][g_snake[0].c] = 3;
        //////////////////////////////////////////////////////////////////////////
    }
    
    void render()//画面渲染
    {
        HDC hDC = GetDC(getHWnd());		//获得系统绘图设备
    
        HDC memDC = CreateCompatibleDC(0);	//创建辅助绘图设备
    
        HBITMAP bmpBack = CreateCompatibleBitmap(hDC,g_nWidth,g_nHeight);//创建掩码位图(画布)
        SelectObject(memDC,bmpBack);	//将画布贴到绘图设备上
    
        HPEN penBack = CreatePen(PS_SOLID,1,RGB(255,0,255));//创建画笔
        SelectObject(memDC,penBack);    //将画笔选到绘图设备上
    
        //擦除背景
        RECT rcClient;//区域结构
        GetClientRect(getHWnd(),&rcClient);//获得客户区域
        HBRUSH brushTemp = (HBRUSH)GetStockObject(WHITE_BRUSH);//获得库存物体,白色画刷。
        FillRect(memDC,&rcClient,brushTemp);//填充客户区域。
        //////////////////////////////////////////////////////////////////////////
    
        //绘制2维网格,矩形画法。
        for (int r=0; r<g_rows; ++ r)
        {
            for (int c=0; c<g_cols; ++c)
            {
                SelectObject(memDC,g_brushs[g_map[r][c]]);
                Rectangle(memDC,c*g_nSize,r*g_nSize,(c+1)*g_nSize,(r+1)*g_nSize);
            }
        }
    
        //////////////////////////////////////////////////////////////////////////
        BitBlt(hDC,0,0,g_nWidth,g_nHeight,memDC,0,0,SRCCOPY);//复制到系统设备上显示
        DeleteObject(penBack);  //释放画笔资源
        DeleteObject(bmpBack);  //释放位图资源
        DeleteDC(memDC);	    //释放辅助绘图设备
        ReleaseDC(getHWnd(),hDC);	//归还系统绘图设备
    
        Sleep(10);
    }
    
    void clear()//资源释放
    {
        //释放画刷资源
        for (int i=0; i<4; ++i)
        {
            if(g_brushs != NULL)
            {
                DeleteObject(g_brushs[i]);
                g_brushs[i] = NULL;
            }
        }
    }
    
    /*窗口过程。如果没有处理消息请返回0,否则返回1。*/
    LRESULT wndProc(HWND hwnd,UINT uMsg, WPARAM wParam,LPARAM lParam )
    {
        switch(uMsg)
        {
        case WM_KEYDOWN:
            {
                switch(wParam)
                {
                case VK_LEFT:  setSnakeDir(0); break; //向左
                case VK_RIGHT: setSnakeDir(1); break; //向右
                case VK_UP  :  setSnakeDir(2); break; //向上
                case VK_DOWN:  setSnakeDir(3); break; //向下
                case VK_ESCAPE: DestroyWindow(hwnd);break;
                }
            }
            break;
        default:
            return 0;
        }
        return 1;
    }
    
    //主函数
    int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE , LPSTR , int  )
    {
        if(!initApp(hInstance,L"贪吃蛇游戏",g_nWidth,g_nHeight))
        {
            return 0;
        }
    
        //初始化游戏
        init();
    
        //游戏循环
        mainLoop();
    
        //释放资源
        clear();
    
        return 0;
    }
    
    



  • 相关阅读:
    sharepoint更新
    生成Log日志文件.NET
    sharepoint绑定
    sharepoint多表查询
    数据库导入
    sharepoint插入数据
    协方差矩阵求解算法分析
    .NET提供的加密算法概述
    掩耳盗铃之使用WebBrowser封装网页
    C#委托BeginInvoke返回值乱序问题
  • 原文地址:https://www.cnblogs.com/ygxsk/p/7694015.html
Copyright © 2011-2022 走看看