Results 1 to 18 of 18
  1. #1
    DCC1 is offline Member
    Join Date
    Jul 2009
    Posts
    10
    Rep Power
    0

    Default NullPointerException even when class is instantiated as expected

    Hello, I am new to Java and am practicing by writing a simple game of Pong.

    I have a PongBall class that defines some simple behaviors of a pong ball, and a PongPanel class that instantiates the class into an array I have declared as follows:

    private PongBall[] pongBalls = new PongBall[5];

    (the goal is to have up to 5 pong balls moving independently on the screen at once)

    I instantiate the class by:

    Java Code:
    		if (!ballinmotion) { //at the start of the program
    			[COLOR="Red"]pongBalls[0] = new PongBall();[/COLOR]
    			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;
    		}
    By default, the ballinmotion boolean variable is initialized to be false.

    This if statement and instantiation is done inside my "paintComponent(Graphics g)" method, and I get the exception thrown where I am trying to access this object for the first time, here:

    Java Code:
    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...
    			}
    Here is the first few of dozens of lines of compiler errors:

    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at PongPanel.paintComponent(PongPanel.java:201)
    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)

    the bold line is where I tried to access the object for the first time;
    Java Code:
    for (int x = 0; x < pongBalls.length; x++) { //draw all the balls in their current positions
    			g.setColor(Color.BLACK);
    			[B]g.fillOval(pongBalls[x].getX(), pongBalls[x].getY(), 14, 14);[/B] //generates null ptr exception...
    			}
    It might be important to note that when I try/catch for the exception so that the window opens and displays the "debuginfo3" string, the if statement behaves as if the pongBalls[0] is an 'instanceof' the class I am trying to instantiate, "PongBall". (the debuginfo3 string displays the message defined in the body of the if statement.

    If there is anything I can post to make my problem clearer, I will be happy to do so. Thanks in advance for any replies/insight as to what I am doing wrong.

  2. #2
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    I see that you try to instantiate pongBalls[0], but how many of the other PongBalls in the array do you instantiate? You may need to post all of your code, indicate the line where your exception is thrown, and note (using System.out.println) the value of the array's index when the exception is thrown.

  3. #3
    DCC1 is offline Member
    Join Date
    Jul 2009
    Posts
    10
    Rep Power
    0

    Default

    Thanks for the reply. My full source code for PongPanel.java is as follows:
    Java 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);
    			[COLOR="Red"][B]g.fillOval(pongBalls[x].getX(), pongBalls[x].getY(), 14, 14); //generates null ptr exception...[/B][/COLOR]
    			}
    			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:

    Java 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:

    Java 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:

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

    Java 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 04:00 AM.

  4. #4
    Mr.Beans's Avatar
    Mr.Beans is offline Senior Member
    Join Date
    Apr 2009
    Location
    Virginia Beach, Virginia
    Posts
    149
    Rep Power
    0

    Default

    How do you create pongBalls[]?

    If you start off with only one ball and pongBalls is of length five, then you are going to get a null pointer exception because pongBalls[1-4] are all null.

  5. #5
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    Yep, you're trying to use PongBalls before you've initialized them. You're also trying to create PongBall objects and do program logic in the paintComponent method, and that's a bad idea.

  6. #6
    DCC1 is offline Member
    Join Date
    Jul 2009
    Posts
    10
    Rep Power
    0

    Default

    Okay, I have read both replies and attemmpted to change the way in which I instantiate the pongBalls. I have also tried to migrate some of the logic and all of the instantiation out of the paintComponent method and into the actionPerformed() method of the moveBall class. Thanks for that extra bit of advice.

    I still have a NullPointerException, however:

    Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
    at PongPanel.paintComponent(PongPanel.java:207)
    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)
    null
    null
    at javax.swing.JComponent.paint(JComponent.java:1015)

    My revised source code for the PongPanel class is here:

    Java 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 int ballsToDraw = 0;
    
    	
    	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 addball = false;
    	private boolean init = false;
    	
    public class moveBall implements ActionListener {
    		public void actionPerformed(ActionEvent evt) {
    			if (lives == 0) {
    				debuginfo = "Game Over";
    				return;
    			}
    			if (!init) {
    			for (int numballs = 0; numballs < 5; numballs++) { //initialize numballs
    				pongBalls[numballs] = new PongBall();
    				}
    			System.out.println(pongBalls[0]);
    			init = true;
    			}
    			if (!ballinmotion) { //at the start of the program
    				ballsToDraw++;
    				randomstart = (int)(Math.floor(Math.random() * 4 + 1)); //random starting
    				ballinmotion = true;
    			}
    			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;
    			}
    			//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.
    				livesremaining = "Lives remaining: " + (lives-1);
    				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
    		g.setColor(Color.BLUE);
    		for (int drawballs = 0, spacer = 0; drawballs < lives-1; drawballs++, spacer+=25) {
    			g.fillOval((getWidth()/2)-((lives-1)*25)+spacer, 700, 14, 14);
    		}
    		if (lives>0) { //if the user hasn't lost...
    			g.setColor(Color.BLACK);
    			for (int x = 0; x < pongBalls.length; x++) { //draw all the balls in their current positions
    			System.out.println(pongBalls[x]); //for debugging
    			g.fillOval(pongBalls[x].getX(), pongBalls[x].getY(), 14, 14);
    			}
    		}
    	}
    
    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);
        }
    
    	public void mouseDragged(MouseEvent evt) {
        }
    
     	}  // end nested class MouseHandler
    }
    I do my new instantiation here:

    Java Code:
    			if (!init) {
    			for (int numballs = 0; numballs < 5; numballs++) { //initialize numballs
    				pongBalls[numballs] = new PongBall();
    				}
    			System.out.println(pongBalls[0]);
    			init = true;
    			}
    Does this properly initialize pongBalls[0,1,2,3,4,5]?

    The System.out.println prints 'null', as expected given the exception at the same line of code as before:
    Java Code:
    g.fillOval(pongBalls[x].getX(), pongBalls[x].getY(), 14, 14);
    < --EDIT-->
    I am thinking this may have something to do with something I read in a tutorial, that the paintComponent() method is called first/immediately on program execution, which will, in this case, result in pongBalls[] access attempts before any instantiation can be done... Could this be what is causing the problem? How might I go about forcing initialization before doing any drawing? (I have tried putting the initialization of pongBalls in the constructor of the PongPanel class, my compiler complains that I am doing something wrong.
    </ --EDIT-->


    Again, I appreciate the help... Hopefully this isn't something I've just noobishly overlooked time and time again... although it probably is.
    Last edited by DCC1; 07-10-2009 at 07:03 PM.

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    I can't get your code to compile. Is this the whole program?

  8. #8
    Singing Boyo is offline Senior Member
    Join Date
    Mar 2009
    Posts
    552
    Rep Power
    6

    Default

    I think paintComponent() is actually called by the JComponent constructor. Therefore, non-static code blocks SHOULD work, as they are called by the class constructor before any super-constructor calls. I could be wrong, however...

    I did not try to compile your code, as Fubarable said it did not compile. However, If you do post your code, attaching it all in a zip file is probably preferable.
    If the above doesn't make sense to you, ignore it, but remember it - might be useful!
    And if you just randomly taught yourself to program, well... you're just like me!

  9. #9
    DCC1 is offline Member
    Join Date
    Jul 2009
    Posts
    10
    Rep Power
    0

    Default

    Okay, I have put all three files of my source code into a zip 'pong.zip'

    There should be three files:
    PongApp.java (to run the program as an application, not applet)
    PongBall.java (the PongBall class that describes the properties and behavior of the ball)
    PongPanel.java (describes the paintComponent() and moveBall() methods, (and some others that deal with mouse listeners and timers) and where the instantiation of the PongBall class is done.

    I compiled these using Eclipse, in the 'default package'.

    I appreciate your time in compiling this to help. Let me know if there is anything else I can do to make this clearer.
    Attached Files Attached Files

  10. #10
    mtyoung is offline Senior Member
    Join Date
    Dec 2008
    Location
    Hong Kong
    Posts
    473
    Rep Power
    6

    Default

    you initialize numballs when action performed,
    before user perform action, all balls are null
    Last edited by mtyoung; 07-11-2009 at 05:19 AM.

  11. #11
    DCC1 is offline Member
    Join Date
    Jul 2009
    Posts
    10
    Rep Power
    0

    Default

    In the constructor of the PongPanel class, which is called automatically when the program executes, is the following code:

    Java Code:
        
    ...
    
        moveBall action = new moveBall();
        Timer timer = new Timer(10, action);
        timer.setInitialDelay(2000); //2 second initial delay
        timer.start();
    The actionPerformed() method, which contains the initialization for PongBall, should be called when timer.start() is executed, right? If this is the case, I would expect the PongBalls to be initialized there. If I am wrong, where should I be able to put the PongBall initialization so that the compiler won't complain, and to assure that PongBall will be initialized for pongBalls[0,1,2,3,4] before any access attempts?

    I have tried placing the initialization,
    Java Code:
    			for (int numballs = 0; numballs < 5; numballs++) { //initialize numballs
    				pongBalls[numballs] = new PongBall();
    				}
    ,
    in the constructor to my PongPanel class, but when I run the program, I get another error:

    UIDefaults.getUI() failed: createUI() failed for PongBall[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignm entX=0.0,alignmentY=0.0,border=,flags=9,maximumSiz e=,minimumSize=,preferredSize=] java.lang.reflect.InvocationTargetException
    java.lang.Error
    at javax.swing.UIDefaults.getUIError(UIDefaults.java: 711)
    at javax.swing.MultiUIDefaults.getUIError(MultiUIDefa ults.java:133)
    at javax.swing.UIDefaults.getUI(UIDefaults.java:757)
    at javax.swing.UIManager.getUI(UIManager.java:1017)
    at javax.swing.JPanel.updateUI(JPanel.java:109)
    at javax.swing.JPanel.<init>(JPanel.java:69)
    at javax.swing.JPanel.<init>(JPanel.java:92)
    at javax.swing.JPanel.<init>(JPanel.java:100)
    at PongPanel.<init>(PongPanel.java:10)
    ...
    ...

    The source code that generates this error is the same as that in the zip file, except that:

    Java Code:
    			for (int numballs = 0; numballs < 5; numballs++) { //initialize numballs
    				pongBalls[numballs] = new PongBall();
    				}
    has been placed in the constructor of the PongPanel class and taken out of the actionPerformed() method of the moveBall class.

    Am I not sure why putting the initialization in the constructor, which, at least to a noob such as myself seems like a good idea, causes a problem.

  12. #12
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    This has nothing to do with your NPE, but why does PongBall extend PongPanel? This seems a set up for a circular reference?

  13. #13
    DCC1 is offline Member
    Join Date
    Jul 2009
    Posts
    10
    Rep Power
    0

    Default

    The PongBall class extends the PongBall to get access to the getHeight() and getWidth() methods that pertain to the PongPanel class (dimensions of the window).

    Is this not the correct way to do this? Might it make more sense to not extend PongPanel and not use those methods?

    By circular reference, is that similar to a Singly Linked Circular List?

  14. #14
    DCC1 is offline Member
    Join Date
    Jul 2009
    Posts
    10
    Rep Power
    0

    Default

    After reading Fubarable's post regarding the extension of the PongPanel class in PongBall, I removed the extension and commented out the methods in the constructor of PongBall. The program no longer throws an exception. It might be important to note that this is after the initialization of PongBall's are done in the constructor of the PongPanel class. I am still interested in hearing about the circular reference situation, as it might be a better/more correct way to do this?

    The program still behaves strangely, but I am confident that without the unexpected exceptions I will be able to work out the other details. Thanks for the time to read this and for the pointers.

  15. #15
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,316
    Blog Entries
    1
    Rep Power
    25

    Default

    Quote Originally Posted by DCC1 View Post
    The PongBall class extends the PongBall to get access to the getHeight() and getWidth() methods that pertain to the PongPanel class (dimensions of the window).
    The question you need to ask yourself is: is a PongBall a PongPanel? In other words does it fulfill an "is-a" relationship (google this term)? Answer: it does not. For example, a class Dog would fulfill an is-a relationship with an Animal class, but not with a DogHouse class, so Dog can extend Animal but should never extend DogHouse. Another important concept is that of the "has-a" relationship. DogHouse does fulfill a has-a relationship with Dog, and thus it can hold Dog objects. PongPanel likewise can fulfill has-a with PongBall and can hold these objects as fields of the class.

    Point number two, making it subclass PongPanel wouldn't automatically give it the width and height since it is not the same object as the "true" PongPanel. Inheritance is not the way to pass this information.

    And final point: PongBall doesn't even need to know this information. Does a physical ball know where the ground is? Nope, it only knows when it collides with something. So give your PongBall class a boolean method contains(int x, int y), to see if a point is contained in the ball or not. That way the object that holds the balls can easily test for collisions.

    Is this not the correct way to do this? Might it make more sense to not extend PongPanel and not use those methods?
    precisely

    By circular reference, is that similar to a Singly Linked Circular List?
    Nope, I mean you have a PongPanel that contains PongBalls, and these subclass PongPanel, and this can contain PongBalls, and these subclass PongPanel...
    It can get downright ugly here.
    Last edited by Fubarable; 07-11-2009 at 09:14 PM.

  16. #16
    DCC1 is offline Member
    Join Date
    Jul 2009
    Posts
    10
    Rep Power
    0

    Default

    I see, and feel I have a better understanding of how this stuff works...

    I see what is meant by the circular reference - didn't even realize that's what I was doing... I have removed the extension of PongPanel in the PongBall class, and am storing each PongBall's coordinates in the objects instantiated by PongBall. I am currently checking for collisions through the PongPanel class, that accesses the x and y coordinates of each ball and checks to see if they are the same as respective coordinates regarding the things I want it to 'bounce' off of, I.E. the paddle and walls.

    I am now passing the information about the initial position of the ball to the constructor of PongBall from PongPanel, instead of using inheritance as you suggested, and this does seem much more reasonable/easy to understand. When drawing the PongBalls in the PongPanel class, I access the PongBalls X and Y coordinates and print the ball with those coordinates to the screen via the paintComponent() method in PongPanel - I think a little different than the method you suggested - but I will certainly your idea.

    About the boolean contains(int x, int y) - this method would be called from the PongPanel class on one of any of the PongBall objects, and this method would check to see if the values I pass by reference are the same as the current PongBall object's ballX and ballY coordinates? This seems like it should work.

    Thanks for the help. I do appreciate it and will try to help others on the forum if it's something I can help with. I hope not to be a 'leecher', but fear that until I get to know more about more complex concepts I won't be much help to many, but you never know.
    Last edited by DCC1; 07-12-2009 at 04:13 AM.

  17. #17
    corlettk is offline Member
    Join Date
    Apr 2009
    Location
    Brisbane
    Posts
    86
    Rep Power
    0

    Default

    regarding the Ball.contains(int x, int y) suggestion... Ummm... The below code isn't "best practice", but it works...

    My move methods primary job is to move the ball into position for it's next paint... and (here's the "not best practice" part) it also has the "side effect" of setting a couple of boolean attributes (hitWall, and isOutOfBounds) which I can query later.

    Java Code:
      private class Ball {
        ....
        void move() {
          hitWall = false;
          if ( x<=Box.LEFT || x+SIZE>=Box.RIGHT ) {
            hitWall = true;
            xDirection *= -1; // u-turn
          }
          if ( y <= Box.TOP ) {
            hitWall = true;
            yDirection *= -1; // u-turn
          } else if (y+SIZE >= Box.BOTTOM) {
            isOutOfBounds = true;
          }
          x += xDirection * speed;
          y += yDirection * speed;
        }
        ....
      }
    In the swing-timer you move the ball, and then ask it "what happened"...

    Java Code:
            for (Ball ball : balls) {
              ball.move();
              if ( ball.hitWall ) {
                ....
    Also see the paddle.hit(ball) method. With 20-20 hindsight I think it would be a better if both Box and Paddle extended a new Rectangle, and give the Ball a within(Rectangle rect) method.

    Here's the full code ...

    Java Code:
    package forums;
    
    import java.util.List;
    import java.util.ArrayList;
    import java.util.Random;
    import java.awt.Graphics;
    import java.awt.Color;
    import java.awt.Dimension;
    //import java.awt.event.MouseListener;
    import java.awt.event.MouseMotionListener;
    import java.awt.event.MouseEvent;
    import java.awt.event.ActionListener;
    import java.awt.event.ActionEvent;
    import java.awt.event.WindowListener;
    import java.awt.event.WindowAdapter;
    import java.awt.event.WindowEvent;
    import javax.swing.JFrame;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    import javax.swing.JOptionPane;
    
    public class DccPongPanel extends JPanel
    {
      private static final long serialVersionUID = 1L;
      private static final Random RANDOM = new Random();
      private static final java.awt.Toolkit TOOLKIT = java.awt.Toolkit.getDefaultToolkit();
      private static final Dimension  PREFERRED_SIZE = new Dimension(Box.WIDTH+100, Box.HEIGHT+100);
    
      private static final int MAX_SPEED = 5;
      private static final int REFRESH_RATE = 1000/76;
    
      private static final int MAX_BALLS = 6;
      private static final int NUM_LIVES = 12;
    
      private static JFrame frame;
    
      private final Box box = new Box();
      private final ScoreBoard scoreBoard = new ScoreBoard();
      private final Paddle paddle = new Paddle();
      private final List<Ball> balls = new ArrayList<Ball>();
    
      private int lives = NUM_LIVES;
      private int score = 0;
      private String scoreString = "Score: "+score;
    
      private Timer timer;
    
      public DccPongPanel() {
        addMouseMotionListener(new MouseHandler());
    
        WindowHandler windowHandler = new WindowHandler();
        frame.addWindowListener(windowHandler);
        frame.addWindowFocusListener(windowHandler);
        frame.addWindowStateListener(windowHandler);
    
        DEBUG("add Ball[0]");
        balls.add(new Ball(Ball.DOWN, 2, 0));
        timer = new Timer(REFRESH_RATE, new Mover());
        timer.setInitialDelay(500); // half-second delay.
        timer.start();
    
      }
    
      public Dimension getPreferredSize() {
        return this.PREFERRED_SIZE;
      }
    
      public void paintComponent(Graphics g) {
        super.paintComponent(g);
        box.paint(g);
        scoreBoard.paint(g);
        synchronized(balls) {
          for (Ball ball : balls) {
            ball.paint(g);
          }
        }
        paddle.paint(g);
      }
    
      public static void DEBUG(String message) {
        if (true) {
          System.err.println("DEBUG: "+message);
        }
      }
    
      private void movePaddle(final int x) {
        if (x < Box.LEFT) {
          paddle.x = Box.LEFT;
        } else if ( x > Box.RIGHT-Paddle.WIDTH )  {
          paddle.x = Box.RIGHT-Paddle.WIDTH;
        } else {
          paddle.x = x;
        }
        repaint();
      }
    
      private class Mover implements ActionListener {
        public void actionPerformed(ActionEvent evt) {
          if (lives == 0) {
            gameOver();
            return;
          }
          synchronized(balls) {
            boolean addBall = false;
            for (Ball ball : balls) {
              ball.move();
              if ( ball.hitWall ) {
                increaseScore();
                addBall |= score==20||score==50||score%100==0;
              } else if ( paddle.hit(ball) ) {
                ball.yDirection = -1; // UP
                increaseScore();
                addBall |= score==20||score==50||score%100==0;
                ball.speedUp();
              } else if ( ball.isOutOfBounds ) {
                DEBUG("lives--");
                ball.reset();
                lives--;
              }
            }
            if (balls.size()<MAX_BALLS && addBall) {
              DEBUG("add Ball["+balls.size()+"]");
              balls.add(new Ball(Ball.UP, 1, balls.size()));
            }
          } //end-synchronized
          repaint();
        }
        private void gameOver() {
          DEBUG("Game Over");
          timer.stop();
          JOptionPane.showMessageDialog(frame, "That's a bit deceptive.", "Game Over", JOptionPane.ERROR_MESSAGE);
          score=0;
          lives=NUM_LIVES;
          balls.clear();
          balls.add(new Ball(Ball.DOWN, 2, 0));
          timer.start();
        }
      }
    
      private void increaseScore() {
        score += 10;
        scoreString = "Score: "+score;
      }
    
      private class MouseHandler implements MouseMotionListener {
        public void mouseMoved(MouseEvent evt) {
          movePaddle(evt.getX());
        }
        public void mouseDragged(MouseEvent evt) { }
      }
    
      private class WindowHandler extends WindowAdapter {
        public void windowDeactivated(WindowEvent e) { timer.stop(); }
        public void windowActivated(WindowEvent e) { timer.start(); }
        public void windowIconified(WindowEvent e) { timer.stop(); }
        public void windowDeiconified(WindowEvent e) { timer.start(); }
      }
    
      private class Box
      {
        static final int WIDTH = 900;
        static final int HEIGHT = 500;
    
        static final int TOP = 50;
        static final int LEFT = 50;
        static final int BOTTOM = TOP+HEIGHT;
        static final int RIGHT = LEFT+WIDTH;
    
        static final int MIDX = (RIGHT-LEFT)/2;
        static final int MIDY = (BOTTOM-TOP)/2;
    
        void paint(Graphics g) {
          g.setColor(Color.BLACK);
          g.drawRect(LEFT, TOP, WIDTH, HEIGHT); // outline
          g.setColor(Color.WHITE);
          g.fillRect(LEFT+1, TOP+1, WIDTH-2, HEIGHT-2);  // shadow
        }
      }
    
      private class Paddle
      {
        static final int THICKNESS = 25;
        static final int WIDTH = 100;
        static final int Y = Box.BOTTOM-THICKNESS;
        int x = Box.MIDX;
    
        boolean hit(Ball ball) {
          return ball.x>=x && ball.x+Ball.SIZE<=x+WIDTH
              && ball.y+Ball.SIZE>=Y && ball.yDirection==Ball.DOWN; 
        }
    
        void paint(Graphics g) {
          g.setColor(Color.RED) ;
          g.fillRect(x+1, Y, WIDTH, THICKNESS);
        }
      }
    
      private class Ball
      {
        static final int SIZE=15, DOWN=1, UP=-1, LEFT=-1, RIGHT=1;
        int x, y, xDirection, yDirection, id;
        private volatile int speed;
        volatile boolean isOutOfBounds, hitWall;;
    
        Ball(int yDirection, int speed, int id) {
          reset();
          this.yDirection = yDirection==UP ? UP : DOWN;
          this.speed = speed>=1&&speed<=MAX_SPEED ? speed : 1;
          this.id = id;
        }
    
        void reset() {
          x = Box.MIDX;
          y = Box.MIDY;
          xDirection = RANDOM.nextBoolean() ? LEFT : RIGHT;
          yDirection = UP;
          speed = 1;
          isOutOfBounds = hitWall = false;
        }
    
        void move() {
          hitWall = false;
          if ( x<=Box.LEFT || x+SIZE>=Box.RIGHT ) {
            hitWall = true;
            xDirection *= -1; // u-turn
          }
          if ( y <= Box.TOP ) {
            hitWall = true;
            yDirection *= -1; // u-turn
          } else if (y+SIZE >= Box.BOTTOM) {
            isOutOfBounds = true;
          }
          x += xDirection * speed;
          y += yDirection * speed;
        }
    
        void speedUp() {
          if(speed<MAX_SPEED) {
            speed++;
            //DEBUG("Ball["+id+"].speed="+speed);
          }
        }
    
        void paint(Graphics g) {
          g.setColor(Color.BLACK);
          g.fillOval(x, y, SIZE-1, SIZE-1);
        }
      }
    
      private class ScoreBoard
      {
        private static final int TOP = 10;
        private static final int HEIGHT = 20;
    
        void paint(Graphics g) {
          g.setColor(Color.LIGHT_GRAY);
          g.fillRect(Box.LEFT, TOP, Box.WIDTH, HEIGHT); // background
          g.setColor(Color.BLACK);
          g.drawString(scoreString, Box.MIDX, TOP+15); // score
          g.setColor(Color.BLUE);
          for (int i=0; i<lives; i++) { // lives
            g.fillRect(Box.LEFT+10+i*12, TOP+6, 8, 8);
          }
        }
      }
    
      public static void buildAndShowGUI(){
        frame = new JFrame("DCC Pong - Rocks my world!");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setContentPane(new DccPongPanel());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
      }
    
      public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(
          new Runnable() {
            public void run() {
              buildAndShowGUI();
            }
          }
        );
      }
    
    }
    Cheers. Keith.

  18. #18
    DCC1 is offline Member
    Join Date
    Jul 2009
    Posts
    10
    Rep Power
    0

    Default

    Very impressed - everything I was trying to accomplish works perfectly right there.

    I have a question regarding the pain() functions defined in some of the classes - how are these functions called? Are they called separately from one another? Until now, I only knew how to use the same paintComponent() command to redraw the entire screen at once - it seems as though here, each item that needs to be drawn on the screen (the paddle, the ball(s), the box, scoreboard etc). Does the paintComponent() method which calls each object's paint() method get called automaticaly itself every REFRESH_RATE interval?

    Some other things like synchronized I will look up myself and learn about, but I am still not 100% clear on the paintComponent() situation... In the meantime I will mark the post as 'resolved' since my original problem - the exception - has been resolved.

Similar Threads

  1. .class expected
    By dre in forum New To Java
    Replies: 6
    Last Post: 06-27-2009, 06:01 PM
  2. Class Expected error
    By Radman23 in forum New To Java
    Replies: 11
    Last Post: 01-14-2009, 04:12 AM
  3. 'class' or 'interface' expected
    By denisdoherty in forum New To Java
    Replies: 23
    Last Post: 04-22-2008, 06:13 PM
  4. class or interface expected -compile err
    By ravi503 in forum Java Servlet
    Replies: 1
    Last Post: 03-26-2008, 11:45 AM
  5. Replies: 9
    Last Post: 08-08-2007, 07:16 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •