Java 游戏(箭头控制)速度减慢,鼠标在 JFrame 外部移动期间除外

标签 java performance swing

所以,我创建了一个横向的“太空入侵者”类型的游戏,我使用了 Swing、JFrame、JPanel、计时器、图形等。

我已将控件设置为箭头键和空格键,因此不需要鼠标。

但是我遇到的问题是,在玩游戏时,游戏似乎“变慢了”,并且仅在鼠标移动时加速到正常速度在 JFrame 之外,并在我停止移动它后持续 1 或 2 秒。

例如,如果其他人正在玩游戏,游戏将以减慢的速度开始。如果我开始将鼠标移动到 JFrame 之外,则当我继续移动鼠标时,游戏会加速到正常速度。当我停止移动它后,速度还会有几秒钟的提高,然后又减慢。

我不知道它可能是什么,因为我没有知道可能会监听鼠标和/或影响性能的代码。运行它的计算机是一个非常干净的系统,有 8 个千兆位和一个 i7。 Eclipse Luna 4.4,Java 1.8。 (8 u 25),因此任何 CPU 性能问题都不太可能发生。

--

这是我的键盘、 Action 监听器和移动相关的代码:

主类:

public class Iniciar extends JFrame{

    private static final long serialVersionUID = 1L;
    JPanel panel;
    JPanel splash;
    JButton botonStart;
    JButton botonExit;
    Board b;
    Timer timer;
    BufferedImage splashimg;

    public Iniciar () throws IOException
    {
        splash = new JPanel();
        panel = new JPanel();

        botonStart = new JButton("START");
        botonExit = new JButton("EXIT");

        panel.setLayout(new BorderLayout());
        botonStart.addActionListener(new ActionListener() {


            public void actionPerformed(ActionEvent e) {
                if (botonStart.getText() == "RESTART")
                {
                    dispose();
                    try {
                        new Iniciar();
                    } catch (IOException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                }
                panel.setVisible(true);
                try {
                    b = new Board(botonStart,panel);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }   
                  panel.add(b);
                  splash.setVisible(false);
                  botonStart.setVisible(false);
            }   
        });

        botonExit.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                System.exit(EXIT_ON_CLOSE);
            }
        });

        JPanel panelBotonStart = new JPanel();
        panelBotonStart.add(botonStart);
        panelBotonStart.add(botonExit);
        botonStart.setBorderPainted(false);
        botonStart.setBackground(Color.white);
        botonExit.setBorderPainted(false);
        botonExit.setBackground(Color.white);

        splashimg = ImageIO.read(getClass().getResource("splash.jpg"));
        ImageIcon splashicon = new ImageIcon(splashimg);
        JLabel splashlabel = new JLabel();
        splashlabel.setIcon(splashicon);
        splash.add(splashlabel);

        add(panel,"Center");
        panel.add(panelBotonStart,"South");
        panelBotonStart.setBackground(Color.black);
        panel.add(splash,"North");

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setSize(1200, 700);
        setLocationRelativeTo(null);
        setTitle("Forgia Invaders");
        setResizable(false);
        setVisible(true);
    }

    public static void main(String [] args) throws IOException
    {
        new Iniciar();

    }
}

我的绘制图形的板:

public class Board extends JPanel implements ActionListener {

    private static final long serialVersionUID = 7017738498086742491L;
    private Timer timer;
    private Craft craft;
    private int vidas = 5;
    private BufferedImage fondoimg, fondoimg2, fondoimg3;
    private ImageIcon fondoicon, fondoiconwin, fondoiconlose;
    private ArrayList<Alien> aliens;
    private boolean ingame;
    private boolean victory;
    private int B_WIDTH;
    private int B_HEIGHT;
    private int puntaje;
    boolean nivel2 = false;
    boolean nivel3 = false;
    boolean nivel4 = false;
    boolean bombas = false;
    boolean boss = false;
    int bossHealth = 200;
    private JLabel fondolabel;

    private int cantaliens;

    JButton restart;
    JPanel p;


    public Timer getTimer()
    {
        return timer;
    }
    public Board(JButton start, JPanel p) throws IOException {





        addKeyListener(new TAdapter());
        setFocusable(true);
        setBackground(Color.BLACK);
        setDoubleBuffered(true);
        ingame = true;
        this.restart = start;
        this.p = p;
        setSize(1200,700);
        craft = new Craft();
        timer = new Timer(5, this);
        timer.start();

        fondoimg = ImageIO.read(getClass().getResource("space3.jpg"));
        fondoicon = new ImageIcon(fondoimg);

        fondoimg2 = ImageIO.read(getClass().getResource("youlose2.png"));
        fondoiconlose = new ImageIcon(fondoimg2);

        fondoimg3 = ImageIO.read(getClass().getResource("youwin2.png"));
        fondoiconwin = new ImageIcon(fondoimg3);

        setLayout(new BorderLayout());
        fondolabel = new JLabel();
        fondolabel.setIcon(fondoicon);
        add(fondolabel,"Center");

//ALIENSINICIALES        
        aliens = new ArrayList<Alien>();

        for (int i = 0; i < 10; i++) {
            int xR;
            int yR;
            xR = 1200 + ((int) (Math.random()*300));
            yR = (int) ((Math.random()*550));
            aliens.add(new Alien2 (xR, yR));
        }
        for (int i = 0; i < 10; i++) {
            int xR;
            int yR;
            xR = 1200 + ((int) (Math.random()*500));
            yR = (int) ((Math.random()*550));
            aliens.add(new Alien3 (xR, yR));
        }
        for (int i = 0; i < 15; i++) {
            int xR;
            int yR;
            xR = 1200 + ((int) (Math.random()*800));
            yR = (int) ((Math.random()*550));
            aliens.add(new Alien4 (xR, yR));
        }

        cantaliens = aliens.size();
    }

    public int getCantaliens() {
        return cantaliens;
    }

    public void addNotify() {
        super.addNotify();
        B_WIDTH = getWidth();
        B_HEIGHT = getHeight();   
    }


    public void paint(Graphics g) {
        super.paint(g);
        Graphics2D g2d = (Graphics2D)g;

        String msg4 = "Score: "+puntaje;
        Font small = new Font("Press Start 2P", Font.BOLD, 54);
        FontMetrics metr = this.getFontMetrics(small);
        Font small2 = new Font("Press Start 2P", Font.BOLD, 24);

    //    if (ingame) {
        if (ingame && !victory) {
            if (craft.isVisible() && vidas >4)
                g2d.drawImage(craft.getImage(), craft.getX(), craft.getY(), this);

            if (craft.isVisible() && vidas >=0 && vidas <=4)
                g2d.drawImage(craft.getImage2(), craft.getX(), craft.getY(), this);

            ArrayList<Missile> ms = craft.getMissiles();

            for (int i = 0; i < ms.size(); i++) {
                Missile m = (Missile)ms.get(i);
                g2d.drawImage(m.getImage(), m.getX(), m.getY(), this);
            }

            for (int i = 0; i < aliens.size(); i++) {
                Alien a = aliens.get(i);
                if (a.isVisible())
                    g2d.drawImage(a.getImage(), a.getX(), a.getY(), this);
            }

            g2d.setColor(Color.WHITE);
            g2d.setFont(new Font("Press Start 2P", Font.PLAIN, 15)); 
            g2d.drawString("Enemigos: " + aliens.size()+ "    Score: " + puntaje, 90 , 20);

            if (vidas > 2)
                g2d.setColor(Color.green);
            else
                if (vidas >1)
                    g2d.setColor(Color.yellow);
                else
                {
                    g2d.setColor(Color.red);                    
                }
            g2d.drawString("Vidas: "+vidas, B_WIDTH/2 -30 ,20);

            if (boss){

                if (bossHealth > 130)
                    g2d.setColor(Color.green);
                else
                    if (bossHealth > 75)
                        g2d.setColor(Color.yellow);
                    else
                        g2d.setColor(Color.red);

                g2d.drawString("Vida Jefe: " + bossHealth, B_WIDTH/2 - 70 , 620);
            }

        } 

        if (!ingame && !victory) {

            timer.stop();
          restart.setText("RESTART");
          restart.setVisible(true);
            g.setFont(small);
            g.setColor(Color.WHITE);
            String msg = "Game Over";
            g.drawString(msg, (B_WIDTH - metr.stringWidth(msg)) / 2,B_HEIGHT / 2);
            g.setFont(small2);
            g.drawString(msg4, (B_WIDTH - metr.stringWidth(msg4)) / 2 + 100, B_HEIGHT / 2 +140); 

            fondolabel.setIcon(fondoiconlose);

        }

//GANASTE
        if (!ingame && victory) {
            String msg = "You Win";
            g.setColor(Color.cyan);
            g.setFont(small);
            g.setColor(Color.white);
            g.drawString(msg, (B_WIDTH - metr.stringWidth(msg)) / 2 , B_HEIGHT / 2 );

            fondolabel.setIcon(fondoiconwin);
//DISPAROS          
            final int dispfinal = Craft.getCounter();
            String msg2 = "Disparos: "+dispfinal;

            g.setColor(Color.white);
            g.setFont(small2);
            g.drawString(msg2, (B_WIDTH - metr.stringWidth(msg2)) / 2 +180, B_HEIGHT / 2 +60);

//EFECTIVDAD&SCORE
            double numerin = Math.round((402 / ((double)dispfinal) * 10)*10) ;
            String msg3 = "Efectividad: "+numerin+"%";

            g.drawString(msg3, (B_WIDTH - metr.stringWidth(msg3)) / 2 +280, B_HEIGHT / 2 +100);
            g.drawString(msg4, (B_WIDTH - metr.stringWidth(msg4)) / 2 +180 , B_HEIGHT / 2 +140);
    }

 //     Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }
    public boolean gamover()
    {
        return !ingame && !victory;
    }

    public int getBossHealth() {
        return bossHealth;
    }
    public void setBossHealth(int bossHealth) {
        this.bossHealth = bossHealth;
    }

    public void actionPerformed(ActionEvent e) {

//NIVELES       
        if (aliens.size()<5 && !nivel2) {

            for (int i = 0; i < 5; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*1500));
                yR = (int) ((Math.random()*550));
                aliens.add(new Alien3 (xR, yR));
            }
            for (int i = 0; i < 15; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*1500));
                yR = (int) ((Math.random()*550));
                aliens.add(new Alien4 (xR, yR));
            }
            for (int i = 0; i < 5; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*1500));
                yR = (int) ((Math.random()*550));
                aliens.add(new Alien5 (xR, yR));
            }

            for (int i = 0; i < 5; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*1500));
                yR = (int) ((Math.random()*550));
                aliens.add(new Alien5bis (xR, yR));
            }

            nivel2 = true;
        }

        if (aliens.size()<4 && nivel2 && !nivel3) {

            for (int i = 0; i < 8; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*1500));
                yR = (int) ((Math.random()*550));
                aliens.add(new Alien5 (xR, yR));
            }

            for (int i = 0; i < 8; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*1500));
                yR = (int) ((Math.random()*550));
                aliens.add(new Alien5bis (xR, yR));
            }

            for (int i = 0; i < 18; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*1500));
                yR = (int) ((Math.random()*550));
                aliens.add(new Alien6 (xR, yR));
            }

            nivel3 = true;
        }

        if (aliens.size()<3 && nivel3 && !bombas) {

            for (int i = 0; i < 10; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*1500));
                yR = (int) ((Math.random()*550));
                aliens.add(new Alien5 (xR, yR));
            }
            for (int i = 0; i < 10; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*1500));
                yR = (int) ((Math.random()*550));
                aliens.add(new Alien6 (xR, yR));
            }

            for (int i = 0; i < 30; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*50));
                yR = (int) ((Math.random()*550));
                aliens.add(new Bomba (xR, yR));
            }

            bombas = true;
        }

        if (aliens.size()<3 && bombas && !boss) {

            for (int i = 0; i < 30; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*50));
                yR = (int) ((Math.random()*550));
                aliens.add(new Slime (xR, yR));
            }

            aliens.add(new Forgio (1250, 350));
            boss = true;
        }

        if (bossHealth==0) {
            ingame = false;
            victory = true;
            for (int i = 0; i < aliens.size(); i++ )
            {
                aliens.get(i).setVisible(false);
            }
        }

        ArrayList<Missile> ms = craft.getMissiles();

        for (int i = 0; i < ms.size(); i++) {
            Missile m = (Missile) ms.get(i);
            if (m.isVisible()) 
                m.move();
            else ms.remove(i);
        }

        for (int i = 0; i < aliens.size(); i++) {
            Alien a = (Alien) aliens.get(i);
            if (a.isVisible()) 
                a.move();
            else aliens.remove(i);
        }

        craft.move();
        checkCollisions();
        repaint();  
    }


    public void checkCollisions() {

        if (bossHealth < 75 && !nivel4)
        {
            for (int i = 0; i < 20; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*50));
                yR = (int) ((Math.random()*550));
                aliens.add(new Bomba (xR, yR));
            }

            for (int i = 0; i < 15; i++) {
                int xR;
                int yR;
                xR = 1200 + ((int) (Math.random()*250));
                yR = (int) ((Math.random()*550));
                aliens.add(new Slimebis (xR, yR));
            }

            for (int i = 0; i < 15; i++) {
                int xR;
                int yR;
                xR = 1400 + ((int) (Math.random()*250));
                yR = (int) ((Math.random()*550));
                aliens.add(new Slime (xR, yR));
            }

            nivel4 = true;
        }

        Ellipse2D.Double navecita = (Double) craft.getBounds();

        for (int j = 0; j<aliens.size(); j++) {
            Alien enemigo = (Alien) aliens.get(j);
            Rectangle areaEnemigo = enemigo.getBounds();

            if (navecita.intersects(areaEnemigo)) {
                if (vidas == 0)
                {
                    craft.setVisible(false);
                    enemigo.setVisible(false);
                    new FinWav().playSound();
                    ingame = false;
                    victory = false;

                    for (int i = 0; i < aliens.size(); i++ )
                    {
                        aliens.get(i).setVisible(false);
                    }

                }
                else
                {
                    enemigo.setVisible(false);
                    vidas--;
                    new FinWav().playSound();
                    if (enemigo instanceof Forgio)
                    {
                        aliens.add(new ExplosionGde (enemigo.x, enemigo.y));
                        enemigo.x = 1300;
                        enemigo.setVisible(true);
                    }
                    else
                    {
                        aliens.add(new Explosion (enemigo.x, enemigo.y));       
                    }
                }
            }
        }

        ArrayList<Missile> listaMisiles = craft.getMissiles();

        for (int i = 0; i < listaMisiles.size(); i++) {
            Missile misil = (Missile) listaMisiles.get(i);

            Rectangle areaMisil = misil.getBounds();

            for (int j = 0; j<aliens.size(); j++) {
                Alien enemigo = (Alien) aliens.get(j);
                Rectangle areaEnemigo = enemigo.getBounds();

                if (areaMisil.intersects(areaEnemigo)) {
                    if (enemigo instanceof Forgio)
                        if (bossHealth > 0)
                        {
                            bossHealth--;
                            puntaje = puntaje + 100;
                        }
                        else 
                        {
                            puntaje = puntaje + enemigo.getPuntitos();
                            enemigo.setVisible(false);

                        }
                    else {
                    enemigo.setVisible(false);
                    puntaje = puntaje + enemigo.getPuntitos();
                    }
                    misil.setVisible(false);
                    new ExplosWAV().playSound();
                }
            }
        }
    }


    private class TAdapter extends KeyAdapter {

        public void keyReleased(KeyEvent e) {
            craft.keyReleased(e);
        }

        public void keyPressed(KeyEvent e) {
            craft.keyPressed(e, ingame);
        }
    }
}

最后,我的工艺课使用了按键/释放:

public class Craft {

    private int dx;
    private int dy;
    private int x;
    private int y;
    private Image image, image2;
    private ArrayList<Missile> missiles;
    private int width;
    private int height;
    private boolean visible;
    private static int counter;    

    public Craft() {

        ImageIcon ii = new ImageIcon(this.getClass().getResource("nabe6.png"));
        ImageIcon ii2 = new ImageIcon(this.getClass().getResource("nabe7.png"));

        image = ii.getImage();  
        image2 = ii2.getImage();    
        width = image.getWidth(null)-25;
        height = image.getHeight(null)-20 ;
        missiles = new ArrayList<Missile>();
        visible = true;
        x = 77;
        y = 241;
    }

    public void move() {
        x += dx*2;
        y += dy*2;

        if (x < 1) {
            x = 1;
        }

        if (y < 1) {
            y = 1;
        }
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public static int getCounter() {
        return counter;
    }

    public void setCounter(int counter) {
        Craft.counter = counter;
    }

    public Image getImage() {
        return image;
    }

    public Image getImage2() {
        return image2;
    }

    public ArrayList<Missile> getMissiles() {
        return missiles;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    public boolean isVisible() {
        return visible;
    }

    public Ellipse2D getBounds() {
        return new Ellipse2D.Double(x, y, width, height);
    }

    public void keyPressed(KeyEvent e, boolean x) {

        int key = e.getKeyCode();

        if (key == KeyEvent.VK_SPACE && x) {

            fire();
        }

        if (key == KeyEvent.VK_LEFT) {
            dx = -1;
        }

        if (key == KeyEvent.VK_RIGHT) {
            dx = 1;
        }

        if (key == KeyEvent.VK_UP) {
            dy = -1;
        }

        if (key == KeyEvent.VK_DOWN) {
            dy = 1;
        }
    }


    public void fire() {
        missiles.add(new Missile(x + width-40, y + height/12));
        new LaserWAV().playSound();
        counter++;
    }

    public void keyReleased(KeyEvent e) {
        int key = e.getKeyCode();

        if (key == KeyEvent.VK_LEFT) {
            dx = 0;
        }

        if (key == KeyEvent.VK_RIGHT) {
            dx = 0;
        }

        if (key == KeyEvent.VK_UP) {
            dy = 0;
        }

        if (key == KeyEvent.VK_DOWN) {
            dy = 0;
        }
    }
}

最佳答案

问题不在于您的代码。问题在于没有多个线程。在制作游戏时,尤其是横向卷轴游戏时,EventQueue 中的所有操作最终都会压垮队列。尝试使用线程缓解队列,您的游戏应该会变得更快。

关于Java 游戏(箭头控制)速度减慢,鼠标在 JFrame 外部移动期间除外,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26548944/

相关文章:

java - CraftBukkit 插件编码错误

java - tomcat服务器启动慢

java - 按钮改变颜色,但我需要它们在单击时停止

java - 将图像加载到 Java 中

java - 在不断缩小的 LispList 中递归查找 INT 的索引

java - 从另一个 Activity 发送实时消息

performance - Haskell - 缓存函数调用的简单方法

java - 嵌套循环与硬编码矩阵乘法的性能

java - JComboBox 对于 JFrame 来说太长

java - 同步是什么意思?