绘制到JPanel以进行2D游戏开发的适当方法?

时间:2012-06-10 06:36:43

标签: java graphics drawing 2d

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

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

这是我的Painter课程:

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);
    }

}

2 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分:2)

对于游戏循环和打印到屏幕上的游戏对象和其他人(图像,爆炸等)的有效方法,你需要一个计时机制和一个JFrame来反复打印,同时,从玩家和游戏状态获取更新。

首先,你需要一个主方法,我猜你在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 for show)。

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

BufferedImage backBuffer;

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

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

在绘制方法中,您将拥有......

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游戏引擎,它易于理解和使用,并且很有趣。希望你坚持下去,快乐编程!!!