I started to make several small JavaFX game demos. I’m doing that to fell where JavaFX is good to make this sort of game and what patterns would be frequently needed to implement, where I will place a little framework for fast development of simple casual games. What I’m calling now just ‘GameFX’. My first experiment was to creating a side scrolling animation that’s is usefull to create the parallax effect in side scrolling games. For that I created the class Slidding. You create an Slidding with a set of nodes and they will slide from right to left and when a node reaches the left side it back to the right side.
Example:
Slidding {
content: [
Circle {
centerX: 100, centerY: 100, radius: 40
fill: Color.RED
},
Circle {
centerX: 300, centerY: 100, radius: 40
fill: Color.BLUE
}
]
clock: 0.05s
}
That produces:
You create a Slidding with a list of Nodes at content, a clock (that will determine the speed of that animation) and a width. If you don’t provide a width, the slidding will do the best effort to determine one. You can use this approach to create more complex scenarios, using more Slidding groups.
This is a example of that:
import javafx.application.*;
import javafx.animation.*;
import javafx.scene.geometry.*;
import javafx.scene.paint.*;
import javafx.scene.*;
import gamefx.Slidding;
var SCREENW = 500;
var SCREENH = 400;
/* the sky is a light blue rectangle */
var sky = Rectangle {
width: SCREENW, height: SCREENH
fill: LinearGradient {
startX: 0.0 , startY: 0.0
endX: 0.0, endY: 1.0
proportional: true
stops: [
Stop { offset: 0.0 color: Color.LIGHTBLUE },
Stop { offset: 0.7 color: Color.LIGHTYELLOW },
Stop { offset: 1.0 color: Color.YELLOW }
]
}
}
/* the ground is a olive rectangle */
var ground = Rectangle {
translateY: 300
width: 500, height: 100
fill: LinearGradient {
startX: 0.0 , startY: 0.0
endX: 0.0, endY: 1.0
proportional: true
stops: [
Stop { offset: 0.2 color: Color.OLIVE },
Stop { offset: 1.0 color: Color.DARKOLIVEGREEN }
]
}
}
/* a clod cloud is like an ellipse */
class Cloud extends Ellipse {
override attribute radiusX = 50;
override attribute radiusY = 25;
override attribute fill = Color.WHITESMOKE;
override attribute opacity = 0.5;
}
/* we create a slidding of clouds */
var clouds = Slidding {
content: [
Cloud{centerX: 100, centerY: 100},
Cloud{centerX: 150, centerY: 20},
Cloud{centerX: 220, centerY: 150},
Cloud{centerX: 260, centerY: 200},
Cloud{centerX: 310, centerY: 40},
Cloud{centerX: 390, centerY: 150},
Cloud{centerX: 450, centerY: 30},
Cloud{centerX: 550, centerY: 100},
]
clock: 0.2s
}
var SUNX = 100;
var SUNY = 300;
var rotation = 0;
/* the sun, with it's corona */
var sun = Group {
rotate: bind rotation
anchorX: SUNX, anchorY: SUNY
content: [
for (i in [0..11]) {
Arc {
centerX: SUNX, centerY: SUNY
radiusX: 500, radiusY: 500
startAngle: 2 * i * (360 / 24), length: 360 / 24
type: ArcType.ROUND
fill: Color.YELLOW
opacity: 0.3
}
},
Circle {
centerX: SUNX, centerY: SUNY, radius: 60
fill: Color.YELLOW
},
]
}
/* animate the corona changing the it rotation angle */
var anim = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time : 0s
values: rotation => 0.0 tween Interpolator.LINEAR
},
KeyFrame {
time : 2s
values: rotation => (360.0/12) tween Interpolator.LINEAR
},
]
}
anim.start();
/* a tree is a simple polygon */
class Tree extends Polygon{
public attribute x = 0;
public attribute y = 0;
override attribute points = [0,0, 10,30, -10,30];
override attribute fill = Color.DARKOLIVEGREEN;
init{
translateX = x;
translateY = y;
}
}
/* a forest is a lot of trees */
var forest = Slidding{
content: [
Tree{x: 20, y: 320}, Tree{x: 80, y: 280}, Tree{x:120, y: 330},
Tree{x:140, y: 280}, Tree{x:180, y: 310}, Tree{x:220, y: 320},
Tree{x:260, y: 280}, Tree{x:280, y: 320}, Tree{x:300, y: 300},
Tree{x:400, y: 320}, Tree{x:500, y: 280}, Tree{x:500, y: 320}
]
clock: 0.1s
width: SCREENW
}
Frame {
title: "Side Scrolling"
width: SCREENW
height: SCREENH
closeAction: function() {
java.lang.System.exit( 0 );
}
visible: true
stage: Stage {
content: [sky, sun, clouds, ground, forest]
}
}
Producing:
If you want to try these examples, place this Slidding implementation as Slidding.fx in a directory named gamefx, or grab here the NetBeans project.
package gamefx;
import javafx.scene.CustomNode;
import javafx.scene.Node;
import javafx.scene.Group;
import javafx.animation.Timeline;
import javafx.animation.KeyFrame;
/*
* The slidding group of nodes for side scrolling animations.
*
* @example
* Slidding {
* width: 300
* content: [
* Circle { centerX: 100, centerY: 100, radius: 40, fill: Color.RED },
* Circle { centerX: 200, centerY: 100, radius: 40, fill: Color.BLUE },
* ]
* clock: 0.05s
* }
*/
public class Slidding extends CustomNode {
public attribute content: Node[];
public attribute clock = 0.1s;
public attribute width: Number;
public attribute autostart = true;
public attribute cycle = true;
public attribute anim = Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames : [
KeyFrame {
time : clock
action: function() {
for(node in content){
node.translateX--;
if (node.getX() + node.translateX + node.getWidth() <= 0){
if(cycle){
node.translateX = width - node.getX();
} else {
delete node from content;
}
}
}
} // action
} // keyframe
]
} // timeline
public function create(): Node {
// if width is not setted, we try to figure out
if(width == 0) {
for(node in content) {
if(node.getX() + node.getWidth() > width) {
width = node.getX() + node.getWidth();
}
}
}
// normaly the slidding will start automaticaly
if(autostart){
anim.start();
}
// just a Group of Nodes
return Group {
content: content
};
}
}
Is not the final implementation but it’s a idea. Soon I’ll show a demo game I did using theses codes.
[…] A simple demo using some techniques described in the post JavaFX side scrolling gaming. […]
it’s cool~
Unbelievable.. thanks !! :0
[…] a prior post, Silveira discusses how to create a side-scrolling game in JavaFX, showing the classes that he’s building to support […]
Cool,
I found JavaFX for two days, when I lookup for plugins for netbeans. I’m new on netbeans and now I’m new on JavaFX 🙂 .
Awesome! Now I modify that retro megaman game ive been working on. THX a million.
try GameFX_version_0.zip with NetBeans 6.5.1 and get errors: attribute not longer suport and start() has script only access
THANX A PUNCH…
REALLY THANKFUL 2 U…
I LL BE GRATEFUL 2 U..
PLZ HELP ME MORE ON JAVA FX
styxnexus@rediffmail.com 🙂
My only concern is that java has not that graphic support very much then flash.
[…] […]
why is it the source codes not running in NetBeans IDE 6.8?
Can you pls provide new codes for the new version of NetBeans?
Tnx.
Lee,
The JavaFX language has suffered some transformation in the period between when I wrote this article until now. Those codes should not work properly in the latest versions of NetBeans.
I ported this to JavaFX 2.0. The post is here.
http://blogs.oracle.com/wayneyoung/entry/side_scroller_in_javafx_2
Hi Wayne Young,
Cool. Good to see it.
I barely understand any of this code and ive been doing javaFX for months. Has java really changed so severly in 7 years
JavaFX changed a LOT since I wrote this.
Hi Silveira,
I’ve been busy developing a game in JavaFX the past 1, 5 year (http://www bee-aware.nl), and am really happy with what JavaFX has to offer. However, I did notice that animations are seldom fluid. Almost all of them have little shocks when moving. It’s not my hardware setup (fast pc, and the graphics are rendered using a geforce 970), and I can’t seem to find any valid information about this phenomenon.
I noticed (in your videos) that your code seems to suffer from the same phenomenon, and was wondering if you have any clue what might cause this. Is it JavaFX specific? Is it Windows screwing up things for JavaFX? I’ve tried all kinds of things, like trying to more or less sync the animations with clockticks (used to do that in good old Turbo-C, don’t even know if that makes any sense nowadays), ruling out stuff like the buffering of mp3’s etc., but nothing seems to help. If you know something, or can point me in the right direction, I’d be much obliged.
Looking forward to your answer and with kind regards,
Danny E.K. van der Kolk.