手把手一步一步教你使用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事件。


目录
相关文章
|
3天前
|
JavaScript 安全 Java
智慧产科一体化管理平台源码,基于Java,Vue,ElementUI技术开发,二开快捷
智慧产科一体化管理平台覆盖从备孕到产后42天的全流程管理,构建科室协同、医患沟通及智能设备互联平台。通过移动端扫码建卡、自助报道、智能采集数据等手段优化就诊流程,提升孕妇就诊体验,并实现高危孕产妇五色管理和孕妇学校三位一体化管理,全面提升妇幼健康宣教质量。
31 12
|
7天前
|
安全 Java 编译器
JAVA泛型类的使用(二)
接上一篇继续介绍Java泛型的高级特性。3. **编译时类型检查**:尽管运行时发生类型擦除,编译器会在编译阶段进行严格类型检查,并允许通过`extends`关键字对类型参数进行约束,确保类型安全。4. **桥方法**:为保证多态性,编译器会生成桥方法以处理类型擦除带来的问题。5. **运行时获取泛型信息**:虽然泛型信息在运行时被擦除,但可通过反射机制部分恢复这些信息,例如使用`ParameterizedType`来获取泛型参数的实际类型。
|
7天前
|
安全 Java 编译器
JAVA泛型类的使用(一)
Java 泛型类是 JDK 5.0 引入的重要特性,提供编译时类型安全检测,增强代码可读性和可维护性。通过定义泛型类如 `Box&lt;T&gt;`,允许使用类型参数。其核心原理是类型擦除,即编译时将泛型类型替换为边界类型(通常是 Object),确保与旧版本兼容并优化性能。例如,`Box&lt;T&gt;` 编译后变为 `Box&lt;Object&gt;`,从而实现无缝交互和减少内存开销。
|
27天前
|
前端开发 Java 程序员
菜鸟之路day02-04拼图小游戏开发一一JAVA基础综合项目
本项目基于黑马程序员教程,涵盖面向对象进阶、继承、多态等知识,历时约24小时完成。项目去除了登录和注册模块,专注于单机游戏体验。使用Git进行版本管理,代码托管于Gitee。项目包含窗体搭建、事件监听、图片加载与打乱、交互逻辑实现、菜单功能及美化界面等内容。通过此项目,巩固了Java基础并提升了实际开发能力。 仓库地址:[https://gitee.com/zhang-tenglan/puzzlegame.git](https://gitee.com/zhang-tenglan/puzzlegame.git)
42 6
|
30天前
|
Java
Java实现贪吃蛇游戏
本文介绍了如何使用Java实现一个简单的贪吃蛇游戏。
56 4
|
30天前
|
IDE Java API
Java游戏开发基础:从零开始制作一个简单的2D游戏
本文介绍了使用Java开发一个简单的2D避障游戏的基础流程。
73 10
|
30天前
|
前端开发 Java 数据库连接
【潜意识Java】深度解读JavaWeb开发在Java学习中的重要性
深度解读JavaWeb开发在Java学习中的重要性
30 4
|
30天前
|
Java 应用服务中间件 API
【潜意识Java】javaee中的SpringBoot在Java 开发中的应用与详细分析
本文介绍了 Spring Boot 的核心概念和使用场景,并通过一个实战项目演示了如何构建一个简单的 RESTful API。
41 5
|
3月前
|
Java 开发者
在 Java 中,一个类可以实现多个接口吗?
这是 Java 面向对象编程的一个重要特性,它提供了极大的灵活性和扩展性。
201 58
|
4月前
|
Java
Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口
【10月更文挑战第20天】《JAVA多线程深度解析:线程的创建之路》介绍了Java中多线程编程的基本概念和创建线程的两种主要方式:继承Thread类和实现Runnable接口。文章详细讲解了每种方式的实现方法、优缺点及适用场景,帮助读者更好地理解和掌握多线程编程技术,为复杂任务的高效处理奠定基础。
68 2

热门文章

最新文章