单击鼠标冻结Java游戏

时间:2016-03-14 22:16:24

标签: java swing freeze mouselistener

我在一个小项目上工作,遇到了一些我不知道如何解决的问题。我试着查看线程,看看这是不是问题,但找不到任何帮助我的东西。问题是每当我点击框架,键输入,动画等都冻结。

这是主类的代码:(如果您需要来自任何其他类的代码,请告诉我,但我认为问题在于此处)

package me.runeglaive.main;

import java.awt.BorderLayout;
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;

import me.runeglaive.gamestate.GameStateManager;

public class Game extends Canvas implements Runnable{

    private static final long serialVersionUID = 1L;

    public static int height = 360;
    public static int width = height * 16 / 9;
    public static int scale = 2;

    private JFrame frame;
    private Graphics g;

    private boolean running = true;

    GameStateManager gsm;

    public Game(){
        frame = new JFrame("Game");

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(this, BorderLayout.CENTER);
        frame.pack();

        frame.setSize(width * scale, height * scale);
        frame.setResizable(false);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        gsm = new GameStateManager();

        init();

        MouseListener ml = new MouseListener(){

            public void mousePressed(MouseEvent e) {
                gsm.mousePressed(e);
            }

            public void mouseReleased(MouseEvent e) {
                gsm.mouseReleased(e);
            }

            public void mouseClicked(MouseEvent e) {}
            public void mouseEntered(MouseEvent e) {}
            public void mouseExited(MouseEvent e) {}
        };

        KeyListener kl = new KeyListener(){

            public void keyPressed(KeyEvent k) {
                gsm.keyPressed(k);
            }

            public void keyReleased(KeyEvent k) {
                gsm.keyReleased(k);
            }

            public void keyTyped(KeyEvent k) {

            }

        };
        frame.addKeyListener(kl);
        frame.addMouseListener(ml);
        frame.setFocusable(true);
    }

    public void init(){

    }

    public void update(double delta){
        gsm.update(delta);
    }

    public void render(){

        //double buffering
        BufferStrategy bs = getBufferStrategy();
        if (bs == null){
            createBufferStrategy(2);
            return;
        }

        g = bs.getDrawGraphics();

        //clear screen
        g.clearRect(0, 0, getWidth(), getHeight());

        //Draw gameState
        gsm.render(g);

        g.dispose();
        bs.show();
    }

    public synchronized void start(){
        running = true;
        new Thread(this).start();
    }

    public synchronized void stop(){
        running = false;
    }

    public void run() {

            //initialize time loop variables
            long lastLoopTime = System.nanoTime();
            final int TARGET_FPS = 60;
            final long OPTIMAL_TIME = 1000000000 / TARGET_FPS;
            double lastFpsTime = 0;

            while(running)
            {
                //Calculate since last update
                long now = System.nanoTime();
                long updateLength = now - lastLoopTime;
                lastLoopTime = now;
                double delta = updateLength / ((double)OPTIMAL_TIME);

                //update frame counter
                lastFpsTime += updateLength;

                //update FPS counter
                if(lastFpsTime >= 1000000000)
                {
                    lastFpsTime = 0;
                }

                //game updates
                update(delta);

                //graphics (gameState)
                render();

                try{
                    Thread.sleep((Math.abs(lastLoopTime - System.nanoTime() + OPTIMAL_TIME)/1000000));
                }catch(InterruptedException e){
                    System.out.println("Error in sleep");
                }
            }
        }
    public static void main(String args[]){
        new Game().start();
    }
}

Heres the Game State Manager:

package me.runeglaive.gamestate;

import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

public class GameStateManager {

    private ArrayList<GameState> states;

    private int currentState;

    public static final int MENUSTATE = 0;
    public static final int MAINSTATE = 1;

    public GameStateManager(){
        states = new ArrayList<GameState>();
        states.add(new MenuState(this));
        states.add(new MainState(this));

        setState(MAINSTATE);
    }

    public void setState(int state){
        currentState = state;
        states.get(state).init();
    }

    public int getCurrentState(){
        return currentState;
    }

    public void update(double delta){
        states.get(currentState).update(delta);
    }

    public void render(Graphics g){
        states.get(currentState).render(g);
    }

    public void keyPressed(KeyEvent k){
        states.get(currentState).keyPressed(k);
    }

    public void keyReleased(KeyEvent k){
        states.get(currentState).keyReleased(k);
    }

    public void mousePressed(MouseEvent e){
        states.get(currentState).mousePressed(e);
    }

    public void mouseReleased(MouseEvent e){
        states.get(currentState).mouseReleased(e);
    }
}

1 个答案:

答案 0 :(得分:0)

gsm.mousePressed(e)的代码是什么;和gsm.mouse发布(e)好吗? :)

你在滥用Java Swing。您不应创建自己的线程并以编程方式重绘场景,因为这会干扰输入队列的线程模型。

如果你正在使用swing,那么不要启动自己的线程,而是启动一个swing计时器。从计时器的事件侦听器调用更新。而不是调用渲染,在帧上发出repaint()并覆盖帧的绘制代码,如果你想玩得好。 http://www.oracle.com/technetwork/java/painting-140037.html

在AWT的情况下,有系统触发的绘画和应用程序触发的绘制。

你正在做的代码是一个完全有效的蛮力游戏编码器思考 - 如果你在屏幕上有完全控制权,则完全有效。在Swing的情况下,情况并非如此,因为Swing确实需要处理更多事情。如果你和Mr.Swing搞混乱,它迟早会咬你; - )

如果您更喜欢更认真地对待这个游戏开发,那么请寻找Java 2D游戏引擎或Java 3D游戏引擎(例如jMonkey)来处理所有细节并提供工作垂直回扫同步 - 这是不可避免的流畅的动作。请注意,您的BufferStrategy 会照顾它,这个主题更复杂。