BestAns

路漫漫其修远兮,吾将上下而求索

VC绘图/游戏简易教程--7:捕获按键,实现动画的简单控制 铜牌收录

教程总目录:https://codebus.cn/bestans/post/concise-lesson-contents(里面包括VC下的graphics.h的配置方法)

最常用的一个捕获按键的函数:_getch()
前几课,都把这个函数当做“按任意键继续”来用,现在我们用变量保存这个按键:

char c = _getch();

然后再做判断即可。

不过程序执行到 _getch() 是会阻塞的,直到用户有按键才能继续执行。可游戏中总不能因为等待按键而停止游戏执行吧?所以,要有一个函数,判断是否有用户按键:_kbhit()
这个函数返回当前是否有用户按键,如果有,再用 _getch() 获取即可,这样是不会阻塞的。

即:

char c;
if (_kbhit())
	c = _getch();

举一个简单的例子,如果有按键,就输出相关按键。否则,输出“.”。每隔 100 毫秒输出一次。按 ESC 退出。
注:ESC 的 ASCII 码是 27。

完整代码如下:

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

int main()
{
	char c = 0;
	while(c != 27)
	{
		if (_kbhit())
			c = _getch();
		else
			c = '.';
		
		printf("%c", c);
		Sleep(100);
	}

	return 0;
}

结合上一课的简单动画,就可以做出来靠按键移动的图形了吧,看以下代码,实现 a、d 控制圆的左右移动:

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

int main()
{
	initgraph(640, 480);
	
	int x = 320;
	
	// 画初始图形
	setlinecolor(YELLOW);
	setfillcolor(GREEN);
	fillcircle(x, 240, 20);
	
	char c = 0;
	while(c != 27)
	{
		// 获取按键
		c = _getch();
		
		// 先擦掉上次显示的旧图形
		setlinecolor(BLACK);
		setfillcolor(BLACK);
		fillcircle(x, 240, 20);
		
		// 根据输入,计算新的坐标
		switch(c)
		{
			case 'a': x-=2; break;
			case 'd': x+=2; break;
			case 27: break;
		}
		
		// 绘制新的图形
		setlinecolor(YELLOW);
		setfillcolor(GREEN);
		fillcircle(x, 240, 20);
		
		// 延时
		Sleep(10);
	}
	
	closegraph();
	return 0;
}

[作业]

请继续完成这个程序,实现以下功能:

  1. 上下的控制;
  2. 边界检测;
  3. 结合 kbhit 实现惯性移动(即按一下方向键,圆就会一直向这个方向移动)

注:上下左右等按键的控制,会返回 2 个字符。由于该系列教程面向初学者,因此有兴趣的请查看 MSDN。

评论 (8) -

  • #include <graphics.h>
    #include <conio.h>
    int eage(int x,int y) {  //返回方向
      if (x <= 20)return 180;
      else if (x >= 620) return 360;
      else if (y <= 20) return 90;
      else if (y >= 460) return 270;
      else return 0;
    }
    int main()
    {
      initgraph(640, 480);

      int x = 320;
      int y = 240;
      // 画初始图形
      setlinecolor(YELLOW);
      setfillcolor(GREEN);
      solidcircle(x, 240, 20);

      char c = 0;
      int dx = 0, dy = 0;
      while (c != 27)
      {
        // 获取按键
        if (_kbhit()) {
          c = _getch();
          dx= 5, dy = 5;
        }
        else {
          if (!eage(x,y))  ;    //未触碰边缘 且没有键入
          else  dx = 0, dy = 0;
        }

        // 先擦掉上次显示的旧图形
        setlinecolor(BLACK);
        setfillcolor(BLACK);
        solidcircle(x, y, 20);

        // 根据输入,计算新的坐标
        //如果到边界,则回退一个,变色
        if (eage(x,y)==360) {
          setfillcolor(RED);
          x -= dx;
        }
        else if (eage(x, y) == 180) {
          setfillcolor(RED);
          x += dx;
        }
        else if (eage(x, y) == 270) {
          setfillcolor(RED);
          y -= dy;
        }
        else if (eage(x, y) == 90) {
          setfillcolor(RED);
          y += dy;
        }
        else {
          setfillcolor(GREEN);
          switch (c)
          {
          case 'a': x -= dx; break;
          case 'd': x += dx; break;
          case 's': y += dy; break;
          case 'w': y -= dy; break;
          case 27: break;
          }
        }

        // 绘制新的图形
        //setlinecolor(YELLOW);
        //setfillcolor(GREEN);
        solidcircle(x, y, 20);

        // 延时
        Sleep(10);
      }

      closegraph();
      return 0;
    }
  • #include <graphics.h>
    #include <conio.h>

    int main()
    {
      initgraph(640, 480);

      int x = 320, y = 240;

      // 画初始图形
      setlinecolor(YELLOW);
      setfillcolor(GREEN);
      fillcircle(x, y, 20);

      char c = 0;
      while (c != 27)
      {
        // 获取按键
        if(_kbhit())
          c = _getch();

        // 先擦掉上次显示的旧图形
        setlinecolor(BLACK);
        setfillcolor(BLACK);
        fillcircle(x, y, 20);

        // 根据输入,计算新的坐标
        switch (c)
        {
        case 'a': x -= 20; break;
        case 'd': x += 20; break;
        case 's': y += 20; break;
        case 'w': y -= 20; break;
        case 27: break;
        }

        // 绘制新的图形
        setlinecolor(YELLOW);
        setfillcolor(GREEN);
        fillcircle(x, y, 20);

        // 延时
        Sleep(400);

        //边界检测,到边界就不动
        if (x - 20 == 0 || y - 20 == 0 || x + 20 == 640 || y + 20 == 480)
          c = 0;
      }

      closegraph();
      return 0;
    }
    • 有一个问题,后面随便按一个键他就会暂停移动,
  • 你好,我想问下那段_kbhit()函数,那个一开始就没有键入值,那么返回值就一直是0.那个程序我们就不能键入任何东西了啊
    • 键入内容以后,_kbhit() 就会返回 true。
  • 怎样让图形自己向下移动的同时通过键盘控制左右移动,两者不冲突
    • 准确来说,就是在while(c!=27)里面,if(_kbhit())后面加一段:先擦除原图形,y+=10,再画新图形,然后整个延时。(大概吧……吧?)

添加评论