我正在尝试建立一个2D游戏。
我有一个静态的背景图像和一个角色的图像。当我按下一个移动键(WASD)时,Mainclass(是keylistener)在一个名为Player的类中调用一个函数。该函数正在改变角色的位置(Image)。在调用此函数后,我使用repaint()重新绘制新位置上的字符。 如果我删除背景我可以看到旧图像仍然从其他位置。因此,我必须重新绘制每个步骤的播放器和背景。
可能有更好的解决方案吗?最糟糕的情况:这是一个在线游戏,并且有很多玩家四处移动,每100毫秒重新调用一次,每个玩家的位置都需要更新。我有一种感觉,这将夺走玩家电脑的所有记忆,或者至少游戏不会感觉那么好
答案 0 :(得分:4)
不要直接在JFrame
内容窗格中绘画。相反,在paintComponent()
中覆盖JComponent
。此AnimationTest
绘制为JPanel
,默认为双缓冲。该示例还显示了一种检查用于绘画的时间预算的方法。
答案 1 :(得分:2)
据我所知,没有其他解决方案。在大多数计算机上,每100毫秒重新绘制通常不会占用大量内存。
答案 2 :(得分:2)
我认为重绘是唯一的解决方案,我曾经创建了一个2D汽车模拟游戏,这就是我做的,我也改变了所有Car对象的坐标,然后重新绘制整个事物。我试图在没有任何问题的情况下模拟以100毫秒重新绘制的2000个Car对象。嘿嘿好玩
答案 3 :(得分:1)
(我在jframe中使用了一个jpanel)并使用了java.awt.image的bufferedimage
相反,您可以尝试使用带有图标的JLabel。然后你要做的就是调用标签的setLocation(...)
方法。 Swing RepaintManager将重新绘制旧位置和新位置。
这是一个让你入门的例子。此示例为每个图像使用单独的计时器。在您的游戏中,您可以在单个计时器触发时同时重置所有图像的位置。
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class AnimationBackground extends JLabel implements ActionListener
{
int deltaX = 2;
int deltaY = 3;
int directionX = 1;
int directionY = 1;
public AnimationBackground(
int startX, int startY,
int deltaX, int deltaY,
int directionX, int directionY,
int delay)
{
this.deltaX = deltaX;
this.deltaY = deltaY;
this.directionX = directionX;
this.directionY = directionY;
setIcon( new ImageIcon("dukewavered.gif") );
setSize( getPreferredSize() );
setLocation(startX, startY);
new javax.swing.Timer(delay, this).start();
}
public void actionPerformed(ActionEvent e)
{
Container parent = getParent();
// Determine next X position
int nextX = getLocation().x + (deltaX * directionX);
if (nextX < 0)
{
nextX = 0;
directionX *= -1;
}
if ( nextX + getSize().width > parent.getSize().width)
{
nextX = parent.getSize().width - getSize().width;
directionX *= -1;
}
// Determine next Y position
int nextY = getLocation().y + (deltaY * directionY);
if (nextY < 0)
{
nextY = 0;
directionY *= -1;
}
if ( nextY + getSize().height > parent.getSize().height)
{
nextY = parent.getSize().height - getSize().height;
directionY *= -1;
}
// Move the label
setLocation(nextX, nextY);
}
public static void main(String[] args)
{
JPanel panel = new JPanel(null)
{
Image image = new ImageIcon("mong.jpg").getImage();
protected void paintComponent(Graphics g)
{
g.drawImage(image, 0, 0, getWidth(), getHeight(), null);
super.paintComponent(g);
}
};
panel.setOpaque(false);
// panel.add( new AnimationBackground(10, 10, 2, 3, 1, 1, 10) );
panel.add( new AnimationBackground(300, 100, 3, 2, -1, 1, 20) );
panel.add( new AnimationBackground(200, 200, 2, 3, 1, -1, 20) );
panel.add( new AnimationBackground(50, 50, 5, 5, -1, -1, 20) );
// panel.add( new AnimationBackground(0, 000, 5, 0, 1, 1, 20) );
panel.add( new AnimationBackground(0, 200, 5, 0, 1, 1, 80) );
JFrame frame = new JFrame();
frame.setContentPane(panel);
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setSize(400, 400);
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
您需要为代码创建ImageIcon的标签提供背景图像和图像。
答案 4 :(得分:0)
可以有效地重新绘制组件的部分。阅读此tutorial。
基本上你必须拨打component.repaint(posX, posY, length, height)
两次:
一旦在他的旧玩家形象位置(将重新绘制背景)然后在新位置。
(G_H在评论中也提出了这个解决方案。)