Computer Science 252
Problem Solving with Java

Spring 2014, The College of Saint Rose

FancyBasketball Demo

A working demo of FancyBasketball will appear below. Click inside the applet to interact with it.



FancyBasketball BlueJ Project

Click here to download a BlueJ project for FancyBasketball.


FancyBasketball Source Code

The Java source code for FancyBasketball is below. Click on a file name to download it.


FancyBasketball.java

import objectdraw.*;
import java.awt.*;

/*
 * A simple basketball program.  It adds 2 points to 
 * a displayed score whenever the ball is dragged into
 * the oval (hoop).
 *
 * This version uses a nicer basketball object from NiceBBall
 *
 * Jim Teresco, Siena College, CSIS 120, Spring 2011
 * The College of Saint Rose, Fall 2013
 * Based on example from Williams College, CSCI 134
 *
 * $Id: FancyBasketball.java 2218 2013-10-18 14:06:39Z terescoj $
 */

public class FancyBasketball extends WindowController {

    // Location of the display
    private static final double DISPLAY_FROM_TOP = 0.5;  // display is half way down
    private static final int DISPLAY_SIZE = 16; // in points

    // Location and dimensions of the hoop
    private static final double HOOP_FROM_TOP = 0.25;
    private static final int HOOP_WIDTH = 100;
    private static final int HOOP_HEIGHT = 60;

    // Initial location and dimensions of the ball
    private static final double BALL_FROM_TOP = 0.75;
    private static final int BALL_SIZE = 40;
    private static final Color BALL_COLOR = new Color(250, 115, 10);

    // instance variables
    // court elements
    private FramedOval hoop;
    private NiceBBall ball;
    private Text scoreboard;

    // keep track of whether we are dragging the ball
    private boolean ballGrabbed;

    // last mouse position for dragging
    private Location lastMouse;

    // current score
    private int score;

    public void begin() {

        // draw the court
        // create scoreboard, adjust font size, center it
        scoreboard = new Text("Drag the ball to the hoop to score points!",
            0, DISPLAY_FROM_TOP * canvas.getHeight(), canvas);
        scoreboard.setFontSize(DISPLAY_SIZE);
        scoreboard.moveTo(canvas.getWidth()/2 - scoreboard.getWidth()/2,
                          DISPLAY_FROM_TOP * canvas.getHeight() - scoreboard.getHeight()/2);
  
        // draw the hoop
        hoop = new FramedOval(canvas.getWidth()/2 - HOOP_WIDTH/2, 
                              canvas.getHeight() * HOOP_FROM_TOP - HOOP_HEIGHT/2, 
                              HOOP_WIDTH, HOOP_HEIGHT, canvas);

        // draw the ball
        ball = new NiceBBall(canvas.getWidth()/2 - BALL_SIZE/2, 
                             canvas.getHeight() * BALL_FROM_TOP - BALL_SIZE/2,
                             BALL_SIZE, canvas);
        // initialize score to 0
        score = 0;
    }

    public void onMousePress(Location point) {

        // check if we pressed the mouse on the ball
        if (ball.contains(point)) {
            // if so, set up for dragging the ball
            ballGrabbed = true;
            lastMouse = point;
        }
    }

    public void onMouseDrag(Location point) {

        // check if we are dragging the ball
        if (ballGrabbed) {
            // if so, update position to current
            ball.move(point.getX() - lastMouse.getX(),
                point.getY() - lastMouse.getY());
            lastMouse = point;
        }
    }

    public void onMouseRelease(Location point) {

        // check if we are dragging the ball
        if (ballGrabbed) {
            // if so, date position to current
            ball.move(point.getX() - lastMouse.getX(),
                point.getY() - lastMouse.getY());

            // check if the ball is in the hoop
            if (hoop.contains(point)) {
                score = score + 2;
                scoreboard.setText("Basket!  Your score is " + score);
            }
            else {
                scoreboard.setText("You missed!  Your score is " + score);
            }
            scoreboard.moveTo(canvas.getWidth()/2 - scoreboard.getWidth()/2,
                              DISPLAY_FROM_TOP * canvas.getHeight() - scoreboard.getHeight()/2);
        }
        ballGrabbed = false;
        ball.moveTo(canvas.getWidth()/2 - BALL_SIZE/2, 
                    canvas.getHeight() * BALL_FROM_TOP - BALL_SIZE/2);
    }
    
    public void onMouseExit(Location point) {
        
        // when the mouse exits the window, we'll give the ball
        // a random color
        ball.changeToRandomColor();
    }
    
    public void onMouseEnter(Location point) {
        
        // when the mouse enters the window, go back to regular color
        ball.backToNormalColor();
    }
}

NiceBBall.java

import objectdraw.*;
import java.awt.Color;
import java.util.Random;

/*
 * A class that implements a nice looking basketball.
 *
 * Jim Teresco, Siena College, CSIS 120, Spring 2011
 * The College of Saint Rose, Fall 2013
 * Based on example from Williams College, CSCI 134
 *
 * $Id: NiceBBall.java 2218 2013-10-18 14:06:39Z terescoj $
 */

// Hey, look, no "extends WindowController"!
// That's because this class will not create a canvas or
// respond to any mouse events -- all of that it the
// responsibility of whoever creates a NiceBBall and
// wants to manipulate it.
public class NiceBBall {

    // the color to draw the ball
    private static final Color BALL_ORANGE = new Color(250, 85, 10);

    // size and starting angles for cut arc in degrees
    private static final int CUTSIZE = 100;
    private static final int RIGHTCUTSTART = 90 + (180 - CUTSIZE) / 2;
    private static final int LEFTCUTSTART = 270 + (180 - CUTSIZE) / 2;

    // the orange part of the ball
    private FilledOval body;

    // the border of the ball
    private FramedOval border;

    // the two curves on the sides of the ball
    private FramedArc leftCut, rightCut;

    // the vertical and horizontal lines through the ball
    private Line vert, horiz;

    // to pick new random color for ball
    private Random colorPicker = new Random();

    /*
     * Create a new basketball on the given DrawingCanvas.  Note how this class
     * does not know about the default "canvas", since that's available only in
     * classes that extend the WindowController class.
     */
    public NiceBBall(double left, double top, double size, DrawingCanvas aCanvas) {

        // draw the circles that make it look like a ball
        body = new FilledOval(left, top, size, size, aCanvas);
        body.setColor(BALL_ORANGE);
        border = new FramedOval(left, top, size, size, aCanvas);

        // draw the lines and arcs that make it look like a basketball
        rightCut = new FramedArc(left + size * 2 / 3, top, size, size, RIGHTCUTSTART, CUTSIZE, aCanvas);
        leftCut = new FramedArc(left - size * 2 / 3, top, size, size, LEFTCUTSTART, CUTSIZE, aCanvas);
        vert = new Line(left + size / 2, top, left + size / 2, top + size, aCanvas);
        horiz = new Line(left, top + size / 2, left + size, top + size / 2, aCanvas);

    }

    /*
     * Move the ball by specified offsets.
     */
    public void move(double dx, double dy) {
        // move each part of the ball by the offsets provided
        body.move(dx, dy);
        border.move(dx, dy);
        vert.move(dx, dy);
        horiz.move(dx, dy);
        leftCut.move(dx, dy);
        rightCut.move(dx, dy);
    }

    /*
     * Check to see if the ball contains a specified location.
     */
    public boolean contains(Location point) {
        return body.contains(point);
    }

    /*
     * Move the ball to a specified position. 
     */
    public void moveTo(double x, double y) {
        // determine how far away (x,y) is
        double dx, dy;
        dx = x - body.getX();
        dy = y - body.getY();

        // move each part of the ball by the offset,
        //   using our own move method.
        this.move(dx, dy);
    }

    /*
     * Return the x coordinate of ball's corner.
     */
    public double getX() {
        return body.getX();
    }

    /*
     * Return the y coordinate of ball's corner.
     */
    public double getY() {
        return body.getY();
    }

    /*
     *  method to change the background color of the ball to one
     *  selected completely at random.
     */
    public void changeToRandomColor() {
        Color newBallColor = new Color(colorPicker.nextInt(256),
                colorPicker.nextInt(256), 
                colorPicker.nextInt(256));
        body.setColor(newBallColor);
    }

    /*
     * method to return the ball back to its original color.
     */
    public void backToNormalColor() {

        body.setColor(BALL_ORANGE);
    }
}