Latest Eclipse Plugin for JavaFX 1.2.1

Posted: under JavaFX News, JavaFX Technology.
Tags: , , ,

Last week, the Eclipse plugin for JavaFX 1.2.1 was released. This is an important update since June 2009 and it is a good news to Eclipse users. Because Sun is the development force behind NetBeans, NetBeans naturally becomes the “default” IDE of JavaFX. This is why JavaFX SDK is usually bundled with NetBeans for download.


I think Eclipse and NetBeans both are excellent open source IDEs for Java developers. They provide comparable features and functions. The only sad thing is that their plug-ins are not compatible with each other. Therefore, the JavaFX plug-ins must be developed separately for Eclipse and NetBeans. I personally do not have much preference from one over the other. For people who get used to the Eclipse environment have been longing for a nice JavaFX IDE without being forced to switch to NetBeans. This newly released JavaFX plug-in not only provides the support of the latest SDK 1.2.1, but also can import NetBeans projects directly. You know this helps a lot because many sample codes are coming as a NetBeans project.


If you are a fan of Eclipse( and javaFX ), you should definitely check out this plug-in here:


http://javafx.com/docs/gettingstarted/eclipse-plugin/release-notes.jsp


Other links:

JavaFX Used in Vancouver Olympics

UK Citizenship Test for Britain Applicant
Australian Citizenship Test Practice Question

British UK Australian Citizenship test on iphone
US Citizenship Test Practise

Citizenship iPhone Apps


Comments (0) Jan 16 2010

JavaFX How-To’s

Posted: under JavaFX News.
Tags: ,

Javafx.com has published a collection of articles on JavaFX techniques. These “How-Tos” articles serve as excellent references for JavaFX coder. You can think of them as “classified FAQs”. It helps people get started to write JavaFX code effectively. If you are new to JavaFX, I am sure it answers most of your “How do I …” questions. You can check them out here.


In the section of “Build a game”, there are two of my articles. One is the Pac-Man Game series published on insideRIA.com. The other is the Online Wish Tree Prototype on this blog. They are about how to develop games in JavaFX.


BTW, I finished reading a JavaFX book recently. It is called “Essential JavaFX” by Gail and Paul Anderson. This book helps you quickly get to know everything “essential” in JavaFX. Though it is not an advanced book, it does let you jump start into the language. You can read a review here. The Chinese version of review is here.



Comments (0) Dec 05 2009

JavaFX Online Game Prototype: Wish Tree (2)

Posted: under JavaFX Games, Wish Tree.
Tags: , , ,

Last week, I introduced a JavaFX prototype of an online game. Readers have been leaving all kinds of wishes on my Wish Tree. It is interesting to see there are more than 20 lucky stars hanging on the Wish Tree now. If you have not tried the program yet, you are encouraged to click on the screenshot on the right to take a look or make an online wish.

Let’s come back to the technical part of the program again. In part 1, we introduced the architecture of this online application and the JavaFX rich client. In this post, I will explain the details of the data exchange between the client and the server. For your convenience, I bring back the architectural figure as shown below:

click to start wish tree online program


Like any client/server system, the server provides data services to the client. Based on the requirement of the Wish Tree, we define two services provided by the server: getAllStars and saveStar.

Service name Parameters Notes
getAllStars none  
saveStar location, name, content, time, color, email for create, returns id
id, content, email for update


The first one getAllStars is for the client to retrieve the data of all the stars(wishes) in the database. The data of a star contains its (x,y) coordinates on the screen and its color. The wish information associated with a star is also returned. Such information includes the wisher’s name, email address, content of the wish and the time when the wish was made. Based on this data, the client restores the stars at the exact location where people hung them on the tree. In this way, every time you start the wish tree client, you always see your star staying at the same place.


The second service is saveStar. When a user creates a star on the tree, the data of the star is sent to the server and saved into the database. The id of the star is returned to the client for later update purpose. The id is nothing more than a unique identifier of each wish stored in the database. You can think of it as the primary key of a database table. We will re-use this service to update a wish. This is due to the fact that most of the handling logic is the same for create and update action. The service first checks whether the client has sent in an id as a request parameter. If id is included, then it is a request of update; otherwise, it is a request of create.


The sequence diagram of these services are depicted as below:




Now that we have a high level design of services, we can elaborate on the protocol between the client and the server. Since our application is stateless, a RESTful style of request and response should be good enough. Therefore, we use HTTP GET request for the getAllStars service and POST for the saveStar service. The format of the response data could be HTML, XML or JSON. Because JavaFX provides a PullParser class which can parse XML or JSON data, we choose JSON in our application. Below is a sample of the JSON response of the getAllStars service:

{
 "Star": {
   "id" : "102",
   "name" : "John Smith",
   "content" : "My first wish",
   "location" : "388.0_248.0",
   "email" : "j.smith@example.com",
   "time": "2009-08-21 16:38:37",
   "color": 3
 },
 "Star": {
   "id" : "108",
   "name" : "Homer Simpson",
   "content" : "This is another wish.",
   "location" : "188.0_228.0",
   "email" : "homer@simpson.com",
   "time": "2009-08-28 18:28:48",
   "color": 4
 }
}


Once we finalize the protocol between the client and the server, we can start to implement the code on both sides. In a large scale project, this usually results in two teams concurrently working on the code of the client and the server respectively. At the client side, the code to parse the above JSON data is in Main.fx :

var parser = PullParser {
    documentType: PullParser.JSON;

    onEvent: function(event: Event) {
      var content: String;
      var name: String;
      var id: String;
      var email: String;
      var color: Integer;
      var time: String;
      var location: String;

      // parse the JSON data and populate the object
      if(event.type == PullParser.END_VALUE) {

        if(event.name == "name") {
          star.name = event.text;
        }
        else if ( event.name == "content" ){
          star.wish = event.text;
        }
        else if ( event.name == "id" ){
          star.id = event.text;
         }
        else if ( event.name == "color" ){
          star.whichColor = event.integerValue;
        }
        else if ( event.name == "time" ){
          star.time = event.text;
        }
        else if ( event.name == "location" ) {
          var pos = event.text.indexOf( "_" );
          var x = event.text.substring(0,pos);
          var y = event.text.substring( pos+1 );

          star.translateX = Float.parseFloat(x);
          star.translateY = Float.parseFloat(y);
        }
        else if ( event.name == "Star" ){
          star.changeStatus();
          star.onMousePressed = handleClick;

          insert star after stage.scene.content[currentIndex++];
          star = Star {};
        }
      }
    }
  }


The JavaFX client uses the class HttpRequest to communicate with the server. HttpRequest allows us to use GET and POST method to send requests to the server. Usually, we only need to override some methods of this class. As shown in ServerConnector.fx below, we rewrote the onOutput and onInput functions to invoke the saveStar service from the server.

/*
 * ServerConnector.fx
 * @author Henry Zhang   http://www.javafxgame.com
 */
package wishtree;
import java.net.URLEncoder;
import java.io.*;
import javafx.io.http.*;

var baseURL = "http://localhost:8888/wishtree/";

public var serverURL1 = "{baseURL}getallstar.php";
var serverURL2 = "{baseURL}savestar.php";

public class ServerConnector extends HttpRequest {
  var star : Star = null;
  var paramString : String ;

  override var onOutput = function( os: java.io.OutputStream): Void {
        try {
            os.write(paramString.getBytes());
        } finally {
            os.close();
        }
    };

  override var onInput = function(is: java.io.InputStream) {
     try {
           var br = new BufferedReader( new InputStreamReader( is ) );
           var line: String;

           while ( ( line=br.readLine() ) != null )
           {
             if ( (star != null) and (star.id == "")  )
                star.id = line;
            }
        } finally {
            is.close();
        }
  };

public function saveStar( s: Star ) {
  if ( s.id.length() == 0 )
    star = s;

  paramString = encode("name", s.name);
  paramString += "&{encode("id", s.id)}&" ;
  paramString += encode("location", "{s.translateX}_{s.translateY}" );
  paramString += "&{encode("content", s.wish )}";
  paramString += "&{encode("email", s.email)}" ;
  paramString += "&{encode("time", s.time)}&" ;
  paramString += encode("color", "{s.whichColor}" );

  headers = [
        HttpHeader {
            name: HttpHeader.CONTENT_LENGTH;
            value: "{paramString.getBytes().length}";
        }
       ];

  method = POST;
  location = serverURL2;
  start();
 }
}

function encode( k: String, v:String): String {
    var result = URLEncoder.encode( k, "UTF-8");
    var value = URLEncoder.encode( v, "UTF-8");
    result += "={value}"
}


On the server side, the PHP code is quite straightforward. Basically, it gets the parameters from the request and convert them into SQL statement for MySQL database. After getting the data from MySQL, it returns the data in JSON format.


Finally, I would discuss how to tie up all the components together. First, we build the JavaFX client in NetBeans. The products are a jar file and a JNLP file. We modify attributes in the JNLP file to match the deployment environment. The most important is to set the correct value of the “codebase” attribute. Then we upload the jar and JNLP files to a folder on a web server. This folder should match the one specified in the codebase attribute. The next step is to deploy the PHP scripts, for simplicity, we just upload the scripts under the same folder where we put the jar. In the scripts, be sure to change the user name and password of the database. In your MySQL database, create a table to store the wish data. The last thing would be putting a link in a web page which contains the web start link to your JNLP file.


For source code, you can get it from the download page of this site. As shown in the architectural figure, there are codes of server side(Mysql and PHP) and client side(JavaFX), respectively. Be sure to read the file README.txt before you try the code.


If you have any questions, please leave comments.



Other JavaFX articles:

JavaFX Online Game Prototype: Wish Tree (1)

JavaFX Menu       Java Code Calls JavaFX APIs


Comments (3) Aug 28 2009

JavaFX Online Game Prototype: Wish Tree (1)

Posted: under JavaFX Technology, Wish Tree.
Tags: , , , ,

I finished a JavaFX prototype of an online game, it is called “Wish Tree”. Strictly speaking, this prototype is not a game. Instead, it is an online multi-user application of fun (esp. for kids). However, it embodys all the essential elements of an online game: a JavaFX rich client for user interaction, a server handling communication among multiple clients, and a database for data persistence. Though it is still relatively simple, it lays a foundation of building an online multi-user game. I am going to demostrate in two posts how to design and write such an application in JavaFX, PHP and MySQL.


Not long ago, I wrote a JavaFX program for fun. You may have heard of the song “Tie a Yellow Ribon on an Old Oak Tree”, my program was called “Hang a Lucky Star on a Wish Tree“. It allowed people hang colorful stars on a tree to keep their wishes. The program was running as a standalone application. Recently, I added in some code to make it an online version. People all over the world now can share their wishes on the same tree.


This online version is a true RIA(Rich Internet Application) now. After a person leaves a lucky star on the tree, he/she can see the star next time she/he runs the program. People can see others’ wishes as well ( sorry, no privacy for now ^_^ ). However, an email address is needed to modify an existing wish.


The main architecture of the whole system is depicted in the below figure. First, the program gets started from a browser by Java Web Start technology. Then the program connects back to the server to obtain data and draws the wish tree hanging with stars. The server component retrieves data from the database and returns to the client. If the client makes a new wish, the data of the wish is sent to the server for persistence.


The requirements of the system are listed below:


1) On the client side, we need a browser that supports JavaFX 1.2. Basically, on our client machine we need JRE 1.5 +, or better with JRE 1.6 U13 later.

2) On the server side, we need a web server that supports PHP and MySQL. We can choose the popular “LAMP” stack (Linux, Apache web server, MySQL and PHP), but the two required things are ‘MySQL’ and ‘PHP’ only. In fact, in my development environment, I use Windows XP, Sun Java Web Server 7.0, MySQL and PHP plugin for JWS.


Before we get into any technical details, you can click on the below screenshot to start the JavaFX
client to see how it works. You can click on existing stars to see others’ wishes, or click on the tree
to leave your wish. Be sure to leave your email address so that you can modify your wish later. After you save your wish, you can check your wish next time you start the program. For testing purpose, please do not leave more than 2 wishes(stars).


click to start wish tree online program


Since this is a typical client/server application, let’s look at the JavaFX client first. A GUI is presented to the user for interaction. The Main.fx contains the main Windows(a Stage instance) of the application. We put in some images of trees and clouds on the stage. To make them look more realistic, the clouds are applied with the GaussianBlur effect.


The Bubble.fx defines a Bubble class which draws a bubble rising from the bottom of the stage. Animation is used to let the bubble eventually vanish into the tree. The Main class has a few instances of Bubble to create a boiling effect.


When the tree is clicked, a star is shown and a dialog is popup for the user to enter a wish. The
Star is a subclass of the Polyon class. It has a few pre-defined color schemes. The part of drawing a star is achieved by the following few lines, a little bit of geometry knowledge here:

  def r1 : Double = 15;
  def r2 : Double = r1 / 1.6;
  var r = [r1, r2];
  ... ...

    points = for ( i in [0..9] ) [
      r[i mod 2] * cos( toRadians(i*36) ),
      r[i mod 2] * sin( toRadians(i*36) )
    ];


The Dialog is a subclass of CustomNode which contains a few buttons and text fields. When the “OK” button of the dialog is pressed, the user’s wish is saved on the server. The user can also click on a star that’s already on the tree to view its content. If the user is the owner of the wish( based on the email address), the user can modify the content of the wish and then save it.


Finally, the class ServerConnector uses HttpRequest to communicate with the server and store wishes in the server’s database. We will walk through the server code next week and illustrate the data interaction between the server and the client.


If you are interested in the source code, you can visit the download page of this site. As shown in the architectural figure, there are source code of server side(Mysql and PHP) and client side(JavaFX), respectively. Be sure to read the file README.txt before you try the code.


If you have any questions, please leave your comments.


Next Article: JavaFX Online Game Prototype: Wish Tree (2)



Other articles on JavaFX:

JavaFX Scene in Swing       JavaFX API for Java

JavaFX Menu       How Java Code Calls JavaFX APIs ?

Review on Book “Essential JavaFX”


Comments (3) Aug 16 2009

Building Menu in JavaFX

Posted: under JavaFX Technology.
Tags: , , ,

The JavaFX APIs do not come with a menu GUI component. Perhaps the JavaFX team in Sun does not think it is an important thing in RIA. However, from time to time, developers are asking questions on how to build a menu bar from JavaFX. So I decided to write an example of the menu bar in JavaFX.

JavaFX provides us a class javafx.ext.swing.SwingComponent, which can wrap a SWING component into a JavaFX node. We know that we can build complicated menus in SWING. Therefore, we can wrap up the SWING menu items and put them into a JavaFX Stage. Let’s take a look at the below code:

/*
 * Main.fx
 * @author Henry Zhang   http://www.javafxgame.com
 */
package menutest;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;

import java.awt.event.*;
import javax.swing.*;
import javafx.ext.swing.SwingComponent;

var w : Number = 480 on replace { fxMenuBar.width = w ; } ;
var h = 300;
var selected = "";

var handler = ActionListener {
  public override function actionPerformed( e: ActionEvent ) {
    selected = e.getActionCommand() ;
  }
};

var menuBar = new JMenuBar();

var menu = new JMenu("Menu A");
menu.setMnemonic(KeyEvent.VK_A);
menuBar.add(menu);

var menuItem = new JMenuItem("Item A-1");
menuItem.setAccelerator(
    KeyStroke.getKeyStroke(KeyEvent.VK_1, ActionEvent.ALT_MASK));
menuItem.addActionListener(handler);
menu.add(menuItem);

menuItem = new JMenuItem("Item A-2");
menuItem.setAccelerator(
    KeyStroke.getKeyStroke(KeyEvent.VK_2, ActionEvent.ALT_MASK));
menuItem.addActionListener(handler);
menu.add(menuItem);

menu = new JMenu("Menu B");
menu.setMnemonic(KeyEvent.VK_B);
menuBar.add(menu);

menuItem = new JMenuItem("Item B-1");
menuItem.setAccelerator(
    KeyStroke.getKeyStroke(KeyEvent.VK_3, ActionEvent.ALT_MASK));
menuItem.addActionListener(handler);
menu.add(menuItem);

menuItem = new JMenuItem("Item B-2");
menuItem.setAccelerator(
    KeyStroke.getKeyStroke(KeyEvent.VK_4, ActionEvent.ALT_MASK));
menuItem.addActionListener(handler);
menu.add(menuItem);

var fxMenuBar : SwingComponent = SwingComponent.wrap(menuBar);
fxMenuBar.width = w;
fxMenuBar.layoutX=0;
fxMenuBar.layoutY=0;

Stage {
    title: "JavaFX Menu Test"
    width: bind w with inverse
    height: h
    scene: Scene {
        content: [
          fxMenuBar,
          Text {
                font : Font {
                    size : 16
                }
                translateX: 50
                translateY: 100
                x: 10
                y: 30
                content: bind if ( selected == "" ) "Ready"
                         else "Menu clicked: {selected}"
            }
        ]
    }
}


In the code, we first constructed a menu bar with two menus. Each menu contained two menu items. This is the standard way in SWING to show a menu bar. The line below created a SwingComponent instance which acted as a wrapper of the SWING menu bar:

var fxMenuBar : SwingComponent = SwingComponent.wrap(menuBar);

The below 3 lines were used to keep the menu bar on the top of the window(Stage).

fxMenuBar.width = w;
fxMenuBar.layoutX=0;
fxMenuBar.layoutY=0;

In the Stage class, we can see that fxMenuBar was used like a normal JavaFX node. Since the window is resizable, we need to adjust the width of the menu bar so that it changes with the window. A trigger has been added on the variable w to adjust the width of the menu bar.

var w : Number = 480 on replace { fxMenuBar.width = w ; };

The actual binding to the window’s width was achieved by this statement:

Stage {
 ...
    width: bind w with inverse
 ...
}

Below is a screenshot of the program. You can use accelerators like Alt+1,2,3,4 to activate the menu items.


Related Articles:

JavaFX Scene Displayed in a Swing JFrame Window

Calling JavaFX Classes from Java Code

Comments (2) Jul 27 2009

JavaFX Scene Embedded in a Swing Window

Posted: under JavaFX Technology.
Tags: , , ,

In Stephen Chin’s open source project JFXtras, a JavaFX wrapper for Swing is included in the current release(V0.5). This wrapper allows us to put JavaFX GUI components into a SWING application. It is very useful for developers to integrate JavaFX GUI features with their Java Swing applications.


The JFXtras project comes with a sample test program( refer to SceneToJComponentScene.fx and SceneToJComponentTest.java). I suppose that Swing developers are probably interested in this topic, so I modified the code a bit and created the below example for better illustration purposes.


First we create a subclass of the Scene. Since the Scene class is the top level container in JavaFX , we can virtually place any GUI components in it and then make a reference to it from the java side. Let’s look at the code:

/*
 * MyScene.fx     http://www.javafxgame.com
 * @author Henry Zhang
 */

package swingtest;

import javafx.scene.Scene;
import javafx.scene.text.*;
import javafx.scene.paint.*;
import javafx.scene.shape.Rectangle;
import javafx.animation.Timeline;
import javafx.animation.KeyFrame;

def w = 500;
def h = 400;

public class MyScene extends Scene {
    var xx = w / 3;
    var yy = h / 2;
    var rotate = 0;
    var text = "";

    var tl = Timeline {

      repeatCount: Timeline.INDEFINITE
      keyFrames : [
        KeyFrame {
          time: 70ms
          action: function() {
             text = JavaFXToSwingTest.tf.getText();
             rotate = (rotate+5) mod 360;
          }
        }
      ]
     }

     override var content= [
        Rectangle {
            width: w, height: h
            fill: Color.BLUE
        },
        Text {
            font : Font {
                    size: 24
                   }
            layoutX: bind  xx
            layoutY: bind yy
            rotate: bind rotate
            content: bind text
            fill: Color.YELLOW
        }
    ];

    init { tl.play(); }
}


In the above MyScene.fx, we define a Timeline object to play an animation of a Text instance. Every 70ms, the text will be rotated by an angle of 5 degree. To demostrate the data exchange between JavaFX and java, we update the content of the text for each cycle of the animation. The line shown below is used to get data from a Java static variable:

text = JavaFXToSwingTest.tf.getText();


Though this is not an elegant approach to update data, we use it here for its simplicity. We will discuss more about this issue later. Now that we have a Scene class, we can work on the java class. The code of JavaFXToSwingTest.java is listed below:


package swingtest;

/**
 * JavaFXToSwingTest.java     http://www.javafxgame.com
 * @author Henry Zhang
 */
import java.awt.*;
import javax.swing.*;
import org.jfxtras.scene.SceneToJComponent;

public class JavaFXToSwingTest extends JFrame {

  public static JTextField tf = new JTextField("JavaFX for SWING");

  public JavaFXToSwingTest() {
    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setTitle("JavaFX in SWING Test");

    Container container = getContentPane();
    container.setLayout(new BorderLayout());

    String sceneClass = "swingtest.MyScene";
    JComponent myScene = SceneToJComponent.loadScene(sceneClass);

    JLabel label = new JLabel(" Below is a JavaFX Animation: ");
    container.add(label, BorderLayout.NORTH);
    container.add(myScene, BorderLayout.CENTER);

    JPanel p = new JPanel();
    p.setLayout(new FlowLayout());

    tf.setColumns(28);
    p.add(tf);
    p.add(new JButton("SWING Button"));

    container.add(p, BorderLayout.SOUTH);
    pack();
  }

  public static void main(String args[]) {
    java.awt.EventQueue.invokeLater(
      new Runnable() {
        public void run() {
          new JavaFXToSwingTest().setVisible(true);
        }
      });
  }
}


The code should be quite straightforward for most Java(Swing) programmers. We used BorderLayout and FlowLayout to arrange a few Swing widgets inside a JFrame. There are two lines to create the JavaFX scene to be loaded into a JFrame:

    String sceneClass = "swingtest.MyScene";
    JComponent myScene = SceneToJComponent.loadScene(sceneClass);


The SceneToJComponent class comes from the JFXtras project. Its loadScene() method loads a JavaFX Scene class and returns a JComponent object, which can be used as a normal Swing JComponent. Running the program you will see a text “JavaFX for SWING” rotating in a window(JFrame). If you change the sentence in the input box, you will see the rotating text changes as well. If you have Windows media player installed on your machine, you can click on the below screenshot to watch a video on how the program runs.


DISCUSSION

1) In the above program, we use the JavaFX code actively poll the data from a Java variable. This may waste quite some processing cycles. We can let the Java code notify JavaFX object instead. This requires a technique of invoking JavaFX classes from Java code. Interested readers can refer to this article for details: Java Code to Call JavaFX Classes.


2) Some people may ask how we should compile and run the code. There are basically two approaches for compiling the code. The first is to use javafxc to compile both the Java and JavaFX code. The second is to use javafxc to compile the JavaFX code into a jar file and javac for the java code. To run the program, you can choose either the javafx or java command. You can refer to my article Calling JavaFX Classes from Java Code for more explanations.


3) The last thing I need to point out is that the JFXtras project uses some internal APIs of JavaFX to implement the loadScene() method. This implies that the code may break in future releases of JavaFX. However, as pointed out by Steve, using the JFXtras Swing wrapper could insulate you from the changes of JavaFX APIs (i.e. he will take care of the changes for you). I think Steve is the one we can bank on, because he always acts fast to keep up with the latest JavaFX version. :)


Please leave comments if you have any questions.


Comments (4) Jul 08 2009

Calling JavaFX Classes from Pure Java Code

Posted: under JavaFX Technology.
Tags: , , , ,

Just after the release of JavaFX 1.0, in one of my posts JavaFX and Java Interoperability, I discussed three possible approaches to invoke JavaFX features from the Java side. These approaches were:

1. The ScriptEngineManager class. It is based on JSR-223, the java scripting API, which allows a java program to call a script(such as JavaFX Script, javascript, perl).
2. The JavaFX reflection API. It can probably call any classes in JavaFX.
3. The JavaFX class implements a Java interface so that a Java program can invoke the JavaFX class via the interface.


The third one seems the most elegant way to call JavaFX from Java. However, there is a drawback: the program should start from the JavaFX side. The reason is that it is simpler to use JavaFX code to instantiate the JavaFX classes which can be passed to Java code. Nevertheless, in some scenario, it would be better to start the program from the java side. For example, if you want to add in some JavaFX features to an existing large java application, it is better to have java code as the entry point. To solve this issue, I am combining the essence of Approach 2 and 3 to create the below example.


Let’s say we want to invoke the latest charting functions of JavaFX 1.2 from the java code. We will first use the JavaFX reflection API to instantiate the JavaFX class. We then use it via its java interface. So we define a Java interface first.

/*
 * JavaInterface.java
 *
 * @author Henry Zhang      http://www.javafxgame.com
 */
package javatest;
public interface JavaInterface {
  public void addData(String name, float data);
  public void showChart();
}

The next step is to create a JavaFX class MyChart to implements this interface:

/*
 * MyChart.fx
 *
 * @author Henry Zhang     http://www.javafxgame.com
 */
package javatest;

import javafx.scene.chart.PieChart;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.chart.PieChart3D;

public class MyChart extends JavaInterface {
  var chartData :  PieChart.Data[] = [];

  public override function addData( l:String, v: Number):Void {
    var labelString = l;

    var data =  PieChart.Data {
      label : l
      value : v
      action: function() {
        println("{labelString} clicked!");
      }
     } ;

    insert data into chartData;
  }

  public override function showChart() : Void {
    var chart =
      PieChart3D {
        data : chartData
        pieThickness: 25
        pieLabelFont: Font{ size: 9 };
        pieToLabelLineOneLength: 10
        pieToLabelLineTwoLength : 20
        pieLabelVisible: true
        pieValueVisible: true
        translateY: -50
     };

    Stage {
      title: "PieChart Window"
      width: 520
      height: 300
      scene: Scene {
        content: [
          Text {
            font : Font {
                    size : 16
                   }
            x: 200
            y: 20
            content: "Pie Chart"
          },
          chart
        ]
      }
    }
  }
}

The last thing is to write the java main class JavaTest.

/*
 * JavaTest.java
 * @author Henry Zhang    http://www.javafxgame.com
 */
package javatest;

import javafx.reflect.FXClassType;
import javafx.reflect.FXLocal;
import javafx.reflect.FXLocal.Context;
import javafx.reflect.FXLocal.ObjectValue;

public class JavaTest {
  public static void main(String args[]) {
    Context context = FXLocal.getContext();
    FXClassType instance = context.findClass("javatest.MyChart");
    ObjectValue obj = (ObjectValue)instance.newInstance();

    JavaInterface ji = (JavaInterface)obj.asObject();

    String [] labels = {"January", "Febuary", "March", "April"};
    int [] values = { 18, 20, 25, 37 };

    for ( int i=0; i < values.length; i++ ) {
      ji.addData(labels[i], values[i]);
    }

    ji.showChart();
  }
}



There are three lines in the above code to instantiate a JavaFX class via reflection:

    Context context = FXLocal.getContext();
    FXClassType instance = context.findClass("javatest.MyChart");
    ObjectValue obj = (ObjectValue)instance.newInstance();



The next line is to convert the JavaFX instance into a java interface so that it can be used by Java side:

    JavaInterface ji = (JavaInterface)obj.asObject();



If you are using NetBeans IDE, you can set javatest.JavaTest as the main class in your project properties. This makes sure that the entry point of your program is a java class. Build this project you will get a javatest.jar. Running this program produces the below screenshot:

Java PieChart via JavaFX


To run it from the command line, use the below command:

   javafx -jar javatest.jar


Actually, you could do it in the purest java style by including all the JavaFX runtime stuffs, the command would look like this:

 java -Djava.library.path="<path to javafx sdk lib>"
     -classpath "<all javafx sdk jars>" -jar javatest.jar



Since there are many jar files used by the JavaFX, this purest java approach turns out to be very troublesome. I would rather use the javafx command, which is a wrapper of the above java command.


Please leave comments if you have any questions.

This article is cross-posted at Pure Java Code to Call JavaFX Class. The Chinese translation can be found at http://www.javafxblogs.com.


P.S. Stephen Chin has released the JFXtras 0.5 version. In this project, a class SceneToJComponent is provided to load a JavaFX scence as a SWING component. Though it uses the internal method of the Scence class, it can insulate your code from future JavaFX change(i.e. Steve will take care of the changes for you. :) )


Comments (4) Jun 21 2009

Hang a Lucky Star on a Wish Tree

Posted: under JavaFX Games, Wish Tree.
Tags: , , ,

It is a game like program for my kids, or say it is some fun for everyone. You can make a wish and place it on a Wish Tree. Hopefully, it will come true some time later. A star hanging on the tree denotes a wish. For phase I, I am building this wish tree as a standalone version. In Phase II, I will make an internet version, so that everyone can place wishes on the same tree.


Wish tree: http://www.javafxgame.com


When you click on the wish tree, a wish star appears and a dialog is shown to allow you to enter your name and your wish. Later on, if you click on the same star, you have a chance to modify your wish. My daughter likes it very much, she places all kinds of wishes( such as I want a Barbie) on the tree and really hope they will come true soon. You can have some fun by clicking on the below image to place your wish too. JDK1.5+ is required, JDK 1.6 U13+ is better:


Wish tree: http://www.javafxgame.com

click to start Wish Tree


The program utilizes the features of JavaFX effect classes. The source code can be downloaded here. I will write a few articles to explain how to create such an application.

Comments (1) Jun 18 2009

How to Write Pac-Man Game in JavaFX(5)

Posted: under JavaFX Technology, pac-man.
Tags: , , ,

Yesterday, my last article of a series, “Writing the Pac-Man Game in JavaFX Part 5“, had been published on insiderRIA.com. This final article detailed the chasing algorithms of the ghosts. I think it is probably one of the most interesting things in the code.


When writing the game, there are a few points we need to consider before designing an algorithm of the ghosts, such as effectiveness, randomness, simplicity. You can refer to the article about considerations on these aspects. An excerpt from the article is listed below in blue text. It discussed the choice of a proper algorithm. This algorithm not only serves as the chasing logic, it can also control the escaping behavior of the ghosts.


. . . . . .
After some thinking, I found that the distance between a ghost and the Pac-Man is a good ranking metric. The shorter the distance is, the higher the score is given to a particular choice. The advantages of using the distance as a metric are obvious. It is very simple and can be caculated easily. Besides, this algorithm makes a ghost move in the direction that has the shortest distance to thePac-Man. To illustrate this algorithm, let’s look at the below figure.

In the figure, the ghost Blinky is moving into an intersection from the right to the left. When it reaches the intersection, it has three possible choices of its next movement: to go up, to go down and to continue heading left. Going down is not a valid move because it hits the border of the maze. So we need to compare the other two options. The below table shows the computation of the distance of the two possible moves:

Choice X distance Y distance Total
Intersection 3 10 13
Up 3 9 12
Left 4 10 14

As shown in the table, the distance from the intersection to the Pac-Man character is 13 (The distance between two adjacent dots is 1). If Blinky goes up, the distance is reduced to 12. If it heads left, the distance becomes 14. Therefore, going up seems a better choice for Blinky. In this way, Blinky should be able to get closer and closer to the Pac-Man and eventually catches him.


Of course, this simple algorithm does not take into consideration for the walls in the maze. For this reason, sometimes the calculated score does not in fact represent the shortest path. However, this inaccuracy makes the ghosts appear “stupid” in the game, which is the randomness we want to achieve in the behavior. So we are going to implement it in our code. We rewrite the class MoveDecision. When the function evaluate() calculates a score, it takes in two arguments: the reference to Pac-Man instance and whether the ghost is in a hollow state. The variable distance is used to compute the score. If the ghost is going after the Pac-Man character, the score is 500-distance, which means a shorter distance yields a higher score. If the Pac-Man is hunting the ghosts(when they are hollow), the score is caculated as 500+distance. This makes the ghosts running away from the Pac-Man.
. . . . . .


Now that all the articles had been published and I hope you enjoyed reading them. The game was originally written in JavaFX 1.0, and was compatible with JavaFX 1.1. Because multi-inheritance has been removed in JavaFX 1.2, I made some minor changes to the code. The abstract class MovingObject had been changed to mixin class. The code for JavaFX 1.2 can be download from JavaFX Game Download Page.


You can now click on the below image to play the completed Pac-Man game, it is based on the newly released JavaFX 1.2 . With the improved performance, the game runs very smoothly.


click to run

click to run

Related Articles:

Develop Games in JavaFX

JavaFX MineSweeper Demo Game

JavaFX Demo Game: LinkUP

WidgetFX Game Widgets: Pac-Man

My First JavaFX Game Demo

JavaFX Discussion Blogs

JavaFX Game Article

The Featured Articles on insideRIA.com:

May 14, 2009: Writing the Pac-Man Game in JavaFX - Part 1

May 21, 2009: Writing the Pac-Man Game in JavaFX - Part 2

May 28, 2009: Writing the Pac-Man Game in JavaFX - Part 3

June 4, 2009: Writing the Pac-Man Game in JavaFX - Part 4

June 11, 2009:Writing the Pac-Man Game in JavaFX - Part 5

Comments (0) Jun 13 2009

Pac-Man Widget for WidgetFX 1.2

Posted: under JavaFX News, JavaFX Technology, pac-man.
Tags: , , ,

To fully take advantage of the power of JavaFX 1.2, Stephen Chin just released the WidgetFX 1.2 API beta version. There is even a widget contest running until the end of July. [Update: Steve had released the WidgetFX 1.2 version on June 29. ]


Just before the JavaOne 2009, Jim Weaver asked me to write a widget for my JavaFX Pac-man game. The WidgetFX API was quite simple to use, so I finished it pretty soon. The game widget later got demo-ed on Jim and Steve’s JavaOne sessions. There was a small problem of the pac-man widget: it run relatively slow due to the performance issue of JavaFX 1.1. Since JavaFX 1.2 and WidgetFX 1.2 are ready now, I am modifying the code to see the improvement on performance.


First, the JavaFX code of the Pac-Man game needs to be modified a little bit for JavaFX 1.2. Since multi inheritance is gone, we need to use mixin classes now. You can refer to my articles on insideRIA.com for details of the code. Changes for JavaFX 1.2 were given on comments of Article 4 by Patrick Webster. I also added in a pausing key(”P” button) handling for the game. I compiled the game into a pacman.jar file.


The next step is to write the widget. Actually, the code is quite simple if you do not have stuffs like configuartion etc. Let’s look at the code below:

/*
 * PacManWidget.fx
 * http://www.javafxgame.com
 */

package pacmanwidget;

import org.widgetfx.Widget;

/**
 * @author Henry Zhang
 */

def defaultWidth = 528.0;
def defaultHeight = 576.0;

def maze =  pacman.Maze {};

var widget:Widget = Widget {
    width: defaultWidth
    height: defaultHeight
    aspectRatio: defaultWidth / defaultHeight
    content: maze
    resizable: false

    onDock: function():Void {
       maze.pauseGame();
    }
}

return widget;

In the standalone game, an instance of the Maze class was put into the content variable of a Stage. Now, instead of putting it into a Stage, we add it into a Widget. To do this, we can just set the content variable of a Widget instance. Other attributes of the Widget class are quite straightforward, mostly for resizing purposes. The next thing is to write a onDock() function to pause the game when the widget gets docked. The game can be resumed after pressing the “p” button when it is undocked.


The last thing is to deploy it on a web server. We need a JNLP file. Be sure to write the jnlp file of the JavaFX 1.2 style. Netbeans can generate the JNLP file which we can modify for deployment. I listed below part of my jnlp file. Besides the widget code PacManWidget.jar, there are supporting jar files( pacman.jar and WidgetFX-API.jar) under the /lib folder as well. Notice that there is a bug in the generated JNLP file by NetBeans 6.5.1: the <update> tag is missing a slash(/) at the end of the tag.


 . . . . . .
 <resources>
     <j2se version="1.5+" />
     <extension name="JavaFX Runtime"
        href="http://dl.javafx.com/1.2/javafx-rt.jnlp"/>
     <jar href="PacManWidget.jar" main="true"/>
     <jar href="lib/pacman.jar"/>
     <jar href="lib/WidgetFX-API.jar"/>
 </resources>
 <application-desc main-class="com.sun.javafx.runtime.main.Main">
    <argument>MainJavaFXScript=pacmanwidget.PacManWidget</argument>
 </application-desc>
 <update check="background" />
 . . . . . .


Now, you can click on the below button to start the Pac-man widget for JavaFX 1.2. Enjoy!


Pac-Man Widget 1.2



Comments (3) Jun 08 2009

How to Write a Pac-Man Game in JavaFX (4)

Posted: under pac-man.
Tags: , , ,

My latest article of the series, “Writing the Pac-Man Game in JavaFX Part 4“, was out on June 4.


In this article, the interaction between Pac-Man character and the ghosts was introduced in detail. The article showed how to determine whether the Pac-man character and a ghost touched each other. A simplified formla was applied to achieve better performance. When Pac-man touches a ghost, he can eat it if the ghost is hollow. The ghost then is thrown back to the cage again. Otherwise, the ghost eats the Pac-man. An animation of showing a dying Pac-Man appears at this moment. This is in fact a shrinking circle(Arc) which disappears at the end of the animation. The animation is accomplished by the DyingPacMan class.


The below figure depicts the animation process of the dying Pac-man character.

shriking pac-man


The code of DyingPacMan.fx is listed below:

/*
 * DyingPacMan.fx
 *
 * Created on 2009-2-6, 17:52:42
 */
package pacman;

import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.shape.Arc;

/**
 * @author Henry Zhang
 */
public class DyingPacMan extends Arc {
   public var maze : Maze;

   var timeline = Timeline {
      repeatCount: 1
      keyFrames: [
        KeyFrame {
           time: 600ms
           action: function() {
             // hide the pacMan character and ghosts before the animation
              maze.pacMan.visible = false;

              for ( g in maze.ghosts ) {
                 g.hide();
               }

              visible = true;
            }
           values: [ startAngle => 90, length=>360 ];
         },
        KeyFrame {
           time: 1800ms
           action: function() {
              visible = false;
            }
           values: [ startAngle => 270 tween Interpolator.LINEAR,
                     length => 0 tween Interpolator.LINEAR ]
         },
      ]
    }

   public function startAnimation(x: Number, y: Number) : Void {
      startAngle = 90;
      centerX = x;
      centerY = y;

      timeline.play();
    }
}

Interpolations of two variables, startAngle and length, are involved during the animation. To better illustrate this process, the below figure shows the change of the shape against a timeline.

timeline pac-man


Hope you enjoy reading the articles. You can use arrow keys to play the current version of the game. The ghosts are moving randomly which makes the game less challenging. In the next article, I will introduced a better algorithm. Try it by clicking the below screenshot:


click to run

click to run


Related Articles:

Develop Games in JavaFX

My JavaFX Demo Game: Pac-Man

Comments (0) Jun 06 2009

The LinkUp Game in JavaFX

Posted: under linkup.
Tags: , ,

You may have remembered that I introduced a JavaFX implementation of the Frozen Bubble game by Liu Xuan. He finished another JavaFX game, LinkUp, recently. This is a game of fun, especially for kids, and had been implemented in many languages, such as flash and java. It is simple to play the game: look for two identical images and eliminate them. There must be a path connecting the two images and the path must have no more than two turns.


Like in any games, visual effect and algorithms are two key elements. In this game, most of the visual effects can be easily achieved by JavaFX API(like fade in/out, animation). According to Liu, the algorithm to find two conntected cells are the hightlight of the game. A breadth-first search algorithm is used to find the shortest path. Check the code at Model.fx, there are three functions: findNoCross(),
findOneCross() and findTwoCross() implemented for this purpose. The first function finds a set of cells that can be reached by a line(directly). If the target cell is not in this set, the second function is invoked to look for cells reachable by a turn. Similarly, the third function is used for searching a path of two turns.


If you are interested in the details of the game, come take a look at the code (Note: Liu Xuan has the copyright of the source code). Or, you can just enjoy playing this game by clicking the below image:


click to start LinkUP game

click to start LinkUP Game

Comments (1) Jun 01 2009

Challenge on Pac-Man Game Widget

Posted: under JavaFX Games, pac-man.
Tags: , , ,

During the weekend, JavaFX expert Jim Weaver had laid a challenge on me to create a WidgetFX widget of the Pac-Man Game, a JavaFX demo game that I introduced in insiderRIA.com. The author of WidgetFX, Stephen Chin even offered to show it in JavaOne if I can finished in time(before June 2-3). With about one week to go, I think it is interesting and fun to give it a try. I will keep track of my progress in this post.


I have installed the WidgetFX package before, but to get a clean start, I re-downloaded the source code from Widgetfx.org. Here is my progress: (updated continuously)



May 24:
Downloaded source code from http://code.google.com/p/widgetfx/downloads/list. Clicked on the Launch Dock link on the front page of widgetfx.org and it run successfully on my computer(Windows XP, with JDK 1.6U13). Read some document from project home. Try to look at some WidgetFX samples, but couldn’t find most of the source code. Anyway, it is not bad for the first day.


May 25:
Got Steve’s response with a tutorial on Calendar widget. This tutorial is quite helpful. From that example, I learnt that the widget container is fundamentally a Stage Class. That’s great! We can put everything into an instance of Group and then put the Group into the Widget class. Because in my Pac-Man Game, I only have a Maze instance in the Stage class, this becomes quite simple now. I quickly modified the Calendar example and put my Maze instance into the Widget. After adjusting the width and height, it was just simply working! (see the image on the left)

Further testing showed that I needed to write some code to handle the docking and resizing events. I will read some more documents and find out more details tomorrow.


May 26:

Steve provided some useful hints on how to deal with the resizing of the widget. It looks like the WidgetFX API is quite intelligent on resizing the window. What I need to do is to define default width/height and aspectRatio and everything else will be taken care of. I modified my original Pac-Man code to allow the game to be paused. Now the game is fully working as a widget. When it is docked, the game will be automatically paused. When it is undocked, it zooms to its original size and the player can press ‘P’ button to continue playing. Click on the below button to see how the Pac-Man widget looks like:


Pac-Man Widget (JavaFX 1.1)


or try widget for WidgetFX 1.2 version

Pac-Man Widget 1.2


Some issues remains: the game is kind of slow on my laptop(single core, 1.6Ghz Intel, WinXP). I am checking with Steve to see if he has any suggestions.



Comments (5) May 25 2009

JavaFX Sample Game: MineSweeper

Posted: under minesweeper.
Tags: , ,

There are lots of talented software developers in China. I saw some of them had written interesting games in JavaFX. As I introduced before, Liu Xuan wrote the Frozen Bubble game in JavaFX. Recently I read a post from blogger mqqqvpppm, who resides in a beautiful city Kun Ming in south western China. He did a good MineSweeper Game with JavaFX. Click on the below screenshot or the “launch” button to play.(JDK1.5 or 1.6U10+)


click to start MineSweeper


click to start MineSweeper


Here are the highlights of the source code:

The cells(Cell.fx) of the broad were implemented by extending the class CustomNode. The interesting part of the code is that four instances of Node are included in the CustomNode, which are used for four possible states of a cell: blank, a bomb, a red flag, or a number. One of the Nodes is visible at a time. The visibility of the nodes are bound to a few instance boolean variables. The main logic then controls these boolean variables to display different states of the cells. We can see the code making good use of JavaFX binding.


In the game, when a cell with a number is clicked, there is an action to uncover adjacent cells like flooding. This is another interesting part of the writing the game. mqqqvpppm implemented the code by indirect recursive functions.


In the current version of the game, a player may hit a mine on the first click. mqqqvpppm said he will modify this soon. Overall, I think the game is well written. Come take a look at the source code here(Note: mqqqvpppm has the copyright of this work), I am sure you will learn something from it.

Comments (1) May 23 2009

How to Write a Pac-Man Game in JavaFX (2)

Posted: under JavaFX Games, pac-man.
Tags: , ,

The 2nd article of the series, “Writing the Pac-Man Game in JavaFX“, is published today.


The first article introduced a data model in Java and the JavaFX drawing logic of the maze. In the 2nd article, the animation part of the Pac-Man character is detailed. When you are reading, you can click on the java web start links to see the Pac-Man opening and closing mouths, and gradually moving inside the maze. The keyboard handling code is illustrated as well.


Some JavaFX features demostrated in these two articles include:

. shapes
. keyboard handling
. animation timeline
. java code integration
. Transfromation


Hope you can enjoy reading the articles. You can use arrow keys to play a no-ghost version of the game. The Pac-Man character now can move around and gobble dots. Try it by clicking the below screenshot:


click to run

click to run


Related Articles:

Develop Games in JavaFX

My JavaFX Demo Game: Pac-Man

Comments (0) May 22 2009

How to Write the Pac-Man Game with JavaFX

Posted: under JavaFX Games, JavaFX Technology, pac-man.
Tags: ,

After the official announcement of JavaFX 1.0, I wrote a JavaFX program for the Pac-Man game. People were interested in the game. They either enjoyed playing or asked me for the details fo the JavaFX code. JavaFX expert Jim Weaver asked me to write some articles about the process of building the game. After a few weeks’ hard work, with Jim’s constructive ideas and great help in proofreading, I finished the articles. Now they are published on nsideRIA.com, an O’Reilly’s web site, as featured articles. There will be 5 articles in total and they will run through the coming 5 weeks.  

In each of the articles, there are web start links that you can click to start a JavaFX program to see how it works. If you follow the 5 articles, you will find out how the game is written bit by bit. I hope the articles can help people who want to learn JavaFX or want to develop games in JavaFX. Thanks Jim for making these articles possible.


Here are the links for the articles:


May 14, 2009:
Writing the Pac-Man Game in JavaFX - Part 1
May 21, 2009:
Writing the Pac-Man Game in JavaFX - Part 2
May 28, 2009:
Writing the Pac-Man Game in JavaFX - Part 3
June 4, 2009:
Writing the Pac-Man Game in JavaFX - Part 4
June 11, 2009:
Writing the Pac-Man Game in JavaFX - Part 5


Related Posts:
First JavaFX Demo Game: PACMAN

Articles on Writing JavaFX Pac-Man Game

JavaFX Demo Game: PAC-MAN

Comments (1) May 17 2009

JavaFX SyntaxHighlighter

Posted: under JavaFX Technology.
Tags: , , , , ,

In a modern IDE(Integrated Development Environment), such as NetBeans or Eclipse, syntax elements of a programming language are usually shown in different colors and styles. On a web page, there are tools for highlighting the keywords. They are either client side or server side tools. The SyntaxHighlighter is a client side(javascript) tool to display keywords of a programming language in a particular style(bold, different color etc). It supports quite a few languages such as Java, C, C#, VB, Ruby, javascript. While I was recently writing articles on JavaFX, I found it necessary to come up with a syntax highlighter for JavaFX.


I did some search and found the reserved keywords, then modified the shBrushJava.js to be shBrushJavaFX.js. Now my articles can have highlighted JavaFX syntax. For example:

package pacman;
import java.lang.Math;
import pacman.MazeData;
import pacman.PacMan;

/**
 * @author Henry Zhang  http://www.javafxgame.com
 */

public class MoveDecision {

  // x and y of an intended move
  public var x: Number;
  public var y: Number;

  // evaluate if the move is valid and its score if it's valid
  public function evaluate(pacMan:PacMan, isHollow:Boolean): Void {
    if ( x < 1 or y < 1 or y >= MazeData.GRID_SIZE
         or x >= MazeData.GRID_SIZE){
      score = -1;
      return ;
    }
  }
 . . .
}


If you are interested in using this JavaFX highlighter, you can download the brush file: shBrushJavaFX.js and the CSS file: SyntaxHighlighter.css. Information about the original SyntaxHighlighter 1.5.1 can be found here: SyntaxHighlighter .


For those who are intersted in the reserved words (keywords) of JavaFX, you can find it here. For your convience, I list them below:

abstract after and as assert at attribute before bind bound break
catch class continue def delete else exclusive extends false finally
first for from function if import indexof in init insert instanceof
into inverse last lazy mixin mod new not null on or override
package postinit private protected public-init public public-read
replace return reverse sizeof static step super then this throw
trigger true try tween typeof var where while with



Comments (0) May 02 2009

JavaFX Frozen Bubble Game

Posted: under JavaFX Games.
Tags: , ,

Liu Xuan, a Chinese programmer, had written a Frozen Bubble game in JavaFX. He is kind to allow me to share his code here. The game was originally developed in Perl/SDL. A java port is available too. Liu’s program implemented a simplified version of the Frozen Bubble game in JavaFX.


Click on the below button to start the game, use left/right arrow key to aim and space button to fire.








The key handling code is accomplished in the class Container:

public class Container extends CustomNode{
    public var bubbles = new HashMap();
    public var fadeBubbles: Bubble[];
    public var fallBubbles: Bubble[];
    public var gun: Gun = Gun{};
    public var shootAngle: Number;
    public var group: Group = Group {
        content: [
            // backgroud
            Rectangle {
                width: 320
                height: 480
                strokeWidth: 1
                stroke: Color.BLACK
                fill: LinearGradient {
                    startX: 0.0,
                    startY: 0.0,
                    endX: 0.0,
                    endY: 1.0
                    proportional: true
                    stops: [ Stop {
                            offset: 0.0
                            color: Color.YELLOWGREEN },
                        Stop {
                            offset: 1.0
                        color: Color.LIGHTBLUE } ]
                }
                onKeyPressed: function(e: KeyEvent):Void {
                      .......   // keyboard event handling
             }
            }
            gun
            //warning line
            Line {
                startX: 0,
                startY: Config.RED_LINE
                endX: 320
                endY: Config.RED_LINE
                strokeWidth: 1
                stroke: Color.RED
            }
            ImageView {
                  .......
            }
        ]
    };   

    public var inverseX = 1;   

    //semi-transparent layer for game over screen
    var layer = Rectangle {
        width: 320
        height: 480
        fill: Color.BLACK
        opacity: .4
    }
    var text = Text {
        content: "Press Enter To Start"
        font: Font {
            size: 20
        }
        x: 60
        y: 250
    }   

    // status of the game
    // 0 - game start and wait for shooting
    // 1 - bubble is moving
    // 2 - game over, the animation timeLine instanc
   // will stop at this value
    public var state = 2 on replace {
        if(state == 2) {
            timeline.stop();
            insert layer into group.content;
            insert text into group.content;
        }
    }   

    override public function create(): Node {
        group
    }   

   public function getLocation(row: Integer, col: Integer) : Point{
        var locationY = Config.ROW_SPACE * row;
        var locationX;
        if(row mod 2 == 0) {
            locationX = Config.BUBBLE_DIAMETER * col
        } else {
            locationX =
            Config.BUBBLE_DIAMETER * (col + .5) as Integer
        }
        return new Point(locationX, locationY)
    }   

   public function getAround(row: Integer, col: Integer): Bubble[] {
        var bArray: Bubble[] = [];
        var flag: Integer = 0;
        if(row mod 2 == 0) {
            flag = -1;
        }
        var bubble0 = getBubble(row, col - 1);
        var bubble1 = getBubble(row - 1, col + flag);
        var bubble2 = getBubble(row - 1, col + 1 + flag);
        var bubble3 = getBubble(row, col + 1);
        var bubble4 = getBubble(row + 1, col + flag);
        var bubble5 = getBubble(row + 1, col + 1 + flag);
        insert bubble0 into bArray;
        insert bubble1 into bArray;
        insert bubble2 into bArray;
        insert bubble3 into bArray;
        insert bubble4 into bArray;
        insert bubble5 into bArray;
        return bArray;
    }   

    public function getAround(bubble: Bubble): Bubble[] {
        var row: Integer = bubble.index.x;
        var col: Integer = bubble.index.y;
        return getAround(row, col);
    }

   public function getSameBubble(bubble: Bubble): Vector {
     var vector: Vector = new Vector();
     vector.add(bubble);
     var cursor = 0;
     while(
      cursor < vector.size()) {
        var bubbleInVector: Bubble =
        vector.get(cursor++) as Bubble;
        var aroundBubbles:Bubble[]=getAround(bubbleInVector);
        for(aroundBubble in aroundBubbles) {
          if ( aroundBubble != null
               and aroundBubble.color == bubble.color
               and vector.indexOf(aroundBubble) == - 1) {
               vector.add(aroundBubble);
                }
            }
        }
        return vector;
    }   

    public function getConnected(bubble: Bubble): Vector {
      var vector: Vector = new Vector();
      vector.add(bubble);
      var cursor = 0;
      while(cursor < vector.size()) {
        var bubbleInVector: Bubble =
        vector.get(cursor++) as Bubble;
        var aroundBubbles:Bubble[]=getAround(bubbleInVector);
        for(aroundBubble in aroundBubbles) {
            if ( aroundBubble != null
              and vector.indexOf(aroundBubble) == - 1) {
              vector.add(aroundBubble);
              }
            }
        }
        return vector;
    }   

  public function getIsolatedBubble(vector: Vector): Vector {
    var islatedBubble: Vector = new Vector();
      for(object in vector) {
        var sameBubble: Bubble = object as Bubble;
        var aroundBubbles:Bubble[] = getAround(sameBubble);
        for(aroundBubble in aroundBubbles) {
          if(aroundBubble != null) {
            var connectedBubble:Vector=getConnected(aroundBubble);
            var islate = true;
            for(col in [0..= 3) {
              for(object in vector) {
                var sameBubble: Bubble = object as Bubble;
                bubbles.remove(sameBubble.index);
                insert sameBubble into fadeBubbles;
              }
              for(object in getIsolatedBubble(vector)) {
                var islatedBubble: Bubble = object as Bubble;
                bubbles.remove(islatedBubble.index);
                insert islatedBubble into fallBubbles;
              }
            }
            state = 0;
            checkGameOver();
        }
    }   

    var timeCount = 0;   

    //moving, erasing, dropping the bubbles
    def timeline = Timeline {
        repeatCount: Timeline.INDEFINITE
        keyFrames:[
            KeyFrame {
                time: 0.005s
                action: function() {
                    ......
                    checkGameOver();
                    .......
            //reduce the transparency to erase the bubbles
            for(fadeBubble in fadeBubbles) {
                fadeBubble.opacity -= .02;
                if(fadeBubble.opacity <= 0) {
                   fadeBubble.visible = false;
                   delete fadeBubble from fadeBubbles;
                   delete fadeBubble from group.content;
                   }
              }
              //drop those isolated bubbles
              for(fallBubble in fallBubbles) {
                fallBubble.locationY += 5;
                if(fallBubble.locationY >= 428) {
                   fallBubble.visible = false;
                   delete fallBubble from fallBubbles;
                   delete fallBubble from group.content;
                   }
                 }   

                if(state == 1) {
                        ......
                //rebounce and collision handling
                checkCollision(bubble);
                }
              }
            }
        ]
    }   

    // initialization
    public function gameStart():Void {
          .....
          timeline.play();
    }
}


Source code can be downloaded here. Please note that Liu Xuan has the copyright of the code.

Comments (0) Apr 09 2009