Moving Images from the Graphics class

I’m using the Graphics class and Image class to draw an image onto an applet. I’m using a keylistener to move the position +5 or -5 in the x direction. The image speeds up way too fast when the key get held down, because the image is contantly incrementing. Is there a better way to do this? I want the image to move slow and constant when the key is held down.

You want the image to move at a constant speed? Then reset the variables that modify its location every frame. Basic math. Say in your keylistener you increase an x and y variable, and then you add those variables onto the images positions. Every frame set those x and y variables back to 0.

int x = 0;
int y = 0;
int dx = 18;

//this is inside the paint method

g.drawImage(img, x, y, this);

//this is inside Keylistener method

case KeyEvent.VK_RIGHT:
x += dx;

Could you please explain a bit more?

Your initial question and the code you have posted do not match. In the initial post you said you are adding 5 to the image’s position in any direction, but in the code you posted you are adding 18. The code you posted should work fine, the speed would be constant because your dx variable never increases. I have a strong suspicion this isn’t the case though, and that’s why you need to post your code instead of just small snippets.

I checked my code, after your post, and noticed dx was 18. The reason I use 18 as a constant is because it moves my character a good distance. Unfortunately, this number adds up pretty fast when the key is held down. Ideally, I’d want the code to increment once and stop for a short time(like a thread or something) and then re increment. This way my character won’t zap across the screen so fast.

I’ve tried to do this by implementing a for loop with a System.out.println() method inside, in order to slow it down but this causes huge lag.

I don’t even… no. You don’t stop a thread for something like this, nor do you use print statements to slow a program down… If you want the player to move slower then simply decrease dx’s value.

I think what the OP is looking for is Thread.sleep(16);
this will give you 60~ fps.

Yeah, but let’s say I just want to move once by tapping the key one time. He will barely move, if I decrease dx. That’s why I’ve found +18 moves my character just far enough.

This is how I want my method to work. It’s obviously not the real code:

KeyIsPressed(){
moveCharacterForward += 18;
waitForAMoment();
startFromTop;
}

What if you store a distToMove variable:


KeyIsPressed(){
   distToMove += 18;
   waitForAMoment();
   startFromTop;
}

...
//somewhere else that is called every frame, like entity update etc

x += walkSpeed;
distToMove -= walkSpeed;


Basically tell the entity how far he needs to move, and then have him move that distance over the next couple dozen frames or so.
There are many ways to model entity movement, but this is what I would likely use in your scenario; it is responsive, but maintains a maximum speed that the entity can move.

This is the basics of the code. When you tap the right key, you move a good amount but when you hold it down you increase too fast.

How do I make the square go 18 pixels and then stop and then go again. Move 18 pixels. Stop for half a second. Go 18px. All while the key is being held down. As though I were tapping the key.



import java.applet.Applet;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;




public class TheApplet extends Applet implements KeyListener, Runnable{
    public int x = 20;
    public int y = 20;
    public int dx = 18;
	
	public void init(){
    	 setSize(800, 600);
    	 setFocusable(true);
    	 addKeyListener(this);
     }
     
     public void start(){
    	 Thread thread = new Thread(this);
    	 thread.start();
     }
     
     public void run(){
    	 while(true){
    		 
    		 repaint();
    		 try {
				Thread.sleep(17);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	 }
     }
     
     public void paint(Graphics g){
    	 g.fillRect(x, y, 40, 40);
     }

	@Override
	public void keyPressed(KeyEvent e) {
		switch(e.getKeyCode()){
		case KeyEvent.VK_RIGHT:
			x += dx;
		}
		
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}
  
	
}




This might work


	public class TheApplet extends Applet implements KeyListener, Runnable{
	    public int x = 20;
	    public int y = 20;
	    public int dx = 18;
	   
	    boolean keydown = false;
	    
	   public void init(){
	        setSize(800, 600);
	        setFocusable(true);
	        addKeyListener(this);
	     }
	     
	     public void start(){
	        Thread thread = new Thread(this);
	        thread.start();
	     }
	     
	     public void run(){
	    	 
	    	 int counter = 0;
	    	 
	        while(true){

	        	if(keydown && counter <= 0) {
	        		x+=dx;
	        		counter = 30;
	        	}
	        	
	        	counter--;
	        	
	           repaint();
	           try {
	            Thread.sleep(17);
	         } catch (InterruptedException e) {
	            e.printStackTrace();
	         }
	        }
	     }
	     
	     public void paint(Graphics g){
	        g.fillRect(x, y, 40, 40);
	     }

	   @Override
	   public void keyPressed(KeyEvent e) {
	      switch(e.getKeyCode()){
	      case KeyEvent.VK_RIGHT:
	         keydown=true;
	      }
	      
	   }

	   @Override
	   public void keyReleased(KeyEvent e) {
		   switch(e.getKeyCode()){
		      case KeyEvent.VK_RIGHT:
		         keydown=false;
		      }	      
	   }

	   @Override
	   public void keyTyped(KeyEvent e) {
	      // TODO Auto-generated method stub
	      
	   }
	  
	   
	}

Snipped some code for clarity.


    public int x = 20;
    public int y = 20;
    public int distStep = 18;

    private boolean stop = false, keyPressed = false;
    private int distMovedThisStep = 0, framesSinceStop = 0;

    public void run(){
        while(true){
            
@@            if(!stop && (keyPressed || distMovedThisStep <= distStep)) {
@@                x++;
@@                distMovedThisStep++;
@@                if(distMovedThisStep > distStep) {
@@                    distMovedThisStep = 0;
@@                    stop = true;
@@                }
@@            } else if(stop) {
@@                framesSinceStop++;
@@                if(framesSinceStop > 30) { //assuming 60 FPS, 30 will be your half-second
@@                framesSinceStop = 0;
@@                stop = false;
@@            }
            
            repaint();
            try {
                Thread.sleep(17);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
     
    public void paint(Graphics g){
        g.fillRect(x, y, 40, 40);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        switch(e.getKeyCode()){
            case KeyEvent.VK_RIGHT:
@@                keyPressed = true;
@@                break; //don't forget the break
        }
		
    }

    @Override
    public void keyReleased(KeyEvent e) {
@@        keyPressed = false;
    }

Wow! You made it move real smooth like, trollwarrior1. I like it, thank you :slight_smile: