Hi everyone, I'm trying to create a simple Java game, The Last Space Invader, where you control the last space invader and the tank automatically tracks and shoots at you. The code for my invader is as follows:

import javax.swing.*;
import java.awt.*;
import java.io.*;
import javax.imageio.*;
import java.awt.event.*;

public class Invader extends JPanel{
	
    private Image sprite;
    private int spriteW;
    private int spriteH;
    private int speedX = 5;
    private int speedY = 8;
    private Point invPos;
    private boolean alive = true;
    private boolean hitright = false;
    private boolean hitleft = false;
	private boolean landed = false;
	static final int RIGHT = 1;
	static final int LEFT = 0;
	private int rightEdge;
	private int leftEdge;
	private int top;
	private int bottom;
	private int lives = 5;
	private int spriteCount = 1;
	
    public Invader()
    {
        this.addKeyListener(new KeyboardListener());
        this.setFocusable(true);
        invPos = new Point(110, 20);
        rightEdge = 256 - getSpriteW();
        setBoundaries(0, 208, 224, 395);
        start();
    }
        
    public void paintInv()
    {
        try{            
            sprite = ImageIO.read(new File("Invader" + spriteCount + ".png"));
            spriteW = sprite.getWidth(this);
            spriteH = sprite.getHeight(this);
        }
        catch(Exception e){
            System.out.println("File not found");
        }
    }
    
    public boolean dead()
    {
        return !alive;
    }
    
    public Point where()
    {
        return invPos;
    }
    
	public void checkPosition()
	{
		if (invPos.x < leftEdge )
		{
			invPos.x = leftEdge;
			if (!hitleft)
			{
				hitleft = true;
				hitright = false;
				invPos.y += speedY;
			}
		}
		
		if (invPos.x > rightEdge )
		{
			invPos.x = rightEdge;
			if (!hitright)
			{
				hitright = true;
				hitleft = false;
				invPos.y += speedY;
			}
		}
		
		if (invPos.y > bottom)
		{
			invPos.y = bottom;
			landed = true;
		}
	}

	public void moveInvader(int direction)
	{
		if (alive && !landed)
		{
			if (direction == LEFT)
			{
				invPos.x -= speedX;
			}
			
			else
			{
				invPos.x += speedX;
			}
			
			checkPosition();
			repaint();
		}
	}
	
	public void setBoundaries(int l, int r, int t, int b)
	{
		leftEdge = l;
		rightEdge = r;
		top = t;
		bottom = b;
	}
	
    public void paintComponent(Graphics g)//Paint the panel component
    {    
    	Graphics2D g2 = (Graphics2D) g;
        if(alive)
        {
            g.drawImage(sprite,invPos.x,invPos.y, this);
            spriteCount++;
            
            if(spriteCount == 4)
            {
            	spriteCount = 1;
            }
            
           	start();
        }
        
        else
        {
            g.setColor(Color.white);
            g.drawString("You Are Dead", 100, 100);
        }
    }
    
	public void setSpriteW(int spriteW) 
	{
		this.spriteW = spriteW;
	}

	public int getSpriteW() 
	{
		return spriteW;
	}
	
    public class KeyboardListener implements KeyListener
    {
        public void keyReleased(KeyEvent k)
        {
        }
        
        public void keyPressed(KeyEvent k)
        {
			int code = k.getKeyCode();
			if (code == KeyEvent.VK_LEFT)
				moveInvader(LEFT);
			if (code == KeyEvent.VK_RIGHT)
				moveInvader(RIGHT);
        }
        
        public void keyTyped(KeyEvent k)
        {\
        }
    }
    
	public void start()
	{
		for(int i=0; i<20; i++)
		{
			repaint();
			paintInv();	
		}
	}
	    
 }

However my CPU usage is at 60-70% when running the complete program. I realise this is probably something to do with my for loop in the start method, but I'm not sure how to make Java wait before updating the sprite image. I know I should probably be using threads but again I'm something of a beginner and haven't wrapped my head around threads yet, however much I try.

EDIT

I'd just like to point out that by code isn't actually that badly set out but it seems to have been changed in pasting it here.

SECOND EDIT

Please ignore this, unless you have any improvements on my code. I've managed to implement it using a thread instead, simpler than I thought.

The for loop with only 20 iterations is not going to cause you trouble. One of the methods called from inside the for loop might, however, or calling the method that contains the for loop repeatedly. Have you actually checked to see how much your .exe is using? And where is your main method?

Right, but I wanted to see it so that I could follow your logic, perhaps see if there is a loop somewhere or some other reason that paintComponent might be getting called repeatedly even if it doesn't need to be, etc

edit:

repaint calls paint which calls paintComponent, just FYI

Ok fair enough, my main is as follows:

import javax.swing.*;
import java.awt.*;
import java.io.*;
import javax.imageio.*;
import java.awt.event.*;

public class SpaceFrame{
	
 	public static void main(String[] args){
		JFrame jf = new JFrame("The Last Space Invader");
		AlienLandingPanel alp = new AlienLandingPanel();
		jf.add(alp);
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		jf.setSize(256, 512);
		jf.setVisible(true);
	}
}

The actual code which initiates everything else is in AlienLandingPanel, as below:

import javax.swing.*;
import java.awt.*;
import java.io.*;
import javax.imageio.*;
import java.awt.event.*;

public class AlienLandingPanel extends JPanel implements Runnable{
	
	private Thread t;
	private Invader inv;
	private Tank tank;
	//private Missile miss;
	private Image backImg;
	boolean changed = true;
	String score;
	String lives;
	int livesRem = 10; 
	
	public AlienLandingPanel() {
		
        inv = new Invader();
        add(inv);
        tank = new Tank();
        try{
            backImg = ImageIO.read(new File("back.jpg"));
        }
        catch(Exception e)
        {
            System.out.println("Not found");
        }
        t = new Thread(this);
        t.start();
    }
        
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(backImg, 0, 0, this);
        inv.paintComponent(g);
        tank.paintComponent(g);
    }    public void run()
    {
        try{
            while(!inv.dead())
            {
                Thread.sleep(50);          
                Point p = inv.where();
                tank.moveTank(p.x);
                repaint();
            }
        }
    

        catch(InterruptedException inter)
        {
            
        }
    }

}

The program as a whole is by no means complete and most likely needs bits adding to it. My other main problem at the moment is that I am entirely unable to get my missiles to work, if I use miss.paintComponent(g); in the AlienLandingPanel the whole thing crashes :-S but I guess that's another problem altogether for another day.

This article has been dead for over six months. Start a new discussion instead.