《Java 2D游戏编程入门》—— 2.2 键盘改进

简介: 尽管键盘输入类允许在游戏循环中访问键盘状态,但是实现起来还是有一些问题。首先,游戏循环代码执行的时候,如果键盘按键没有按下,将会错过keypress事件。尽管对于这些简单的示例来说,不太可能发生这种情况,但当应用程序变得更强大并且游戏循环需要更多的时间来处理代码时,游戏循环就可能变得太慢而导致错过了输入。

本节书摘来异步社区《Java 2D游戏编程入门》一书中的第2章,第2.2节,作者:【美】Timothy Wright(莱特),更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.2 键盘改进

尽管键盘输入类允许在游戏循环中访问键盘状态,但是实现起来还是有一些问题。首先,游戏循环代码执行的时候,如果键盘按键没有按下,将会错过keypress事件。尽管对于这些简单的示例来说,不太可能发生这种情况,但当应用程序变得更强大并且游戏循环需要更多的时间来处理代码时,游戏循环就可能变得太慢而导致错过了输入。现在,只需要知道这可能是一个问题就行了。我们将会在第11章中讨论确保事件不会被错过的一种解决方案。

第二个问题是,当按键第一次被按下的时候,很难进行测试。如果需要跟踪20个按键,并且其中一些按键会根据游戏的状态而改变行为,那么,试图使用类似下面的代码来跟踪所有这些状态,可能会变得非常糟糕:

// SimpleKeyboardExample.java
if( keys.keyDown( KeyEvent.VK_SPACE ) ) {
  if( !space ) {
    System.out.println( "VK_SPACE" );
  }
  space = true;
} else {
  space = false;
}```
为了更新KeyboardInput类来跟踪初始的按键事件以及键盘状态,添加了一个整数型数值的数组。这些值将会记录按键被按下了多少帧。实现KeyListener接口的代码并不会改变,但是keyDown()方法不再会从布尔的按键数组提取值。

poll()方法同步地保护共享的按键数组,将键盘状态从布尔型数组转换为整数型数组。如果按键按下,这个值将会增加1;否则的话,它将会设置为0。现在,keyDown()方法将检测这个值是否为0,并且当这个值确实为1的时候,新的方法keyDownOnce()将会返回真。

package javagames.util;
import java.awt.event.*;
public class KeyboardInput implements KeyListener {
  private boolean[] keys;
  private int[] polled;
  public KeyboardInput() {
    keys = new boolean[ 256 ];
    polled = new int[ 256 ];
  }
  public boolean keyDown( int keyCode ) {
    return polled[ keyCode ] > 0;
  }
  public boolean keyDownOnce( int keyCode ) {
    return polled[ keyCode ] == 1;
  }
  public synchronized void poll() {
    for( int i = 0; i < keys.length; ++i ) {
      if( keys[i] ) {
        polled[i]++;
      } else {
        polled[i] = 0;
      }
    }
  }
  public synchronized void keyPressed( KeyEvent e ) {
    int keyCode = e.getKeyCode();
    if( keyCode >= 0 && keyCode < keys.length ) {
      keys[ keyCode ] = true;
    }
  }
  public synchronized void keyReleased( KeyEvent e ) {
    int keyCode = e.getKeyCode();
    if( keyCode >= 0 && keyCode < keys.length ) {
      keys[ keyCode ] = false;
    }
  }
  public void keyTyped( KeyEvent e ) {
    // Not needed
  }
}`

别忘了,针对每一帧要调用KeyboardInput.poll() 方法。
通过使用如下代码替换前面例子中的游戏循环代码,可以使用这个新的类。检查空格键按下一次所需的代码大大简化了。

// replacing the game loop
public void gameLoop() {
  keys.poll(); 
  if( keys.keyDownOnce( KeyEvent.VK_SPACE ) ) {
    System.out.println( "VK_SPACE" );
  }
  if( keys.keyDown( KeyEvent.VK_UP ) ) {
    System.out.println( "VK_UP" );
  }
  if( keys.keyDown( KeyEvent.VK_DOWN ) ) {
    System.out.println( "VK_DOWN" );
  }
  if( keys.keyDown( KeyEvent.VK_LEFT ) ) {
    System.out.println( "VK_LEFT" );
  }
  if( keys.keyDown( KeyEvent.VK_RIGHT ) ) {
    System.out.println( "VK_RIGHT" );
  }
  try {
    Thread.sleep( 10 );
  } catch( InterruptedException ex ) { }
相关文章
|
1月前
|
XML Java 数据库连接
谈谈Java反射:从入门到实践,再到原理
谈谈Java反射:从入门到实践,再到原理
60 0
|
15天前
|
Java
java_键盘录入、随机数
本文介绍了Java中键盘录入和Random类的使用。键盘录入用于从用户那里获取数据,通过导入`java.util.Scanner`,创建`Scanner`对象,调用`nextInt()`或`nextDouble()`读取整数和小数,`next()`读取字符串。Random类用于生成随机整数,导入该类后创建对象,调用`nextInt(int bound)`生成[0, bound-1]范围内的随机数。在JDK17及以上版本,可以使用`nextInt(int start, int end)`生成[start, end)范围的随机数。常见应用包括猜数字游戏和随机点名。
13 0
|
16天前
|
Java
Java练习题-键盘录入字符串实现大小写转换
Java练习题-键盘录入字符串实现大小写转换
20 2
|
24天前
|
关系型数据库 Java 开发工具
Java入门高频考查基础知识9(15问万字参考答案)
本文探讨了Spring Cloud的工作原理,包括注册中心的心跳机制、服务发现机制,以及Eureka默认的负载均衡策略。同时,概述了Spring Boot中常用的注解及其实现方式,并深入讨论了Spring事务的注解、回滚条件、传播性和隔离级别。文章还介绍了MySQL的存储引擎及其区别,特别关注了InnoDB如何实现MySQL的事务处理。此外,本文还详细探讨了MySQL索引,包括B+树的原理和设计索引的方法。最后,比较了Git和SVN的区别,并介绍了Git命令的底层原理及流程。
32 0
Java入门高频考查基础知识9(15问万字参考答案)
|
24天前
|
存储 缓存 算法
Java入门高频考查基础知识4(字节跳动面试题18题2.5万字参考答案)
最重要的是保持自信和冷静。提前准备,并对自己的知识和经验有自信,这样您就能在面试中展现出最佳的表现。祝您面试顺利!Java 是一种广泛使用的面向对象编程语言,在软件开发领域有着重要的地位。Java 提供了丰富的库和强大的特性,适用于多种应用场景,包括企业应用、移动应用、嵌入式系统等。下是几个面试技巧:复习核心概念、熟悉常见问题、编码实践、项目经验准备、注意优缺点、积极参与互动、准备好问题问对方和知其所以然等,多准备最好轻松能举一反三。
49 0
Java入门高频考查基础知识4(字节跳动面试题18题2.5万字参考答案)
|
24天前
|
存储 算法 JavaScript
Java入门高频考查算法逻辑基础知识3-编程篇(超详细18题1.8万字参考编程实现)
解决这类问题时,建议采取下面的步骤: 理解数学原理:确保你懂得基本的数学公式和法则,这对于制定解决方案至关重要。 优化算法:了解时间复杂度和空间复杂度,并寻找优化的机会。特别注意避免不必要的重复计算。 代码实践:多编写实践代码,并确保你的代码是高效、清晰且稳健的。 错误检查和测试:要为你的代码编写测试案例,测试标准的、边缘情况以及异常输入。 进行复杂问题简化:面对复杂的问题时,先尝试简化问题,然后逐步分析和解决。 沟通和解释:在编写代码的时候清晰地沟通你的思路,不仅要写出正确的代码,还要能向面试官解释你的
33 0
|
24天前
|
存储 Java 编译器
Java入门高频考查基础知识2(超详细28题2.5万字答案)
多态是面向对象编程中的一个重要概念,它允许不同类的对象对同一消息作出不同的响应。在具体实现上,多态允许一个父类的引用指向其子类的对象,并根据实际指向的对象的类型来调用相应的方法。在 Java 中,多态可以通过以下几种方式实现:在同一个类中,方法名相同,但形参列表不同,实现了多态。子类可以重写(覆盖)其父类的方法,实现多态。在父类引用中调用该方法时,根据实际指向的子类对象的类型来调用相应的方法实现。
39 0
|
25天前
|
编解码 算法 安全
【Java技术专题】「入门到精通系列」深入探索Java技术中常用到的六种加密技术和实现
【Java技术专题】「入门到精通系列」深入探索Java技术中常用到的六种加密技术和实现
44 0
|
1月前
|
算法 Java
Java必刷入门递归题×5(内附详细递归解析图)
Java必刷入门递归题×5(内附详细递归解析图)
21 1
|
1月前
|
Java
Java入门必刷的基础题1(八道)
Java入门必刷的基础题1(八道)
20 0