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