Ok, i'm trying to make two player, no-network pong. i don't know what the problem is, there are some very strange things happening...

at the beginning of the program i try to set a y value to half the height, but it doesn't it stays at y=0
when the user tries to use the up (up arrow/w key) button it works like it should, but when the user presses down (down arrow/s key) the entire program freezes, but the close button still works (basically the animation freezes)

theres quite a bit of code, four classes:
Main.java

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

/**
 * Write a description of class Main here.
 * @author William Peckham
 * @version 1.0A
 */
public class Main extends JFrame {
 PlayArea pa = new PlayArea ( ) ;

 /**make a new Main*/
 public Main ( ) {
  this.setTitle ( "Pong Remake" ) ;
  this.add ( pa , BorderLayout.WEST ) ;
  this.pack ( ) ;
  this.setVisible ( true ) ;
  ScheduledThreadPoolExecutor executer = new ScheduledThreadPoolExecutor ( 3 ) ;
  executer.scheduleAtFixedRate ( new Thread ( ) {
   public void run ( ) {
    pa.run ( ) ;
   }
  } , 0L , 100L , TimeUnit.MILLISECONDS ) ;
 }

 /**main*/
 public static void main ( String [ ] args ) {
  new Main ( ) ;
 }
}

PlayArea.java

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

/**
 * This Class holds the code for the game.
 * @author William Peckham
 * @version 1.0A
 */
public class PlayArea extends JComponent {
 /**Variable for the Hieght of the Play Area*/
 public int height = 300 ;
 /**Variable for the Width of the Play Area*/
 public int width = 600 ;
 /**Because this is Pong we need a Ball*/
 public Ball ball ;
 /**This will be player one's paddle*/
 public Paddle player1 ;
 /**This will be player two's paddle*/
 public Paddle player2 ;
 /**This variable will hold player one's score*/
 public int score1 = 0 ;
 /**This variable will hold player two's score*/
 public int score2 = 0 ;
 /**This variable will keep track of whether the game is paused 
  * it's default is false, so the game will not be paused at start*/
 public boolean paused = false ;
 /**variable will keep track of player one's up ('w') key*/
 public volatile boolean wpressed = false ;
 /**variable will keep track of player one's down ('s') key*/
 public volatile boolean spressed = false ;
 /**variable will keep track of player two's up (up arrow) key*/
 public volatile boolean uppressed = false ;
 /**variable will keep track of player two's down (down arrow) key*/
 public volatile boolean downpressed = false ;

 /**make a new PlayArea*/
 public PlayArea ( ) {
  System.out.println ( "djkl;" ) ;
  this.setSize ( width , height ) ;
  this.setPreferredSize ( new Dimension ( width , height ) ) ;
  this.addKeyListener ( new keylistener ( ) ) ;
  setFocusable ( true ) ;
  requestFocusInWindow ( ) ;
  ball = new Ball ( this ) ;
  player1 = new Paddle ( this , 0 ) ;
  player2 = new Paddle ( this , 0 ) ;
  player2.x = width - player2.width ;
 }

 public void run ( ) {
  if ( ! paused ) {
   if ( wpressed ) {
    player1.step ( true , true ) ;
   } else if ( spressed ) {
    player1.step ( true , false ) ;
   } else {
    player1.step ( false , false ) ;
   }
   if ( uppressed ) {
    player2.step ( true , true ) ;
   } else if ( downpressed ) {
    player2.step ( true , false ) ;
   } else {
    player2.step ( false , false ) ;
   }
   ball.step ( ) ;
   if ( ! ball.checkAndCollideWithHorizWall ( ) ) {
    if ( ball.x > width / 2 ) {
     ball.checkAndCollideWithPaddle ( player2 ) ;
    } else {
     ball.checkAndCollideWithPaddle ( player1 ) ;
    }
   } else {
    ball.initialize ( ) ;
   }
  }
  repaint ( ) ;
 }

 public void paint ( Graphics g ) {
  Graphics2D g2 = ( Graphics2D ) g ;
  g2.fill ( player1 ) ;
  g2.fill ( player2 ) ;
  g2.fill ( ball ) ;
 }
 class keylistener implements KeyListener {
  public void keyReleased ( KeyEvent e ) {
   if ( e.getKeyCode ( ) == KeyEvent.VK_W ) {
    PlayArea.this.wpressed = false ;
   } else if ( e.getKeyCode ( ) == KeyEvent.VK_S ) {
    PlayArea.this.spressed = false ;
   }
   if ( e.getKeyCode ( ) == KeyEvent.VK_UP ) {
    PlayArea.this.uppressed = false ;
   } else {
    if ( e.getKeyCode ( ) == KeyEvent.VK_DOWN ) {
     PlayArea.this.downpressed = false ;
    }
   }
   System.out.println ( e.getKeyText ( e.getKeyCode ( ) ) + " released" ) ;
  }

  public void keyPressed ( KeyEvent e ) {
   System.out.println ( "dsssd" ) ;
   if ( e.getKeyCode ( ) == KeyEvent.VK_W ) {
    PlayArea.this.wpressed = true ;
   }
   if ( e.getKeyCode ( ) == KeyEvent.VK_S ) {
    PlayArea.this.spressed = true ;
   }
   if ( e.getKeyCode ( ) == KeyEvent.VK_UP ) {
    PlayArea.this.uppressed = true ;
   }
   if ( e.getKeyCode ( ) == KeyEvent.VK_DOWN ) {
    PlayArea.this.downpressed = true ;
   }
   System.out.println ( e.getKeyText ( e.getKeyCode ( ) ) + " pressed" ) ;
  }

  public void keyTyped ( KeyEvent e ) {
   System.out.println ( "DDDD" ) ;
  }
 }
}

Ball.java

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

/**
 * Write a description of class Ball here.
 * @author (your name)
 * @version (a version number or a date)
 */
public class Ball extends Ellipse2D.Double {
 /**X part of position*/
 public int x ;
 /**Y part of position*/
 public int y ;
 /**This Variabl is for the total speed*/
 public int speed ;
 /**X part of velocity*/
 public int xVel ;
 /**Y part of velocity*/
 public int yVel ;
 /**Diameter of the ball*/
 public int diameter = 10 ;
 /**This holds a copy of the PlayArea for wall comparisons*/
 private PlayArea parent ;

 /**make a new Ball*/
 public Ball ( PlayArea parent1 ) {
  parent = parent1 ;
  initialize ( ) ;
 }

 /**set initial values to relevant variables*/
 public void initialize ( ) {
  x = parent.width / 2 - diameter / 2 ;
  y = parent.height / 2 - diameter / 2 ;
  randomDirection ( ) ;
 }

 /**Find a random direction that is not completely verticle*/
 public void randomDirection ( ) {
  double angle = Math.PI / 2 ;
  while ( angle == Math.PI / 2 || angle == 3 * Math.PI / 2 ) {
   angle = 2 * Math.PI * Math.random ( ) ;
  }
  speed = ( int ) Math.ceil ( 5 + 10 * Math.random ( ) ) ;
  xVel = ( int ) ( speed * Math.cos ( angle ) ) ;
  yVel = ( int ) ( speed * Math.sin ( angle ) ) ;
 }

 /**Checks for collisions with the walls of the play area*/
 public void checkAndCollideWithVertWall ( ) {
  if ( y <= 0 || y + diameter >= parent.height ) {
   yVel = - yVel ;
  }
 }

 /**Checks for collisions with the walls of the play area*/
 public boolean checkAndCollideWithHorizWall ( ) {
  if ( x <= 0 || x + diameter >= parent.width ) return true ;
  return false ;
 }

 /**check for collision with a paddle*/
 public void checkAndCollideWithPaddle ( Paddle p ) {
  if ( p.intersects ( new Rectangle2D.Double ( x , y , diameter , diameter ) ) ) {
   xVel = - xVel ;
  }
 }

 /**update the rectangle class so that we draw in the right place*/
 public void updateSuper ( ) {
  super.x = x ;
  super.y = y ;
  super.width = diameter ;
  super.height = diameter ;
 }

 /**step the ball one frame*/
 public void step ( ) {
  checkAndCollideWithVertWall ( ) ;
  x += xVel ;
  y += yVel ;
  updateSuper ( ) ;
 }
}

Paddle.java

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

/**
 * Write a description of class Paddle here.
 * @author William Peckham
 * @version 1.0A
 */
public class Paddle extends Rectangle2D.Double {
 /**This is the x position and shouldn't change*/
 public int x ;
 /**This is the y position which is changed by the user*/
 public int y ;
 /**This is the speed at which the paddle should move
  * when the user presses a button.
  */
 public int speed = 10 ;
 /**This is the width*/
 public int width = 10 ;
 /**This is the height*/
 public int height = 20 ;
 /**This is a variable to hold the play area for wall checks*/
 private PlayArea parent ;

 /**make a new Paddle*/
 public Paddle ( PlayArea parent1 , int nX ) {
  parent = parent ;
  x = nX ;
 }

 public void initialize ( ) {
  y = parent.height / 2 - height / 2 ;
  updateSuper ( ) ;
 }

 public void updateSuper ( ) {
  super.x = x ;
  super.y = y ;
  super.width = width ;
  super.height = height ;
 }

 public void step ( boolean any , boolean up ) {
  if ( any ) {
   System.out.println ( "move" ) ;
   if ( up ) {
    System.out.println ( "up processing" ) ;
    if ( y - speed >= 0 ) {
     System.out.println ( "enough room" ) ;
     y -= speed ;
    } else {
     System.out.println ( "not enough room" ) ;
     y = 0 ;
    }
   } else {
    System.out.println ( "down processing" ) ;
    if ( y + speed + height <= parent.height ) {
     System.out.println ( "enough room" ) ;
     y += speed ;
    } else {
     System.out.println ( "not enough room" ) ;
     y = parent.height - height ;
    }
   }
  }
  System.out.println ( "updating" ) ;
  updateSuper ( ) ;
 }
}

this is actually supposed to accompany a final paper for my writing class, which i have to hand in on friday 12/19 so, it would be appreciated if i could get some help by then, but i still got a week, so no real rush...

thanks for the help

Recommended Answers

All 7 Replies

Difficult to wade through this code, but general recommendations to start finding the problems:
- if you're subclassing things like Ellipse2D, don't spuriously have extra variables like 'x', 'y' that duplicate functionality of the underlying class -- you'll just tie yourself in knots keeping them up to date. When you need to set the position of the object, just set the position of the underlying class, full stop.
- I'd recommend that you don't use ScheduledThreadPoolExecutor; use the java.swingx.Timer class, which makes sure that the code is executed in the GUI thread;
- if your animation is stopping, that may be an exception occurring that isn't being logged out -- put a try/catch around your PlayArea's run() method (by the way, I'd recommend calling it something other than run() since it isn't actually a Runnable) and print out any exception.

how would i go about using javax.swing.timer? i've never been told there was a problem with ScheduledThreadPoolExecutor nor have i had one is there something i should be aware of? What exceptions would be thrown that would stop the animation that wouldn't be logged?

how would i go about using javax.swing.timer? i've never been told there was a problem with ScheduledThreadPoolExecutor nor have i had one is there something i should be aware of?

There's nothing wrong with it per se -- it's a very powerful component -- but it's not designed for what you're trying to do. It is designed for cases where you want to run code in some arbitrary thread from a pool of threads. What you want to do is execute code in the GUI thread, because you are updating GUI components.

What exceptions would be thrown that would stop the animation that wouldn't be logged?

Any RuntimeException -- NullPointerException, NumberFormatException, ArrayIndexOutOfBoundsException etc etc. Why not just add the logging and find out?

You seem to not believe me, but it's clearly stated in the documentation to ScheduledThreadPoolExecutor.scheduleAtFixedRate() that if an exception does occur, future executions will be cancelled, so I really would check that this isn't what's happening!!

commented: Important points. Good info. +15

it's not that i don't believe you, i'm just a bit cynical... and i didn't have time to try it, so i figured i would ask. i figured that asking wouldn't hurt, sorry if i offended you in some way...

still doesn't explain why it won't originally place the Paddle in the correct location though any thoughts on that?

oh, by the way, about the variable names, i can change them, i just like to have a variable in the class i'm working with so i don't have to remember that i'm using the superclass. i find it helps when trying to do cirtain things, like use the center of a circle as where it gets positioned rather than the top left corner. is it possible that there are conflicts with the super's variables and the subclasses?

Oh the positioning -- I think that's just because you're not actually calling the initialize() method, isn't it?

crap, i can't believe i didn't catch that one... thanks, i have a bit of time now, i'm going to try{}catch{} that now

wow... i figured it out when i actually called initialize it did log an exception, a NullPointerException, i realized that i was setting parent=parent rather than parent1... that fixed everything thank you for you help

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.