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()); } }