创建游戏循环线程

Posted

技术标签:

【中文标题】创建游戏循环线程【英文标题】:create game loop thread 【发布时间】:2013-02-27 19:00:32 【问题描述】:

您好,我刚刚搞砸了多边形和 awt。我已经创建了一个 Jframe 并且可以绘制多边形并让其中一个通过按键移动。

我想知道如何启动一个游戏循环线程(以及将它放在哪里!),它将独立更新 jframe。

通过谷歌搜索,我相信我应该有一个线程用于用户输入,一个线程用于游戏本身。

目前我已经在 board 类上实现了 KeyListener(代码如下所示),我应该把它放到它自己的类中并使其实现可运行吗?就代码而言,我只是在 keypressed() 方法中重新绘制 JFrame所以我可以看到它移动正确

一天中的大部分时间都在做这件事,我让自己非常非常困惑 :) 一如既往,非常感谢您的帮助!

另外,当我从在线教程中学习时,我应该使用 JPanel 而不是 JFrame 和 paintComponent() 而不是 paint()?

    import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.geom.AffineTransform;

import javax.swing.JFrame;

public class Board extends JFrame implements KeyListener
    AffineTransform identity = new AffineTransform();
    Graphics2D g2d;

    Ship ship = new Ship();

    public static final int ALIENS = 3;
    Alien[] alien = new Alien[ALIENS];


    Board()
        super("The Board");
        setSize(1280,1024);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setBackground(Color.BLACK);
        for(int x=0;x<ALIENS;x++)
            alien[x]=new Alien();
        
    

    public void paint(Graphics g)
        super.paint(g);
        addKeyListener(this);
        //draw ship
        g2d = (Graphics2D)g;    
        g2d.setTransform(identity);
        g2d.translate(ship.getxPos(),ship.getyPos());
        g2d.scale(2,2);
        g2d.setColor(Color.ORANGE);
        g2d.fill(ship.getShape());
        g2d.setColor(Color.BLACK);
        g2d.draw(ship.getShape());

        // draw aliens
        for(int x=0;x<ALIENS;x++)
            //if alien alive
            if(alien[x].isAlive())
                //draw alien
                g2d = (Graphics2D)g;    
                g2d.setTransform(identity);
                g2d.translate(alien[x].getxPos(),alien[x].getyPos());
                g2d.scale(2,2);
                g2d.setColor(Color.BLUE);
                g2d.fill(alien[x].getShape());
                g2d.setColor(Color.BLACK);
                g2d.draw(alien[x].getShape());
            
        
    //end paint


    /*****************************************************
     * key listener events
     *****************************************************/
    public void keyReleased(KeyEvent k)  
    public void keyTyped(KeyEvent k)  
    public void keyPressed(KeyEvent k) 
        int keyCode = k.getKeyCode();

        switch (keyCode) 

        case KeyEvent.VK_A:
            //move ship left
            if(ship.getxPos()<20)
                ship.setxPos(20);
            else
            ship.setxPos(ship.getxPos()-1);
            break;
        case KeyEvent.VK_D:
            if(ship.getxPos()>1260)
                ship.setxPos(1260);
            else
            ship.setxPos(ship.getxPos()+1);
        
       repaint();
    //end keypressed event

    public static void main(String[] args)
        new Board();
    

【问题讨论】:

【参考方案1】:

这些答案在某种程度上取决于您要创建的游戏类型。

通过谷歌搜索,我相信我应该有一个线程用于用户输入,一个线程用于游戏本身。

您创建了一个主游戏循环,该循环在其自己的线程中运行。在伪代码中

while (running) 
    update game model
    draw game
    wait x milliseconds
 

您的用户输入将直接更新游戏模型。如果需要计算机做出动作或对您的动作做出反应,则游戏循环会更新游戏模型。然后,游戏循环读取游戏模型并根据模型中的值绘制游戏。

目前我已经在board类上实现了KeyListener(代码如下),我应该把它放到它自己的类中,让它实现runnable吗?

是的,你应该把 KeyListener 放到它自己的类中。不,您不必将其设为单独的线程。

为了避免以后的麻烦,应该在 Event Dispatch 线程上定义和使用 Swing 组件。

这是你的做法。

public static void main(String[] args) 
    SwingUtilities.invokeLater(new Runnable() 
        public void run() 
            new Board();
        
    );

我应该使用 JPanel 代替 JFrame 并使用paintComponent() 代替paint() 吗?

是的。

您应该在 JFrame 内有一个 JPanel。 JPanel 是您使用paintComponent 方法执行绘图游戏伪代码的地方。

有些人会不同意我的观点,但我发现最好游戏中的每个对象都有一个绘制方法来绘制自己。

public void draw(Graphics g)

游戏模型还有一个 draw 方法,可以绘制模型中的所有对象。

JPanel paintComponent 方法如下所示:

public void paintComponent(Graphics g) 
    super.paintComponent(g);
    gameModel.draw(g);

【讨论】:

以上是关于创建游戏循环线程的主要内容,如果未能解决你的问题,请参考以下文章

构建和同步多线程游戏循环

从分离线程停止主游戏循环的最佳方法

游戏循环 - 元素存在的时间越长越快

多线程游戏服务器的基本设计?

Qt如何循环创建线程

java for循环中创建线程池