« February 2008 | Main | April 2008 »

March 2008

March 27, 2008

Create a Yahtzee Dice Roller and Scorer in Compiled JavaFX Script

I'm still at The Server Side Java Symposium in Las Vegas, and I think that walking by all these slot machines has inspired this blog post. Today's example builds on the program in the Roll the Dice post in order to create a Yahtzee dice roller and scorer.  Each time you click the Roll button, the five dice assume random values, and the combination of values is scored according to the possible categories in the bottom portion of a Yahtzee scoring sheet.  Here's a screenshot:

Yahtzee_2

In addition to the Dice.fx and PipPlacement.fx files from the Roll the Dice post, this program consists of the following source code files.

YahtzeeMain.fx

/*
*  YahtzeeMain.fx -
*  A compiled JavaFX program that demonstrates creating custom
*  components with CompositeNode and evaluates Yahtzee dice rolls.
*
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a JavaFX Script example.
*/

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.System;

Frame {
  var model = YahtzeeModel {}
  width: 510
  height: 400
  title: "Roll Dice and Evaluate Yahtzee Combinations"
  background: Color.WHITE
  content:
    BorderPanel {
      center:
        Box {
          var evalFont =
            Font {
              size: 20
            }
          orientation: Orientation.VERTICAL
          content: [
            Canvas {
              content:
                for (diceNum in [0 .. model.numDice - 1]) {
                  model.newDice =
                  Dice {
                    x: diceNum * 100 + 10
                    y: 10
                    width: 80
                    height: 80
                    faceColor: Color.RED
                    pipColor: Color.WHITE
                  }
                }
            },
            GroupPanel {
              var fiveOfKindRow = Row { alignment: Alignment.BASELINE }
              var largeStraightRow = Row { alignment: Alignment.BASELINE }
              var smallStraightRow = Row { alignment: Alignment.BASELINE }
              var fullHouseRow = Row { alignment: Alignment.BASELINE }
              var fourOfKindRow = Row { alignment: Alignment.BASELINE }
              var threeOfKindRow = Row { alignment: Alignment.BASELINE }
              var chanceRow = Row { alignment: Alignment.BASELINE }

              var labelsColumn = Column {
                alignment: Alignment.TRAILING
              }
              var fieldsColumn = Column {
                alignment: Alignment.LEADING
              }
              rows: [
                fiveOfKindRow,
                largeStraightRow,
                smallStraightRow,
                fullHouseRow,
                fourOfKindRow,
                threeOfKindRow,
                chanceRow
              ]
              columns: [
                labelsColumn,
                fieldsColumn
              ]
              content: [
                SimpleLabel {
                  font: evalFont
                  row: fiveOfKindRow
                  column: labelsColumn
                  text: "Five of a Kind (Yahtzee):"
                },
                SimpleLabel {
                  font: evalFont
                  row: fiveOfKindRow
                  column: fieldsColumn
                  text: bind
                    if (model.fiveOfKind)
                      "{model.fiveOfKindScore}"
                    else "N/A"
                },
               
                SimpleLabel {
                  font: evalFont
                  row: largeStraightRow
                  column: labelsColumn
                  text: "Large Straight:"
                },
                SimpleLabel {
                  font: evalFont
                  row: largeStraightRow
                  column: fieldsColumn
                  text: bind
                    if (model.largeStraight)
                      "{model.largeStraightScore}"
                    else "N/A"
                },
               
                SimpleLabel {
                  font: evalFont
                  row: smallStraightRow
                  column: labelsColumn
                  text: "Small Straight:"
                },
                SimpleLabel {
                  font: evalFont
                  row: smallStraightRow
                  column: fieldsColumn
                  text: bind
                    if (model.smallStraight)
                      "{model.smallStraightScore}"
                    else "N/A"
                },
               
                SimpleLabel {
                  font: evalFont
                  row: fullHouseRow
                  column: labelsColumn
                  text: "Full House:"
                },
                SimpleLabel {
                  font: evalFont
                  row: fullHouseRow
                  column: fieldsColumn
                  text: bind
                    if (model.fullHouse)
                      "{model.fullHouseScore}"
                    else "N/A"
                },
               
                SimpleLabel {
                  font: evalFont
                  row: fourOfKindRow
                  column: labelsColumn
                  text: "Four of a Kind:"
                },
                SimpleLabel {
                  font: evalFont
                  row: fourOfKindRow
                  column: fieldsColumn
                  text: bind
                    if (model.fourOfKind)
                      "{model.sumOfDiceValues}"
                    else "N/A"
                },
               
                SimpleLabel {
                  font: evalFont
                  row: threeOfKindRow
                  column: labelsColumn
                  text: "Three of a Kind:"
                },
                SimpleLabel {
                  font: evalFont
                  row: threeOfKindRow
                  column: fieldsColumn
                  text: bind
                    if (model.threeOfKind)
                      "{model.sumOfDiceValues}"
                    else "N/A"
                },
               
                SimpleLabel {
                  font: evalFont
                  row: chanceRow
                  column: labelsColumn
                  text: "Chance:"
                },
                SimpleLabel {
                  font: evalFont
                  row: chanceRow
                  column: fieldsColumn
                  text: bind "{model.sumOfDiceValues}"
                },
              ]
            },
          ]
        } 
      bottom:
        FlowPanel {
          content:
            Button {
              text: "Roll"
              defaultButton: true
              action:
                function():Void {
                  model.roll();
                }
            }
        }
    }
  visible: true
  onClose:
    function():Void {
      System.exit(0);
    }
}

YahtzeeModel.fx

/*
*  YahtzeeModel.fx -
*  The model behind the Yahtzee dice roll and combination evaluation
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a JavaFX Script example.
*/
import javafx.lang.Sequences;
import java.lang.System;

class YahtzeeModel {
  attribute numDice:Integer = 5;
  attribute diceDistribution:Integer[];
  attribute newDice:Dice on replace {
    insert newDice into dice;
  }
  attribute dice:Dice[];
 
  attribute fiveOfKind:Boolean;
  attribute largeStraight:Boolean;
  attribute smallStraight:Boolean;
  attribute fullHouse:Boolean;
  attribute fourOfKind:Boolean;
  attribute threeOfKind:Boolean;

  attribute fiveOfKindScore:Integer = 50;
  attribute largeStraightScore:Integer = 40;
  attribute smallStraightScore:Integer = 30;
  attribute fullHouseScore:Integer = 25;

  attribute sumOfDiceValues:Integer = 0;
 
  function roll():Void {
    for (die in dice) {
      die.roll();
    }
    evalYahtzeeCombos();
  }
 
  function evalYahtzeeCombos() {
    var values =
    for (val in dice) {
      val.value;
    }

    var maxVal:Integer = Sequences.max(values, null) as Integer;
    var minVal:Integer = Sequences.min(values, null) as Integer;

    // Create a sequence that contains the distribution of values
    // and Calclulate the sum of the dice values
    diceDistribution =
      for (i in [1 .. 6]) 0;

    sumOfDiceValues = 0;
   
    for (val in values) {
      diceDistribution[val - 1]++;
      sumOfDiceValues += val;
    }
   
    // Determine if five-of-a-kind
    fiveOfKind =
      ((for (occurance in diceDistribution
           where occurance >= 5) occurance) <> []);       
   
    // Determine if four-of-a-kind
    fourOfKind =
      ((for (occurance in diceDistribution
           where occurance >= 4) occurance) <> []);
   
    // Determine if three-of-a-kind
    threeOfKind =
      sizeof (for (occurance in diceDistribution
              where occurance >= 3) occurance) > 0;      

    // Determine if full house
    fullHouse =
      sizeof (for (occurance in diceDistribution
              where occurance == 3) occurance) > 0 and      
      sizeof (for (occurance in diceDistribution
              where occurance == 2) occurance) > 0;   

    // Determine if large straight
    largeStraight =
      sizeof (for (occurance in diceDistribution
              where occurance > 1) occurance) == 0 and
      (maxVal - minVal == 4);
             
    // Determine if small straight
    smallStraight =
      sizeof (for (occurance in diceDistribution
              where occurance == 2) occurance) == 1 and
      (maxVal - minVal == 3);
  }
}

A JavaFX Script concept that we haven't covered yet is the set of functions available in the new javafx.lang.Sequences package.  These functions enable you to perform operations (such as sorting) on a sequence. In this program I'm using the max and min functions of that class to find the largest and smallest value in a dice roll.

Enjoy!
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications

Immediate eBook (PDF) download available at the book's Apress site

March 25, 2008

My New Favorite IDE for Compiled JavaFX Script Development

As you may know, in order to develop compiled JavaFX Script applications, it has been necessary to compile and run from the command line.  That is no longer true, as the compiled JavaFX Script plug-in is now available for NetBeans (6.1 beta).  Here's a screenshot of the program example (a Yahtzee dice roller and scorer) for my next blog post being developed in my new favorite IDE :-)

Netbeans_wjavafxplugin_2

The compiled JavaFX Script plug-in is built in the same continuous build that compiled JavaFX Script is, so updates will be available frequently.  To get both NetBeans 6.1 beta and the compiled JavaFX Script plug-in, visit the OpenJFX Community site and check for the JavaFX Script Plugin Daily Builds Available news item.

Enjoy!
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications

Immediate eBook (PDF) download available at the book's Apress site

March 22, 2008

Roll the Dice - A Compiled JavaFX Script Example

I'm on my way to Vegas to speak at The Server Side Java Symposium, so in keeping with that theme I wanted to create a simple dice program as today's example.  When you click the Roll button, random values appear on the dice.  Here's a screenshot of this application:

Dice

GameMain.fx

/*
 *  GameMain.fx - 
 *  A compiled JavaFX program that demonstrates creating custom
 *  components with CompositeNode
 * 
 *
 *  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
 *  to serve as a JavaFX Script example.
 */

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.System;

Frame {
  var model = GameModel {}
  width: 210
  height: 170
  title: "Dice"
  background: Color.WHITE
  content: 
    BorderPanel {
      center:
        Canvas {
          content:
            for (diceNum in [0 .. model.numDice - 1]) {
              model.newDice =
              Dice {
                x: diceNum * 100 + 10
                y: 10
                width: 80
                height: 80
                faceColor: Color.RED
                pipColor: Color.WHITE
              }
            }
        }
      bottom:
        FlowPanel {
          content:
            Button {
              text: "Roll"
              defaultButton: true
              action:
                function():Void {
                  model.roll();
                }
            }
        }
    } 
  visible: true
  onClose:
    function():Void {
      System.exit(0);
    }
}

Dice.fx

/*
 *  Dice.fx - 
 *  A compiled JavaFX program that demonstrates creating custom
 *  components with CompositeNode
 * 
 *
 *  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
 *  to serve as a JavaFX Script example.
 */

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.Math;
import java.lang.System;

public class Dice extends CompositeNode {
  public attribute value:Integer = 5;
  public attribute x:Integer;
  public attribute y:Integer;
  public attribute width:Integer;
  public attribute height:Integer;
  public attribute faceColor:Color;
  public attribute pipColor:Color;
  
  attribute pipPlace:PipPlacement[];
  
  postinit {
    insert
      PipPlacement {
        pipLocsX: [
          .5, 0, 0, 0, 0, 0
        ]
        pipLocsY: [
          .5, 0, 0, 0, 0, 0
        ]
      }
      into pipPlace;
    insert
      PipPlacement {
        pipLocsX: [
          0.3, 0.7, 0, 0, 0, 0
        ]
        pipLocsY: [
          0.7, 0.3, 0, 0, 0, 0
        ]
      }
      into pipPlace;
    insert
      PipPlacement {
        pipLocsX: [
          0.2, 0.5, 0.8, 0, 0, 0
        ]
        pipLocsY: [
          0.8, 0.5, 0.2, 0, 0, 0
        ]
      }
      into pipPlace;
    insert
      PipPlacement {
        pipLocsX: [
          0.25, 0.25, 0.75, 0.75, 0, 0
        ]
        pipLocsY: [
          0.25, 0.75, 0.25, 0.75, 0, 0
        ]
      }
      into pipPlace;
    insert
      PipPlacement {
        pipLocsX: [
          0.2, 0.5, 0.8, 0.8, 0.2, 0
        ]
        pipLocsY: [
          0.8, 0.5, 0.2, 0.8, 0.2, 0
        ]
      }
      into pipPlace;
    insert
      PipPlacement {
        pipLocsX: [
          0.3, 0.3, 0.3, 0.7, 0.7, 0.7
        ]
        pipLocsY: [
          0.8, 0.5, 0.2, 0.8, 0.5, 0.2
        ]
      }
      into pipPlace;
  } 
    
  public function roll():Void {
    value = (Math.random() * 6 + 1) as Integer;
  }
  
  public function composeNode():Node {
    Group {
      transform: bind [
        Translate.translate(x, y)
      ]
      content: bind [
        Rect {
          x: 0
          y: 0
          width: this.width;
          height: this.height;
          fill: faceColor
        },
        for (pipIdx in [0 .. value-1]) {
          Circle {
            cx: bind pipPlace[value - 1].pipLocsX[pipIdx] * width
            cy: bind pipPlace[value - 1].pipLocsY[pipIdx] * height
            radius: width * .1
            fill: pipColor
          }
        }
      ]  
    }
  }
}

GameModel.fx

/*
 *  GameModel.fx - 
 *  The model behind the dice game
 *
 *  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
 *  to serve as a JavaFX Script example.
 */

class GameModel {
  attribute numDice:Integer = 2;
  attribute newDice:Dice on replace {
    insert newDice into dice;
  }
  attribute dice:Dice[];
  
  function roll():Void {
    for (die in dice) {
      die.roll();
    }
  }
}


PipPlacement.fx

/*
 *  PipPlacement.fx - 
 *  The placement of the pips on a dice
 *
 *  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
 *  to serve as a JavaFX Script example.
 */

public class PipPlacement {
  public attribute pipLocsX:Number[];
  public attribute pipLocsY:Number[];
}

Good luck!
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications

Immediate eBook (PDF) download available at the book's Apress site

March 19, 2008

A JavaFX Script Calendar that Displays a Google Calendar Feed

Today I'd like to show you the humble beginnings of a JavaFX Script calendar that displays a Google Calendar feed.  It is currently pointing to my Google Calendar, which I've sparsely populated with some sample data.  You can change the program to point to your Google Calendar if you choose. 

I'll improve this Calendar program over time, but wanted to demonstrate JavaFX Script's ability to easily parse an XML stream over the Internet.  You may also want to take a look at the Compiled JavaFX Script Now Speaks JSON post which demonstrates parsing JSON streams over the Internet.  Here's a screenshot of today's example, followed by the program's code:

Calendarjfx


The Code Behind the User Interface

Obviously there are many improvements that I can make to this calendar, but here are the four source files that comprise this example in its current state:


CalendarJFX.fx

/*
*  CalendarJFX.fx -
*  The main program for a compiled JavaFX calendar program
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a compiled JavaFX Script example.
*/

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.System;

Frame {
  var calModel =
    CalendarModel {}
  title: "CalendarJFX"
  width: 600
  height: 600
  visible: true
  content:
    BorderPanel {
      top:
        BorderPanel {
          left:
            FlowPanel {
              content: [
                Button {
                  text: "<<"
                  action:
                    function():Void {
                      calModel.prevYear();
                    }
                },
                Button {
                  text: "<"
                  action:
                    function():Void {
                      calModel.prevMonth();
                    }
                }
              ]
            }
          center:
            FlowPanel {
              content:
                SimpleLabel {
                  text: bind "{calModel.selectedMonthStr} {calModel.selectedYearStr}"
                  font:
                    Font {
                      size: 24
                      style: FontStyle.BOLD
                    }
                }
            }
          right:
            FlowPanel {
              content: [
                Button {
                  text: ">"
                  action:
                    function():Void {
                      calModel.nextMonth();
                    }
                },
                Button {
                  text: ">>"
                  action:
                    function():Void {
                      calModel.nextYear();
                    }
                }
              ]
            }
          bottom:
            GridPanel {
              // TODO: Internationalize days of the week
              var days = ["Sun", "Mon", "Tue",
                          "Wed", "Thu", "Fri", "Sat"]
              rows: 1
              columns: 7
              cells:
                for (day in days) {
                  SimpleLabel {
                    text: day
                    font:
                      Font {
                        size: 18
                        style: FontStyle.BOLD
                      }
                    horizontalAlignment:
                      HorizontalAlignment.CENTER
                  }
                }
            }
        }
      center:
        GridPanel {
          vgap: 1
          hgap: 1
          rows: 6
          columns: 7
          cells:
            for (idx in [1..42]) {
              CalendarCell {
                calModel: calModel
                dayOfMonthStr: bind calModel.getDayInMonthStrForCell(idx as Integer);
                cellGregCal: bind calModel.getDateForCell(idx as Integer);
              }
            }
        }
    }
  onClose:
    function():Void {
      System.exit(0);
    } 
}


CalendarCell.fx

/*
*  CalendarCell.fx -
*  The UI for an individual cell (day) in the calendar
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a compiled JavaFX Script example.
*/

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.System;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

public class CalendarCell extends CompositeWidget {
  public attribute calModel:CalendarModel;
  attribute dayInMonthFmt = new SimpleDateFormat("d");
  public attribute cellGregCal:GregorianCalendar;
  public attribute dayOfMonthStr:String;

  public function composeWidget():Widget {
    BorderPanel {
      top:
        FlowPanel {
          background: Color.LIGHTBLUE
          alignment: Alignment.TRAILING
          content: [
            SimpleLabel {
              text: bind dayOfMonthStr
              font:
                Font {
                  size: 12
                  style: FontStyle.BOLD
                }
            }
          ]
        }
      center:
        Box {
          orientation: Orientation.VERTICAL
          content: bind
            for (calEntry in calModel.calEntries
              where cellGregCal.get(Calendar.YEAR) ==
                    calEntry.startTime.get(Calendar.YEAR) and
                    cellGregCal.get(Calendar.MONTH) ==
                    calEntry.startTime.get(Calendar.MONTH) and
                    cellGregCal.get(Calendar.DAY_OF_MONTH) ==
                    calEntry.startTime.get(Calendar.DAY_OF_MONTH)) {
              SimpleLabel {
                text: calEntry.title
              }
            }
        }
    }
  }
}


CalendarModel.fx

/*
*  CalendarModel.fx -
*  The model behind a compiled JavaFX calendar program
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a compiled JavaFX Script example.
*/

import javafx.xml.*;
import java.text.SimpleDateFormat;
import java.lang.System;
import java.util.Calendar;
import java.util.GregorianCalendar;

class CalendarModel {
  attribute calendarFeedURI =
    "http://www.google.com/calendar/feeds/james.l.weaver%40gmail.com/public/full";
  attribute docBuilder =
    DocumentBuilder {
      namespaceAware:true
      validating:true
      ignoringComments:false
    };
  attribute document =
    docBuilder.parseURI(calendarFeedURI);
  attribute calEntries:CalendarEntry[];
  attribute selectedGregCal:GregorianCalendar = new GregorianCalendar();
  attribute utilGregCal:GregorianCalendar = new GregorianCalendar();
  attribute selectedMonth:Integer;
  attribute selectedYear:Integer;
  attribute dayInMonthFmt = new SimpleDateFormat("d");
  attribute monthFmt = new SimpleDateFormat("MMMM");
  attribute yearFmt = new SimpleDateFormat("yyyy");
  attribute cellNumber:Integer;
  attribute selectedDayInMonthStr:String;
  attribute selectedMonthStr:String;
  attribute selectedYearStr:String;
 
  postinit {
    var calElements = document.getElementsByTagName("entry");
    calEntries = for (calElement in calElements)
      CalendarEntry {
        title: calElement.queryString("title")
        startTimeStr: calElement.queryString("when/@startTime")
        endTimeStr: calElement.queryString("when/@endTime")
        location: calElement.queryString("where/@valueString")
      };
    populateDateParts();
  }
 
  function prevMonth():Void {
    selectedGregCal.add(Calendar.MONTH, -1);
    selectedMonth = selectedGregCal.get(Calendar.MONTH);
    populateDateParts();
  }

  function nextMonth():Void {
    selectedGregCal.add(Calendar.MONTH, 1);
    selectedMonth = selectedGregCal.get(Calendar.MONTH);
    populateDateParts();
  }

  function prevYear():Void {
    selectedGregCal.add(Calendar.YEAR, -1);
    selectedYear = selectedGregCal.get(Calendar.YEAR);
    populateDateParts();
  }

  function nextYear():Void {
    selectedGregCal.add(Calendar.YEAR, 1);
    selectedYear = selectedGregCal.get(Calendar.YEAR);
    populateDateParts();
  }

  function populateDateParts():Void {
    var selDate = selectedGregCal.getTime();
    selectedDayInMonthStr = dayInMonthFmt.format(selDate);
    selectedMonthStr = monthFmt.format(selDate);
    selectedYearStr = yearFmt.format(selDate);
  }
 
  function getDateForCell(cellNumber:Integer):GregorianCalendar {
    utilGregCal.set(Calendar.YEAR, selectedYear);
    utilGregCal.set(Calendar.MONTH, selectedMonth);
    utilGregCal.set(Calendar.DAY_OF_MONTH, 1);
    var firstDayOffset = utilGregCal.get(Calendar.DAY_OF_WEEK);
    utilGregCal.add(Calendar.DAY_OF_MONTH, firstDayOffset * -1 + cellNumber);
    return utilGregCal;
  }

  function getDayInMonthStrForCell(cellNumber:Integer):String {
    utilGregCal.set(Calendar.YEAR, selectedYear);
    utilGregCal.set(Calendar.MONTH, selectedMonth);
    utilGregCal.set(Calendar.DAY_OF_MONTH, 1);
    var firstDayOffset = utilGregCal.get(Calendar.DAY_OF_WEEK);
    utilGregCal.add(Calendar.DAY_OF_MONTH, firstDayOffset * -1 + cellNumber);
    dayInMonthFmt.format(utilGregCal.getTime());
  }
}


CalendarEntry.fx

/*
*  CalendarEntry.fx -
*  A calendar entry, which is part of the model.
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a compiled JavaFX Script example.
*/

import java.lang.System;
import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.Calendar;
import java.util.Date;

class CalendarEntry {
  private attribute sdf = new SimpleDateFormat
      ("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
  attribute title:String;
  attribute startTime:Calendar;
  attribute endTime:Calendar;
  attribute startTimeStr:String on replace {
    //TODO: Accommodate all-day events
    var d:Date = sdf.parse("{startTimeStr.substring(0, 26)}{startTimeStr.substring(27)}");
    var cal:Calendar = Calendar.getInstance();
    cal.setTime(d);
    startTime = cal;
  };
  attribute endTimeStr:String on replace {
    var d:Date = sdf.parse("{endTimeStr.substring(0, 26)}{endTimeStr.substring(27)}");
    var cal:Calendar = Calendar.getInstance();
    cal.setTime(d);
    endTime = cal;
  };
  attribute location:String;
}

Enjoy, and as always, please post a comment if you have any questions.

Regards,
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications

Immediate eBook (PDF) download available at the book's Apress site

March 18, 2008

JavaFXOne is Going to Rock! (JavaFX Sessions at JavaOne 2008)

I'm getting excited about presenting at, and attending, JavaOne this year.  There will be lots of JavaFX sessions that show how far JavaFX has come in one year, as well as (hopefully) disclosing some closely guarded plans for the future.

Javafxone

For your convenience, I did a search on JavaFX sessions at the JavaOne 2008 Conference Catalog site, which returned the following sessions:

TS-5152
Overview of the JavaFX™ Script Programming Language Technical Session Christopher Oliver, Sun Microsystems, Inc.
TS-6271
Java™ Platform, Standard Edition: A Youthful Maturity Technical Session Danny Coward, Sun Microsystems, Inc.
TS-4794
A JavaFX™ Script Programming Language Tutorial Technical Session James Weaver, LAT
TS-5138
The JavaFX™ Platform: Sexy Interfaces For Mere Mortals Technical Session Joshua Smith, Aerospace & Defense
TS-6290
Applets Reloaded: Introducing the Next-Generation Java™ Plug-in Technology Technical Session Sven Gothel, Sun Microsystems, Inc.; Kenneth Russell, Sun Microsystems, Inc.
PAN-7372
Case Studies from the JavaFX™ Technology World Panel Session Erik Hellman, IBS JavaSolutions AB; Jeff Martin, ReportMill Software, Inc.; Raghavan Srinivas, Sun Microsystems, Inc.; Jo Voordeckers, Dolmen/JCS
TS-6610
Inside The JavaFX™ Script Technology-Based Runtime APIs: Scene Graph & WebKit Technical Session Igor Kushnirskiy, Sun Microsystems, Inc.; Hans Muller, Sun Microsystems, Inc.
TS-7051
JavaFX™ Mobile Platform Architecture and APIs Technical Session Craig Newell, Sun Microsystems, Inc.; Noel Poore, Sun Microsystems, Inc.
BOF-5804
Meet with the JavaFX™ Tools Team Birds-of-a-Feather Session (BOF) Nandini Ramani, Sun Microsystems, Inc.; Gerard Ziemski, Sun Microsystems, Inc.
BOF-6511
The Java™ Media Components API BOF Birds-of-a-Feather Session (BOF) Brian Burkhalter, Sun Microsystems, Inc.; Tony Wyant, Sun Microsystems, Inc.
BOF-5936
Meet the Java 2D™ API Graphics and Java Advanced Imaging Team Birds-of-a-Feather Session (BOF) Jim Graham, Sun Microsystems; Phil Race, Sun Microsystems, Inc.
BOF-5965
3-D Graphics APIs for the Java™ and JavaFX™ Platforms Birds-of-a-Feather Session (BOF) Kevin Rushforth, Sun Microsystems, Inc.; Chien Yang, Sun Microsystems Inc
TS-5449
Java™ Technology for Blu-ray and TV: Authoring for Performance Diversity Technical Session Bill Foote, Sun Microsystems, Inc.
TS-5968
JavaFX™ Platform Tools Strategy and Direction Technical Session Martin Ryzl, Sun Microsystems, Inc.; Param Singh, Sun Microsystems, Inc.
TS-5815
Going Mobile with JavaFX™ Script Technology, Groovy, and Google Android Technical Session Dierk König, Canoo Engineering AG; Mike Mannion, Canoo Engineering AG
TS-6019
A Look into Development for the JavaFX™ Mobile/TV Platform with the NetBeans™ IDE Technical Session Petr Suchomel, Sun Microsystems, Inc.
TS-6074
High-Performance Graphics for Mobile Devices Technical Session Pavel Petroshenko, Sun Microsystems, Inc.; Oleg Pliss, Sun Microsystems, Inc.
TS-6609
Using JavaFX™ Script To Build Swing Applications Technical Session Amy Fowler, Sun Microsystems, Inc.; Hans Muller, Sun Microsystems, Inc.
TS-6213
Boldly Go Where the Java™ Programming Language Has Never Gone Before Technical Session Geert Bevin, Terracotta
TS-6509
Incorporating Media into JavaFX™ and Java™ Technology-Based Applications Technical Session Marc Owerfeldt, Sun Microsystems, Inc.; Tony Wyant, Sun Microsystems, Inc.
BOF-5501
Java™ Champions BOF: The Latest Buzz, Highlights, and Panel Discussion Birds-of-a-Feather Session (BOF) Calvin Austin, SpikeSource, Inc.; Aaron Houston, Sun Microsystems, Inc.; Manfred Riem, Java Champion
BOF-5992
How to Build RESTful Clients with the JavaScript™, Ruby, and JavaFX™ Programming Languages Birds-of-a-Feather Session (BOF) Ayub Khan, Sun Microsystems, Inc.; Samaresh Panda, Sun Microsystems, Inc.
BOF-4798
Parleys.com: An Adobe Flex/AIR and JavaFX™ Case Study Birds-of-a-Feather Session (BOF) Stephan Janssen, BeJUG
BOF-5506
JavaFX™ TV Platform Overview Birds-of-a-Feather Session (BOF) Bartley Calder, Sun Microsystems, Inc.
TS-6127
Build Your Own Multitouch Interface with Java™ and JavaFX™ Technology Technical Session Angela Caicedo, Sun Microsystems, Inc.; Simon Ritter, Sun Microsystems, Inc.
TS-6656
Extreme GUI Makeover: Swing Meets FX Technical Session Christopher Campbell, Sun Microsystems, Inc.; Shannon Hickey, Sun Microsystems, Inc.
TS-5657
JavaFX™ Technology: Bring the Web with You--Multiple Interfaces to Games, Chat, and More Technical Session Joshua Marinacci, Sun Microsystems, Inc.; Anthony Rogers, Sun Microsystems
TS-5349
So Many Faces: Web 2.0 XD Experience with JavaServer™ Faces and JavaFX™ Technology, Flex, and Windows Presentation Foundation Technical Session Ray Lai, Intuit; George Mount, nVidia
LAB-7350
JavaFX™ Technology-Based Applications: Rich Client Applications with Cool Effects Hands-On Lab Sridhar Reddy, Sun Microsystems Inc; Raghavan Srinivas, Sun Microsystems, Inc.

In addition to the JavaFX Technical Session above, I'll be teaching a University session on JavaFX Script with Sang Shin on Monday, May 5th (Java University Day).  If you attend one of my sessions, please introduce yourself!

Indicthreads_3 Also, you might check out a JavaFX interview that Harshad Oak of IndicThreads.com conducted with me.  IndicThreads.com is a great resource for developers, and I really appreciated Harshad's professionalism and expertise.

Regards,
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications

Immediate eBook (PDF) download available at the book's Apress site

March 15, 2008

Me and You and a Dog Named Boo - Oh, Not *that* Lobo?

I suppose that I need to explain the title of this post.  Lobo is a singer/songwriter from the 70's that was well-known for several songs, including "Me and You and a Dog Named Boo".  Lobo also means "wolf" in Spanish.  Now, thanks to Jose Solorzano and crew, Lobo is an extensible, pure Java web browser that is capable of rendering links that contain JavaFX (and Java) source code files.  Jose contacted me a couple of days ago about using the code from one of my "Creating a Tetris Program in Compiled JavaFX Script" articles for demonstration purposes.  Here's a screenshot of the partially baked Tetris game running in the Lobo Browser:

Lobotetris

One nice thing about this approach is that the developer doesn't have to compile the JavaFX Script source files.  Rather, the Lobo browser recognizes them as JavaFX Script files, and immediately compiles and runs them.  The Lobo browser download comes with a recent version of the javafxrt.jar, javafxc.jar, and Scenario JAR files, which you may recognize from previous posts as necessary to compile and run compiled JavaFX Script files.  For more information on the Lobo browser, see Geertjan Wielenga's latest JavaLobby post on the subject, and check out the Lobo browser website.  After installing and running the Lobo browser, navigate to the http://www.lobobrowser.org/ext/jfx/TetrisMain.fx URL, and watch it automatically render the JavaFX Script code in that URL.  Nice work, Jose!

Regards,
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications

Immediate eBook (PDF) download available at the book's Apress site

March 14, 2008

A Compiled JavaFX Script Playground - The Assortis Demo

Today I'd like to call your attention to a new compiled JavaFX Script demo, named JavaFX Assortis, from the JavaFX Script compiler team.  It's purpose is to enable you to experiment with and learn about various JavaFX Script UI features.  It is my understanding that Assortis means "sampler", or "assortment" in French, kind of like a box of chocolates (I'll spare you the Forrest Gump reference, by the way).  Anyway, here's a screenshot of JavaFX Assortis:

Assortisdemo

From the panes on the left side you can choose to work with Nodes (graphical objects like Circle), Widgets (UI objects like CheckBox), or come cool samples (like the animated Planetary System shown above).  You can then work with your selected objects in the right panes, altering the code to see the effects.

How can you get access to this demo, you ask?  Just download and build the OpenJFX Compiler, navigate to the demos/JavaFXAssortis directory, and run the following command from the command-line:

ant run

This will cause this demo to be built (if necessary) and executed.  It's a great way to get up to speed quickly on using some of the UI features of JavaFX Script.

Regards,
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications

Immediate eBook (PDF) download available at the book's Apress site

March 10, 2008

Creating Compiled JavaFX Script Applets - Method Two

Important Note:  As of the JavaFX SDK Preview, this article is technically outdated.  Please see the Using the Java Deployment Toolkit with JavaFX Applets article for an updated example of creating and deploying JavaFX Applets.

In the previous post, I showed you one of the two ways that the JavaFX Script compiler team has provided for creating compiled JavaFX Script applets.  Today's example program demonstrates the second of these ways, by converting the Binding to a Function example into a compiled JavaFX Script applet.   Here's a screenshot of the JavaFX Script applet, running in Firefox 3:

Bindtofunctionapplet2

This method of creating a compiled JavaFX Script applet is more "JavaFX-like" than the method that I showed you in the previous post.  Using this approach, we:

  • Declaratively express the JavaFX applet using the Applet object as the top level (see BindToFunctionApplet2.fx below).
  • Assign javafx.ui.Applet to the code attribute of the applet element in the HTML file (see BindToFunctionAppletPage2.html below).
  • Specify an AppletClass parameter with the name of the class in which the applet is expressed (in this case BindToFunctionApplet2, see the HTML file below). 

Also, this approach requires that the applet be signed, so in this post I'm going to walk you through the process of creating a JAR file that contains the applet classes, and signing each of the JAR files.

Compare the following code with the Binding to a Function example, the major difference being the absence of the Frame object. It isn't required since the applet provides its own UI container.

/*
*  BindToFunctionApplet2.fx - A compiled JavaFX program that demonstrates
*                             a "JavaFX-like" way of creating compiled JavaFX applets.
*                             It also demonstrates binding to a function.
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a JavaFX Script example.
*/

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.Math;
import java.lang.System;

class CircleModel {
  attribute diameter:Number;
 
  function getArea():Number {
    Math.PI * Math.pow(diameter / 2, 2);
  }
}

Applet {
  var cModel = CircleModel {}
  content:
    BorderPanel {
      center:
        Canvas {
          content: [
            Circle {
              cx: 240
              cy: 250
              radius: bind cModel.diameter * 2
              stroke: Color.PURPLE
              strokeWidth: 1
              fill: Color.MAGENTA
            },
            Text {
              font:
                Font {
                  face: FontFace.SANSSERIF
                  style: FontStyle.BOLD
                  size: 24
                }
              x: 20
              y: 10
              stroke: Color.RED
              fill: Color.RED
              content: bind "Diameter: {cModel.diameter}"
            },
            Text {
              font:
                Font {
                  face: FontFace.SANSSERIF
                  style: FontStyle.BOLD
                  size: 24
                }
              x: 240
              y: 10
              stroke: Color.RED
              fill: Color.RED
              content: bind "Area: {%3.2f cModel.getArea()}"
            }
          ]
        }
      bottom:
        Slider {
          min: 0
          max: 100
          border:
            TitledBorder {
              title: "Diameter:"
            }
          value: bind cModel.diameter with inverse
          minorTickSpacing: 5
          majorTickSpacing: 10
          paintTicks: true
          paintLabels: true
          labels: [
            SliderLabel {
              value: 0
              label:
                SimpleLabel {
                  text: "0"
                }
            },
            SliderLabel {
              value: 50
              label:
                SimpleLabel {
                  text: "50"
                }
            },
            SliderLabel {
              value: 100
              label:
                SimpleLabel {
                  text: "100"
                }
            }
          ]
        }
    }
}

Supplying an HTML File to Run the Applet

Here is the HTML file (that I've named BindToFunctionAppletPage2.html) that runs the applet:

<html>
  <body>
    <applet code="javafx.ui.Applet" width=480 height=560
     archive="javafxrt.jar,Scenario.jar,BindToFunctionApplet2.jar">
        <param name="AppletClass" value="BindToFunctionApplet2">
    </applet>
  </body>
</html>

You'll need to put the JAR files (shown in the archive tag above) in the same directory as the HTML file. You can get these files from the compiler download in the dist/lib directory.  To compile this applet, I used the -target parameter so that it will run within browsers that have JRE 5 or later:

javafxc -target 1.5 BindToFunctionApplet2.fx

As I mentioned previously, you'll need to create a JAR file that contains the class files for this applet.  To do this, I used the following command at my operating system prompt:

jar cvf BindToFunctionApplet2.jar BindToFunctionApplet2*.class

You'll also need to sign the JAR file that contains the applet classes, as well as the javafxrt.jar and Scenario.jar files.  To do this, you'll need a signature key, which you can create with the following command:

keytool -genkey -alias jfx -dname "CN=John Doe, O=JFX Inc." (continued on next line)
  -validity 9999 -keystore jfx.keystore -keypass keyPassword -storepass storePassword

Use the following commands to sign the JAR files:

jarsigner -keystore jfx.keystore -verbose -keypass keyPassword (continued on next line) 
 
-storepass storePassword BindToFunctionApplet2.jar jfx
jarsigner -keystore jfx.keystore -verbose -keypass keyPassword (continued on next line)
 
-storepass storePassword javafxrt.jar jfx
jarsigner -keystore jfx.keystore -verbose -keypass keyPassword (continued on next line)
 
-storepass storePassword Scenario.jar jfx

To execute this compiled JavaFX Script applet, either open the BindToFunctionAppletPage2.html file in a browser, or use appletviewer as shown below:

appletviewer BindToFunctionAppletPage2.html

Enjoy, and please post a comment if you have any questions!

Regards,
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications

Immediate eBook (PDF) download available at the book's Apress site

March 09, 2008

Creating Compiled JavaFX Applets - Method One (of Two)

Important Note:  As of the JavaFX SDK Preview, this article is technically outdated.  Please see the Using the Java Deployment Toolkit with JavaFX Applets article for an updated example of creating and deploying JavaFX Applets.

The JavaFX Script compiler team has provided two ways of creating compiled JavaFX Script applets.  Today's example program demonstrates one of these ways, by converting the Binding to a Function example into a compiled JavaFX Script applet.   Here's a screenshot of the JavaFX Script applet, running in Firefox 3:

Bindtofunctionapplet1

This way of creating a JavaFX Applet is more "Java-like" in that it uses the approach of extending the javafx.ui.Applet class.  Notice that it overrides a couple of applet life-cycle functions to demonstrate that ability.  Compare the following code with the Binding to a Function  example, the major difference being the absence of the Frame object.  It isn't required since the applet provides its own UI container.

/*
*  BindToFunctionApplet1.fx - A compiled JavaFX program that demonstrates
*                             one way of creating compiled JavaFX applets.
*                             It also demonstrates binding to a function.
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a JavaFX Script example.
*/

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.Math;
import java.lang.System;

public class BindToFunctionApplet1 extends Applet {
  public function start(): Void {
    System.out.println("BindToFunctionApplet1.start()");
  }
  public function stop(): Void {
    System.out.println("BindToFunctionApplet1.stop()");
  }
}

class CircleModel {
  attribute diameter:Number;
 
  function getArea():Number {
    Math.PI * Math.pow(diameter / 2, 2);
  }
}

BorderPanel {
  var cModel = CircleModel {}
  background: Color.WHITE
  center:
    Canvas {
      content: [
        Circle {
          cx: 240
          cy: 250
          radius: bind cModel.diameter * 2
          stroke: Color.PURPLE
          strokeWidth: 1
          fill: Color.CYAN
        },
        Text {
          font:
            Font {
              face: FontFace.SANSSERIF
              style: FontStyle.BOLD
              size: 24
            }
          x: 20
          y: 10
          stroke: Color.RED
          fill: Color.RED
          content: bind "Diameter: {cModel.diameter}"
        },
        Text {
          font:
            Font {
              face: FontFace.SANSSERIF
              style: FontStyle.BOLD
              size: 24
            }
          x: 240
          y: 10
          stroke: Color.RED
          fill: Color.RED
          content: bind "Area: {%3.2f cModel.getArea()}"
        }
      ]
    }
  bottom:
    Slider {
      min: 0
      max: 100
      border:
        TitledBorder {
          title: "Diameter:"
        }
      value: bind cModel.diameter with inverse
      minorTickSpacing: 5
      majorTickSpacing: 10
      paintTicks: true
      paintLabels: true
      labels: [
        SliderLabel {
          value: 0
          label:
            SimpleLabel {
              text: "0"
            }
        },
        SliderLabel {
          value: 50
          label:
            SimpleLabel {
              text: "50"
            }
        },
        SliderLabel {
          value: 100
          label:
            SimpleLabel {
              text: "100"
            }
        }
      ]
    }
}

Supplying an HTML File to Run the Applet

Here is the HTML file (that I've named BindToFunctionAppletPage1.html) that runs the applet:

<html>
  <body>
    <applet code="BindToFunctionApplet1"
            width=480 height=560
     archive="javafxrt.jar, Scenario.jar">
    </applet>
  </body>
</html>

You'll need to put the JAR files (shown in the archive tag above) in the same directory as the HTML file. You can get these files from the compiler download in the dist/lib directory.  To compile this applet, I used the -target parameter so that it will run within browsers that have JRE 5 or later:

javafxc -target 1.5 BindToFunctionApplet1.fx

To execute this compiled JavaFX Script applet, either open the BindToFunctionAppletPage1.html file in a browser, or use appletviewer as shown below:

appletviewer BindToFunctionAppletPage1.html

Enjoy, and please post a comment if you have any questions!  The next post will cover the other way of creating compiled JavaFX Script applets.

Regards,
Jim Weaver
JavaFX Script: Dynamic Java Scripting for Rich Internet/Client-side Applications

Immediate eBook (PDF) download available at the book's Apress site

March 06, 2008

Really This Time - Part Three of Creating Tetris in Compiled JavaFX Script

As I mentioned in the previous post (which I accidentally published prematurely), I've been speaking on JavaFX Script at Sun Tech Days in Sydney, Australia.  This was a great experience, as it was a well-run, informative conference.   Of course, Sydney is a beautiful city, filled with wonderful people.

Tetrisstacking_2

Also, that post referenced the first two articles in this Tetris series, so please take a look at these articles to get up to speed on where we're at:

1) Let's Create a Tetris Game in Compiled JavaFX Script

2) Creating a Tetris Program (Part Two) in Compiled JavaFX Script

During the conference, I've made some progress on the Tetris application, and used it in one of my presentations.  Please refer to the screenshot shown above.

This version of the Tetris application is not 100% functional, nor is it bug-free, but it did suffice for teaching JavaFX Script concepts in the presentation.  One of my next posts will be a more fully functioning Tetris game (e.g. a layer of blocks will disappear when filled).  That post will show this game as a JavaFX Script applet, running inside a browser.  Take a look at the source code below, and you'll notice that I've changed quite a few things from the last version.  For example, the TetrisPlayingField custom component is bound to the model of all of squares in the playing field.

TetrisMain.fx:

/*
*  TetrisMain.fx - The main program for a compiled JavaFX Script Tetris game
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a compiled JavaFX Script example.
*/
package tetris_ui;

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.System;
import tetris_model.*;

Frame {
  var canvas:Canvas
  width: 350
  height: 500
  title: "TetrisJFX"
  background: Color.LIGHTGREY
  content:
    StackPanel {
      content: [
        Canvas {
          content:
            ImageView {
              image:
                Image {
                  url: "images/background.jpg"
                }
            }
        },
        BorderPanel {
          var model =
            TetrisModel {}
          center:
            FlowPanel {
              alignment: Alignment.LEADING
              vgap: 20
              hgap: 20
              content: [
                Canvas {
                  content:
                    TetrisPlayingField {
                      model: model
                    }
                },
                Label {
                  text: bind "<html><font color=#B0E0E6 size=24>
                              {model.score}</font></html>"
                }
              ]
            }
          bottom:
            FlowPanel {
              alignment: Alignment.LEADING
              content: [
                Button {
                  text: "Play"
                  foreground: Color.DARKBLUE
                  action:
                    function() {
                      model.t.start();
                    }
                },
                Button {
                  text: "Rotate"
                  foreground: Color.DARKBLUE
                  action:
                    function() {
                      model.rotate90();
                    }
                },
                Button {
                  text: "Left"
                  foreground: Color.DARKBLUE
                  action:
                    function() {
                      model.moveLeft();
                    }
                },
                Button {
                  text: "Right"
                  foreground: Color.DARKBLUE
                  action:
                    function() {
                      model.moveRight();
                    }
                }
              ]
            }
        }
      ]
    }
  visible: true
  onClose:
    function():Void {
      System.exit(0);
    }
}

TetrisPlayingField.fx:

/*
*  TetrisPlayingField.fx -
*  A custom graphical component that is the UI for the
*  playing field.
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a compiled JavaFX Script example.

*/
package tetris_ui;

import javafx.ui.*;
import javafx.ui.canvas.*;
import java.lang.System;
import tetris_model.*;

class TetrisPlayingField extends CompositeNode {
  private static attribute squareOutlineColor = Color.BLACK;
  private static attribute squareOutlineWidth = 1;
  public attribute model:TetrisModel;
  public function composeNode():Node {
    Group {
      content: bind [
        Rect {
          x: 0
          y: 0
          width: model.NUM_COLS * model.SQUARE_SIZE
          height: model.NUM_ROWS * model.SQUARE_SIZE
          strokeWidth: 1
          stroke: Color.BLACK
          fill: Color.BLUE
          opacity: .5
        },
        for (cell in model.fieldCells
               where cell <> TetrisShapeType.NONE) {
          Rect {
            var yPos:Integer = indexof cell / model.NUM_COLS
            x: (indexof cell % model.NUM_COLS).intValue() * model.SQUARE_SIZE
            y: yPos * model.SQUARE_SIZE
            width: model.SQUARE_SIZE
            height: model.SQUARE_SIZE
            fill: cell.squareColor
            stroke: squareOutlineColor
            strokeWidth: squareOutlineWidth
          }
        }
      ]
    }
  }
}

TetrisModel.fx:

/*
*  TetrisModel.fx - The model behind the Tetris UI
*
*  Developed 2008 by James L. Weaver (jim.weaver at lat-inc.com)
*  to serve as a compiled JavaFX Script example.

*/
package tetris_model;

import javafx.ui.animation.*;
import java.lang.System;
import com.sun.javafx.runtime.PointerFactory;
import java.lang.Double;

public class TetrisModel {
  /** Size of each tetromino in pixels */
  public static attribute SQUARE_SIZE = 20;
 
  /** Number of rows in the playing field */
  public static attribute NUM_ROWS = 20;
 
  /** Number of columns in the playing field */
  public static attribute NUM_COLS = 10;
 
  private attribute stopDropping:Boolean;

  /**
   * Sequence of objects that represent the
   * type of shapes (including no shape) in each playing field cell
   */
  public attribute fieldCells:TetrisShapeType[] =
    for (i in [1..(NUM_ROWS * NUM_COLS)]) {
      TetrisShapeType.NONE;
    };
      
 
  /**
   * The active tetromino shape type.
   */
  public attribute activeShapeType:TetrisShapeType;
 
  public attribute score:Integer = 10000;
 
  /**
   * This value is incremented via the KeyFrame animation mechanism,
   * and represents the row in which the pivotal block is currently residing.
   */
  public attribute a:Integer on replace (oldVal) {
    if (a == 0) {
      stopDropping = false;
    }
    if (not stopDropping) {
      // Update score. TODO: Implement real scoring later