0

So, I have created a horizontal 'space invaders' type of game, and I'm using Swing, a JFrame, JPanel, Timer, Graphics, etc.

I have set my controls to be arrow keys and spacebar, so the mouse isn't needed.

However the problem I'm having is that while playing the game, the game seems "slowed down", and only speeds up to what should be normal speed while and during the mouse is being moved outside the JFrame and for 1 or 2 seconds after I stop moving it.

So for example, if someone else is playing, the game will start at a slowed speed. If I start moving the mouse for them outside of the JFrame, the game speeds up to normal speed WHILE I keep moving it. After I stop moving it, there will be another few seconds of improved speed and then slown down again.

I have NO idea what it could be, given that I have no code that I'm aware could be listening to the mouse and/or affecting performance. The computer running it is a pretty clean system with 8 gigs and an i7. Eclipse Luna 4.4, Java 1.8. (8 u 25), so any CPU performance issues are very unlikely.

--

Here's my keyboard, actionlistener and movement related code:

Main class:

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();

    }
}

My board where graphics are painted:

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);
        }
    }
}

Finally my craft class where keypressed/released is used:

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;
        }
    }
}
Frakcool
  • 10,915
  • 9
  • 50
  • 89
MdE
  • 117
  • 2
  • 10
  • [`if (botonStart.getText() == "RESTART")`](http://stackoverflow.com/questions/513832/how-do-i-compare-strings-in-java) – Paul Samsotha Oct 24 '14 at 13:42
  • 1
    It's just an fyi link. Probably not the cause of your problem. As far as you post, it has _way_ too much code. Haven't checked but it looks somewhere in the 400 hundred range. And you want us to help you optimize the code with no idea where the issue is? Doubt you're going to get an answer. Would be truly surprised if you did. Take some time to read [How to create a Minimal, Complete, and Verifiable example](http://stackoverflow.com/help/mcve) – Paul Samsotha Oct 24 '14 at 13:51
  • Please try to remove this code to the bare minimum required to reproduce the problem (if you don't already find the bug in the process of doing so). Right now, it is impossible to tell what's wrong, as it is too much code to "interpret" by reading, and does not have all the required classes to run. – tobias_k Oct 24 '14 at 13:55
  • Please don't vandalize your question removing the code that might be useful for someone else... – Frakcool Oct 27 '17 at 13:56
  • I realized it's better for whomever should read this question, to acually skip the code, as per the chosen answer indicates the problem wasn't there in the first place. – MdE Oct 27 '17 at 14:29

1 Answers1

1

The problem is not with your code. The problem is from not having multiple threads. When making a game, especially a sidescrolling game, all of the actions in the EventQueue can eventually overwhelm the queue. Try alleviating the queue using threads and your game should become significantly faster.

DanSchneiderNA
  • 378
  • 4
  • 16
  • I figured it from the fact that you did not have any threads and you are trying to manipulate the GUI. It is very common for it to respond slowly without threads to handle other events. Your code was extremely long and I only glanced over it. I noticed you did not have threads handling anything besides the Event Queue and the main thread. – DanSchneiderNA Oct 24 '14 at 14:55
  • 1
    In short, there may be more inefficiencies among your code. You should shorten it to get a more concise answer. But from what i see, I believe it to be the lack of threads bogging down the EventQueue. – DanSchneiderNA Oct 24 '14 at 14:58