Reducing Lag in java 2D game

Ok so I have been making this game for a while now and adding in features here and there and just recently i decided to create my own type of particle effect for explosions. Ever since I did this my game starts to get pretty bad lag in the higher levels (6-7+).

I have tried lowering the amount of particles as much as I can to still have it look like an effect and I still get lag.
I do have about 5 for loops that each activate to create each particle needed depending on what is being blown up, is it possible having 5 for loops is causing this?

The only other thing I could think of is that my Board class has a ton of code that I should be putting into new classes, around 2100 lines of code where about half or more of that could be split up into different class files. I just have been to lazy to do it. Could this cause lag?

Here is a link to my game if you want to try it. Its a .msi download because I made it installable using Advanced Installed because I have no idea on how to use or set up a JLP and most tutorials are useless or confusing.

Here is the link to it.
http://shaneisrael.homelinux.com:1337

The game is called Galaxy Defender.

EDIT:
I am using a Timer to continuously run the actionPerformed and Paint method. My board is also extending a JPanel.

I Believe I know the issue. I think its my thread. I believe its doing this because after each level it stops the thread with thread.stop; and then when i begin a new level it creates the thread with the following method.


	private void initGameThread()
	{
		// TODO Auto-generated method stub
		gThread = new GameThread(this, craft);
		gThread.start();
		GameThread.ALIEN_SHOT_DELAY -= 5;
	}

Is there a better way to do this so that I do not have to keep stopping the thread and recreating it? Also I think it may be because within my thread to keep it running I am constantly calling the run(); method from within itself “recursion” and I believe its acting like a while loop and using up my system resources fairly quick. Is there a way around this?

Here is my current game thread code.

import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.io.IOException;
import java.util.Random;

import javax.swing.Box;


public class GameThread extends Thread
{
	static int DELAY = 100;
    Board b;
    Craft c;
    Random r = new Random();
    float bs, bd, hp, os, sw,ts,ds, reload;
    static int shotTimer = 0;
    int bsI, bdI, hpI, osI, swI, tsI,dsI, fireTimer = 0;
    int[] am = new int[1000], ranTimeI = new int[1000];
    double[] ranTime = new double[1000];
    public static int ALIEN_SHOT_DELAY = 105;
    public static int ALIEN_SHOT_DELAY_MIN = 10;
	
    static double reloadDelay;
    
    public GameThread(Board b, Craft c)
    {
    	bsI =r.nextInt(100)+150;
    	bdI =r.nextInt(100)+100;
    	hpI = r.nextInt(100)+200;
    	osI = r.nextInt(100)+300;
    	swI =r.nextInt(100)+150;
    	tsI = r.nextInt(100)+200;
    	dsI = r.nextInt(100)+100;
//    	tsI = 5;
//    	dsI = 10;
    	
    	this.b = b;
    	this.c = c;
    	GetDelayBetweenShots();

    }

	private void GetDelayBetweenShots()
	{
		// TODO Auto-generated method stub
		
		
    	if(b.LEVEL > 1)
    	{
    		for(int i = 0; i < b.alienList.size(); i++)
    		{
    			
    			if(b.boss)
    			{
    				ranTimeI[i] = 10;
    			}
    			else
    			{
    				ranTimeI[i] = r.nextInt(ALIEN_SHOT_DELAY)+ALIEN_SHOT_DELAY_MIN;
    			}
    		}
    	}
		
	}

	public void run()
    {
		
        try
        {
        	Thread.yield();
        	Thread.sleep( DELAY );
        	bs+=1; bd+=1; hp+=1; os+=1; sw+=1; ts+=1;ds+=1; shotTimer+=1; fireTimer+=1;
        	if(b.LEVEL > 1)
        	{
        		for( int i = 0; i < b.alienList.size(); i++)
        		{
      
        			ranTime[i]+=1;
        		}
        	}
        		

        }
        catch(Exception e)
        {
            System.out.println( "An error occured in " + e.getMessage());
        }
//Will make this drop the trip shot power up then when its grabbed it will make c.tripShot = true
//and will set the shotTimer to 0 this will take place in the collision section.
        if(ts == tsI)
        {
        	b.TrippleShot();
        }
        if(ds == dsI)
        {
        	b.DoubleShot();
        }
        if(shotTimer == 120)
        {
        	if(c.tripShot)
        		ts = 0;
        	else if(c.doubleShot)
        		ds = 0;
        	
        	c.tripShot = false;
        	c.doubleShot = false;
        	
        }

    	if(bs == bsI)
    	{
    		b.Bigshot();
    		bs = 0;
    	}
      	if(bd == bdI)
    	{
    		b.Bubble();
    		bd = 0;
    	}
      	if(hp == hpI)
    	{
    		b.Health();
    		hp = 0;
    	}
      	if(os == osI)
    	{
    		b.Overshield();
    		os = 0;
    	}
      	if(sw == swI)
    	{
    		b.PowerUp();
    		sw = 0;
    	}
      	if(b.LEVEL > 1)
      	{
      		for(int i = 0; i < b.alienList.size(); i++)
      		{
      			Alien a = (Alien) b.alienList.get(i);
      			if(ranTime[i] == ranTimeI[i])
      			{
      				try
					{
						a.fire();
					} 
      				catch (IOException e)
					{
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
      				System.out.println(ranTimeI[i]);
      				ranTime[i] = 0;
      			}
      		}
      	}
      	CheckFireTimer();
      	run();
    }

	private void CheckFireTimer()
	{
		// TODO Auto-generated method stub
		if(fireTimer >= 2)
		{
			if(b.fire)
	        {
				if(!b.pause)
				{
					fireTimer = 0;
					try
					{
						b.playCraftAudio();
					} 
					catch (IOException e1)
					{
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
					Craft.fire();
					Board.shotsFired+=2;
				}
	        
	        }
		}
		
	}
}

This is too broad a problem for any hope of a forum member to invest time an effort in narrowing the problem for you. I suggest you profile your game to give you actual statistics which should help to narrow the problem.

yeah, I didnt really go through much of your code. but I did notice “Thread.sleep( DELAY );”

this is not a good way to handle pauses, as it doesnt take into account the previous calculations that have taken place since the last sleep() call.

Here is a Timer class that works really well for keeping a constant time, in pure java (also applet friendly)

it has a main() method to show you how to use it. instead of sleep() call timer.sync();


public class BasicTimer {
	private int fps;
	private long timeThen;
	boolean newVersion = true;
	public BasicTimer(int frameRate) {
		if (System.getProperty("java.version").startsWith("1.4"))
			newVersion = false;
		if (newVersion) {
			fps = frameRate;
			timeThen = System.nanoTime();
		}
		else {
			fps = frameRate;
			System.out.println("Old Version Detected:" +
				Running Old Java Timer Version");
			timeThen = System.currentTimeMillis();
		}
	}
	public void changeFPS(int frameRate) {
		fps = frameRate;
	}
	public void sync() {
		if (newVersion) {
			long gapTo = 1000000000L / fps + timeThen;
			long timeNow = System.nanoTime();
				
			while (gapTo > timeNow) {
				try { Thread.sleep(1);
				} catch (InterruptedException e) {}
				timeNow = System.nanoTime();
			}
			
			timeThen = timeNow;
		} else {
			long gapTo = 1000 / fps + timeThen;
			long timeNow = System.currentTimeMillis();
				
			while (gapTo > timeNow) {
				try { Thread.sleep(1);
				} catch (InterruptedException e) {}
				timeNow = System.currentTimeMillis();
			}
			
			timeThen = timeNow;
		}
	}
	
	
	public static void main(String args[]) {
		System.out.println("Simple Timer Test: " + 
			"set to 2 (should actually be 60 for most games)");
		BasicTimer timer = new BasicTimer(2);
		while (true) {
			timer.sync();
			System.out.println("TICK");
		}
		
	}
}

If it really is a problem of timing in the main loop then you can read a bit about it here: Timing in main loops
@ Bobjob: Looks like your code would fit well in at “Call for help: Code example” under “Fixed framerate” on that page. Do add the code if it makes sense.

@ Shane75776, do as Moogie suggests, and profile the code in any case. You could spend lots of time fixing the wrong thing, if you don’t really know where the problem is at.

I’ve had trouble with such methods because the sleep(x) never sleeps for that amount, usually it sleeps for 20ms for any x < 20, so there’s no accuracy (at least on windows)

I’ve seen this type of thing used before though:


			while (gapTo > timeNow) {
				Thread.yield();
				timeNow = System.currentTimeMillis();
			}

but I haven’t used it yet… i normally do non-fixed time steps.

You probably don’t want to use Thread.stop(), this method is deprecated and is very unstable.

Also, you shouldn’t invoke run() at the end of the run() method to create loops. Eventually you’ll reach the stack limit and crash (and the only reason you’re not is that you have a 100ms delay each time probably). I would organize your run() like so:


public void run() {
   while (playGame) {
       // do everything from old run() except for the last call to run
   }
}

You’ll need to define a member variable “playGame” and make sure it’s declared volatile:


volatile boolean playGame

This lets the Threads see changes right away. Then when you need to stop the thread, just set playGame to false and it will end gracefully.

Thanks for the replies, It has helped alot. And sorry about making it such a broad statement I didnt post all the code because it isnt very clean and wold be confusing as hell to go through if you are not me, So thats why I only posted that little bit.