Results 1 to 17 of 17
  1. #1
    Join Date
    Mar 2011
    Posts
    4
    Rep Power
    0

    Question change thread.sleep() to timer.

    Since I have used the thread.sleep() method, my graphics is updating way to slowly. How would I convert this into a timer?

    The point of the applet is just to move the black dot around the screen based on the arrow keys that are pressed. (I am eventually going to make this into a snake game, but am taking it one step at a time.)

    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    import javax.swing.Timer;
     
    import java.applet.*;
    import java.util.*;
    import static java.lang.System.*;
     
    public class SnakeSimple extends Applet implements KeyListener{
     
    	int x = 0;
    	int y = 0;
    	byte direction;
    	final byte UP = 1;
    	final byte RIGHT = 2;
    	final byte DOWN = 3;
    	final byte LEFT = 4;
     
    	public void init() {
    	    x = 100;
    	    y = 100;
    	    addKeyListener(this); 
    	}
    	public void paint(Graphics g) {
    		g.setColor(Color.black);
    		g.fillOval(x, y, 10, 10);
    		run();
    	}
    	public void run(){
    		try {
    			Thread.sleep(100);
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
     
    		if(direction==UP){
    			y-=10;
    		}
    		if(direction==DOWN){
    			y+=10;
    		}
    		if(direction==LEFT){
    			x-=10;
    		}
    		if(direction==RIGHT){
    			x+=10;
    		}
     
    		repaint();
     
     
    	}
    	@Override
    	public void keyPressed(KeyEvent e) {
    		if(e.getKeyCode()==37){
    			direction = LEFT;
    		}
    		if(e.getKeyCode()==38){
    			direction = UP;
    		}
    		if(e.getKeyCode()==39){
    			direction = RIGHT;
    		}
    		if(e.getKeyCode()==40){
    			direction = DOWN;
    		}
    		repaint();
    	}
    	@Override
    	public void keyReleased(KeyEvent e) {
     
    	}
    	@Override
    	public void keyTyped(KeyEvent e) {
    		// TODO Auto-generated method stub
     
    	}
    }

  2. #2
    ra4king's Avatar
    ra4king is offline Senior Member
    Join Date
    Apr 2011
    Location
    Atlanta, Georgia, US
    Posts
    396
    Rep Power
    4

    Default

    I strongly recommend not to use the Swing Timer for games. Making your own loop with Thread.sleep() is more efficient and better. What problems have you been having with that exactly?

  3. #3
    Join Date
    Mar 2011
    Posts
    4
    Rep Power
    0

    Default

    well the problem that I am having is when the dot moves around the screen flashes white every time the dot moves. I am trying to make the animation smooth.

  4. #4
    ra4king's Avatar
    ra4king is offline Senior Member
    Join Date
    Apr 2011
    Location
    Atlanta, Georgia, US
    Posts
    396
    Rep Power
    4

    Default

    Oh that's because you're not double buffering. Every time the screen repaints, it redraws all the pixels on the screen itself, so you can see it "drawing" when you see flickering or flashing. Double buffering is when you draw everything in a hidden image and then that image is drawn all at once on the screen so there is no flickering. To use this, you need to start drawing in a java.awt.Canvas and start using BufferStrategy.

  5. #5
    Join Date
    Mar 2011
    Posts
    4
    Rep Power
    0

    Default

    Thank you very much by the way your doodle jump game is cool

  6. #6
    ra4king's Avatar
    ra4king is offline Senior Member
    Join Date
    Apr 2011
    Location
    Atlanta, Georgia, US
    Posts
    396
    Rep Power
    4

    Default

    Glad to help! and Thanks :D

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

    Default

    I dislike giving code solutions, but since you've been told not to use a Swing Timer, I'd like to show you that it can be done and easily with a Swing Timer:

    Java Code:
    package yr2011.m04.c;
    
    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    @SuppressWarnings("serial")
    public class SnakeSimple2 extends JApplet {
       public void init() {
          try {
             javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                   createGUI();
                }
             });
          } catch (Exception e) {
             System.err.println("createGUI didn't successfully complete");
          }
       }
    
       private void createGUI() {
          getContentPane().add(new ImagePanel());
       }
    }
    
    @SuppressWarnings("serial")
    class ImagePanel extends JPanel {
       private static final Color SPRITE_COLOR = Color.blue;
       private static final int SPRITE_WIDTH = 10;
       private static final int TIMER_DELAY = 30;
       private static final int VELOCITY_STEP = 2;
       private static final Point INITIAL_LOCATION = new Point(20, 20);
       private int upVelocity = 0;
       private int rightVelocity = 0;
       private Point location = INITIAL_LOCATION;
       
       public ImagePanel() {
          new Timer(TIMER_DELAY, new TimerListener()).start();
          setupKeyBindings();
       }
       
       private void setupKeyBindings() {
          setFocusable(true);
          requestFocusInWindow();
          
          int condition = JComponent.WHEN_IN_FOCUSED_WINDOW;
          InputMap inMap = getInputMap(condition ); 
          ActionMap actMap = getActionMap();
          
          for (final Directn direction : Directn.values()) {
             inMap.put(KeyStroke.getKeyStroke(direction.getKeyStroke(), 0), 
                      direction.toString());
             actMap.put(direction.toString(), new AbstractAction() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                   upVelocity += direction.getUp();
                   rightVelocity += direction.getRight();
                }
             });
          }
       }
    
    
       private class TimerListener implements ActionListener {
    
          public void actionPerformed(ActionEvent e) {
             int x = location.x + rightVelocity * VELOCITY_STEP;
             int y = location.y - upVelocity * VELOCITY_STEP;
             
             int oldX = location.x;
             int oldY = location.y;
             
             
             location.x = x;
             location.y = y;
             repaint(oldX - SPRITE_WIDTH, oldY - SPRITE_WIDTH, 
                      SPRITE_WIDTH * 3, SPRITE_WIDTH * 3);
             repaint(location.x - SPRITE_WIDTH, location.y - SPRITE_WIDTH, 
                      SPRITE_WIDTH * 3, SPRITE_WIDTH * 3);
    
          }
       }
       
       @Override
       protected void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2 = (Graphics2D) g;
          g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
          g2.setColor(SPRITE_COLOR);
          g2.fillOval(location.x, location.y, SPRITE_WIDTH, SPRITE_WIDTH);
       }
    }
    
    enum Directn {
       UP(KeyEvent.VK_UP, 1, 0),
       DOWN(KeyEvent.VK_DOWN, -1, 0),
       RIGHT(KeyEvent.VK_RIGHT, 0, 1),
       LEFT(KeyEvent.VK_LEFT, 0, -1);
       
       private int keyStroke;
       private int up;
       private int right;
       private Directn(int keyStroke, int up, int right) {
          this.keyStroke = keyStroke;
          this.up = up;
          this.right = right;
       }
       
       public int getUp() {
          return up;
       }
       
       public int getRight() {
          return right;
       }
       
       public int getKeyStroke() {
          return keyStroke;
       }
    }
    Now, if I were using a Swing Timer in a true game, I'd be getting system time and basing my movement distances on the delta time since the Swing timer's delay is not very reliable (but Thread.sleep isn't 100% reliable either).

  8. #8
    Join Date
    Mar 2011
    Posts
    4
    Rep Power
    0

    Question

    I have gotten much farther with the snake game. It now moves the snake and grows when you pick up the apples and tells you when you have lost. I still have not figured out the white flash problem. I cannot figure out how to use a canvas. Please help.

    Java Code:
    import java.awt.*;
    
    import java.awt.event.*;
    import java.applet.*;
    import java.util.*;
    
    class Coord{
    	private int x;
    	private int y;
    	public Coord(int x, int y){
    		this.x = x;
    		this.y = y;
    	}
    	
    	public int getX() {return x;}
    	public void setX(int x) {this.x = x;}
    	public int getY() {return y;}
    	public void setY(int y) {this.y = y;}
    
    	
    }
    
    public class SnakeSimple extends Applet implements KeyListener{
    
    	int y = 0;
    	int x = 0;
    	int LoseCount = 0;
    	int score = 0;
    	boolean gameOver = false;
    	Coord appleLocation;
    	ArrayList <Coord> cord;
    	byte direction;
    	final byte UP = 1;
    	final byte RIGHT = 2;
    	final byte DOWN = 3;
    	final byte LEFT = 4;
    	boardCreator b;
    	boolean isApple = false;;
    	
    	public void init() {
    	    x = 100;
    	    y = 100;
    	    addKeyListener(this); 
    	    cord= new ArrayList <Coord>();
    	    cord.add(new Coord(100,100));
    	}
    	public void paint(Graphics g) {
    		if(gameOver){
    			g.setFont(new Font("Comic Sans",16,16));
    			g.drawString("You Have Lost " + LoseCount + " Times", 5,30 );
    			g.drawString("Your Score is: " + score, 5, 60);
    		}
    		
    		if(!isApple){
    			Coord h = makeAppleLocation();
    			g.fillOval(h.getX(),h.getY(),10,10);
    			isApple = true;
    			appleLocation = h;
    		}
    		for(int x = 0; x < cord.size();x++){
    			g.fillOval(cord.get(x).getX(), cord.get(x).getY(), 10, 10);
    		}
    		g.fillOval(appleLocation.getX(), appleLocation.getY(), 10, 10);
    		
    		
    		
    		
    		run();
    	}
    	public void run(){
    		try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}
    		
    		if(direction==UP){
    			
    			y-=10;
    			if(isValid(new Coord(x,y))){
    				
    			}
    			else{
    				gameOver = true;
    				LoseCount++;
    			}
    			cord.add(new Coord(x,y));
    			if(isSame(cord.get(cord.size()-1),appleLocation)){
    				score++;
    				isApple=false;
    				cord.add(0, cord.get(0));
    			}
    			
    			if(cord.size()>4){
    			cord.remove(0);
    			}
    		}
    		if(direction==DOWN){
    			
    			y+=10;
    			if(isValid(new Coord(x,y))){
    				
    			}
    			else{
    				gameOver = true;
    				LoseCount++;
    			}
    			
    			cord.add(new Coord(x,y));
    			if(isSame(cord.get(cord.size()-1),appleLocation)){
    				score++;
    				isApple=false;
    				cord.add(0, cord.get(0));
    			}
    			
    			if(cord.size()>4){
    				cord.remove(0);
    			}
    		}
    		if(direction==LEFT){
    			
    			x-=10;
    			if(isValid(new Coord(x,y))){
    				
    			}
    			else{
    				gameOver = true;
    				LoseCount++;
    			}
    			cord.add(new Coord(x,y));
    			if(isSame(cord.get(cord.size()-1),appleLocation)){
    				score++;
    				isApple=false;
    				cord.add(0, cord.get(0));
    			}
    			
    			if(cord.size()>4){
    				cord.remove(0);
    			}
    		}
    		if(direction==RIGHT){
    			
    			x+=10;
    			if(isValid(new Coord(x,y))){
    				
    			}
    			else{
    				gameOver = true;
    				LoseCount++;
    			}
    			cord.add(new Coord(x,y));
    			if(isSame(cord.get(cord.size()-1),appleLocation)){
    				score++;
    				isApple=false;
    				cord.add(0, cord.get(0));
    			}
    			
    			if(cord.size()>4){
    				cord.remove(0);
    			}
    		}
    		repaint();
    	}
    	@Override
    	public void keyPressed(KeyEvent e) {
    		if(e.getKeyCode()==37&&direction!=RIGHT){
    			direction = LEFT;
    		}
    		if(e.getKeyCode()==38&&direction!=DOWN){
    			direction = UP;
    		}
    		if(e.getKeyCode()==39&&direction!=LEFT){
    			direction = RIGHT;
    		}
    		if(e.getKeyCode()==40&&direction!=UP){
    			direction = DOWN;
    		}
    		repaint();
    	}
    	@Override
    	public void keyReleased(KeyEvent e){}
    	@Override
    	public void keyTyped(KeyEvent e) {}
    	public Coord makeAppleLocation(){
    		int x = (int) Math.round(Math.random()*20);
    		int y = (int) Math.round(Math.random()*20);
    		
    		return new Coord(x*10,y*10);
    		
    	}
    	public boolean isSame(Coord a, Coord b){
    		if(a.getX()==b.getX()){
    			if(b.getY()==a.getY()){
    				return true;
    			}
    		}
    		return false;
    	}
    	public boolean isValid(Coord c){
    		int x = c.getX();
    		int y = c.getY();
    		
    		if(x<0||x>200){
    			return false;
    		}
    		if(y<0||y>200){
    			return false;
    		}
    		for(int z = 0; z < cord.size();z++){
    			if(isSame(cord.get(z), c)){
    				return false;
    			}
    		}
    		
    		return true;
    		
    	}
    }

  9. #9
    ra4king's Avatar
    ra4king is offline Senior Member
    Join Date
    Apr 2011
    Location
    Atlanta, Georgia, US
    Posts
    396
    Rep Power
    4

    Default

    @Fubarable
    Swing Timer is only for simple things that you want synchronized with Swing Components, because it uses the EDT. It is not appropriate for time critical apps, like games. Util Timer and Thread.sleep(int) are more efficient; they are the closest to perfect you can ever get.

    @OP
    To use canvas, you create a new Canvas object in your applet, and draw into it. The white flashes happen because you are drawing directly on the screen and it doesn't really draw it all at once. To make graphics smooth, you have to use double buffering, which means you draw into a temporary hidden image and then draw that image all at once. Here is an example of how you would do this with Canvas.

    Java Code:
    public class Game extends Applet implements Runnable {
        //your variables
        Canvas canvas;
        
        public void init() {
            canvas = (Canvas)add(new Canvas());
            canvas.createBufferStrategy(2);
        }
        
        public void start() {
            new Thread(this).start();
        }
        
        public void update(int deltaTime) {
            //COPY YOUR GAME CODE HERE
        }
        
        public void run() {
            //game loop
            
            long startTime = System.nanoTime();
            int FPS = 60;
            
            while(isActive()) {
                int timeDiff= (int)Math.round((System.nanoTime()-startTime)/1000000000.0);
                startTime = System.nanoTime();
                
                update(timeDiff);
                
                //You get the buffer strategy from the canvas.
                BufferStrategy strategy = canvas.getBufferStrategy();
                do{
                    do{
                        Graphics2D g = (Graphics2D)strategy.getDrawGraphics();
                        
                        paint(g);
                        
                        g.dispose();
                    }while(strategy.contentsLost());
                    
                    strategy.show();
                }while(strategy.contentsRestored());
                
                try{
                    int sleepTime = (1000000000/FPS)-(int)(System.nanoTime-lastTime);
                    Thread.sleep((int)Math.round(sleepTime/1000000000));
                } catch(Exception exc) {
                    exc.printStackTrace();
                }
            }
        }
        
        public void paint(Graphics2D g) {
            //Put drawing code here
        }
    }
    Last edited by ra4king; 04-14-2011 at 11:34 PM.

  10. #10
    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 ra4king View Post
    @Fubarable
    Swing Timer is only for simple things that you want synchronized with Swing Components, because it uses the EDT. It is not appropriate for time critical apps, like games. Util Timer and Thread.sleep(int) are more efficient; they are the closest to perfect you can ever get.

    And creating a simple snake GUI doesn't exactly qualify as a that of a state of the art game app. In my book this is one of the best cases for using Swing Timer. :)

  11. #11
    ra4king's Avatar
    ra4king is offline Senior Member
    Join Date
    Apr 2011
    Location
    Atlanta, Georgia, US
    Posts
    396
    Rep Power
    4

    Default

    I dislike Swing Timers and gave up on them a long time ago because, looking at the source code, it is used implemented as a linked-list, plus it is very inefficient. Try this, create a --desktop-- (i meant command line) app that just creates a Timer that displays the current date and time every second. Tell me what happens ;)

    Hint: It will only run once.
    Last edited by ra4king; 04-15-2011 at 12:08 AM.

  12. #12
    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 ra4king View Post
    I dislike Swing Timers and gave up on them a long time ago because, looking at the source code, it is used implemented as a linked-list, plus it is very inefficient. Try this, create a desktop app that just creates a Timer that displays the current date and time every second. Tell me what happens ;)

    Hint: It will only run once.
    ?

    It seems to work OK for me:

    Java Code:
    import java.awt.*;
    import java.awt.event.*;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import javax.swing.*;
    
    public class DateTimeDisplay extends JLabel {
       
       private static final Dimension SIZE = new Dimension(300, 50);
       private static final int TIMER_DELAY = 1000;
       private static final String FORMAT_STRING = "MMMM dd, yyyy    hh:mm:ss aa";
       private SimpleDateFormat dateFormat = new SimpleDateFormat(FORMAT_STRING);
    
       public DateTimeDisplay() {
          super("", SwingConstants.CENTER);
          setPreferredSize(SIZE);
          
          Timer timer = new Timer(TIMER_DELAY, new ActionListener() {
             @Override
             public void actionPerformed(ActionEvent e) {
                String dateString = dateFormat.format(new Date());
                setText(dateString);
             }
          });
          timer.setInitialDelay(0);
          timer.start();
       }
       
       private static void createAndShowUI() {
          JFrame frame = new JFrame("DateTimeDisplay");
          frame.getContentPane().add(new DateTimeDisplay());
          frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          frame.pack();
          frame.setLocationRelativeTo(null);
          frame.setVisible(true);
       }
    
       public static void main(String[] args) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
                createAndShowUI();
             }
          });
       }
    }

  13. #13
    ra4king's Avatar
    ra4king is offline Senior Member
    Join Date
    Apr 2011
    Location
    Atlanta, Georgia, US
    Posts
    396
    Rep Power
    4

    Default

    No, don't use GUI:

    Java Code:
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Date;
    import javax.swing.Timer;
    
    public class Test {
        public static void main(String args[]) {
            new Timer(1000, new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    System.out.println(new Date());
                }
            }).start();
        }
    }

  14. #14
    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 ra4king View Post
    No, don't use GUI:

    Java Code:
    import java.awt.event.ActionEvent;
    import java.awt.event.ActionListener;
    import java.util.Date;
    import javax.swing.Timer;
    
    public class Test {
        public static void main(String args[]) {
            new Timer(1000, new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    System.out.println(new Date());
                }
            }).start();
        }
    }
    That doesn't make sense since a Swing Timer is for use when running *Swing* GUI's. It only runs on the EDT and won't exist if the EDT doesn't exist, but when used appropriately it works well. Just as I don't use my lawn mower for washing the dishes, but it does a bang up job for cutting my grass. Don't go then tell me that a lawn mower is a poor tool when you're using it incorrectly.

  15. #15
    ra4king's Avatar
    ra4king is offline Senior Member
    Join Date
    Apr 2011
    Location
    Atlanta, Georgia, US
    Posts
    396
    Rep Power
    4

    Default

    The EDT is created. The Swing Timer doesn't have to be used with Swing GUI's but is there to make life easier for programmers worried about Thread safety if they create Swing GUI. I couldn't really understand exactly why this happens from my instructor a while ago.

  16. #16
    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 ra4king View Post
    The EDT is created. The Swing Timer doesn't have to be used with Swing GUI's but is there to make life easier for programmers worried about Thread safety if they create Swing GUI. I couldn't really understand exactly why this happens from my instructor a while ago.
    Are you familiar with daemon threads? Consider the thread that the Timer runs in a deamon thread, and if there is nothing else to make the EDT continue, the Timer will end (as documented in its API). Its "weakness" is the same as for any daemon thread type process -- i.e., none if you understand it.

  17. #17
    ra4king's Avatar
    ra4king is offline Senior Member
    Join Date
    Apr 2011
    Location
    Atlanta, Georgia, US
    Posts
    396
    Rep Power
    4

    Default

    I have actually never really understood what the word "daemon" means here.

Similar Threads

  1. Thread Doesn't Sleep
    By Creativelymad in forum Threads and Synchronization
    Replies: 3
    Last Post: 03-07-2011, 04:29 AM
  2. Difference between Thread.yield() and Thread.sleep() methods
    By Nageswara Rao Mothukuri in forum New To Java
    Replies: 12
    Last Post: 07-30-2010, 05:37 PM
  3. how to reduce the thread sleep time and wake up the thread
    By baktha.thalapathy in forum Threads and Synchronization
    Replies: 2
    Last Post: 06-24-2010, 07:36 PM
  4. Sleep in thread
    By jithan in forum New To Java
    Replies: 1
    Last Post: 08-27-2008, 02:27 PM
  5. How to use the sleep and thread?
    By jiuhu in forum Java Applets
    Replies: 4
    Last Post: 08-07-2007, 02:56 AM

Posting Permissions

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