0

我想做一个 2D 游戏,但我无法找到使用 BufferStrategy 绘制到 2D Surface/Canvas 的最佳和最有效的方法。我将使用 JFrame 作为主窗口,并希望在其表面上进行绘制。我很想看到一些关于如何完成的示例代码(如果这是一个很好的方法)以及其他示例。如果有人也能解释这样做的一些优点和缺点,那就太好了。

我目前正在使用 'frame.add(new Painter());' 将我的绘图类添加到我的 JFrame 然后覆盖paintComponent 方法。我发现的唯一问题是它似乎只调用了一次这个方法。

这是我的画家课:

public class Painter extends JPanel{

    public static Player player;

    public Painter() {
        player = new Player(300, 300);

    }

    public void paint(Graphics g) {
        player.x++;
        g.setColor(Color.white);
        g.fillRect(player.x, player.y, 32, 32);
    }

}
4

2 回答 2

3

在最简单的情况下,您的游戏只需要根据用户操作更新屏幕,您需要repaint()在更新某些内容时调用(例如在 JFrame 上)。

在其他情况下,您需要构建一个所谓的Game Loop,在其中更新游戏状态并及时渲染更新的游戏状态。可以在此处找到有关使用 Java 代码的简单游戏循环的精彩教程:http: //obviam.net/index.php/the-android-game-loop/

如果您开发一款严肃的游戏,您应该坚持使用游戏引擎来管理游戏循环和其他常规游戏开发方面。可以在这里找到一个好的 Java 游戏引擎:http ://code.google.com/p/playn/

于 2012-06-10T07:50:26.817 回答
3

对于游戏循环和将游戏对象和其他对象(图像、爆炸等)打印到屏幕的有效方式,您需要一个计时机制和一个 JFrame 来一遍又一遍地打印,同时获取更新来自玩家和游戏状态本身。

首先,你需要一个 main 方法,我猜你对 java 中的这种类型的字段很陌生,所以我会尽可能快速和清楚地为你分解它。

public static main(String[] args)
{
  yourClassName game = new yourClassName();
  game.run();
  System.exit(0);
}

这个主要方法首先做两件事,为你的 run 方法创建一个对象(因为不建议在游戏循环中使用静态引用),然后用你新创建的对象调用该方法。当该运行方法完成时,系统将退出程序。

现在我不会在这里详细介绍,但是一旦你运行了 run 方法,你需要一个只运行一次的 init 方法。在此方法中,您将创建要渲染到的 JFrame。这样做相当简单,所以我不会再进一步​​创建 JFrame 类。但是,您的 Run 方法应如下所示...

void Run()
{
   init();
   while(isRunning)
   {
     update();
     draw();

     time = (1000 / fps) - (System.currentTimeMillis() - time);

            if (time > 0) 
            {
                try 
                { 
                        Thread.sleep(time); 
                } 
                catch(Exception e){} 
            }

   }
}

此方法会将计算速度减慢到您想要的某个 fps(在这种情况下,fps 变量被命名为 fps 用于显示)。

现在在您的更新方法中,您将拥有 keyBinding 和其他东西来查找键盘或鼠标的更改(在我的情况下,目前是服务器)。大多数人不知道如何在不接收 Repaint 方法所需的参数的情况下打印或绘制到 JFrame,因此我们将通过添加双缓冲来覆盖它。

BufferedImage backBuffer;

在初始化方法中,您将添加

backBuffer = new BufferedImage(getWidth(),getHeight(),
                            BufferedImage.TYPE_INT_RGB)

在 draw 方法中,您将拥有...

Graphics g = getGraphics();

Graphics bbg = backBuffer.getGraphics();

对于那些您可以绘制到由 init 类创建的 JFrame 的能力(此外,通过这样做,您可以从任何类或线程中绘制以减少处理负载)。

要查看它是否有效,请继续使用bbg.fillRect(updateX,updateY,5,5)

updateX 和 updateY 表示用于更新矩形位置的变量。将它们保存为全局变量或保存在字符类中的公共变量。

如果一切都失败了,这里是我用来创建自己的游戏引擎的示例代码......

import input.InputHandler; 

import java.awt.*; 
import java.awt.event.KeyEvent; 
import java.awt.image.BufferedImage; 
import javax.swing.JFrame; 

/** 
 * Main class for the game 
 */ 
public class GameTutorial extends JFrame 
{        
    boolean isRunning = true; 
    int fps = 30; 
    int windowWidth = 500; 
    int windowHeight = 500; 

    BufferedImage backBuffer; 
    Insets insets; 
    InputHandler input; 

    int x = 0; 

    public static void main(String[] args) 
    { 
            GameTutorial game = new GameTutorial(); 
            game.run(); 
            System.exit(0); 
    } 

    /** 
     * This method starts the game and runs it in a loop 
     */ 
    public void run() 
    { 
            initialize(); 

            while(isRunning) 
            { 
                    long time = System.currentTimeMillis(); 

                    update(); 
                    draw(); 

                    //  delay for each frame  -   time it took for one frame 
                    time = (1000 / fps) - (System.currentTimeMillis()-          time); 

                    if (time > 0) 
                    { 
                            try 
                            { 
                                    Thread.sleep(time); 
                            } 
                            catch(Exception e){} 
                    } 
            } 

            setVisible(false); 
    } 

    /** 
     * This method will set up everything need for the game to run 
     */ 
    void initialize() 
    { 
            setTitle("Game Tutorial"); 
            setSize(windowWidth, windowHeight); 
            setResizable(false); 
            setDefaultCloseOperation(EXIT_ON_CLOSE); 
            setVisible(true); 

            insets = getInsets(); 
            setSize(insets.left + windowWidth + insets.right, 
                            insets.top + windowHeight + insets.bottom); 

        backBuffer = new BufferedImage(windowWidth, windowHeight,   BufferedImage.TYPE_INT_RGB); 
            input = new InputHandler(this); 
    } 

    /** 
     * This method will check for input, move things 
     * around and check for win conditions, etc 
     */ 
    void update() 
    { 
            if (input.isKeyDown(KeyEvent.VK_RIGHT)) 
            { 
                    x += 5; 
            } 
            if (input.isKeyDown(KeyEvent.VK_LEFT)) 
            { 
                    x -= 5; 
            } 
    } 

    /** 
     * This method will draw everything 
     */ 
    void draw() 
    {               
            Graphics g = getGraphics(); 

            Graphics bbg = backBuffer.getGraphics(); 

            bbg.setColor(Color.WHITE); 
            bbg.fillRect(0, 0, windowWidth, windowHeight); 

            bbg.setColor(Color.BLACK); 
            bbg.drawOval(x, 10, 20, 20); 

            g.drawImage(backBuffer, insets.left, insets.top, this); 
    } 
} 

我希望这会有所帮助,我知道这可能是一个非常晚的答案,但我还没有看到一个体面的 Java 游戏引擎,它易于理解和使用并且使用起来很有趣。希望你坚持下去,祝你编程愉快!!!

于 2015-07-05T00:49:55.953 回答