EasyX图形库note4,动画及键盘交互

简介: EasyX图形库note4,动画及键盘交互

动画

在之前的笔记中,我们所绘制的图形都是静态的,现在我们通过代码让图形动起来。

就像小时候我们看的葫芦娃小金刚一样,动画是由一帧一帧的图片逐个快速播放,利用人的视觉停留,就可以达到动画的效果。一般来说电视每秒播放24帧画面,游戏更高,在打游戏时游戏帧率越高,游戏画面也就越流畅。

用前边的知识绘制一个半径100圆形,窗体大小800*600,圆心初始坐标为(-400,0)。颜色可以自己选择。

  • 要实现像动画一样逐帧播放,我们可以不断改变圆心的x坐标,更改后清除上一次画的圆形,然后重新画出位置变化的圆形,同时要使用Sleep()函数暂停程序一段时间。

代码如下

int main()
{
  initgraph(800,600);
  setbkcolor(RGB(150, 205, 205));
  cleardevice();
  setorigin(400, 300);
  setaspectratio(1, -1);
  setfillcolor(RGB(106, 90, 205));
  int dx = 15;
  for (int x = -400; x <= 400; x += dx)
  {
    solidcircle(x, 0, 100);
    Sleep(200);
    cleardevice();
  }
  getchar();
  return 0;
}

画出一个圆形后,Sleep200毫秒,清空屏幕后画出下一个,再Sleep200毫秒。直到运动到最右端循环结束,getchar阻塞进程。

运行后效果如下

因为休眠函数在每次循环时休眠200毫秒,所以在一秒内可以播放五帧画面,每次移动的距离为15像素,所以圆形的移动速度为每秒75像素。

如果想让画面更加流畅,然而圆形的移动速度几乎不变,就要加大帧率,减小每次移动的像素。

  • 将休眠时间改为50毫秒,将每次移动的像素即dx设置为5。
    运行后效果如图

    对比上边流畅很多。

键盘交互

在动画的基础上,加入键盘交互功能,按下w键,圆形向上移动,按下a键,圆形向左移动,按下d键,圆形向右移动,按下s键,圆形向下移动。

首先如何从键盘上读取信息?

我们会想到使用getchar函数,有了思路就开始编写代码实现按下w键,圆形向上移动50像素。

int main()
{
  initgraph(800,600);
  setbkcolor(RGB(150, 205, 205));
  cleardevice();
  setorigin(400, 300);
  setaspectratio(1, -1);
  int x = 0;
  int y = 0;
  setfillcolor(GREEN);
  solidcircle(x, y, 50);//画出圆形
  while (1)
  {
    char c = getchar();
    if (c == 'w')
    {
      y += 50;
    }
    cleardevice();//清除窗体
    solidcircle(x, y, 50);//画出圆形
  }
  getchar();
  return 0;
}

编写完成后运行代码,发现按下’w’键没有任何反应,按下回车后才会向上移动,而且点击n次w键,会直接向上移动n*50像素。这是为什么呢?

  • 让我们深入了解一下getchar函数

getchar函数从输入缓存区中读取一个字符,如果读取成功,就返回读取到的字符,如果缓存区中没有数据,函数将会阻塞进程,直到缓存区里有数据。

在控制台上输入数据,但数据还没有进入输入缓存区,需要按下回车键,才会将输入的全部数据放在缓存区,然后getchar函数取出第一个字符并返回这个字符。若在循环中,getchar会依次取出这些数据,直到没有数据为止。

我们想让动画和键盘交互组合,但getchar函数明显不满足需求,想要实现实时型交互,按下键盘后程序就作出反应,而不是按下回车后才运行,运行之后又堵塞。


这里就要提到getch函数


无需回车,只需要按下键盘就可以将数据送进输入缓存区。

别忘记包含头文件<conio.h>

写一串代码探究其特性

注:在使用getch函数时,要写成_getch的形式。

代码如下

#include <conio.h>
int main()
{
  while (1)
  {
    char c;
    c = _getch();
    putchar(c - 32);
  }
  return 0;
}

运行后输入小写a就直接在控制台打印出A,输入b就直接打印B。

解决了回车问题,我们想在圆形移动的时候就可以控制圆移动的方向,而getch仍然具有阻塞程序运行的作用。这种用户输入之后场景才发生变化的适合推箱子游戏,2048等,然而对于就算没有输入整个场景仍然会变化的场景则不适用。

介绍一下函数kbhit

int kbhit(void);

kbhit函数会检查getch函数的输入缓存区中是否有数据,若没有数据就返回0,如果有数据就返回非0的数。

这个函数不会阻塞程序的运行,可以借此判断是否用户按下了键盘,然后再做出反应,这样就不会阻塞程序的运行。kbhit函数也要写作_kbhit。


对前边的圆形动画做出改变,加上键盘交互功能。

代码如下

int main()
{
  initgraph(800, 600);
  setbkcolor(RGB(150, 205, 205));
  cleardevice();
  setorigin(400, 300);
  setaspectratio(1, -1);
  setfillcolor(RGB(106, 90, 205));
  int x = -400, y = 0;
  int dx = 5 , dy=0;
  while (1)
  {
    cleardevice();
    solidcircle(x, y, 50);
    Sleep(40);
    if (_kbhit() != 0)
    {
      char c = _getch();
      switch (c)
      {
      case'w':
        dx = 0;
        dy = 5;
        break;
      case'a':
        dx = -5;
        dy = 0;
        break;
      case's':
        dx = 0;
        dy = -5;
        break;
      case'd':
        dx = 5;
        dy = 0;
        break;
      }
    }
    x =x+ dx;
    y =y+ dy;
  }
  getchar();
  return 0;
}

起始位置在最左边,刚开始设置dx为5,即圆形向右移动,只有我们按下键盘才会进入switch语句,更改dx与dy的值,从而实现在运动中改变运动的方向。

运行后效果如下

接下来会用今天所学的知识来实现一个简单的弹球小游戏。希望大家有所收获。

目录
相关文章
|
传感器 数据采集 算法
【软件设计师备考 专题 】系统可靠性分析评价
【软件设计师备考 专题 】系统可靠性分析评价
748 0
|
12月前
|
人工智能 搜索推荐 安全
正式上线!阿里云短信模板 AI 助手,10 秒生成/改写个性化、合规短信内容
阿里云短信服务 - 短信模板AI 助手已全面开放,欢迎体验!
744 6
|
SQL Java 数据库连接
MyBatis-Plus高级用法:最优化持久层开发
MyBatis-Plus 通过简化常见的持久层开发任务,提高了开发效率和代码的可维护性。通过合理使用条件构造器、分页插件、逻辑删除和代码生成器等高级功能,可以进一步优化持久层开发,提升系统性能和稳定性。掌握这些高级用法和最佳实践,有助于开发者构建高效、稳定和可扩展的企业级应用。
815 13
|
Prometheus 监控 Cloud Native
基于Docker安装Grafana和Prometheus
Grafana 是一款用 Go 语言开发的开源数据可视化工具,支持数据监控和统计,并具备告警功能。通过 Docker 部署 Grafana 和 Prometheus,可实现系统数据的采集、展示和告警。默认登录用户名和密码均为 admin。配置 Prometheus 数据源后,可导入主机监控模板(ID 8919)进行数据展示。
1016 2
|
数据采集 监控 数据可视化
万界星空科技低代码云mes,更适合中小企业的mes系统
万界星空科技的低代码云MES系统,针对中小企业设计,确实展现出了诸多适应性和灵活性,特别是在提升生产管理效率、优化资源配置以及增强数据可视化方面。
252 7
万界星空科技低代码云mes,更适合中小企业的mes系统
SDL基础使用04(SDL_image与SDL_mixer扩展库)
本文介绍了如何使用SDL_image和SDL_mixer扩展库在SDL项目中加载和显示图片以及播放音频文件。
743 1
|
存储 SQL 关系型数据库
MySQL存储过程与触发器:提升数据库操作效率与数据一致性
本文深入探讨了MySQL数据库中的存储过程与触发器,通过丰富的代码示例,详细介绍了存储过程的定义与调用、参数与变量的应用,以及触发器的创建、使用和实际案例。存储过程作为预定义的一组SQL语句,能够提高数据库操作的效率,实现数据逻辑和复杂计算。同时,触发器作为在特定事件触发时自动执行的SQL语句,能够保障数据一致性和逻辑完整性。通过代码实例,读者将了解如何创建、调用存储过程,如何利用参数和变量进行数据处理,以及如何创建触发器并应用于实际场景。这些技术将使读者能够在数据库管理中更高效地进行操作和保障数据的完整性,为应用程序提供可靠的数据支持。
1414 0
|
前端开发 Java Maven
springboot整合websocket最基础入门使用教程详解
springboot整合websocket最基础入门使用教程详解
4355 0
springboot整合websocket最基础入门使用教程详解
|
Java 程序员
Java中的强制类型转换(Explicit Type Casting)
Java中的强制类型转换(Explicit Type Casting)
1046 0
|
前端开发 网络协议 JavaScript