zoukankan      html  css  js  c++  java
  • 简单RPG场景实现

    //windows.h文件中包含应用程序中所需的数据类型和数据结构的定义
    #include <windows.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <time.h>
    #include "menu_4.h"
    #include <math.h>
    //TransparentBlt需要导入以下头文件
    #pragma  comment(lib,"Msimg32.lib")
    #include <wingdi.h>
    
    HBITMAP hBm_Dir[24]; //人物动作
    HBITMAP hBm_bg;     //背景图
    HBITMAP hBm_dia;    //弹出对话的图片
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,LPSTR lpszCmdLine,int nCmdShow)
    {
        HWND hwnd;
        MSG Msg;
        WNDCLASS wndclass;
        /*
          关于为啥在WINMAIN里面载入位图
          是因为LoadBitmap需要传入HInstance参数
          当然在WinProc里载入也是可以的
          就需要设一个全局的HInstance变量
          所以为了方便还是在WINmain里载入
        */
        //载入动作图
        hBm_Dir[0] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_L1));
        hBm_Dir[1] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_L2));
        hBm_Dir[2] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_L3));
        hBm_Dir[3] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_R1));
        hBm_Dir[4] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_R2));
        hBm_Dir[5] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_R3));
        hBm_Dir[6] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_U1));
        hBm_Dir[7] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_U2));
        hBm_Dir[8] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_U3));
        hBm_Dir[9] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_D1));
        hBm_Dir[10] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_D2));
        hBm_Dir[11] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_D3));
        hBm_Dir[12] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RD1));
        hBm_Dir[13] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RD2));
        hBm_Dir[14] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RD3));
        hBm_Dir[15] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RU1));
        hBm_Dir[16] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RU2));
        hBm_Dir[17] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_RU3));
        hBm_Dir[18] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LD1));
        hBm_Dir[19] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LD2));
        hBm_Dir[20] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LD3));
        hBm_Dir[21] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LU1));
        hBm_Dir[22] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LU2));
        hBm_Dir[23] = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_LU3));
        //载入背景图
        hBm_bg = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_BG));
        //载入对话图
        hBm_dia = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BITMAP_DIA));
        char lpszClassName[] = "窗口";
        char lpszTitle[] = "[Vic.]模仿_上古神器2";    //窗口标题名
    
        //窗口类的定义
        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 = (HBRUSH)GetStockObject(WHITE_BRUSH);
        //载入rs文件
        wndclass.lpszMenuName = "menu4" ;
        wndclass.lpszClassName = lpszClassName;
    
        if (!RegisterClass(&wndclass))
        {
            MessageBeep (0);
            return FALSE;
        }
    
    //创建窗口
        hwnd = CreateWindow(
                            lpszClassName, lpszTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,  //窗口左上角坐标为默认值
                            640,   //窗口宽度
                            510,  //窗口的髙
                            NULL, NULL, hInstance,  NULL
                            );
    
        ShowWindow( hwnd, nCmdShow);
        UpdateWindow(hwnd);
        while( GetMessage(&Msg, NULL, 0, 0))
        {
            TranslateMessage(&Msg);
            DispatchMessage(&Msg);
        }
        return Msg.wParam;
    }
    
    //窗口函数
    LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        // hdc_old和 hBmp是用于双缓冲,如果不懂双缓冲是啥,可以看看我的博客
        HDC hDC, hdc_old;
        HBITMAP hBmp;
        // 用于与hDC绑定的位图hDC与hBmp(人物,背景,对话)
        static HDC hdcmem_ch, hdcmem_bg, hdcmem_dia;
        static BITMAP bm_ch, bm_bg, bm_dia;
    
        RECT rect;
        PAINTSTRUCT ps;
        //j是用来
        static int i, j = 0;
    
        static int mx, my; //记录鼠标的位置
        static int toX = 0, toY = 0; //记录鼠标点击时的位置
        static int beforeX, beforeY;    //记录鼠标点击之前的坐标
        //设置全局标记(上下左右,左上下,右上下,鼠标点击移动,对话)
        static bool isLeft = false, isRight = false, isUp = false, isDown = false, isOut = false;
        static bool isMoving = false, isDia = false;
        static bool isLeDown = false, isRiDown = false, isRiUp = false, isLeUp = false;
        /*
        state代表的时加载哪种类型的位图
        0:抬右手
        1:抬左手
        2:静止
    
        这个主要是因为我的人物动作位图每个方位都分解为3张
        之后我将它们按这样的顺序命名与载入了
        */
        static int state = 2;
    
        /*
            dir代表的是方位标记
            按照载入顺序进行标记
            L,R,U,D, RD,RU,LD,LU
        */
        static int dir = 0;
        char str[100];
        static int x = 12, y = 204; //人物的初始位置坐标
        static int keep; //用于切换方向位图
        static int pre_dir = dir; //用于记录两次按键是否同一方向
    
        switch(message)
        {
        case WM_KEYDOWN:
            //对话状态,键盘将无法使用
            if (!isDia)
            {
                isMoving = false; //将用鼠标移动的标记打成false
                InvalidateRect(hWnd, NULL,1);//刷新
            }
            return 0;
        case WM_MOUSEMOVE:
            //对话状态,不需要记录鼠标的位置
            if (!isDia)
            {
                mx = LOWORD(lParam);
                my = HIWORD(lParam);
                InvalidateRect(hWnd, NULL,1);
            }
            return 0;
        case WM_LBUTTONDOWN:
            //对话状态,如果用鼠标左键点击则解除对话状态
            if (isDia)
            {
                isDia = false;
                x -= 10;//将人物位置后退一点以免重复触发
            }
            //其他状态,鼠标点击代表移动
            else
            {
                j = 0;
    
                beforeX = x, beforeY = y; //记录点击之前人物的位置
                if (state == 2) state = 0; //将人物重置为静止状态先
                toX = mx-bm_ch.bmWidth, toY = my-bm_ch.bmHeight; //将点击位置作为人物的落脚点(右下角)
                //设置边界
                if (toX >= 430) toX = 430;
                if (toX <= 20) toX = 20;
                if (toY >= 239) toY = 239;
                if (toY <= 179) toY = 179;
    
                isMoving = true;//将鼠标移动状态置真
                //重置方向标记
                isLeft = isRight = isUp = isDown = false;
                isLeDown = isRiDown = isLeUp = isRiUp = false;
    
                //判断人物方向
                if (mx <= x && my <= y) isLeUp = true, dir = 7;
                else if (mx <= x && my >= y+bm_ch.bmHeight) isLeDown = true, dir = 6;
                else if (mx >= x+bm_ch.bmWidth && my >= y+bm_ch.bmHeight) isRiDown = true, dir = 4;
                else if (my <= y && mx >= x+bm_ch.bmWidth) isRiUp = true, dir = 5;
                else if (my <= y) isUp = true, dir = 2;
                else if (my >= y+bm_ch.bmHeight) isDown = true, dir = 3;
                else if (mx <= x) isLeft = true, dir = 0;
                else if (mx >= x+bm_ch.bmWidth) isRight = true, dir = 1;
    
            }
            InvalidateRect(hWnd, NULL,1);
            return 0;
        case WM_CHAR:
            //对话状态,键盘将无法使用
            if (!isDia)
            {
                // 判断运动方位
                if ((HIWORD(GetAsyncKeyState('W')) || HIWORD(GetAsyncKeyState('w'))) && (HIWORD(GetAsyncKeyState('D')) || HIWORD(GetAsyncKeyState('d'))))
                {
                    //将静止状态转换为行动状态
                    if (state == 2)
                        state = 0;
                    isRiUp = true, dir = 5;
                }
                else if ((HIWORD(GetAsyncKeyState('W')) || HIWORD(GetAsyncKeyState('w'))) && (HIWORD(GetAsyncKeyState('A')) || HIWORD(GetAsyncKeyState('a'))))
                {
                    if (state == 2)
                    state = 0;
                    isLeUp = true, dir = 7;
    
                }
                else if ((HIWORD(GetAsyncKeyState('s')) || HIWORD(GetAsyncKeyState('S'))) && (HIWORD(GetAsyncKeyState('D')) || HIWORD(GetAsyncKeyState('d'))))
                {
                    if (state == 2)
                    state = 0;
                    isRiDown = true, dir = 4;
                }
                else if ((HIWORD(GetAsyncKeyState('S')) || HIWORD(GetAsyncKeyState('s'))) && (HIWORD(GetAsyncKeyState('A')) || HIWORD(GetAsyncKeyState('a'))))
                {
                    if (state == 2)
                    state = 0;
                    isLeDown = true, dir = 6;
    
                }
                else if (HIWORD(GetAsyncKeyState('A')) || HIWORD(GetAsyncKeyState('a')))
                {
                    if (state == 2)
                    state = 0;
                    isLeft = true, dir = 0;
    
                }
                else if (HIWORD(GetAsyncKeyState('D')) || HIWORD(GetAsyncKeyState('d')))
                {
                    if (state == 2)
                    state = 0;
                    isRight = true, dir = 1;
    
                }
                else if(HIWORD(GetAsyncKeyState('W')) || HIWORD(GetAsyncKeyState('w')))
                {
                    if (state == 2)
                    state = 0;
                    isUp = true, dir = 2;
    
                }
                else if(HIWORD(GetAsyncKeyState('s')) || HIWORD(GetAsyncKeyState('S')))
                {
                    if (state == 2)
                    state = 0;
                    isDown = true, dir = 3;
    
                }
            }
            InvalidateRect(hWnd, NULL, 1);
            return 0;
        case WM_KEYUP:
            //方向键抬起的时候换为静止状态
            if (!isDia)
                state = 2;
            InvalidateRect(hWnd, NULL, 1);
            return 0;
        case WM_ERASEBKGND:
            return 1;
        case WM_CREATE:
            //创建位图hDC
            hDC=GetDC(hWnd);
            hdcmem_ch=CreateCompatibleDC(hDC);
            hdcmem_dia=CreateCompatibleDC(hDC);
            hdcmem_bg=CreateCompatibleDC(hDC);
            ReleaseDC(hWnd, hDC);
            return 0;
        case WM_PAINT:
            //双缓冲绑定
            hdc_old = BeginPaint(hWnd, &ps);
            hDC = CreateCompatibleDC(hdc_old);
            GetClientRect(hWnd,&rect);
            hBmp = CreateCompatibleBitmap(hdc_old,rect.right,rect.bottom);
            SelectObject(hDC,hBmp);
    
            SelectObject(hdcmem_ch, hBm_Dir[dir*3+state]);
            //判断是否对话状态
            if (!isDia)
            {
                SelectObject(hdcmem_bg, hBm_bg);
                GetObject(hBm_bg, sizeof(BITMAP), &bm_bg);
            }
            else
            {
                SelectObject(hdcmem_dia, hBm_dia);
                GetObject(hBm_dia, sizeof(BITMAP), &bm_dia);
            }
            //绑定动作位图
            GetObject(hBm_Dir[dir*3+state], sizeof(BITMAP), &bm_ch);
            //如果持续在一个方向上就使keep增加
            //if (pre_dir == dir) 
                keep++;
            //如果不在一个方向上就将keep初始话
            //else pre_dir = dir, keep = 0;
            //如果键盘走动
            if (!isMoving)
            {
                if (isLeUp)
                {
                    //限制边界
                    if (x >= 20) x -= 3;
                    if (y >= 179) y -= 3;
                    if (keep >=5)
                    {
                        if (state == 0)
                            state = 1;
                        else if (state == 1)
                            state = 0;
                        keep = 0;
                    }
                }
                else if (isRiUp)
                {
                    if (x <= 430) x += 3;
                    if (y >= 179) y -= 3;
                    if (keep >= 5)
                    {
                        if (state == 0)
                            state = 1;
                        else if (state == 1)
                            state = 0;
                        keep = 0;
                    }
                }
                else if (isLeDown)
                {
                    if (y <= 239) y += 3;
                    if (x >= 20) x -= 3;
                    if (keep >= 5)
                    {
                        if (state == 0)
                            state = 1;
                        else if (state == 1)
                            state = 0;
                        keep = 0;
                    }
                }
                else if (isRiDown)
                {
                    if (y <= 239) y += 3;
                    if (x <= 430) x += 3;
                    if (keep >= 5)
                    {
                        if (state == 0) state = 1;
                        else if (state == 1) state = 0;
                        keep = 0;
                    }
                }
                else if (isLeft)
                {
                    if (x >= 20) x -= 5;
                    if (keep >= 5)
                    {
                        if (state == 0) state = 1;
                        else if (state == 1) state = 0;
                        keep = 0;
                    }
                }
                else if (isRight)
                {
                    if (x <= 430) x += 5;
                    if (keep >= 5)
                    {
                        if (state == 0) state = 1;
                        else if (state == 1) state = 0;
                        keep = 0;
                    }
                }
                else if (isUp)
                {
                    if (y >= 179) y -= 5;
                    if (keep >= 5)
                    {
                        if (state == 0) state = 1;
                        else if (state == 1) state = 0;
                        keep = 0;
                    }
                }
                else if (isDown)
                {
                    if (y <= 239) y += 5;
                    if (keep >= 5)
                    {
                        if (state == 0) state = 1;
                        else if (state == 1) state = 0;
                        keep = 0;
                    }
                }
                
                //将方向置空
                isLeft = isRight = isUp = isDown = false;
                isLeDown = isRiDown = isLeUp = isRiUp = false;
            }
            //如果鼠标点击
            else
            {
                Sleep(10);
                //j代表
                j++;
                int di = sqrt((toY-beforeY)*(toY-beforeY)+(toX-beforeX)*(toX-beforeX))/3;
                x = beforeX + (toX-beforeX)*j/di, y = beforeY + (toY-beforeY)*j/di;
                if (j == di) isMoving = false, state = 2;
                if (keep >= 10)
                {
                    if (state == 0) state = 1;
                    else if (state == 1) state = 0;
                    keep = 0;
                }
                InvalidateRect(hWnd, NULL, 1);
            }
            //如果到了那个位置就弹出对话
            if (x >= 430) isDia = true;
            //加载对话图片
            if (isDia) BitBlt(hDC, 0, 0, bm_dia.bmWidth, bm_dia.bmHeight,hdcmem_dia,0,0,SRCCOPY);
            //加载背景图片
            else BitBlt(hDC, 0, 0, bm_bg.bmWidth, bm_bg.bmHeight,hdcmem_bg,0,0,SRCCOPY);
            //加载人物图片
            //sprintf(str," %d %d", x, y);
            //DrawText(hDC, str, -1, &rect, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
            TransparentBlt(hDC, x, y, bm_ch.bmWidth, bm_ch.bmHeight, hdcmem_ch, 0, 0, bm_ch.bmWidth, bm_ch.bmHeight, RGB(255,255,255));
            BitBlt(hdc_old,0,0,rect.right,rect.bottom,hDC,0,0,SRCCOPY);
            DeleteObject(hBmp);
            DeleteDC(hDC);
            ReleaseDC(hWnd, hDC); //释放
            EndPaint(hWnd, &ps); //结束缓制
            return 0;
    
        case WM_DESTROY:
            //将位图释放
            for (i = 0; i < 24; i++) DeleteObject(hBm_Dir[i]);
            DeleteObject(hBm_bg);
            DeleteObject(hBm_dia);
            PostQuitMessage(0);                 //调用 PostQuitMessage 发出 WM_QUIT 消息
    
            return 0;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam); //默认时采用系统消息默认处理函数
    
        }
    
    }

     

     

     

     

  • 相关阅读:
    给读者、学生、初学者的话(不管你买哪一本计算机书,都适用)
    [回忆]我是怎么落进「写程序」这个大火坑的?
    CF1093E [Intersection of Permutations]
    CF712E [Memort and Casinos]
    CF1093G [Multidimensional Queries]
    FFT与一些冷门问题
    平面图转对偶图&19_03_21校内训练 [Everfeel]
    19_03_26校内训练[魔法卡片]
    洛谷 P4515 [COCI20092010#6] XOR
    NTT模板(无讲解)
  • 原文地址:https://www.cnblogs.com/Vikyanite/p/12654426.html
Copyright © 2011-2022 走看看