游戏JFrame在重新绘制后仍然是空白

时间:2016-10-06 05:44:14

标签: java swing jframe paintcomponent surface

我的这个老项目已经存在了很长时间。我有两个版本的同一个游戏,一个显示游戏,另一个只显示一个空白的白色面板。原来是一个大网格,我试图改变它以逐个像素显示,但现在它只给我一个空白的白色屏幕,但我不知道如何解决它。我已经搜索了很长时间的代码,逐行交叉引用,注释掉代码行以查看它们是否导致了问题,但我无法弄清楚它的生命周期。我。我试着在这里寻找类似的案例,但我没有运气。

要查看很多代码,但是我真的很感谢比我更有知识的人提供的帮助。具体来说,我认为这个问题可能出现在main()函数中的某个地方在WizardGame.java,或paintComponent()中的GamePanel.java功能,或可能GamePanel()本身,但此时我甚至不知道在哪里看。

这是破碎的代码:

WizardGame.java

package wizard.game;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class WizardGame implements KeyListener
{
    private static final int WIDTH = 800;
    private static final int HEIGHT = 600;
    private static JPanel surface;
    private static boolean keyUpPressed;
    private static boolean keyDownPressed;
    private static boolean keyRightPressed;
    private static boolean keyLeftPressed;
    private static int keyFramesX;
    private static int keyFramesY;
    private static double moveXValue;
    private static double moveYValue;
    private static double moveXCount;
    private static double moveYCount;
    private static double lastFrame;
    private static double currentFrame;
    private static boolean painted;

    public static int getWIDTH() { return WIDTH; }
    public static int getHEIGHT() { return HEIGHT; }
    public static double getMoveX() { return moveXCount; }
    public static double getMoveY() { return moveYCount; }
    public static void resetXY() { moveXValue = 0; moveYValue = 0; }
    private static double getTime() { return System.currentTimeMillis(); }
    public static void setFrame() { currentFrame = getTime(); }
    public static void setPainted(boolean p) { painted = p; }

    public WizardGame()
    {
        BufferedImage icon = null;
        try {
            icon = ImageIO.read(getClass().getResource("Wizard.png"));
        } catch (IOException ex) {
            Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex);
        }
        // Set frame time counter to 0
        currentFrame = (double)0.0;
        lastFrame = (double)0.0;

        JFrame wizard = new JFrame();
        wizard.setTitle("Wizard");
        wizard.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        wizard.setSize(WIDTH+6,HEIGHT+28);
        wizard.setResizable(false);
        wizard.setIconImage(icon);
        wizard.setVisible(true);

        surface = new GamePanel();
        wizard.getContentPane().add(surface);
        surface.addKeyListener(this);
        surface.setFocusable(true);
        surface.setDoubleBuffered(true);
        surface.grabFocus();
    }

    public static void main(String[] args)
    {
        new WizardGame();
        while(true){
            lastFrame = currentFrame;
            surface.repaint();
            while(painted != true){
                surface.repaint();
                painted = true;
            }
            painted = false;
            currentFrame = getTime();
            setMoveCount();

        }
    }

    private static void setMoveCount() {
        double frameDelta = currentFrame - lastFrame;
        setVelocity();
        moveXCount = (frameDelta * moveXValue);
        moveYCount = (frameDelta * moveYValue);
    }

    private static void setVelocity() {
        if(keyRightPressed == true) {
            if(keyFramesX < 3)
                keyFramesX = 3;
            if(keyFramesX < 15)    
                keyFramesX ++;
            moveXValue = 0.005 * keyFramesX;
        }
        if(keyLeftPressed == true) {
            if(keyFramesX < 3)
                keyFramesX = 3;
            if(keyFramesX < 15)    
                keyFramesX ++;
            moveXValue = -0.005 * keyFramesX;
        }
        if(keyDownPressed == true) {
            if(keyFramesY < 3)
                keyFramesY = 3;
            if(keyFramesY < 15)
                keyFramesY ++;
            moveYValue = 0.005 * keyFramesY;
        }
        if(keyUpPressed == true) {
            if(keyFramesY < 3)
                keyFramesY = 3;
            if(keyFramesY < 15)
                keyFramesY ++;
            moveYValue = -0.005 * keyFramesY;
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {}
    @Override
    public void keyPressed(KeyEvent e) {
        // Right arrow key
        if (e.getKeyCode() == 39) {
            keyRightPressed = true;
        }
        // Left arrow key
        if (e.getKeyCode() == 37) {
            keyLeftPressed = true;
        }
        // Down arrow key
        if (e.getKeyCode() == 40) {
            keyDownPressed = true;
        }
        // Up arrow key
        if (e.getKeyCode() == 38) {
            keyUpPressed = true;
        }
    }
    @Override
    public void keyReleased(KeyEvent e) {
        // Right arrow key
        if (e.getKeyCode() == 39) {
            keyRightPressed = false;
            keyFramesX = 0;
        }
        // Left arrow key
        if (e.getKeyCode() == 37) {
            keyLeftPressed = false;
            keyFramesX = 0;
        }
        // Down arrow key
        if (e.getKeyCode() == 40) {
            keyDownPressed = false;
            keyFramesY = 0;
        }
        // Up arrow key
        if (e.getKeyCode() == 38) {
            keyUpPressed = false;
            keyFramesY = 0;
        }
    }
}

GamePanel.java

package wizard.game;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class GamePanel extends JPanel
{
    private Wizard wizard;
    private static Entity[][] spaces;
    private static ArrayList<Entity> spacesList;
    private static final int width = WizardGame.getWIDTH();
    private static final int height = WizardGame.getHEIGHT();
    boolean instantiated;
    BufferedImage textBox;
    BufferedImage invBox;
    BufferedImage invBoxNums;
    BufferedImage background;

    private static final Color PAULGRAY = new Color(25, 25, 25);
    private static final Color PAULTEXT = new Color(229, 0, 202);

    public GamePanel() {
        spaces = new Entity[width][height];
        spacesList = new ArrayList<Entity>();
        // Tell whether entities have been instantiated yet or not
        wizard = new Wizard(24, 20, 1);

        /*try {
            loadLevel("src/wizard/game/levelOne.txt");
        } catch (FileNotFoundException ex) {
            Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex);
        }*/
        new Potion(10, 10, "heal_instant", 50, 0);
        new Potion(15, 10, "harm_instant", 15, 0);
        new Potion(20, 10, "mult_maxHealth", 1.1, 0);
        // Random instantiations must come after non-random instantiations
        // to prevent location overlapping
        EntitySpawner.spawnEnemies(20);
    }

    // *** Interfacing methods ***
    // Return entity from a given location
    public static Entity getEntity(int x, int y) {
        if(isInBounds(x, y)) {
            if(spaces[x][y] == null)
                return null;
            return spaces[x][y];
        }
        return null;
    }
    // Determine whether a given entity is an instance of Wizard
    public static boolean isWizard(Entity e) {
        if(e instanceof Wizard)
            return true;
        return false;
    }
    // Determine whether a location is within the bounds of the game
    public static boolean isInBounds(int x, int y) {
        if(x<getW() && x>=0 && y<getH() && y>=0)
            return true;
        return false;
    }
    // Determine whether a loacation is within 3 sapaces of the 'Wizard'
    public static boolean isNearWizard(int x, int y) {
        if(Math.sqrt(Math.pow(getWizardX() - x, 2) + Math.pow(getWizardY() - y, 2)) <= 3)
            return true;
        return false;
    }
    // Instatntiate entites in a level from a text file
    public static void loadLevel(String l) throws FileNotFoundException {
        File level = new File(l);
        Scanner s = new Scanner(level);
        for(int y=1; y<=GamePanel.getH(); y++) {
            for(int x=1; x<=GamePanel.getW(); x++) {
                int a = x-1;
                int b = y-1;
                if(isInBounds(a, b)) {
                    String nextIdentifier = s.next();
                    switch(nextIdentifier) {
                        case("x"):
                            // Nothing
                            break; 
                        case("s"):
                            new WallSandstone(a, b);
                            break;
                        case("e"):
                            EntitySpawner.spawnEnemy(a, b);
                            break;
                    }
                }
            }
        }
    }
    // Return the width of the GamePanel
    public static int getW() { return width; }
    // Return the height of the GamePanel
    public static int getH() { return height; }
    // Return X position of Wizard
    public static int getWizardX() { return Wizard.getX(); }
    // return Y position of Wizard
    public static int getWizardY() { return Wizard.getY(); }
    // Return the entire 'spaces' array
    public static Entity[][] getSpaces() { return spaces; }
    // Return the list of entities
    public static ArrayList<Entity> getSpacesList() { return spacesList; }
    // Overwrite the entire spaces array
    public static void setSpaces( Entity[][] newSpaces ) { spaces = newSpaces; }
    // Overwrite the list of entities
    public static void setSpacesList( ArrayList<Entity> newList ) { spacesList = newList; }
    // Add entity to 'spacesList'
    public static void addEntity( Entity newEnt ) {spacesList.add(newEnt);}

    @Override
    public void paintComponent(Graphics g)
    {
        // Ugly sprite instantiation bullshit
        try { textBox = ImageIO.read(getClass().getResource("textbox.png")); } catch (IOException ex) { Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex); }
        try { invBox = ImageIO.read(getClass().getResource("invbox.png")); } catch (IOException ex) { Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex); }
        try { invBoxNums = ImageIO.read(getClass().getResource("invboxnums.png")); } catch (IOException ex) { Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex); }
        try { background = ImageIO.read(getClass().getResource("tempbackground.png")); } catch (IOException ex) { Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex); }

        // No idea what this is, I only know I need it
        super.paintComponent(g);

        // Paints the background
        g.setColor(PAULGRAY);
        g.fillRect( 0, 0, WizardGame.getWIDTH(), WizardGame.getHEIGHT() );
        g.drawImage(background, 0, 0, this);

        // Update health stats and draw the Wizard
        wizard.attack();
        g.drawImage(wizard.getSprite(), wizard.getSetX(), wizard.getSetY(), 16, 21, null);

        // Paints all entities 
        // Search through 'spaces'
        for(Entity ent: spacesList) {
            int x = ent.getX();
            int y = ent.getY();
                // Only accept non-'Wizard' entities
                if((getEntity(x, y) != null) && (!(getEntity(x, y) instanceof Wizard))) {
                    g.drawImage(getEntity(x, y).getSprite(), 
                        getEntity(x, y).getSetX(), 
                        getEntity(x, y).getSetY(), 16, 21, null);
                    // Determine if entity is an instance of 'Character'
                    if(getEntity(x, y) instanceof Character) {
                        // Update all variables of the character
                        ((Character)getEntity(x, y)).updateStats();
                        // Determine if entity is still an instance of 'Character'
                        if(getEntity(x, y) instanceof Character) {
                            // Determing if character is supposed to display stats
                            if((boolean)((Character)getEntity(x, y)).dispLev()==true) {
                                // Display character stats
                                g.drawString("" + (int)((Character)getEntity(x, y)).getLevel(),
                                        getEntity(x, y).getX()+5, getEntity(x, y).getY()-8);
                                g.setColor(Color.RED);
                                g.fillRect(getEntity(x, y).getX()-6, getEntity(x, y).getY()-6, 28, 2);
                                g.setColor(Color.GREEN);
                                int m = (int)((Character)getEntity(x, y)).getMaxHealth();
                                g.fillRect(getEntity(x, y).getX()-6, getEntity(x, y).getY()-6,
                                       (int)(((double)((Character)getEntity(x, y)).getHealth()/m)*28), 2);
                            }
                    }
                }
            }
        }

        // Paints the Textbox
        g.drawImage(textBox, 4, WizardGame.getHEIGHT()-204, this);
        g.setColor(PAULTEXT);
        int textX = 55;
        int textYStart = WizardGame.getHEIGHT()-140;
        g.drawString("XP: " + wizard.getEXP() + "\\" + wizard.getNextXP(), 
                textX, textYStart);
        g.setColor(PAULTEXT);
        g.fillRect( textX, textYStart + 12, (int)(((double)wizard.getEXP()/
                wizard.getNextXP())*100.00), 7);
        g.setColor(Color.GREEN);
        g.drawLine(textX, textYStart + 10, textX, textYStart + 20);
        g.drawLine(textX + 50, textYStart + 10, textX + 50, textYStart + 20);
        g.drawLine(textX + 100, textYStart + 10, textX + 100, textYStart + 20);
        g.setColor(PAULTEXT);
        g.drawString("Level: " + wizard.getLevel(), textX, textYStart + 40);
        g.drawString("Health: " + wizard.getHealth() + "\\" + wizard.getMaxHealth(), 
                textX, textYStart + 60);
        g.setColor(Color.RED);
        g.fillRect(textX, textYStart + 70, 100, 10);
        g.setColor(Color.GREEN);
        g.fillRect(textX, textYStart + 70, (int)(((double)wizard.getHealth()
                /wizard.getMaxHealth())*100.00), 10);

        // Paints the inventory boxes
        g.drawImage(invBox, 6, WizardGame.getHEIGHT()-240, this);
        g.drawImage(invBoxNums, 6, WizardGame.getHEIGHT()-240, this);

        // Clears GamePanel
        //WizardGame.resetXY();
        //WizardGame.setPainted(true);
    }
}

这是工作版本:

WizardGame.java

package wizard.game;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class WizardGame implements KeyListener
{
    private static final int WIDTH = 800+6;
    private static final int HEIGHT = 600+28;
    private static JPanel surface;
    private static int moveX;
    private static int moveY;
    private static int direction;

    public static int getWIDTH() { return WIDTH-6; }
    public static int getHEIGHT() { return HEIGHT-28; }
    public static int getMoveX() { return moveX; }
    public static int getMoveY() { return moveY; }
    public static void resetXY() { moveX = 0; moveY = 0; }
    public static int getDirection() { return direction; }

    public WizardGame()
    {
        BufferedImage icon = null;
        try {
            icon = ImageIO.read(getClass().getResource("Wizard.png"));
        } catch (IOException ex) {
            Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex);
        }

        JFrame wizard = new JFrame();
        wizard.setTitle("Wizard");
        wizard.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        wizard.setSize(WIDTH,HEIGHT);
        wizard.setVisible(true);
        wizard.setResizable(false);
        wizard.setIconImage(icon);

        surface = new GamePanel();
        wizard.getContentPane().add(surface);
        surface.addKeyListener(this);
        surface.setFocusable(true);
        surface.setDoubleBuffered(true);
        surface.grabFocus();
    }

    public static void main(String[] args)
    {
        new WizardGame();
        while(true){
            long startTime =  System.currentTimeMillis();
            long endTime = System.currentTimeMillis();
            while(endTime%startTime<=20){
                endTime = System.currentTimeMillis();
            }
            surface.repaint();
        }
    }

    @Override
    public void keyTyped(KeyEvent e) {
    }
    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == 39){
            moveX = 1;
            direction = 90;
        }
        if (e.getKeyCode() == 37){
            moveX = -1;
            direction = 270;
        }
        if (e.getKeyCode() == 40){
            moveY = 1;
            direction = 0;
        }
        if (e.getKeyCode() == 38){
            moveY = -1;
            direction = 180;
        }
    }
    @Override
    public void keyReleased(KeyEvent e) {
    }
}

GamePanel.java

package wizard.game;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JPanel;

public class GamePanel extends JPanel
{
    public Wizard wizard;
    public static Entity[][] spaces;
    public static final int width = 49;
    public static final int height = 28;
    boolean instantiated;
    BufferedImage textBox;
    BufferedImage invBox;
    BufferedImage invBoxNums;

    private static final Color PAULGRAY = new Color(25, 25, 25);
    private static final Color PAULTEXT = new Color(229, 0, 202);

    public GamePanel() {
        spaces = new Entity[width][height];
        // Tell whether entities have been instantiated yet or not
        instantiated = false;
    }

    // *** Interfacing methods ***
    // Return entity from a given location
    public static Entity getEntity(int x, int y) {
        if(isInBounds(x, y)) {
            if(spaces[x][y] == null)
                return null;
            return spaces[x][y];
        }
        return null;
    }
    // Determine whether a location is within the bounds of the game
    public static boolean isInBounds(int x, int y) {
        if(x<getW() && x>=0 && y<getH() && y>=0 && !(x<13 && y>15))
            return true;
        return false;
    }
    // Determine whether a loacation is within 3 sapaces of the 'Wizard'
    public static boolean isNearWizard(int x, int y) {
        for(int a = x-3; a <= x+3; a++) {
            for(int b = y-3; b <= y+3; b++) {
                if( getEntity(a, b) instanceof Wizard ) {
                    return true;
                }
            }
        }
        return false;
    }
    // Instatntiate entites in a level from a text file
    public static void loadLevel(String l) throws FileNotFoundException {
        File level = new File(l);
        Scanner s = new Scanner(level);
        for(int y=1; y<=GamePanel.getH(); y++) {
            for(int x=1; x<=GamePanel.getW(); x++) {
                int a = x-1;
                int b = y-1;
                if(isInBounds(a, b)) {
                    String nextIdentifier = s.next();
                    switch(nextIdentifier) {
                        case("x"):
                            // Nothing
                            break;
                        case("s"):
                            new WallSandstone(a, b);
                            break;
                        case("e"):
                            EntitySpawner.spawnEnemy(a, b);
                            break;
                    }
                }
            }
        }
    }
    // Return the width of the GamePanel
    public static int getW() { return width; }
    // Return the height of the GamePanel
    public static int getH() { return height; }
    // Return the entire 'spaces' array
    public static Entity[][] getSpaces() { return spaces; }
    // Overwrite the entire spaces array
    public static void setSpaces( Entity[][] newSpaces ) { spaces = newSpaces; }

    @Override
    public void paintComponent(Graphics g)
    {
        // Instantiate entities here only once
        while(instantiated == false){
            wizard = new Wizard(24, 20, 1);

            try {
                loadLevel("src/wizard/game/levelOne.txt");
            } catch (FileNotFoundException ex) {
                Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex);
            }
            new Potion(10, 10, "heal_instant", 50, 0);
            new Potion(15, 10, "harm_instant", 15, 0);
            new Potion(20, 10, "mult_maxHealth", 1.1, 0);
            // Random instantiations must come after non-random instantiations
            // to prevent location overlapping
            EntitySpawner.spawnEnemies(30);

            instantiated = true;
        }
        // Ugly sprite instantiation bullshit
        try { textBox = ImageIO.read(getClass().getResource("textbox.png")); } catch (IOException ex) { Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex); }
        try { invBox = ImageIO.read(getClass().getResource("invbox.png")); } catch (IOException ex) { Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex); }
        try { invBoxNums = ImageIO.read(getClass().getResource("invboxnums.png")); } catch (IOException ex) { Logger.getLogger(GamePanel.class.getName()).log(Level.SEVERE, null, ex); }
        // No idea what this is, I only know I need it
        super.paintComponent(g);

        // Paints the background
        g.setColor(PAULGRAY);
        g.fillRect( 0, 0, WizardGame.getWIDTH(), WizardGame.getHEIGHT() );

        // Paints the Textbox
        g.drawImage(textBox, 4, WizardGame.getHEIGHT()-204, this);
        g.setColor(PAULTEXT);
        int textX = 55;
        int textYStart = WizardGame.getHEIGHT()-140;
        g.drawString("XP: " + wizard.getEXP() + "\\" + wizard.getNextXP(), 
                textX, textYStart);
        g.setColor(PAULTEXT);
        g.fillRect( textX, textYStart + 12, (int)(((double)wizard.getEXP()/
                wizard.getNextXP())*100.00), 7);
        g.setColor(Color.GREEN);
        g.drawLine(textX, textYStart + 10, textX, textYStart + 20);
        g.drawLine(textX + 50, textYStart + 10, textX + 50, textYStart + 20);
        g.drawLine(textX + 100, textYStart + 10, textX + 100, textYStart + 20);
        g.setColor(PAULTEXT);
        g.drawString("Level: " + wizard.getLevel(), textX, textYStart + 40);
        g.drawString("Health: " + wizard.getHealth() + "\\" + wizard.getMaxHealth(), 
                textX, textYStart + 60);
        g.setColor(Color.RED);
        g.fillRect(textX, textYStart + 70, 100, 10);
        g.setColor(Color.GREEN);
        g.fillRect(textX, textYStart + 70, (int)(((double)wizard.getHealth()
                /wizard.getMaxHealth())*100.00), 10);

        // Paints the inventory boxes
        g.drawImage(invBox, 6, WizardGame.getHEIGHT()-240, this);
        g.drawImage(invBoxNums, 6, WizardGame.getHEIGHT()-240, this);

        wizard.attack();
        g.drawImage(wizard.getSprite(), wizard.getSetX(), wizard.getSetY(), 16, 21, null);

        // Paints all entities 
        // Search through 'spaces'
        for(int w = 0; w < spaces.length; w++) {
            for(int h = 0; h < spaces[1].length; h++) {
                // Only accept non-'Wizard' entities
                if((getEntity(w, h) != null) && (!(getEntity(w, h) instanceof Wizard))) {
                    g.drawImage(getEntity(w, h).getSprite(), 
                        getEntity(w, h).getSetX(), 
                        getEntity(w, h).getSetY(), 16, 21, null);
                    // Determine if entity is an instance of 'Character'
                    if(getEntity(w, h) instanceof Character) {
                        // Update all variables of the character
                        ((Character)getEntity(w, h)).updateStats();
                        // Determine if entity is still an instance of 'Character'
                        if(getEntity(w, h) instanceof Character) {
                            // Determing if character is supposed to display stats
                            if((boolean)((Character)getEntity(w, h)).dispLev()==true) {
                                // Display character stats
                                g.drawString("" + (int)((Character)getEntity(w, h)).getLevel(),
                                        getEntity(w, h).getX()+5, getEntity(w, h).getY()-8);
                                g.setColor(Color.RED);
                                g.fillRect(getEntity(w, h).getX()-6, getEntity(w, h).getY()-6, 28, 2);
                                g.setColor(Color.GREEN);
                                int m = (int)((Character)getEntity(w, h)).getMaxHealth();
                                g.fillRect(getEntity(w, h).getX()-6, getEntity(w, h).getY()-6,
                                       (int)(((double)((Character)getEntity(w, h)).getHealth()/m)*28), 2);
                            }
                        }
                    }
                }
            }
        }

        // Clears GamePanel
        WizardGame.resetXY();
    }
}

1 个答案:

答案 0 :(得分:0)

我明白了!实体实例化必须在GamePanel.java中的paintComponent()函数内发生。我不知道为什么。