Computer Science 252
Problem Solving with Java
Spring 2014, The College of Saint Rose
BigSnowman Demo
A working demo of BigSnowman will appear below. Click inside the applet to interact with it.
BigSnowman BlueJ Project
Click here to download a BlueJ project for BigSnowman.
BigSnowman Source Code
The Java source code for BigSnowman is below. Click on a file name to download it.
import objectdraw.*;
import java.awt.*;
/*
* Example BigSnowman: a recursive object to create a many-leveled
* snowman-like object. Its base snowball is determined by
* the point and diameter passed to the constructor, and successive
* smaller snowballs are placed atop that one until they become too small
*
* Jim Teresco, The College of Saint Rose, CSC 252, Spring 2014
*
* $Id: BigSnowman.java 2333 2014-03-12 17:48:14Z terescoj $
*/
public class BigSnowman {
// the minimum size of a snowball to be added as the "head"
private static final double MIN_HEAD_SIZE = 25;
// scaling factor for each smaller snowball
private static final double SCALE_FACTOR = 0.7;
// the slightly blue colors for the interior and borders of snowballs
private static final Color SNOW_COLOR = new Color(240, 250, 255);
private static final Color BORDER_COLOR = new Color(200, 200, 255);
// our instance variables to represent the snowman
// the 2 components that make up the base snowball
private FilledOval base;
private FramedOval baseFrame;
// and an instance variable to keep track of any additional snowballs
private BigSnowman rest;
// construct one
public BigSnowman(Location upperLeft, double diameter, DrawingCanvas canvas) {
// The base is easy: Just construct our two graphical components
base = new FilledOval(upperLeft, diameter, diameter, canvas);
base.setColor(SNOW_COLOR);
baseFrame = new FramedOval(upperLeft, diameter, diameter, canvas);
baseFrame.setColor(BORDER_COLOR);
// how big would the next snowball up be?
double newDiameter = diameter * SCALE_FACTOR;
// now, we construct the rest if it would be large enough to be displayed
if (newDiameter >= MIN_HEAD_SIZE) {
// how much to move right to center next snowball on this one?
double xOffset = (diameter - newDiameter)/2;
upperLeft.translate(xOffset, -newDiameter);
rest = new BigSnowman(upperLeft, newDiameter, canvas);
}
}
// we'll need contains and move to support dragging
public boolean contains(Location point) {
if (base.contains(point)) return true;
if (rest != null) return rest.contains(point);
return false;
}
public void move(double dx, double dy) {
// move the pieces we're responsible for
base.move(dx, dy);
baseFrame.move(dx, dy);
// and if there's more, move those recursively
if (rest != null) {
rest.move(dx, dy);
}
}
}
import objectdraw.*;
import java.awt.*;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
/*
* Example BigSnowman: the window controller to make many-leveled
* snowman-like objects on the canvas.
*
* The game:
* - Press the mouse to create a new snowman whose base size
* is determined by the JSlider
* - Press on most recent snowman to drag him instead of creating
* a new snowman
*
* Jim Teresco, The College of Saint Rose, CSC 252, Spring 2014
*
* $Id: BigSnowmanController.java 2333 2014-03-12 17:48:14Z terescoj $
*/
public class BigSnowmanController extends WindowController
implements ChangeListener {
// keep track of the newest snowman
private BigSnowman newestSnowman;
// valid range of snowman base sizes
private static final int MIN_SIZE = 35;
private static final int MAX_SIZE = 200;
// our Swing components: a slider and label for current selected size
private JLabel sizeDisplay;
private JSlider sizer;
// standard dragging code
private boolean dragging;
private Location lastMouse;
// set up GUI
public void begin() {
// Swing setup
Container contentPane = getContentPane();
// we'll put our slider and label up north
JPanel northPanel = new JPanel();
// label and slider into the panel
sizeDisplay = new JLabel("" + MIN_SIZE);
northPanel.add(sizeDisplay);
sizer = new JSlider(JSlider.HORIZONTAL, MIN_SIZE, MAX_SIZE, MIN_SIZE);
northPanel.add(sizer);
// put our panel in the north
contentPane.add(northPanel, BorderLayout.NORTH);
// and we'll listen for slider changes so we can update the label
sizer.addChangeListener(this);
contentPane.validate();
}
public void onMousePress(Location point) {
// drag if we've pressed on the newest snowman
if (newestSnowman != null && newestSnowman.contains(point)) {
dragging = true;
lastMouse = point;
}
// create a new one otherwise
else {
newestSnowman = new BigSnowman(point, sizer.getValue(), canvas);
dragging = false;
}
}
public void onMouseDrag(Location point) {
if (dragging) {
newestSnowman.move(point.getX() - lastMouse.getX(),
point.getY() - lastMouse.getY());
lastMouse = point;
}
}
public void onMouseRelease(Location point) {
if (dragging) {
newestSnowman.move(point.getX() - lastMouse.getX(),
point.getY() - lastMouse.getY());
lastMouse = point;
}
}
// our change listener
public void stateChanged(ChangeEvent e) {
sizeDisplay.setText("" + sizer.getValue());
}
}