Computer Science 252
Problem Solving with Java

Spring 2014, The College of Saint Rose

WindyFallingSnow Demo

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



WindyFallingSnow BlueJ Project

Click here to download a BlueJ project for WindyFallingSnow.


WindyFallingSnow Source Code

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


FallingSnow.java

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

/*
 * 
 * Example FallingSnow: the snowflakes that fall, but now with their
 * x speeds determined by the current wind speed, provided by a Wind
 * object.
 *
 * Jim Teresco, Siena College, CSIS 120, Spring 2011
 * The College of Saint Rose, Fall 2013, Fall 2014
 * Based on example from CSCI 134, Williams College
 *
 * $Id: FallingSnow.java 2452 2014-10-13 15:59:20Z terescoj $
 */

public class FallingSnow extends ActiveObject {

    // delay between snow motions
    private static final int DELAY_TIME = 33;

    private DrawingCanvas canvas;

    // speed of fall
    private double ySpeed;

    // the snowflake
    private VisibleImage snow;

    // the wind, which is responsible for providing a current
    // wind speed on demand
    private Wind wind;
    
    // initialize the instance variables and start the active object
    public FallingSnow(DrawingCanvas aCanvas, Image aSnowPic, Wind w,
                       double x, double aSpeed) {
        canvas = aCanvas;
        ySpeed = aSpeed;
        wind = w;

        snow = new VisibleImage(aSnowPic, 0, 0, canvas);
        snow.move(x, - snow.getHeight());

        start();
    }

    public void run() {

        // as long as the snow is still on the screen
        // move it and pause
        while (snow.getY() < canvas.getHeight()) {
            pause(DELAY_TIME);
            // we will query the Wind object to get the current wind speed
            snow.move(wind.getSpeed(),ySpeed);
        }

        snow.removeFromCanvas();
    }

}

Snow.java

import objectdraw.*;
import java.awt.*;
/*
 * 
 * Example WindyFallingSnow: the main class that creates clouds, which in turn
 * create falling snowflakes.
 * 
 * This one adds a varying wind, controlled by another active object!
 *
 * Jim Teresco, The College of Saint Rose, Fall 2013, Fall 2014
 * Based on example from CSCI 134, Williams College
 *
 * $Id: Snow.java 2452 2014-10-13 15:59:20Z terescoj $
 */

// Program which creates clouds which create snow when the user clicks
public class Snow extends WindowController {

    // constants for the moon size and location
    private static final double MOON_INSET = 50;
    private static final int MOON_SIZE = 70;

    // sizes and locations for the bricks
    private static final double BRICK_LINE = 40;  // from bottom
    private static final double BRICK_HEIGHT = 12;
    private static final double BRICK_WIDTH = 30;
    private static final double BRICK_SPACING = 3;

    // colors of the sky, mortar, and brick
    private final Color NIGHTSKY = new Color(50, 50, 100);
    private final Color MORTAR = new Color(200, 200, 200);
    private final Color BRICKRED = new Color(150, 40, 40);

    // image of the snow
    private Image snowPic;
    
    // our wind generator
    private Wind wind;

    public void begin() {

        // where to draw next brick
        double brickPosition;

        // get leaf picture
        snowPic = getImage("snow.gif");

        // draw solid sky, mortar, and moon
        new FilledRect(0, 0, canvas.getWidth(), canvas.getHeight() - BRICK_LINE, canvas).setColor(NIGHTSKY);
        new FilledRect(0, canvas.getHeight() - BRICK_LINE, canvas.getWidth(), 
                       canvas.getHeight(),
                       canvas).setColor(MORTAR);
        new FilledOval(MOON_INSET,MOON_INSET,MOON_SIZE,MOON_SIZE,
                       canvas).setColor(Color.white);

        // add the bricks
        brickPosition = 0;
        while ( brickPosition < canvas.getWidth() ) {
            new FilledRect(brickPosition, canvas.getHeight() - BRICK_LINE,
                           BRICK_WIDTH, BRICK_HEIGHT,
                           canvas).setColor(BRICKRED);

            brickPosition = brickPosition + BRICK_WIDTH + BRICK_SPACING;
        }

        // construct our Wind object that will be passed to each Cloud
        // and in turn to each FallingSnow object, which will query it
        // for current wind speeds.
        wind = new Wind();
    }

    public void onMouseClick(Location point) {
        // make a new snow-dropping cloud when the user clicks
        // note the extra parameter for the Wind object
        new Cloud(snowPic, wind, canvas);
    }
}


Cloud.java

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

/*
 * 
 * Example FallingSnow: the cloud class which is responsible for
 * creating a bunch of snowflakes, in this case remembering and 
 * passing along the Wind obect to each snowflake.
 *
 * Jim Teresco, Siena College, CSIS 120, Spring 2011
 * The College of Saint Rose, Fall 2013, Fall 2014
 * Based on example from CSCI 134, Williams College
 *
 * $Id: Cloud.java 2452 2014-10-13 15:59:20Z terescoj $
 */

public class Cloud extends ActiveObject {

    // total number of snowflakes
    private static final int MAX_SNOW = 150;
    // time between flakes
    private static final int FLAKE_INTERVAL = 900;

    // the canvas
    private DrawingCanvas canvas;

    // picture of a snowflake
    private Image snowPic;

    // used to generate random speeds and positions for snowflakes
    private Random snowGen;
    
    // our Wind generator, just here to be passed along
    private Wind wind;

    public Cloud(Image aSnowPic, Wind wind, DrawingCanvas aCanvas) {

        // save the parameters for the "run" method
        canvas = aCanvas;
        snowPic = aSnowPic;
        this.wind = wind;
 
        snowGen = new Random();

        start();
    }

    public void run()
    {
        int snowCount= 0;

        // continue creating snow until the maximum amount
        // has been created
        while (snowCount < MAX_SNOW ) {

            snowCount = snowCount + 1;

            new FallingSnow(canvas, snowPic, wind,
                            snowGen.nextInt((int)canvas.getWidth()),   // x coordinate
                            snowGen.nextDouble()*2+2); // y speed
            pause(FLAKE_INTERVAL);
        }
    }
}

Wind.java

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

/**
 * A class to generate a randomly-fluctuating wind.
 * 
 * @author Jim Teresco, The College of Saint Rose
 * Fall 2013
 * 
 * $Id: Wind.java 2218 2013-10-18 14:06:39Z terescoj $
 */

public class Wind extends ActiveObject {
    
    // constants to define the wind's behavior
    // update the wind once per second
    private static final int WIND_ADJ_DELAY = 1000;
    
    // maximum change per iteration in wind speed
    private static final double WIND_ADJ_MAX = 3.0;
    
    // current wind velocity (x-direction)
    private double currentWind;
    
    // random number generator to generate changes in
    // wind speed periodically
    private Random r;
    
    // construct and active our Wind object
    public Wind() {
        
        currentWind = 0.0;
        r = new Random();
        
        start();
    }
    
    // the life of the wind
    public void run() {
        
        // the wind never stops, it just changes direction
        while (true) {
            currentWind += ((r.nextDouble() * 2 * WIND_ADJ_MAX) - WIND_ADJ_MAX);
            pause(WIND_ADJ_DELAY);
        }
    }
    
    // public accessor method to allow our snowflakes to query the 
    // current wind velocity
    public double getSpeed() {
        
        return currentWind;
    }

}