【问题标题】:Background image for simple game?简单游戏的背景图片?
【发布时间】:2012-08-18 10:32:54
【问题描述】:

我一直在关注Java Game Programming for Beginners 教程系列,并希望通过应用背景图像来进行实验。不幸的是,当我通过paintComponent 方法渲染它时,它会随着我的精灵移动(尽管连续一个单位而不是五个);当我通过paint方法渲染它时,我得到一个奇怪的闪烁框,它与JFramesetBackground (color)属性中指定的颜色相匹配,并且它随着精灵的移动与前一个实例的精灵相同(在@987654329内@)。

我如何编码图像以保持静态,作为背景应该是?

代码:

public class JavaGame extends JFrame{

int x, y;
private Image dbImage;
private Graphics dbg;
Image ghost;
Image bg;


public class AL extends KeyAdapter{
    public void keyPressed(KeyEvent e){
        int keyCode = e.getKeyCode();

        if(keyCode == e.VK_LEFT){
            if(x <= 8)
                x = 8;
            else
                x += -5;
        }
        if(keyCode == e.VK_RIGHT){
            if(x >= 235)
                x = 235;
            else
                x += +5;
        }
        if(keyCode == e.VK_UP){
            if(y <= 18)
                y = 18;
            else
                y += -5;
        }
        if(keyCode == e.VK_DOWN){
            if(y >= 235)
                y = 235;
            else
                y += +5;
        }
    }
    public void keyReleased(KeyEvent e){

    }

}

public JavaGame(){
    //Load images
    ImageIcon i = new ImageIcon("C:/Users/Taylor/workspace/Java game/src/ghost.png");
    ghost = i.getImage();

    ImageIcon j = new ImageIcon("C:/Users/Taylor/workspace/Java game/src/bg.png");
    bg = j.getImage();

    //Game properties
    addKeyListener(new AL());
    setTitle("Java Game");
    setSize(500, 500);
    setResizable(false);
    setVisible(true);
    setBackground(Color.GRAY);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    x = 150;
    y = 150;
}

public void paint(Graphics g){
    g.drawImage(bg, 0, 0, null);

    dbImage = createImage(getWidth(), getHeight());
    dbg = dbImage.getGraphics();
    paintComponent(dbg);
    g.drawImage(dbImage, x, y, this);
}

public void paintComponent(Graphics g){
    g.setColor(Color.WHITE);
    g.drawImage(ghost, x, y, this);

    repaint();
}


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

}

图片:

【问题讨论】:

  • 一般来说,当你截取屏幕截图时,你应该编辑它们以只包含相关部分(IE,游戏窗口)。
  • 不要从paintComponent 拨打repaintrepaint(最终)调用paint 调用paintComponent 调用repaint,这是一个无限循环。
  • @Jeffrey 正如How do I create screenshots? 中提到的,一个组合。 Windows 上的 alt+printscreen 将捕获活动窗口区域。
  • Show an animated BG in Swing 的可能副本(是的,弗吉尼亚,它也适用于静态背景)。
  • 取消那个想法我的评估太仓促了。此问题不是链接问题的副本。对于那个很抱歉。 :P

标签: java image swing background-image


【解决方案1】:

您是否随意复制/粘贴代码?这就是它的样子。该代码有很多奇怪的方面,我没有将它们全部记录下来(可能是一个很好的代码审查)。该示例使用异步方法加载图像(为了获取动画图像,动画)。使用ImageIO.read(URL) 同步加载静态图片。

这里有一些简短的提示:

  1. 当它被部署时,图像可能会成为嵌入式资源,File 对象将无法访问这些图像。将它们添加到运行时类路径并通过 URL 访问它们。
  2. 应在 EDT 上启动和更改 Swing GUI(请参阅对 main() 的更改)。
  3. 始终在方法开始时调用super.paint(g);(或paintComponent(g))。
  4. 不要扩展框架,不要绘制到顶级组件。而是扩展面板并覆盖paintComponent()。将面板添加到框架中。

代码

import java.awt.*;
import java.awt.event.*;
import java.net.URL;
import javax.swing.*;

public class JavaGame extends JPanel {

    int x, y;
    private Image dbImage;
    private Graphics dbg;
    Image ghost;
    Image bg;

    public class AL extends KeyAdapter {
        public void keyPressed(KeyEvent e) {
            int keyCode = e.getKeyCode();

            if (keyCode == e.VK_LEFT) {
                if (x <= 8)
                    x = 8;
                else
                    x += -5;
            }
            if (keyCode == e.VK_RIGHT) {
                if (x >= 235)
                    x = 235;
                else
                    x += +5;
            }
            if (keyCode == e.VK_UP) {
                if (y <= 18)
                    y = 18;
                else
                    y += -5;
            }
            if (keyCode == e.VK_DOWN) {
                if (y >= 235)
                    y = 235;
                else
                    y += +5;
            }
        }

        public void keyReleased(KeyEvent e) {
        }
    }

    public JavaGame() throws Exception {
        // Load images
        //ImageIcon i = new ImageIcon(
            //  "C:/Users/Taylor/workspace/Java game/src/ghost.png");
        URL urlGhost = new URL("http://1point1c.org/gif/thum/plnttm.gif");
        ghost = Toolkit.getDefaultToolkit().createImage(urlGhost);

        //ImageIcon j = new ImageIcon(
            //  "C:/Users/Taylor/workspace/Java game/src/bg.png");
        URL urlBG = new URL("http://pscode.org/media/stromlo2.jpg");
        bg = Toolkit.getDefaultToolkit().createImage(urlBG);
        
        setFocusable(true);

        // Game properties
        addKeyListener(new AL());
        x = 150;
        y = 150;
        
        ActionListener al = new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                repaint();
            }
        };
        Timer timer = new Timer(50,al);
        timer.start();
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(bg, 0, 0, null);

        //dbImage = createImage(getWidth(), getHeight());
        //dbg = dbImage.getGraphics();
        //paintComponent(dbg);
        g.drawImage(dbImage, x, y, this);

        g.setColor(Color.WHITE);
        g.drawImage(ghost, x, y, this);

        //repaint();
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    JFrame f = new JFrame("Java Game");
                    f.setSize(500, 500);
                    f.setResizable(false);
                    f.setVisible(true);
                    f.setBackground(Color.GRAY);
                    f.setContentPane(new JavaGame());
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

【讨论】:

  • 我想你的意思是注释掉g.drawImage(dbImage, ...)
  • @Jeffrey 实际上,除了多余的图像之外,我完全错过了我的代码版本中的null。我会进一步评论它,但我对它为什么会在那里感到困惑!但你确实提醒我提到了.. g.drawImage(bg, 0, 0, null); 应该是 g.drawImage(bg, 0, 0, this); -- 还有别的吗?在糟糕的代码中很容易迷失方向。
  • 几乎我要发布的所有内容-击败我+1
  • @AndrewThompson OP 可能正在尝试实现双缓冲。看起来没有其他东西,但由于我没有测试代码,因此很难 100% 确定。
  • 成为“初学者”并不是生成该代码的教程的借口。是来自RoseIndia吗?但是无论您在哪里找到它,都将其放回原处并阅读 Oracle Java 教程的等效部分。如果你有什么不明白的地方,人们会愿意提供帮助的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-08
  • 2013-04-14
  • 1970-01-01
  • 2013-10-28
  • 2014-04-30
  • 1970-01-01
  • 2022-01-25
相关资源
最近更新 更多