简体   繁体   中英

A tile-based game frequently freezes when I run it. How can I fix this?

I recently posted this but my question wasn't properly worded, so I'm trying this again. I've been diligently working on a tile-based Java game as a project for my Java class. Everything is going very well so far, but a pretty big problem that I'm having is that when I run my game, it will start frozen about 50% of the time, not reacting to any keys pressed or anything like it should. Sometimes it works and sometimes it doesn't. It's somewhat similar in structure to this tutorial , but there are obviously a lot of changes and additions that I have made. I have a feeling it is happening in my game panel class, because everything seems to function as intended when the game DOES run correctly, so I'll put post that class. I also apologize for anything strange or unconventional in my code, I'm still kind of an amateur at coding so if clarification is needed I will supply it.

So my main question is does anyone know what the problem is or have any suggestions for how I can remedy the freezing? Thanks!

panel.java:

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import javax.swing.ImageIcon;
import javax.swing.JPanel;

public class panel extends JPanel implements KeyListener, Runnable
{
    //game variables
    private Thread game;
    private boolean running = false;
    private boolean mapFinished = false;
    player p1;

    //panel variables
    static final int Width = 480;
    static final int Height = 432;
    static final Dimension dim = new Dimension(Width,Height);

    //maps
    map map1;
    map map2;
    map map3;
    map map4;

    enemy e;

    boolean map1Finished;
    boolean map2Finished;
    boolean map3Finished;
    boolean map4Finished;

    //drawing variables
    private BufferedImage image;
    private Graphics g;
    private long time = 6*1000000;
    goal ng;
    private Image winningImage;

    private boolean map2Spawn;
    private boolean map3Spawn;
    private boolean map4Spawn;

    public panel(){
        map1 = new map("tester.txt");
        map2 = new map("tester2.txt");
        map3 = new map("tester3.txt");
        map4 = new map("tester4.txt");
        p1 = new player(map1);
        ng = new goal(map1);
        e = new enemy(map1);
        setPreferredSize(new Dimension(Width,Height));
        setFocusable(true);
        requestFocus();
    }

    public void run(){
        long startTime;
        long elapsedTime;
        long diff;
        long sleepTime;
        long overSleep=0;

        image=new BufferedImage(Width,Height,BufferedImage.TYPE_INT_RGB);
        g=image.getGraphics();
        running = true;

        while (running){
            startTime=System.nanoTime();
            gameUpdate();
            gameRender();
            gameDraw();
            elapsedTime=System.nanoTime();
            diff=elapsedTime-startTime;
            if(diff<time){
                sleepTime=time-diff-overSleep;
                try{
                    game.sleep(sleepTime/1000000);
                }
                catch(Exception e){

                }
            }
            else{
                overSleep=diff-time;
            }
        }
    }

    private void gameUpdate(){
        p1.update();

        if((p1.playerRec.x/48)==(ng.goalRec.x/48) && (p1.playerRec.y/48)==(ng.goalRec.y/48)){
            if(!map1Finished){
                map1Finished=true;
            }
            else if(map1Finished&&!map2Finished){
                map2Finished=true;
            }
            else if(map2Finished&&!map3Finished){
                map3Finished=true;
            }
            else if(map3Finished&&!map4Finished){
                map4Finished=true;
            }

        }

        changeSpawn();
    }

    private void gameRender(){
        g.setColor(Color.WHITE);
        g.fillRect(0,0,Width,Height);
        g.setColor(Color.BLACK);
        if (!map1Finished){
            map1.draw(g);
            p1.draw(g);
        }


        if (map1Finished&&!map2Finished){
            map2.draw(g);
            p1.draw(g);
            winningImage=new ImageIcon("sprites/level1.png").getImage();
            g.drawImage(winningImage,5,5,null);
        }
        if (map2Finished&&!map3Finished){
            map3.draw(g);
            p1.draw(g);
            winningImage=new ImageIcon("sprites/level1.png").getImage();
            g.drawImage(winningImage,5,5,null);
        }
        if (map3Finished&&!map4Finished){
            map4.draw(g);
            p1.draw(g);
            winningImage=new ImageIcon("sprites/level1.png").getImage();
            g.drawImage(winningImage,5,5,null);
        }
        //g.drawString(""+map1.tileMap[1][7], 100, 100);
    }

    public void gameDraw(){
        Graphics g2=this.getGraphics();
        g2.drawImage(image, 0, 0, null);
        g2.dispose();
    }

    public void keyTyped(KeyEvent key) {}

    public void keyPressed(KeyEvent key) {

    int code = key.getKeyCode();    
    if(code == KeyEvent.VK_LEFT) {
            p1.setLeft(true);
    }
    if(code == KeyEvent.VK_RIGHT) {
            p1.setRight(true);
    }
    if(code == KeyEvent.VK_UP) {
            p1.setUp(true);
    }
    if(code == KeyEvent.VK_DOWN) {
            p1.setDown(true);
    }
    }

    public void keyReleased(KeyEvent key) {
    int code = key.getKeyCode();
    if(code == KeyEvent.VK_LEFT) {
        p1.setLeft(false);
    }
    if(code == KeyEvent.VK_RIGHT) {
        p1.setRight(false);
    }
    }

    public void addNotify(){
        super.addNotify();
        if(game==null){
            game=new Thread(this);
            game.start();
        }
        addKeyListener(this);
    }

    public void startGame(){
        if (running == false){
            running = true; 
        }
    }

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

    public boolean boolTimer(){
        long now=System.currentTimeMillis();
        long end = now+1*3000;
        long current = System.currentTimeMillis();
        while(current<end){
            current = System.currentTimeMillis();
        }
        return true;
    }

    public void changeSpawn(){
        if(map1Finished==true && map2Spawn==false){
            p1=new player(map2);
            ng=new goal(map2);
            map2Spawn=true;
        }

        else if(map2Finished==true && map3Spawn==false){
            p1=new player(map3);
            ng=new goal(map3);
            map3Spawn=true;
        }
        else if(map3Finished==true && map4Spawn==false){
            p1=new player(map4);
            ng=new goal(map4);
            map4Spawn=true;
        }
    }
}
  1. don't use getGraphics() of a Swing component to do painting. Custom painting is done by overriding the paintComponent() method of the JPanel.

  2. Use a Swing Timer to schedule the animation, not a Thread.

  3. Don't use a KeyListener to listen for KeyEvents. Instead you should be using Key Bindings .

I suggest you start by reading the Swing tutorial . There are sections in the tutorial that cover the above points.

  1. Don't use requestFocus(). The better method to use is requestFocusInWindow() . Although neither method will work unless the component is displayed on a visible GUI, so placing the code in the constructor doesn't do anything.

  2. static final constant variables should be completely upper cased, not just the first letter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM