手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏07游戏输入管理

简介: 手把手一步一步教你使用Java开发一个大型街机动作闯关类游戏07游戏输入管理

项目源码


项目源码


输入管理

package managers;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class InputManager implements KeyListener {
    private static InputManager singleton = null;
    protected InputManager() {
    }
    public static InputManager getInstance() {
         if(singleton==null) {
              singleton = new InputManager();
         }
         return singleton;
    }
    private int[] keys = new int[256];
    private boolean[] key_state_up = new boolean[256];
    private boolean[] key_state_down = new boolean[256];
    private boolean keyPressed = false;
    private boolean keyReleased = false; 
    private char keyChar;
    @Override
    public void keyTyped(KeyEvent e) {
    }
    public void keyPressed(KeyEvent e) {
        if( e.getKeyCode() >= 0 && e.getKeyCode() < 256 ) {
            keys[e.getKeyCode()] = (int) System.currentTimeMillis();
            key_state_down[e.getKeyCode()] = true;
            key_state_up[e.getKeyCode()] = false;
            keyPressed = true;
            keyReleased = false;
        }
    }
    public char getKeyChar(){
        return keyChar;
    }
    public void keyReleased(KeyEvent e) {
        if( e.getKeyCode() >= 0 && e.getKeyCode() < 256 ) {
            keys[e.getKeyCode()] = 0;
            key_state_up[e.getKeyCode()] = true;
            key_state_down[e.getKeyCode()] = false;
            keyChar = e.getKeyChar();
            keyPressed = false;
            keyReleased = true;
        }
    }
    public boolean isKeyDown( int key ) {
        return key_state_down[key];
    }
    public boolean isKeyUp( int key ) {
        return key_state_up[key];
    }
    public boolean isAnyKeyDown() {
        return keyPressed;
    }
    public boolean isAnyKeyUp() {
        return keyReleased;
    }
    public void update() {
        key_state_up = new boolean[256];
        keyReleased = false;
    }
}

InputManager类实现KeyListener接口,监听keyPressed键按下事件和keyReleased键释放事件。

接下来我们在game主循环中就可以调用isKeyDown和isKeyUp方法来查询是否某个键被按下或释放。并且我们在每一次游戏循环中

都需要调用update方法重新分配key_state_up数组,这样可以保证每次循环最多检测到一次isKeyUp。

下面是一个测试类。


InputManager测试类

package main;
import managers.InputManager;
import java.awt.*;
import java.awt.event.*;
/**
 * This is just a simple test example for the input manager snippet. It is
 * just a simple frame and a threaded loop that runs about every 16 milliseconds
 * or so which is 62.5 times per second.
 */
public class InputManagerTest extends Frame implements Runnable {
    // The test input manager
    private final InputManager input;
    // Used to only start the looping thread once.
    private boolean             isTestLoopRunning   = false;
    /**
     * Add the InputManager as the KeyListener to the Frame.
     */
    public InputManagerTest() {
        input = InputManager.getInstance();
        this.addKeyListener(input);
        this.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentShown(ComponentEvent e) {
                startTestLoop();
            }
        });
    }
    /**
     * Starts a new thread using this class as the Runnable instance for that
     * thread.
     */
    public void startTestLoop() {
        //only want to run once.
        if (!isTestLoopRunning) {
            (new Thread(this)).start();
            isTestLoopRunning = true;
        }
    }
    /**
     * The meat of the test to check and make sure the input manager is working
     * correctly.
     */
    @Override
    public void run() {
        System.out.println("Start Test Loop");
        //use this to test how many times the loop detects a key is down
        int count = 0;
        //run while the frame is showing
        while (this.isShowing()) {
            // run test cases
            if (input.isAnyKeyDown()) {
                System.out.println("Some key is down");
            }
            if (input.isAnyKeyUp()) {
                System.out.println("Some key is up");
            }
            if(input.isKeyDown(KeyEvent.VK_SPACE)) {
                ++count;
                System.out.println("Spacebar is down");
            }
            if(input.isKeyUp(KeyEvent.VK_SPACE)) {
                System.out.println("Spacebar is up");
                System.out.format("Spacebar detected down %d times\n", count);
                count = 0; //reset the counter
            }
            input.update();
            try {
                Thread.sleep(16);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } // just do a constant 16 milliseconds
        }
        System.out.println("End Test Loop");
    }
    /**
     * Main method to use to run the test from, it creates a basic awt frame and
     * displays the frame.
     * 
     * @param args Command line arguments.
     */
    public static void main(String[] args) {
        final Frame frame = new InputManagerTest(); //create our test class.
        // set a default size for the window, basically just give it some area.
        frame.setSize(640, 480);
        frame.setLocationRelativeTo(null); // centers window on screen
        // Need to add this to handle window closing events with the awt Frame.
        frame.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent arg0) {
                frame.setVisible(false);
                frame.dispose();
                System.exit(0);
            }
        });
        // show the frame
        frame.setVisible(true);
    }
}

该类不详细解释了,执行InputManagerTest,按一下空格键,得到以下输出:

Start Test Loop
Some key is down
Spacebar is down
Some key is down
Spacebar is down
Some key is down
Spacebar is down
Some key is down
Spacebar is down
Some key is down
Spacebar is down
Some key is down
Spacebar is down
Some key is up
Spacebar is up
Spacebar detected down 6 times
End Test Loop
Process finished with exit code 0

为什么检测到多次isKeyDown事件,而只有一次isKeyUp事件?

注意上面

input.update();


每次循环我们都会调用InputManager的update方法,重新分配key_state_up数组。

我们按下空格键这个短暂的时间,主循环循环了多次,但因为每次我们都重新分配了key_state_up数组,

故检测到多次isKeyDown事件,而只有一次isKeyUp事件。


目录
相关文章
|
21天前
|
Java 开发者 微服务
Spring Boot 入门:简化 Java Web 开发的强大工具
Spring Boot 是一个开源的 Java 基础框架,用于创建独立、生产级别的基于Spring框架的应用程序。它旨在简化Spring应用的初始搭建以及开发过程。
38 6
Spring Boot 入门:简化 Java Web 开发的强大工具
|
8天前
|
存储 JavaScript 前端开发
基于 SpringBoot 和 Vue 开发校园点餐订餐外卖跑腿Java源码
一个非常实用的校园外卖系统,基于 SpringBoot 和 Vue 的开发。这一系统源于黑马的外卖案例项目 经过站长的进一步改进和优化,提供了更丰富的功能和更高的可用性。 这个项目的架构设计非常有趣。虽然它采用了SpringBoot和Vue的组合,但并不是一个完全分离的项目。 前端视图通过JS的方式引入了Vue和Element UI,既能利用Vue的快速开发优势,
55 13
|
13天前
|
算法 Java API
如何使用Java开发获得淘宝商品描述API接口?
本文详细介绍如何使用Java开发调用淘宝商品描述API接口,涵盖从注册淘宝开放平台账号、阅读平台规则、创建应用并申请接口权限,到安装开发工具、配置开发环境、获取访问令牌,以及具体的Java代码实现和注意事项。通过遵循这些步骤,开发者可以高效地获取商品详情、描述及图片等信息,为项目和业务增添价值。
46 10
|
6天前
|
前端开发 Java 测试技术
java日常开发中如何写出优雅的好维护的代码
代码可读性太差,实际是给团队后续开发中埋坑,优化在平时,没有那个团队会说我专门给你一个月来优化之前的代码,所以在日常开发中就要多注意可读性问题,不要写出几天之后自己都看不懂的代码。
43 2
|
16天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
27天前
|
存储 缓存 安全
java 中操作字符串都有哪些类,它们之间有什么区别
Java中操作字符串的类主要有String、StringBuilder和StringBuffer。String是不可变的,每次操作都会生成新对象;StringBuilder和StringBuffer都是可变的,但StringBuilder是非线程安全的,而StringBuffer是线程安全的,因此性能略低。
44 8
|
28天前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
61 1
|
Java 开发工具 git
Java开发初级6.24.3
5.在Git使用过程中,进行Git配置的操作命令是哪个() A. config B. config -g C. config -a D. git config 相关知识点: 在git中,经常使用git config 命令用来配置git的配置文件,git配置级别主要有:仓库级别 local 【优先级最高】、用户级别 global【优先级次之】、系统级别 system【优先级最低】 正确答案:D 10.RDBMS是什么? A. Rela Database Management Systems B. Relational Database Management Systems C. Relation
140 0
|
SQL 前端开发 JavaScript
Java开发初级6.24.2
3.Java网站src/main/java目录保存的是什么资源? A. Java源代码文件 B. 测试代码 C. JavaScript、CSS等文件 D. 图片资源 正确答案:A 4.什么是索引Index? A. SQL数据库里的表管理工具 B. SQL数据库里的查询工具 C. SQL数据库里的目录工具 D. SQL数据库用来加速数据查询的特殊的数据结构 正确答案:D
149 0
|
Java
Java开发初级6.24.1
1.下面关于泛型的描述中错误的一项是? A. “? extends 类”表示设置泛型上限 B. “? super 类”表示设置泛型下限 C. 利用“?”通配符可以接收全部的泛型类型实例,但却不可修改泛型属性内容 D. 如果类在定义时使用了泛型,则在实例化类对象时需要设置相应的泛型类型,否则程序将无法编译通过 相关知识点: https://edu.aliyun.com/course/35 正确答案:D 2.下列选项中属于SVN中控制鉴权用户访问版本库的权限默认权限的是() A. write B. read C. none D. null 相关知识点: auth-access:取值范围为"writ
245 0
下一篇
DataWorks