游戏循环 - 线程

时间:2012-03-10 00:58:38

标签: java multithreading

java程序中的游戏循环是否总是在事件派发线程中运行? 因为我的keylisteners在AWT事件线程中运行,我希望在与游戏其余部分相同的线程中处理关键事件,以避免基于线程的错误。 如果我不在事件线程中运行游戏循环,我可以使用ArrayBlockingQueue将事件从事件处理程序发送到游戏循环吗?有更好的解决方案吗? 感谢

也许是这样的?

ConcurrentLinkedQueue<AWTEvent> eventQueue = new ConcurrentLinkedQueue<AWTEvent>(); 

JFrame frame = new JFrame() {
    @override
    protected void processEvent(AWTEvent e) {
        if(e instanceof InputEvent) eventQueue.add(e);
        else super.processEvent(e);
    }
}

//game loop
while(true) {
    while(!eventQueue.isEmpty()) frame.super.processEvent(eventQueue.poll());
    ...
}

编辑:谢谢,我想我现在知道怎么做了。我会这样做的

import java.util.concurrent.ConcurrentLinkedQueue;
import java.awt.AWTEvent;
import java.awt.Dimension;
import java.awt.event.*;
import javax.swing.*;

public class QueueTest {

    static ConcurrentLinkedQueue<AWTEvent> eventQueue = new ConcurrentLinkedQueue<AWTEvent>(); 

    public static void main(String[] args) {
        final JPanel panel = new JPanel() {
            @Override
            protected void processEvent(AWTEvent e) {
                eventQueue.add(e);
            }
            {
                enableEvents(  AWTEvent.MOUSE_EVENT_MASK
                             | AWTEvent.MOUSE_MOTION_EVENT_MASK
                             | AWTEvent.KEY_EVENT_MASK);
            }
        };
        final JFrame frame = new JFrame();
        frame.addComponentListener(new ComponentAdapter() {
            @Override
            public void componentShown(ComponentEvent e) {
                panel.requestFocusInWindow();
            }
        });
        frame.add(panel);
        panel.setPreferredSize(new Dimension(800,600));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

        while(true) {
            while(!eventQueue.isEmpty()) System.out.println(eventQueue.poll()+"\n");
        }
    }
}

2 个答案:

答案 0 :(得分:1)

我不是游戏程序员所以你的问题引发了一些研究:)你无法在事件调度线程中运行游戏循环,因为它处于自己的服务用户输入的循环中。您的应用程序基本上会冻结,不会响应任何进一步的输入事件。您的游戏循环应该是一个单独的线程,其中包含游戏事件的线程安全队列 - 队列应该是非阻塞的,因为即使没有用户输入,您也希望游戏循环继续。由于输入而需要进行的任何渲染可能必须放回到事件队列中 - swing为此提供SwingUtilities,但不确定您所处的环境。

我现在可能会被经验丰富的游戏开发者抨击。

答案 1 :(得分:1)

我在我写的游戏引擎中遇到了类似的问题。

最后,我必须为我的游戏引擎循环设置一个单独的线程。当AWT事件被触发时,我必须存储它们,并在游戏循环中的下一次逻辑更新期间触发它们。

这是我的解决方案,然而,我相信事件的“最简单”事实是实际轮询它们!:)