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

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 ) { }
时间: 2024-10-26 08:31:18

《Java 2D游戏编程入门》—— 2.2 键盘改进的相关文章

《Java 2D游戏编程入门》—— 2.1 处理键盘输入

2.1 处理键盘输入 在大多数应用程序中,软件都不需要处理键盘事件.当某些事情发生变化的时候,由任意的组件(如文本框)来处理输入并通知软件.但是,大多数计算机游戏使用键盘不是为了录入,而是为了游戏输入.根据游戏的不同,虽然可能会有录入,但键盘按键常用做方向键和发射激光武器.很多计算机游戏具有不同的输入配置,并且有些游戏甚至允许用户根据自己的意愿来设置按键.不管游戏如何使用键盘(并且它可能采用一种全新的方式来使用键盘,监听键盘事件的常用方法都不适用于游戏循环程序设计. Swing组件允许在实现了K

《Java 2D游戏编程入门》—— 导读

前言 多年前,当我第一次将软件开发作为专业工作的时候,有人请我编写一个applet.那时候,我对于Java语言知道得并不多.在整个上学期间,我很广泛地使用C++.我确实用Java编写过一些代码,但认为它太慢并且是C++的没落版. 同时,我购买和阅读了很多可以接触到的游戏编程图书.我通读了一本关于人工智能的书,其中包含很多不错的示例,但它们都是用C++和DirectX编写的.由于忙着学习Java以便在工作中使用,我认为将示例转换为由Java编写可能是学习这门语言的一种好办法. 毕竟,Java游戏编

《Java 2D游戏编程入门》—— 2.3 处理鼠标输入

2.3 处理鼠标输入 SimpleMouseInput类位于javagames.util包中,它和前面小节中开发的键盘输入类非常相似.处理鼠标按键的方式与处理键盘按键的方式相同.实现MouseListener接口的类包含了如下的方法: mouseClicked(MouseEvent e) mouseEntered(MouseEvent e) mouseExited(MouseEvent e) mousePressed(MouseEvent e) mouseReleased(MouseEvent

《Java 2D游戏编程入门》—— 2.4 相对鼠标移动

2.4 相对鼠标移动 对于图2.3所示的当前的鼠标输入类来说,有一个问题.首先,它看上去似乎挺明显,但是,只有在鼠标位于窗口之中的时候,程序才接受鼠标事件.一旦鼠标离开了窗口,鼠标指针的坐标位置在应用程序中就变得不再有效.更为糟糕的是,在全屏模式中,当鼠标到达屏幕边缘的时候,它会直接停下来,而不会继续注册事件.根据应用程序的需要,可能需要相对鼠标移动.好在,更新鼠标输入类以支持相对鼠标移动并不难. RelativeMouseInput类位于javagames.util包中,构建于前面示例中的类的

《Java 2D游戏编程入门》—— 1.7 全屏显示模式中的主动渲染

1.7 全屏显示模式中的主动渲染 位于javagames.render包中的FullScreenRenderingExample,包含了主动渲染框架和切换到全拼模式的显示模式代码:它创建了一个简单的全屏游戏框架.这个示例包含了前面各部分中展示的很多代码.此外还可以直接给JFrame设置背景颜色并且忽略重绘,以及设置setUndecorated()标志.由于在前面的示例中应用程序是从窗口模式切换到全屏模式的,因此没有设置该标志:但是当只使用全屏模式的时候,应该对JFrame进行该项设置. 保存当前

《Java 2D游戏编程入门》—— 8.1 创建一个多边形包装类

8.1 创建一个多边形包装类 制作一款2D太空飞船游戏时,首先要解决的大问题是,当飞船到达屏幕边缘时,会发生什么事情.一个解决方案是,将飞船保持在屏幕的中央,而移动其周围的环境.没有对加载文件的任何支持,也没有关卡编辑器的话,要做到这点似乎有点难.另一个选择是,当飞船到达屏幕边界的时候,将其弹回.这样做似乎显得很奇怪.第三种选择是,让飞船从一端到另一端折返.让我们采用第三种方法. 还有很多方法可以解决这一问题.一种方法是,让飞船完全离开屏幕,然后让其在另一端返回,如图8.1所示. 尝试这一想法似

《Java 2D游戏编程入门》—— 1.6 修改显示模式

1.6 修改显示模式 要创建全屏的应用程序,需要修改显示模式.DisplayModeTest如图1.4所示,它使用了Swing组件.这个示例也位于javagames.render包中.如果你还没有编写过任何的Swing程序,一些代码可能会看上去很陌生.有很多相关的图书和教程可供参考,并且如果要详细介绍Swing所提供的所有功能,需要比这本书更大的篇幅. 这个示例应用程序列出了所有可用的屏幕分辨率,这允许用户在全屏模式之间来回切换,以使用任何可用的显示模式.这个示例不仅展示了使用Swing组件编程

《Java 2D游戏编程入门》—— 8.5 原型Bullet类

8.5 原型Bullet类 PrototypeBullet代码位于javagames.prototype包中,这是一个最简单的原型游戏源代码.除了绘制圆以便可以调整屏幕大小外,没有其他任何值得讨论的内容. package javagames.prototype; import java.awt.*; import javagames.util.*; public class PrototypeBullet { private Vector2f velocity; private Vector2f

《Java 2D游戏编程入门》—— 第2章 输入

第2章 输入 如图2.1所示,输入对于视频游戏来说是非常重要的.游戏之所以与电影不同,在于游戏有输入,而这也是本章的主题.尽管很多人在游戏的外观上投入了较多的精力,但不管游戏外观看上去有多么壮观,如果操控不稳定.糟糕或很难的话,玩家会感到非常沮丧. 尽管如今有很多的输入设备可供使用,但本书只介绍最常见的两种:键盘和鼠标. 本文仅用于学习和交流目的,不代表异步社区观点.非商业转载请注明作译者.出处,并保留本文的原始链接.