Noob first codelet, wanting to smooth out my animation

So I’ve been trying to learn to use awt to make some basic graphics driven stuff, and managed to make a jumping ball that can be controlled with the keyboard. It’s functional enough, but the animation isn’t very smooth looking. I can’t seem to figure out how to use the frame delta that is generated by the variable timestep loop I implemented thanks to the incredibly useful post at http://www.java-gaming.org/topics/game-loops/24220/view.html


public class JumpingBall{

	/**
	 * @param args
	*/ 
	//variables

	//Methods
	public static void main(String[] args) {
		Screen screen = new Screen(Globals.DESIRED_FPS);
		screen.run(true);
		
	}
}

public class Ball {

	// variables
	private int Radius;
	private double xLocation;
	private double yLocation;
	private double deltaX;
	private double deltaY;
	
	//Getters/Setters for the Balls features
	public int getRadius() {
		return Radius;
	}
	public void setRadius(int radius) {
		this.Radius = radius;
	}
	public double getxLocation() {
		return xLocation;
	}
	public void setxLocation(double xLocation) {
		this.xLocation = xLocation;
	}
	public double getyLocation() {
		return yLocation;
	}
	public void setyLocation(double yLocation) {
		this.yLocation = yLocation;
	}
	public double getDeltaX() {
		return deltaX;
	}
	public void setDeltaX(double deltaX) {
		this.deltaX = deltaX;
	}
	public double getDeltaY() {
		return deltaY;
	}
	public void setDeltaY(double deltaY) {
		this.deltaY = deltaY;
	}
	public Ball(int radius, double xLocation, double yLocation) {
		this.Radius = radius;
		this.xLocation = xLocation;
		this.yLocation = yLocation;

	}
	
	//Methods
}

public class Globals {
	public final static int SCREEN_WIDTH = 800; // The screen width
	public final static int SCREEN_HEIGHT = 600; // The screen height
	
	public final static int DESIRED_FPS = 60; // Desired max FPS
}

package net.traverse.jumpingball;

import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;

import javax.swing.JFrame;
import javax.swing.JPanel;


public class Screen extends Canvas{

	private static final long serialVersionUID = 1L; //Version UID
	
	//Variables used by the game loop itself
	private int targetFPS; //The target FPS the game should run at, will be passed in the constructor
	private int FPS; // The current actual frames per second being rendered
	private long optimalTime; //the optimal time in nanoseconds
	private long lastLoopTime; //time in nanoseconds of the last loop pass
	
	Ball b; // 
	
	BufferStrategy strategy;
	
	public Screen(int tFPS){
		this.targetFPS = tFPS;
		this.optimalTime = 1000000000 / tFPS;
		this.FPS = 0;
		this.lastLoopTime = System.nanoTime();
		this.b= new Ball(30, 400, 300);
		JFrame container = new JFrame("My first JFrame");
		JPanel panel = (JPanel) container.getContentPane();
		panel.setPreferredSize(new Dimension(Globals.SCREEN_WIDTH - 10, Globals.SCREEN_HEIGHT - 10));
		panel.setLayout(null);
		
		setBounds(0, 0, Globals.SCREEN_WIDTH, Globals.SCREEN_HEIGHT);
		
		panel.add(this);
		
		setIgnoreRepaint(true);
		
		container.pack();
		container.setLocationRelativeTo(null);
		container.setResizable(false);
		container.setVisible(true);

		container.addWindowListener(new WindowAdapter() 
		{
			public void windowClosing(WindowEvent e) 
			{
				System.exit(0);
			}
		});
		
		addKeyListener(new KeyboardHandler());
		
		requestFocus();
		setFocusable(true);
		
		createBufferStrategy(2);
		strategy = getBufferStrategy();

	}
	private class KeyboardHandler extends KeyAdapter 
	{

		public void keyReleased(KeyEvent e) 
		{
			int key = e.getKeyCode();
			
			if (key == KeyEvent.VK_LEFT) 
			{
				b.setDeltaX(0);
			}

			if (key == KeyEvent.VK_RIGHT) 
			{
				b.setDeltaX(0);
			}

		}

		public void keyPressed(KeyEvent e) 
		{

			int key = e.getKeyCode();
			
			if (key == KeyEvent.VK_LEFT) 
			{
				b.setDeltaX(-10);
			}

			if (key == KeyEvent.VK_RIGHT) 
			{
				b.setDeltaX(10);
			}

			if (key == KeyEvent.VK_UP) 
			{
				if(b.getDeltaY()>=0){
					b.setDeltaY(b.getDeltaY()+10);
				}
				else{
					b.setDeltaY(b.getDeltaY()-10);
				}
			}

			if (key == KeyEvent.VK_DOWN) 
			{
				if(b.getDeltaY()>=0){
					b.setDeltaY(b.getDeltaY()-10);
				}
				else{
					b.setDeltaY(b.getDeltaY()+10);
				}
			}

			
		}

		
		public void keyTyped(KeyEvent e) 
		{
			
			if (e.getKeyChar() == 27) 
			{
				System.exit(0);
			}
			
		}

	}
	
	public void run(boolean gameRunning){
		long lastFpsTime = 0;
		int fpsUpdate=0;
		
		while(gameRunning){
			//this section works out how long it's been since the last update
			// in order to calculate how far the entities should move on this pass
			long now = System.nanoTime();
			long updateLength = now - lastLoopTime;
			lastLoopTime = now;
			double delta = updateLength / ((double)optimalTime);
			lastFpsTime += updateLength;
		    fpsUpdate++;
		    if (lastFpsTime >= 1000000000)
		      {
		    	this.FPS = fpsUpdate;
		         lastFpsTime = 0;
		         fpsUpdate = 0;
		      }
		    //This is the game logic update function
		    gameRunning = doGameUpdates(delta);
		    
		    //This function draws the updated entities to the screen
		    
		    Graphics2D g2D = (Graphics2D) strategy.getDrawGraphics();
		    g2D.setColor(Color.BLACK);
			g2D.fillRect(0, 0, Globals.SCREEN_WIDTH, Globals.SCREEN_HEIGHT);
		    renderEntities(g2D);
		    g2D.dispose();
			strategy.show();
			Toolkit.getDefaultToolkit().sync();
			try{
				Thread.sleep(((System.nanoTime()- lastLoopTime) + optimalTime)/1000000);
				}
			catch (InterruptedException e)
			{
				System.out.println("interrupted");
			}
		    
		}
	}
	private boolean doGameUpdates(double delta){
			boolean gameRunning = true;
			
			
			/* 
			 * Fill in with entities to be updated
			 */
			if (b.getyLocation() >= Globals.SCREEN_HEIGHT-(b.getRadius()*2)){
				b.setDeltaY((-1*b.getDeltaY()));
			}
			else if(b.getyLocation() <= 0){
				b.setDeltaY((-1*b.getDeltaY()));
			}
			else{
				b.setDeltaY((b.getDeltaY()+5));
			}
			System.out.println(delta);
			b.setyLocation(b.getyLocation()+ b.getDeltaY());
			b.setxLocation(b.getxLocation()+b.getDeltaX());
			
			return gameRunning;
	}

	private void renderEntities(Graphics2D g2D){
		
		g2D.setFont(new Font("Courier New", Font.BOLD, 24));
		g2D.setColor(Color.BLUE);
		g2D.drawString("FPS : " + FPS, 0, 24);
		g2D.fillOval((int)b.getxLocation(), (int)b.getyLocation(),b.getRadius()*2, b.getRadius()*2);
	}
	
}




On the console I show the delta as outputting at 1. something fairly consistently, but when I run this the bouncing ball doesn’t seem smooth to me.