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