View Single Post
  #3 (permalink)  
Old 07-10-2009, 04:57 AM
DCC1 DCC1 is offline
Member
 
Join Date: Jul 2009
Posts: 10
Rep Power: 0
DCC1 is on a distinguished road
Default
Thanks for the reply. My full source code for PongPanel.java is as follows:
Code:
import java.awt.*;
import java.awt.event.*;

import javax.swing.JPanel;
import javax.swing.Timer;

@SuppressWarnings("serial")
public class PongPanel extends JPanel {
	
	public PongPanel() { //constructor
	
    MouseHandler listener = new MouseHandler();
    addMouseListener(listener);
    addMouseMotionListener(listener);
    
    moveBall action = new moveBall();
    Timer timer = new Timer(10, action);
    timer.setInitialDelay(2000); //2 second initial delay
    timer.start();
	}
	
	private int mouseX;
	private int rightbound = 1235;
	private int leftbound = 50;
	private int bottombound = 635;
	private int topbound = 50;
	private int i = 0; //iterator for array of objects
	
	private PongBall[] pongBalls = new PongBall[5];

	private int lives = 6;
	private int pts = 0;
	private int loopcount = 0;
	private int randomstart;
	private int balltodraw;

	
	private String debuginfo = "no direction yet...";
	private String debuginfo2 = "no case executed yet...";
	private String debuginfo3 = "no ball spawned yet...";
	private String livesremaining = "";	
	private String points = "Score: " + pts;
	
	private boolean redrawball = true;
	private boolean ballinmotion = false;
	private boolean mouseMoved = false;
	private boolean addball = false;
	
public class moveBall implements ActionListener {
		public void actionPerformed(ActionEvent evt) {
			if (lives == 0) {
				debuginfo = "Game Over";
				return;
			}
			//iterate through the balls
			for (int y = 0; y < pongBalls.length; y++) {
			if (!pongBalls[y].hasContactedBound()) {
				switch(randomstart) {
				case 1: 
					debuginfo2 = "case 1 executed... for ball " + y;
					pongBalls[y].setDirY(PongBall.DirectionY.DOWN);
					pongBalls[y].setDirX(PongBall.DirectionX.LEFT);
				case 2:
					debuginfo2 = "case 2 executed... for ball " + y;
					pongBalls[y].setDirY(PongBall.DirectionY.DOWN);
					pongBalls[y].setDirX(PongBall.DirectionX.RIGHT);
				case 3:
					debuginfo2 = "case 3 executed... for ball " + y;
					pongBalls[y].setDirY(PongBall.DirectionY.UP);
					pongBalls[y].setDirX(PongBall.DirectionX.LEFT);

				case 4:
					debuginfo2 = "case 4 executed... for ball " + y;
					pongBalls[y].setDirY(PongBall.DirectionY.UP);
					pongBalls[y].setDirX(PongBall.DirectionX.RIGHT);
					}
			}
			
			
			
			//now determine the direction based on if the ball has hit a bound or paddle...
			for (loopcount = 0; loopcount < 4; loopcount++) {
				//for (int y = 0; y < pongBalls.length; y++) {
			if (pongBalls[y].getX() == rightbound) {
				pongBalls[y].setDirX(PongBall.DirectionX.LEFT);
				pongBalls[y].setContactedBound();
			}
			if (pongBalls[y].getX() == leftbound) {
				pongBalls[y].setDirX(PongBall.DirectionX.RIGHT);
				pongBalls[y].setContactedBound();
			}
			if (pongBalls[y].getY() == topbound) {
				pongBalls[y].setDirY(PongBall.DirectionY.DOWN);
				pongBalls[y].setContactedBound();
			}
			
			if (pongBalls[y].getY() == bottombound) { //user fails
				pongBalls[y].setContactedBound();
				lives--; //take away a life.
				redrawball = true; //redraw a ball
				balltodraw = y;
				//need to also set a delay for the timer, how to do this?
			}
			if ((pongBalls[y].getX() >= mouseX-5 && pongBalls[y].getX() <= mouseX+101) && 
					(pongBalls[y].getY() == 485) && pongBalls[y].getDirY() == PongBall.DirectionY.DOWN) { 
				//if the ball hits the 
				//paddle on the way down...
				pongBalls[y].setDirY(PongBall.DirectionY.UP);
				pongBalls[y].setContactedBound();
				pts += 10;
				if (pts%100 == 0)
					addball = true;
				points = "Score: " + pts;
			}
			
			
			
			//now check the directions and move the ball accordingly
			if (pongBalls[y].getDirY() == PongBall.DirectionY.DOWN && pongBalls[y].getDirX() == PongBall.DirectionX.LEFT) {
				debuginfo = "Direction is DOWN and LEFT";
				pongBalls[y].incY();
				pongBalls[y].decX();
			}
			if (pongBalls[y].getDirY() == PongBall.DirectionY.DOWN && pongBalls[y].getDirX() == PongBall.DirectionX.RIGHT) {
				debuginfo = "Direction is DOWN and RIGHT";
				pongBalls[y].incY();
				pongBalls[y].incX();
			}
			if (pongBalls[y].getDirY() == PongBall.DirectionY.UP && pongBalls[y].getDirX() == PongBall.DirectionX.LEFT) {
				debuginfo = "Direction is UP and LEFT";
				pongBalls[y].decY();
				pongBalls[y].decX();
			}
			if (pongBalls[y].getDirY() == PongBall.DirectionY.UP && pongBalls[y].getDirX() == PongBall.DirectionX.RIGHT) {
				debuginfo = "Direction is UP and RIGHT";
				pongBalls[y].decY();
				pongBalls[y].incX();
			}
				}//end the for loop for each ball
			}//end for loopcount, while loopcount caused problems, such as the window not being filled in and freezing up...
			
			repaint();
			}
		
	}
	
	private void movePaddle(MouseEvent evt) {
		mouseX = evt.getX();
		if (mouseX < 50)
			mouseX = 50;
		if (mouseX > 1148)
			mouseX = 1148;
		repaint();		
	}
	
	public void paintComponent(Graphics g) {
		
		g.setColor(Color.BLACK);
		g.drawRect(50, 50, 1200, 600); //the outline of the box
		
		g.setColor(Color.WHITE);
		g.fillRect(51, 51, 1200-2, 600-2); //the background inside the box
		
		g.setColor(Color.LIGHT_GRAY);
		g.fillRect(0, 10, getWidth(), 20); //the background for the string info	
		g.fillRect(0, 700, getWidth(), 20); 
		
		g.setColor(Color.BLACK);
		
		g.drawString(debuginfo, 25, 25); // maybe remove this later...
		g.drawString(debuginfo2, 200, 25);
		g.drawString(debuginfo3, 900, 25);
		
		g.drawString(livesremaining, 400, 25);
		g.drawString(points, getWidth()/2, 25); //players score at the top of the window
		
		//END DEBUG INFO
		/*The rest of the paintComponent method describes the behaviors of each ball, and the paddle*/
		if (!ballinmotion) { //at the start of the program
			pongBalls[0] = new PongBall();
			if (pongBalls[0] instanceof PongBall) {
			i++; //so the iterator when adding balls based on score is used, it doesnt overlap the starting ball.
			debuginfo3 = "ball 0 spawned from ballinmotion check at first run through of paintComponent method";
			}
			randomstart = (int)(Math.floor(Math.random() * 4 + 1)); //random starting
			ballinmotion = true;
		}
		
		for (int drawballs = 0, spacer = 0; drawballs < lives-1; drawballs++, spacer+=25) {
			g.setColor(Color.BLUE);
			g.fillOval((getWidth()/2)-((lives-1)*25)+spacer, 700, 14, 14);
		}
		
		if (mouseMoved) {
			g.setColor(Color.RED) ;
			g.fillRect(mouseX+1, 500, 100, 25); //the paddle
		}
		if (lives>0) { //if the user hasn't lost...s
			for (int x = 0; x < pongBalls.length; x++) { //draw all the balls in their current positions
			g.setColor(Color.BLACK);
			g.fillOval(pongBalls[x].getX(), pongBalls[x].getY(), 14, 14); //generates null ptr exception...
			}
			livesremaining = "Lives remaining: " + (lives-1);
		}

		if (redrawball == true) { //draw a new replacement ball in the middle
			pongBalls[balltodraw].setX(getWidth()/2);
			pongBalls[balltodraw].setY(getHeight()/2);
			redrawball = false;
		}
		if (addball && i <= 5) {
			pongBalls[i] = new PongBall();
			i++;
			
		    if (pongBalls[i-1] instanceof PongBall) {
		    	System.out.println("pongBalls " + (i-1) + "spawned");
		    	debuginfo3 = "Ball " + (i-1) + "spawned using addball check";
		    	}
		    
		    addball = false;
		}
	}

private class MouseHandler implements MouseListener, MouseMotionListener {
    
    public void mousePressed(MouseEvent evt) {
    }
    
    public void mouseReleased(MouseEvent evt) {
    }
    
    public void mouseClicked(MouseEvent evt) {
    }
    
    public void mouseEntered(MouseEvent evt) {
    }
    
    public void mouseExited(MouseEvent evt) {
    }
    
    public void mouseMoved(MouseEvent evt) {
       movePaddle(evt);
       mouseMoved = true;
    }

	public void mouseDragged(MouseEvent evt) {
    }

 	}  // end nested class MouseHandler
}
The full source code for the PongBall class is as follows:

Code:
@SuppressWarnings("serial")
public class PongBall extends PongPanel {
	
	public PongBall() { //constructor, start the ball in the middle
		ballX = getWidth()/2;
		ballY = getHeight()/2;
	}
	
	private int ballX;
	private int ballY;
	private boolean hitBound = false;
	public enum DirectionY {UP,  DOWN};
	public enum DirectionX {LEFT, RIGHT};
	private DirectionY directionY;
	private DirectionX directionX;
	
	public int getX() {return ballX;};
	public void incX() {ballX++;};
	public void decX() {ballX--;};
	public void setX(int newX) {ballX = newX;};	
	
	public int getY() {return ballY;};
	public void incY() {ballY++;};
	public void decY() {ballY--;};
	public void setY(int newY) {ballY = newY;};
	
	public DirectionX getDirX() {return directionX;};
	public DirectionY getDirY() {return directionY;};	
	public void setDirX(DirectionX newDirX) {directionX = newDirX;};
	public void setDirY(DirectionY newDirY) {directionY = newDirY;};
	
	public boolean hasContactedBound() {return hitBound;};
	public void setContactedBound() {hitBound = true;};
}
I instantiate pongBalls[0] the first time through the paintComponent() method, before any pongBalls object needs to be/is accessed. My understanding is that this ensures that the accesses I make inside my 'for' loops will succeed by accessing the 0'th element of the pongBalls object array (terminology?)

I instantiate more pongBalls when the addball boolean variable is true, which is triggered whenever the users score reaches a multiple of 100. Here is the bit of code that does the extra ball adding:

Code:
if (addball && i <= 5) {
			pongBalls[i] = new PongBall();
			i++;
			
		    if (pongBalls[i-1] instanceof PongBall) {
		    	System.out.println("pongBalls " + (i-1) + "spawned");
		    	debuginfo3 = "Ball " + (i-1) + "spawned using addball check";
		    	}
		    
		    addball = false;
		}
The line of code that throws the exception is:

Code:
			g.fillOval(pongBalls[x].getX(), pongBalls[x].getY(), 14, 14); //generates null ptr exception...
When I add the line:

Code:
System.out.println(pongBalls[x]);
before the line that throws the exception, the following is printed:

PongBall[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignm entX=0.0,alignmentY=0.0,border=,flags=9,maximumSiz e=,minimumSize=,preferredSize=]
null
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at PongPanel.paintComponent(PongPanel.java:202)
at javax.swing.JComponent.paint(JComponent.java:1029)
at javax.swing.JComponent.paintChildren(JComponent.ja va:864)
at javax.swing.JComponent.paint(JComponent.java:1038)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:5 67)
at javax.swing.JComponent.paintChildren(JComponent.ja va:864)
at javax.swing.JComponent.paintToOffscreen(JComponent .java:5131)
at javax.swing.RepaintManager$PaintManager.paintDoubl eBuffered(RepaintManager.java:1475)
at javax.swing.RepaintManager$PaintManager.paint(Repa intManager.java:1406)
at javax.swing.RepaintManager.paint(RepaintManager.ja va:1220)
at javax.swing.JComponent.paint(JComponent.java:1015)
at java.awt.GraphicsCallback$PaintCallback.run(Graphi csCallback.java:21)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGra phicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraph icsCallback.java:97)
at java.awt.Container.paint(Container.java:1780)
at javax.swing.RepaintManager.paintDirtyRegions(Repai ntManager.java:814)
at javax.swing.RepaintManager.paintDirtyRegions(Repai ntManager.java:714)
at javax.swing.RepaintManager.seqPaintDirtyRegions(Re paintManager.java:694)
at javax.swing.SystemEventQueueUtilities$ComponentWor kRequest.run(SystemEventQueueUtilities.java:128)
at java.awt.event.InvocationEvent.dispatch(Invocation Event.java:209)
at java.awt.EventQueue.dispatchEvent(EventQueue.java: 597)
at java.awt.EventDispatchThread.pumpOneEventForFilter s(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(E ventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarch y(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispa tchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispa tchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThre ad.java:122)
...
...

Last edited by DCC1; 07-10-2009 at 05:00 AM.
Reply With Quote