JavaFX Frozen Bubble Game
Posted: under JavaFX Games.
Tags: Frozen Bubble, game, javafx
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