This year I had to miss Devoxx 2008, but really wanted to go. Not only is it a great conference, but this year it is the first major conference since the JavaFX SDK 1.0 was released, so there are some great JavaFX sessions and speakers on the agenda.
So, in honor of the Devoxx conference and the excellent leadership that Stephan Janssen provides to it, I've created a game in JavaFX. I'm not a game programmer nor am I a graphic designer, and I didn't enlist the help of either for this quick effort. With those disclaimers, and the hope that Stephan Janssen will take this in good-natured fun, I give you: "Whack-A-Janssen", styled loosely after the old "Whac-a-Mole" game.
Click on the Launch icon to run it as a Java Web Start application. To play the game, simply click the Start Game button and then click on Stephan's faces when they pop up. While the game is in progress the Start Game button changes to Stop Game. If all three faces appear, the game is over and the Start Game button reappears.
The Code Behind the Game
This game makes use of the transition convenience classes in the javafx.animation.transition package to achieve animated movement, scaling and fading. It also uses the Timeline and KeyFrame classes in the javafx.animation package to popup the many faces of Stephen:
/*
* WhackAJanssen.fx
*
* Developed 2008 by James L. Weaver (jim.weaver at javafxpert.com)
* to demonstrate creating applications using JavaFX SDK 1.0, and for
* having some good-natured fun with Stephan Janssen of Devoxx.
*/
package javafxpert;
import javafx.animation.*;
import javafx.animation.transition.*;
import javafx.ext.swing.*;
import javafx.scene.*;
import javafx.scene.effect.*;
import javafx.scene.image.*;
import javafx.scene.input.*;
import javafx.scene.paint.*;
import javafx.scene.shape.*;
import javafx.scene.text.*;
import javafx.scene.transform.*;
import javafx.stage.Stage;
import java.lang.Math;
Stage {
// Transitions for popups
var popupRefs:Transition[] = [
ScaleTransition {
node: bind stephen1Ref
duration: 1s
fromX: 0.1
fromY: 0.1
toX: 1.0
toY: 1.0
},
TranslateTransition {
node: bind stephen2Ref
duration: 1s
fromY: 0
byY: -70
//autoReverse: true
},
FadeTransition {
node: bind stephen3Ref
duration: 1s
fromValue: 0.0
toValue: 1.0
//autoReverse: true
}
];
// Transitions for knock-downs
var knockdownRefs:Transition[] = [
ScaleTransition {
node: bind stephen1Ref
duration: 500ms
fromX: 1.0
fromY: 1.0
toX: 0.1
toY: 0.1
},
TranslateTransition {
node: bind stephen2Ref
duration: 500ms
fromY: -70
byY: 70
//autoReverse: true
},
FadeTransition {
node: bind stephen3Ref
duration: 500ms
fromValue: 1.0
toValue: 0.0
//autoReverse: true
}
];
var stephen1Ref:ImageView;
var stephen2Ref:ImageView;
var stephen3Ref:ImageView;
// Timeline that causes random Stephens to popup
var gameTimeline = Timeline {
keyFrames: [
KeyFrame {
time: 2s
action: function():Void {
var stephenNum:Integer =
(Math.random() * sizeof stephensDown) as Integer;
if (stephensDown[stephenNum]) {
stephensDown[stephenNum] = false;
popupRefs[stephenNum].playFromStart();
}
}
}
]
repeatCount: Timeline.INDEFINITE
}
// Position that the stephens are in. The trigger evaluates whether
// the game is over and stops the game Timeline
var stephensDown:Boolean[] = [true, true, true] on replace {
var downs = for (stephen in stephensDown where stephen == true) stephen;
if (sizeof downs == 0) {
gameTimeline.stop();
}
};
title: "Whack-A-Janssen"
scene: Scene {
var btn:SwingButton;
width: 300
height: 350
fill: Color.#010101
content: [
ImageView {
transforms: Translate.translate(24, 56)
image: Image {
url: "{__DIR__}images/devoxx250.jpg"
}
},
// Left-most face
stephen1Ref = ImageView {
transforms: [
Translate.translate(63, 99),
]
opacity: 1.0
image: Image {
url: "{__DIR__}images/sj_face_small.gif"
}
cursor: Cursor.HAND
onMouseClicked: function(me:MouseEvent):Void {
stephensDown[0] = true;
knockdownRefs[0].playFromStart();
}
},
// Middle face
Group {
transforms: Translate.translate(120, 20)
content: [
Group {
content: [
stephen2Ref = ImageView {
transforms: Translate.translate(0, 90)
image: Image {
url: "{__DIR__}images/sj_head_small.gif"
}
},
]
clip: Group {
content: [
Polygon {
points: [
0, 0,
0, 46
15, 80
51, 80,
66, 46,
66, 0
]
},
Arc {
centerX: 33
centerY: 80
startAngle: 180
length: 180
radiusX: 18
radiusY: 10
}
]
}
},
Rectangle {
width: 66
height: 98
fill: Color.TRANSPARENT
cursor: Cursor.HAND
onMouseClicked: function(me:MouseEvent):Void {
stephensDown[1] = true;
knockdownRefs[1].playFromStart();
}
}
]
},
// Right-most face
stephen3Ref = ImageView {
transforms: Translate.translate(190, 95)
image: Image {
url: "{__DIR__}images/sj_left_facing.gif"
}
opacity: 0.0
effect: Glow {}
cursor: Cursor.HAND
onMouseClicked: function(me:MouseEvent):Void {
stephensDown[2] = true;
knockdownRefs[2].playFromStart();
}
},
// Start Game button
btn = SwingButton {
transforms: [
Translate.translate(200, 207),
Scale.scale(0.7, 0.7),
Rotate { angle: -4}
]
text: bind if (gameTimeline.running) "Stop Game" else "Start Game"
foreground: bind if (gameTimeline.running) Color.BLACK else Color.RED
font: Font {
name: "Arial Bold"
}
action: function():Void {
if (not gameTimeline.running) {
stephensDown[0] = true;
stephensDown[1] = true;
stephensDown[2] = true;
knockdownRefs[0].playFromStart();
knockdownRefs[1].playFromStart();
knockdownRefs[2].playFromStart();
gameTimeline.playFromStart();
}
else {
gameTimeline.stop();
}
}
}
]
}
}
Enjoy the conference if you're attending, and this very simple and lame Whack-A-Janssen game!
Regards,
Jim Weaver
JavaFXpert.com
Recent Comments