-1

我正在关注 Java 游戏开发教程的一系列教程。如果有帮助的话,我已经从 thenewboston 获得了 Java 的基本知识。无论如何,我被困在本教程上:http ://www.youtube.com/watch?v= hN1v1ZhITDc&feature=c4-overview-vl&list=PL54DB126285ED0420 我为本教程创建的程序有点像 2D Minecraft,并且在此时,程序应显示一个窗口,其中按特定顺序显示了几块泥土、石头和天空。当我运行它时,它只显示一个空白的 JFrame,并且出现以下错误:

at mineGameMain.World.draw(World.java:80)
at mineGameMain.GamePanel.draw(GamePanel.java:91)
at mineGameMain.GamePanel.gameRender(GamePanel.java:85)
at mineGameMain.GamePanel.run(GamePanel.java:51)
at java.lang.Thread.run(Unknown Source)

我有三个课程,主要:

package mineGameMain;

import javax.swing.JFrame;

public class Main extends JFrame{

    GamePanel gp;

    public Main(){

        gp = new GamePanel();
        setSize(500, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setVisible(true);
        setResizable(false);
        add(gp);

    }

    public static void main(String[] args){
        Main m = new Main();

    }

}

游戏面板:

    package mineGameMain;

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

    public class GamePanel extends JPanel implements Runnable{

        //Double Buffering
        private Image dbImage;
        private Graphics dbg;
        //JPanel variables
        static final int GWIDTH = 500, GHEIGHT = 400;
        static final Dimension gameDim = new Dimension(GWIDTH, GHEIGHT);
        //Game Variables
        private Thread game;
        private volatile boolean running = false;

        //Game Objects
        World world;

        public GamePanel(){

            world = new World();
            setPreferredSize(gameDim);
            setBackground(Color.WHITE);
            setFocusable(true);
            requestFocus();
            //Handle all key inputs
            addKeyListener(new KeyAdapter(){

                public void keyPressed(KeyEvent e){

                }
                public void keyReleased(KeyEvent e){

                }
                public void Typed(KeyEvent e){

                }           

            });

        }


        public void run(){
            while(running){

                gameUpdate();
                gameRender();
                paintScreen();

            }

        }

        private void gameUpdate(){
            if(running && game != null){
                //Update game state


            }

        }

        private void gameRender(){
            if(dbImage == null){

                dbImage = createImage(GWIDTH, GHEIGHT);
                if(dbImage == null){

                    System.err.println("dbImage IS STILL NULL SO SHUTUPBEQUIET!");
                    return;
                }else{
                    dbg = dbImage.getGraphics();

                }

            }
            //Clear the screen
            dbg.setColor(Color.WHITE);
            dbg.fillRect(0, 0, GWIDTH, GHEIGHT);
            //draw Game Methods
            draw(dbg);
        }

        /*Draw all game content in this method*/
        private void draw(Graphics g) {

            world.draw(g);

        }

        private void paintScreen(){
            Graphics g;
            try{
                g = this.getGraphics();
                if(dbImage != null && g != null){

                    g.drawImage(dbImage, 0, 0, null);

                }

                Toolkit.getDefaultToolkit().sync();

            }catch(Exception e){

                System.err.println(e);

            }


        }


        public void addNotify(){

            super.addNotify();
            startGame();

        }

        private void startGame(){

            if(game == null || !running){
                game = new Thread(this);
                game.start();
                running = true;

            }

        }

        public void stopGame(){
            if(running){
                running = false;

            }
        }

        private void log(String s){

            System.out.println(s);

        }
    }

最后,世界:

package mineGameMain;

import java.awt.Image;
import java.awt.*;

import javax.swing.ImageIcon;

public class World {

    private Rectangle[] blocks;
    private Image[] blockImg;
    private final int arrayNum = 500;
    //Block images
    private Image BLOCK_DIRT_TOP, BLOCK_DIRT, BLOCK_STONE, BLOCK_SKY;

    private int x, y;

    public World(){

        BLOCK_DIRT_TOP = new ImageIcon("/MineGame/src/mineGameMain/Tile_Grass.png").getImage();
        BLOCK_DIRT = new ImageIcon("/MineGame/src/mineGameMain/Tile_Dirt.png").getImage();
        BLOCK_STONE = new ImageIcon("/MineGame/src/mineGameMain/Tile_Stone.png").getImage();
        BLOCK_STONE = new ImageIcon("/MineGame/src/mineGameMain/Tile_Sky.png").getImage();
        blocks = new Rectangle[500];
        blockImg = new Image[500];

        loadArrays();

    }

    private void loadArrays(){

        for(int i = 0; i < arrayNum; i++){

            if(x >= 500){

                x = 0;
                y += 20;

            }

            if( i >= 0 && i < 100){

                blockImg[i] = BLOCK_SKY;
                blocks[i] = new Rectangle(x, y, 20, 20);

            }

            if( i >= 100 && i < 120){

                blockImg[i] = BLOCK_DIRT_TOP;
                blocks[i] = new Rectangle(x, y, 20, 20);

            }

            if( i >= 125 && i < 220){

                blockImg[i] = BLOCK_DIRT;
                blocks[i] = new Rectangle(x, y, 20, 20);

            }

            if( i >= 225 && i < 500){

                blockImg[i] = BLOCK_STONE;
                blocks[i] = new Rectangle(x, y, 20, 20);

            }

            x += 20;

        }

    }

    public void draw(Graphics g){

        for(int i = 0; i < arrayNum; i++){

            g.drawImage(blockImg[i], blocks[i].x, blocks[i].y, null);

        }

    }

}

感谢您的时间。如果我在发布此内容时做错了什么,或者我遗漏了任何细节,请告诉我。

4

1 回答 1

1

在下面找到一种将您的问题变成SSCCE的方法(实际上它是一个固定版本)

在代码中应该避免很多错误

  • 不用自己实现双缓冲,Swing默认是双缓冲的
  • 所有对 UI 的访问都应该在 EDT(事件调度线程)上进行,而不是从您创建的随机线程中进行。您还应该从 EDT 启动您的 UI,使用invokeLater
  • 要绘制组件,请在您希望调用它时覆盖paintComponent并调用它。repaint()
  • 永远不要使用getGraphicson JComponent,总是Graphics作为方法参数提供的对象(如在 paintComponent 中)。
  • 不需要在JFrame这里扩展——>如果你不需要就不要扩展(你实际上并没有向JFrame.
  • 确保调用setVisible(true)作为您对JFrame.
  • 您忘记处理块 120 到 125 和块 220 到 225(可能在您的draw方法中导致 NullPointerException (这可能是您的错误的根源)。
  • 当您发布 Java 错误时,请确保发布整个堆栈跟踪和堆栈跟踪上方提供的消息(还请确保人们可以识别您的行号,通过添加类似的评论// this is line 80 of the World class

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Rectangle;
import java.net.MalformedURLException;
import java.net.URL;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class Main extends JFrame {

    GamePanel gp;

    public Main() throws MalformedURLException {

        gp = new GamePanel();
        setSize(500, 400);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        add(gp);
        pack();
        setVisible(true);

    }

    public static class World {

        private Rectangle[] blocks;
        private Image[] blockImg;
        private final int arrayNum = 500;
        // Block images
        private Image BLOCK_DIRT_TOP, BLOCK_DIRT, BLOCK_STONE, BLOCK_SKY;

        private int x, y;

        public World() throws MalformedURLException {

            BLOCK_DIRT_TOP = new ImageIcon(new URL("http://i909.photobucket.com/albums/ac298/XxEnoAsaIxX/grass2test.png?t=1303852677"))
                    .getImage();
            BLOCK_DIRT = new ImageIcon(new URL(
                    "http://i909.photobucket.com/albums/ac298/XxEnoAsaIxX/sparsedirtandgrasstile.png?t=1300172998")).getImage();
            BLOCK_STONE = new ImageIcon(new URL("http://www.stonetilesupply.com/v/vspfiles/photos/MARBL-BTTCNCLASSICO-2S.jpg")).getImage();
            BLOCK_SKY = new ImageIcon(new URL("http://lacoste.scene7.com/is/image/lacoste/swatch_10_CH0783-00_SVH_24?$swatch$")).getImage();
            blocks = new Rectangle[500];
            blockImg = new Image[500];

            loadArrays();

        }

        private void loadArrays() {

            for (int i = 0; i < arrayNum; i++) {

                if (x >= 500) {

                    x = 0;
                    y += 20;

                }

                if (i >= 0 && i < 100) {

                    blockImg[i] = BLOCK_SKY;
                    blocks[i] = new Rectangle(x, y, 20, 20);

                }

                if (i >= 100 && i < 120) {

                    blockImg[i] = BLOCK_DIRT_TOP;
                    blocks[i] = new Rectangle(x, y, 20, 20);

                }

                // Here missing block for 120 to 125
                if (i >= 120 && i < 125) {
                    blockImg[i] = BLOCK_STONE;
                    blocks[i] = new Rectangle(x, y, 20, 20);
                }

                if (i >= 125 && i < 220) {

                    blockImg[i] = BLOCK_DIRT;
                    blocks[i] = new Rectangle(x, y, 20, 20);

                }
                // Here missing block for 220 to 225
                if (i >= 220 && i < 225) {
                    blockImg[i] = BLOCK_SKY;
                    blocks[i] = new Rectangle(x, y, 20, 20);
                }

                if (i >= 225 && i < 500) {

                    blockImg[i] = BLOCK_STONE;
                    blocks[i] = new Rectangle(x, y, 20, 20);

                }

                x += 20;

            }

        }

        public void draw(Graphics g) {

            for (int i = 0; i < arrayNum; i++) {

                g.drawImage(blockImg[i], blocks[i].x, blocks[i].y, null);

            }

        }

    }

    public static class GamePanel extends JPanel {

        // JPanel variables

        // Game Objects
        World world;

        public GamePanel() throws MalformedURLException {

            world = new World();
            setPreferredSize(new Dimension(500, 400));
            setBackground(Color.WHITE);
            setFocusable(true);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            world.draw(g);
        }

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    new Main();
                } catch (MalformedURLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        });

    }

}
于 2013-08-25T21:24:45.453 回答