时语-shine 2022-08-15 16:35 采纳率: 61.5%
浏览 87
已结题

对于GetAsyncKeyState()函数实现贴图移动的问题

最近在做类似于飞机大战的小游戏,其中就有对于飞机移动的实现,为了按键移动更流畅,都是用的GetAsyncKeyState()函数,而不是getch()来获取按键。但我自己在编程的时候遇到移动过于灵敏的情况,找不出原因,测试代码如下:

#include <graphics.h>
#include <conio.h>

struct gamer {
    int x;
    int y;
};
struct gamer gamer1;
IMAGE img;

void move() {
    if (GetAsyncKeyState(VK_UP)) {
        gamer1.y -=10;

    }
    if (GetAsyncKeyState(VK_DOWN)) {
        gamer1.y +=10;

    }
}
int main() {
    initgraph(640, 480);
    gamer1.x = 0;
    gamer1.y = 0;
    loadimage(&img,"dog.jpg");
    while (1) {
        putimage(gamer1.x, gamer1.y, &img);
        move();
        //_getch();
        cleardevice();
    }
    return 0;
}

运行的时候发现按一下方向键,贴图会移动的飞快(这段代码中没有编写边界保护),即使把贴图移动速度设置的很慢也解决不了问题。
为什么会出现这样的情况?

  • 写回答

3条回答 默认 最新

  • 赵4老师 2022-08-15 17:11
    关注

    仅供参考:

    #include <conio.h>
    #include <windows.h>
    
    void ConPrintAt(int x, int y, char *CharBuffer, int len)
    {
       DWORD count;
       COORD coord = {x, y};
       HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
       SetConsoleCursorPosition(hStdOut, coord);
       WriteConsole(hStdOut, CharBuffer, len, &count, NULL);
    }
    void HideTheCursor()
    {
       CONSOLE_CURSOR_INFO cciCursor;
       HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    
       if(GetConsoleCursorInfo(hStdOut, &cciCursor))
       {
          cciCursor.bVisible = FALSE;
          SetConsoleCursorInfo(hStdOut, &cciCursor);
       }
    }
    
    void ShowTheCursor()
    {
       CONSOLE_CURSOR_INFO cciCursor;
       HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
    
       if(GetConsoleCursorInfo(hStdOut, &cciCursor))
       {
          cciCursor.bVisible = TRUE;
          SetConsoleCursorInfo(hStdOut, &cciCursor);
       }
    }
    void GetWH(int *w,int *h) {
        HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        if (GetConsoleScreenBufferInfo(hStdOut, &csbi)) {
            *w=csbi.srWindow.Right;
            *h=csbi.srWindow.Bottom;
        } else {
            *w=80;
            *h=25;
        }
    }
    void ClearConsole()
    {
       //Get the handle to the current output buffer...
       HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
       //This is used to reset the carat/cursor to the top left.
       COORD coord = {0, 0};
       //A return value... indicating how many chars were written
       //   not used but we need to capture this since it will be
       //   written anyway (passing NULL causes an access violation).
       DWORD count;
       //This is a structure containing all of the console info
       // it is used here to find the size of the console.
       CONSOLE_SCREEN_BUFFER_INFO csbi;
       //Here we will set the current color
       if(GetConsoleScreenBufferInfo(hStdOut, &csbi))
       {
          //This fills the buffer with a given character (in this case 32=space).
          FillConsoleOutputCharacter(hStdOut, (TCHAR) 32, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
          FillConsoleOutputAttribute(hStdOut, csbi.wAttributes, csbi.dwSize.X * csbi.dwSize.Y, coord, &count);
          //This will set our cursor position for the next print statement.
          SetConsoleCursorPosition(hStdOut, coord);
       }
    }
    
    int main() {
        unsigned short k;
        int x,y,w,h;
    
        SetConsoleOutputCP(437);
        ClearConsole();
        GetWH(&w,&h);
        x=w/2;y=h/2;
        HideTheCursor();
        ConPrintAt(x,y,"O",1);
        while (1) {
            Sleep(50);
            k=getch();
            if (27==k) break;//按Esc键退出
            if (0==k||0xe0==k) k|=getch()<<8;//非字符键
            switch (k) {
                case 0x48e0:case 0x04800://if (y>0) {
                        ConPrintAt(x,y," ",1);
                        y--;
                        ConPrintAt(x,y,"O",1);
                    }
                break;
                case 0x50e0:case 0x05000://if (y<h) {
                        ConPrintAt(x,y," ",1);
                        y++;
                        ConPrintAt(x,y,"O",1);
                    }
                break;
                case 0x4be0:case 0x04b00://if (x>0) {
                        ConPrintAt(x,y," ",1);
                        x--;
                        ConPrintAt(x,y,"O",1);
                    }
                break;
                case 0x4de0:case 0x04d00://if (x<w-1) {
                        ConPrintAt(x,y," ",1);
                        x++;
                        ConPrintAt(x,y,"O",1);
                    }
                break;
            }
    //      cprintf("%04x pressed.\r\n",k);
    
        }
        ClearConsole();
        ShowTheCursor();
        return 0;
    }
    
    
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月30日
  • 已采纳回答 11月22日
  • 创建了问题 8月15日

悬赏问题

  • ¥15 matlab实现基于主成分变换的图像融合。
  • ¥15 对于相关问题的求解与代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 信号傅里叶变换在matlab上遇到的小问题请求帮助
  • ¥15 保护模式-系统加载-段寄存器
  • ¥15 电脑桌面设定一个区域禁止鼠标操作
  • ¥15 求NPF226060磁芯的详细资料
  • ¥15 使用R语言marginaleffects包进行边际效应图绘制
  • ¥20 usb设备兼容性问题
  • ¥15 错误(10048): “调用exui内部功能”库命令的参数“参数4”不能接受空数据。怎么解决啊