I wasn't sure if this should go in games development or here but it's java so I put it here. This is homework so please don't write my code for me. My assignment is to create a game. It has to have moving parts, keyboard controls, buttons, the works. I am recreating asteroids except the ship is going to be in a vein and it will be shooting viruses. I have most of it working the way I want it to. The viruses float around, the background shows up and sits there like it should, I have a bunch of classes. The problem I am having is that I can't get my ship to paint and if I can get it to paint (by just putting the image in the panel instead of the class which doesn't help) then it won't move. I am using a key listener for moving the ship and I want to use the spacebar to fire but that comes after if I can get it to paint. I don't know of any way to give you my images for testing. If you need them I could try and email them or something unless you know of a better way. If not just use random images. I used png's because of the transparency. Also I removed getters and setters to conserve space. Here is the code:

Game Class:

package virus_game;

import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;   // New library classes, Swing extends AWT

/**
 * @author 24x24
 */
public class Game extends JFrame implements ActionListener, KeyListener {

    // size of the window
    private static final int WINDOW_WIDTH = 800;
    private static final int WINDOW_HEIGHT = 600;
    ArrayList balls;
    private Ship ship;
    private GamePanel gamePanel;
    ArrayList<Integer> keys = new ArrayList<Integer>();
    private int fireLimit = 0;
    KeyEvent e;

    /**
     * Pause command used to control the speed of the virus animation.
     * Currently pauses for 20 ms.  Use smaller values for faster animation and
     * vice versa.
     */
    public static void pause() {
        try {
            Thread.sleep(20); // pause for 20 ms
        } catch (Exception e) {
            System.out.println(e);
            e.printStackTrace();
        }
    }

    /** Creates a new instance of Game */
    public Game() {
        super("Virus: Annihilation");  // set frame name

        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //this.setSize(windowWidth, windowHeight);
        this.setResizable(false);
        this.setLocation(100, 100);
        this.setVisible(true);
        //  this.addKeyListener(this);

        this.createBufferStrategy(2);
        setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
        setLayout(new BorderLayout());
        gamePanel = new GamePanel();
        add(gamePanel);
        center(this);
        setVisible(true);
// This doesn't work yet
       // JButton pauseGame = new JButton();
      //  pauseGame.setText("Pause");
      //  pauseGame.addActionListener(this);
      //  add(pauseTheGame, BorderLayout.SOUTH);

        gamePanel.addViruses(); // calls user input

        ship = new Ship();

//  This is where the keys should be used
//        int code = e.getKeyCode();

//        if (code == 40) {
//            ship.moveUp();
//            }
//        }
//        if (code == 38) {
//            ship.moveDown();
//            }
//        }
//        if (code == 37) {
//            ship.moveLeft();
//        }
//        if (code == 39) {
//            ship.moveRight();
//        }
        
        
//        // Fires bullet (Hopefully)
//        if (keys.contains(new Integer(32))) {
//            if (fireLimit == 0) {
//                ship.fire();
//                fireLimit = 5;
//            } else {
//                fireLimit--;
//            }

//           This is theoretical and probably won't work
        
//        // check if the ship goes through any walls, if so respawn it on the other side
//        if (ship.getshipxCoord() > WINDOW_WIDTH + 20) {
//            ship.set(20, ship.getshipxCoord());
//        } else if (ship.getshipyCoord() < -20) {
//            ship.set(WINDOW_WIDTH - 20, ship.getshipyCoord());
//        }
//        if (ship.getshipyCoord() > WINDOW_HEIGHT + 20) {
//            ship.set(ship.getshipxCoord(), 20);
//        } else if (ship.getshipyCoord() < 0) {
//            ship.set(ship.getShipxCoord(), WINDOW_HEIGHT);
//        }

        // infinite animation loop, program halts when window is closed.
        while (true) {

            pause();
            gamePanel.move();
            gamePanel.repaint();

        } // end while
    } // end Game

    /** Helper routine to center a frame on the screen (will cause problems if
    frame is bigger than the screen!)
     */
    public static void center(JFrame frame) {
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        Point center = ge.getCenterPoint();

        int w = frame.getWidth();
        int h = frame.getHeight();

        int x = center.x - w / 2, y = center.y - h / 2;
        frame.setBounds(x, y, w, h);
        frame.validate();
    }

    public static void main(String[] args) {
        Game t = new Game();
    }

    /**
     * This method creates a button at the bottom of the screen that adds more
     * balls to the arrayList when pressed
     * @param e 
     */
    @Override
    public void actionPerformed(ActionEvent e) {
        gamePanel.moreViruses();
    }

    @Override
    public void keyPressed(KeyEvent e) {
        if (!keys.contains(new Integer(e.getKeyCode()))) {
            keys.add(new Integer(e.getKeyCode()));
        }
    }

    @Override
    public void keyReleased(KeyEvent e) {
        keys.remove(new Integer(e.getKeyCode()));
    }

    @Override
    public void keyTyped(KeyEvent e) {
        // not used
    }
} // end method Main

GamePanel Class:

package virus_game;

import java.awt.*;
import javax.swing.*;
import java.util.*;
import java.awt.event.*;

/**
 * @author 24x24
 */
/**
 * A panel containing viruses.  This panel may be placed in a JFrame.
 */
public class GamePanel extends JPanel {

    ArrayList viruses = new ArrayList();
    Viruses virus;
    Viruses r;
    Image background = new ImageIcon("images/blood.jpg").getImage();
    // Image ship = new ImageIcon("images/ship.png").getImage();
    Ship ship;

    /** Creates a new instance of GamePanel */
    public GamePanel() {
        super();
        viruses = new ArrayList();
    }

    /**
     * Adds a new virus to viruses. Also prints the size of the array to the console
     * as a check
     */
    public void moreViruses() {
        Viruses virus = new Viruses();
        viruses.add(virus);
        System.out.println(viruses.size()); // A check to make sure viruses were added

    }
   
    /**
     * This method asks the user how many viruses to start with and adds that 
     * number of viruses to the array list
     * @return viruses
     */
    public ArrayList addViruses() {

        String stringVirus = JOptionPane.showInputDialog("How many viruses would you like?");
        int numViruses = Integer.parseInt(stringVirus); // Turns string into int
        for (int i = 0; i < numViruses; i++) {
            Viruses virus = new Viruses();
            viruses.add(virus);
            System.out.println(viruses.size()); // A check to make sure viruses were added

        }
        return viruses;
    } // End of addViruses

    /**
    Paints the viruses at their current positions within the panel.
     */
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        g.drawImage(background, 0, 0, this);
        // g.drawImage(ship, WIDTH, HEIGHT, this); // only way ship appears in panel but wrong
        // ship.paintComponent(g); // gives error:
// Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
//	at virus_game.GamePanel.paintComponent(GamePanel.java:131)
//	at javax.swing.JComponent.paint(JComponent.java:1029)
// just keeps going

        for (int i = 0; i < viruses.size(); i++) {
            ((Viruses) viruses.get(i)).paintComponent(g);
           
        }

    } // end method paintComponent   

    /**
    Computes the next position for the viruses and updates their positions.
     */
    public void move() {
        // Move Viruses 
        // If virus is approaching a wall, reverse direction
        for (Object b : viruses) {
            ((Viruses) b).move(getWidth(), getHeight());

        }
// I used the same move method that I used for virus and called it here
// It didn't work so I removed it. It was just for testing purposes
        //ship.move(WIDTH, HEIGHT); // makes panel white and gives NullPointer errors
        
    } // end method move
} // End of GamePanel

Virus Class:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package virus_game;

import java.awt.*;
import javax.swing.*;
import java.util.*;

/**
 *
 * @author 24x24
 */
public class Viruses {

    int virusxCoord;
    int virusyCoord;
    int virusHeight;
    int virusWidth;
    int virusRise;
    int virusRun;
    GamePanel gamePanel;
    double size;
    ArrayList viruses;
// Bigger picture for bigVirus, etc
    Image bigVirus = new ImageIcon("images/bigVirus.png").getImage();
    Image medVirus = new ImageIcon("images/medVirus.png").getImage();
    Image smallVirus = new ImageIcon("images/smallVirus.png").getImage();
    Image virusSize = null;
    

    /** Creates a new instance of GamePanel */
    public Viruses() {
int randVirus = (int) ((Math.random()*3)+1);
        System.out.println("Random " + randVirus);
        // Initialize Viruses with random values

        virusxCoord = (int) (Math.random() * (50));
        virusyCoord = (int) (Math.random() * (50));
        virusRise = (int) (Math.random() * (5));
        virusRun = (int) (Math.random() * (5));

        switch (randVirus){
            case 1: {
            virusHeight = bigVirus.getHeight(gamePanel);//(int) (10 + (int) (Math.random() * ((20 - 10) + 1)));
        virusWidth =  bigVirus.getWidth(gamePanel);}//(int) (10 + (int) (Math.random() * ((20 - 10) + 1)));
            virusSize = bigVirus;
        break;
            case 2:
        {
            virusHeight = medVirus.getHeight(gamePanel);//(int) (10 + (int) (Math.random() * ((20 - 10) + 1)));
        virusWidth =  medVirus.getWidth(gamePanel);//(int) (10 + (int) (Math.random() * ((20 - 10) + 1)));
        virusSize = medVirus;
        }break;
            case 3:
        {
            virusHeight = smallVirus.getHeight(gamePanel);//(int) (10 + (int) (Math.random() * ((20 - 10) + 1)));
        virusWidth =  smallVirus.getWidth(gamePanel);//(int) (10 + (int) (Math.random() * ((20 - 10) + 1)));
        virusSize = smallVirus;
        }
        }
        size = virusHeight + virusWidth; // Used for comparison
    }


    /**
    Paints the viruses at their current positions within the panel.
     */
    public void paintComponent(Graphics g) {

    Graphics2D g2 = (Graphics2D) g;
        // Paint Viruses
        g.drawImage(virusSize, virusxCoord, virusyCoord, gamePanel);
    }

    /**
     * This method moves the viruses
     * @param pWidth
     * @param pHeight 
     */
    public void move(int pWidth, int pHeight) {


        // Move Viruses 
        // If ball is approaching a wall, reverse direction
        if (virusxCoord < (0 - virusRun) || virusxCoord > (pWidth - virusWidth)) {
            virusRun = -virusRun;
        }

        if (virusyCoord < (0 - virusRise) || virusyCoord > (pHeight - virusHeight)) {
            virusRise = -virusRise;
        }

        // "Move" ball according to values in rise and run
        virusxCoord += virusRun;
        virusyCoord += virusRise;
    }


    // Getters and setters

} // end of Viruses class

Ship class:

package virus_game;

import java.awt.*;
import javax.swing.*;
import java.util.*;

/**
 *
 * @author 24x24
 */
public class Ship {

    int shipxCoord;
    int shipyCoord;
    int shipHeight;
    int shipWidth;
    int shipRise;
    int shipRun;
    
    GamePanel ballPanel;
    double size;
    
    Image ship = new ImageIcon("images/ship.png").getImage();
    

    /** Creates a new instance of GamePanel */
    public Ship() {

        // Initialize Ship with random values

        shipxCoord = (int) 50;
        shipyCoord = (int) 50;
        shipRise = (int) (Math.random() * (5));
        shipRun = (int) (Math.random() * (5));
        size = shipHeight + shipWidth; // Used for comparison
    }


    /**
    Paints the balls at their current positions within the panel.
     */
    public void paintComponent(Graphics g) {

    Graphics2D g2 = (Graphics2D) g;
        // Paint Ball
        //g.setColor(shipColor);
        //g.setColor(Color.white);
        //g.fillOval(ballxCoord, ballyCoord, ballWidth, ballHeight);
        g.drawImage(ship, shipxCoord, shipyCoord, ballPanel);
    }

    public void moveLeft() {

shipxCoord -=5;
     
    }
public void moveRight() {

shipxCoord +=5;
     
    }
public void moveUp() {

shipRise +=5;
shipRun +=5;
     
    }
public void moveDown() {

shipRise -=5;
shipRun -=5;
     
    }

// getters and setters
   
    

    
} // end of Ship class

Thanks for any help you can give.

Recommended Answers

All 5 Replies

General strategy:
Don't try to use paintComponent for viruses or ships, they do not extend anything with that method. Just have a public paintMe(Graphics g) method for each.
Have the game panel with its overridden paintComponent method, and within that method call paintMe(g) for all the viruses and ships so they paint themselves on the game panel.
Rather than dodgy pause methods, use a javax.swing.Timer timer to call your move/repaint method at regular intervals. This is designed to work properly with Swing's approach to threads.

Thanks for the quick reply! I'll try this out and get back to you

OK so hours of frustration and possibly throwing a minor temper tantrum (that would never happen!) I realized what I was missing which when missing meant no matter how I painted my ship, it would never show up: Ship ship = new Ship ();
Wow. That made me feel dumb. Now I have a spaceship hanging out in my panel!
Now I am trying to map the arrow keys to make it move and the space bar to fire. Any suggestions?

See How to Write a Key Listener. Check the key code and increment your positional variables based on that. Repaint as needed.

Be mindful about focus issue with key listeners. The listener will only receive events if that component has the focus.

Hey it took me a while but I got it to work! The movement part anyway. I had to do a lot of rewriting of the code to get it together and working properly but all in all I could not have done it without this site. Thanks all! I am having some other issues but I'll put that in a new thread because it's unrelated to movement. Thanks again

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.