Java, JavaFX, Groovy, Grails …
JavaFX Bubble Breaker
Originally posted by me on ericonjavafx.com
package bubblebreaker;
import javafx.stage.Stage;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import java.util.Random;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.CustomNode;
import javafx.scene.effect.Glow;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.paint.RadialGradient;
import javafx.scene.paint.Stop;
import javafx.scene.Scene;
import javafx.scene.shape.Circle;
import javafx.scene.text.TextAlignment;
import javafx.scene.effect.InnerShadow;
import javafx.scene.effect.DropShadow;
import javafx.ext.swing.SwingButton;
var shift = 10; // from from scene.x and scene.y
var score_count: Number = 0;
var group: Group = new Group;
var slots = [];
var checkedGroup = Group {
};
var totalScore = 0;
function initGroup() {
group = new Group;
slots = [];
totalScore = 0;
for (i in [1..10]) {
for (j in [1..10]) {
insert "true" into slots;
insert Ball2 {
radius: 25;
vx: i * 50 + shift;
vy: j * 50 + (shift * 5);
slot: sizeof slots;
id: "{sizeof slots}";
} into group.content;
}
}
insert "true" into slots;//this is required for the 100 slot
}
initGroup();
function fallStep() {
var aball ;
//1. iterate through the entire set of balls
for (node in group.content) {
aball = (node as Ball2);
//2. if a ball is marked for deletion then remove from the group and mark the slot as empty(false)
if (aball.flaggedfordeletion) {
slots[aball.slot] = "false";
totalScore = totalScore + Integer.parseInt(aball.score);
delete aball from group.content;
}
//3. if the slot below a ball is empty and not ending with a 1
if (slots[aball.slot + 1] == "false") {
var aa = aball.slot + 1;
if (aa == 11 or aa == 21 or aa == 31 or aa == 41 or aa == 51 or aa == 61 or aa == 71 or aa == 81 or aa == 91) {
//do nothing
} else {
//4. mark the slot at taken(true) and move the ball into it....also mark the previous slot as empty(false);
slots[aball.slot + 1] = "true";
slots[aball.slot] = "false";
aball.slot = aball.slot + 1;
aball.vy = aball.vy + 50;
aball.id = "{aball.slot}";
}
}
}
}
function shiftRightStep() {
for (i in [100..20 step -10]) {
if (slots[i] == "false") {
for (j in [(i - 10)..1 step -1]) {
var aa =
group.lookup("{j}") as Ball2;
if (aa != null) {
slots[j + 10] = "true";
aa.slot = aa.slot + 10;
aa.vx = aa.vx + 50;
aa.id = "{aa.slot}";
slots[j] = "false";
}
}
}
}
}
function findNeighbors(aball: Ball2): Void {
var val ;
//1.calculate all neighbors
var r_nball = group.lookup("{aball.slot + 10}") as Ball2;
var d_nball = group.lookup("{aball.slot + 1}") as Ball2;
var l_nball = group.lookup("{aball.slot - 10}") as Ball2;
var u_nball = group.lookup("{aball.slot - 1}") as Ball2;
//2. make a recursive call to check left,right,up and down
if (aball.slot <= 90 and not r_nball.checked) {
r_nball.checked = true;
val = check(aball, r_nball);
if (val) {
aball.checked = true;
findNeighbors(r_nball);
}
}
if (aball.slot mod 10 != 0 and not d_nball.checked) {
d_nball.checked = true;
val = check(aball, d_nball);
if (val) {
findNeighbors(d_nball);
}
}
if (aball.slot > 10 and not l_nball.checked) {
l_nball.checked = true;
val = check(aball, l_nball);
if (val) {
findNeighbors(l_nball);
}
}
if (aball.slot mod 10 != 1 and not u_nball.checked) {
u_nball.checked = true;
val = check(aball, u_nball);
if (val) {
findNeighbors(u_nball);
}
}
}
function check(aball: Ball2, u_nball: Ball2): Boolean {
var return_value: Boolean = false;
if (checkColor(aball, u_nball)) {
aball.effect = Glow {
level: .4
input: InnerShadow {
choke: 0.05
radius: 25
color: Color.BLACK
}
}
u_nball.effect = Glow {
level: .4
input: InnerShadow {
choke: 0.05
radius: 25
color: Color.BLACK
}
}
u_nball.initialSelect = true;
return_value = true;
}
return return_value;
}
function checkColor(aball: Ball2, nball: Ball2): Boolean {
var returnvalue: Boolean = false;
if (aball.colorval == nball.colorval) {
returnvalue = true;
}
return returnvalue;
}
function displayScore() {
for (node in group.content) {
var tball = (node as Ball2);
if (tball.effect != null) {
tball.score = "{score_count.intValue()}";
}
}
}
Timeline {
repeatCount: Timeline.INDEFINITE
keyFrames: KeyFrame {
time: 30ms
action: function () {
var aball ;
for (node in group.content) {
aball = (node as Ball2);
if (aball.flaggedfordeletion == true) {
for (i in [0..9]) {
fallStep();
}
for (i in [0..9]) {
shiftRightStep();
}
}
}
}
}
}.play();
class Ball2 extends CustomNode {
var radius: Number;
var vx: Number;
var vy: Number;
var slot: Integer;
var initialSelect: Boolean;
var flaggedfordeletion: Boolean;
var checked: Boolean;
var colorval ;
var score: String;
def acolor = [Color.ORANGE, Color.BLACK, Color.DODGERBLUE, Color.PURPLE];
var random: Random = Random {
};
override function create() {
colorval = random.nextInt(4);
Group {content: [
Circle {
translateX: bind vx
translateY: bind vy
radius: radius - 1
effect: DropShadow {
offsetX: 10
offsetY: 10
color: Color.BLACK
radius: 24
}
fill: RadialGradient {
radius: radius * .9;
focusX: radius * 0.2
focusY: radius * -8
proportional: false
stops: [
Stop {
offset: 0
color: Color.WHITE
}
Stop {
offset: 1
color: acolor[colorval];
}
]
}
onMousePressed: function (event) {
score_count = 0;
//1. for every event check to see if the a group has already been identified and this is the second click to initiate deletion
if (initialSelect) {
var flagged = [];//this is to check to see if only one ball is select FIX ME
for (node in group.content) {
var aball = (node as Ball2);
if (aball.initialSelect == true) {
insert aball into flagged;
}
}
if (sizeof flagged > 1) {//this is to check to see if only one ball is select FIX ME
for (flag in flagged) {
var f = (flag as Ball2);
f.flaggedfordeletion = true;
}
}
} else { //2. if we have a group identified but the user doesn't want to delete that group ( by selecting another groups ball) then
// remove the intialSelects and effects from the first group
for (node in group.content) {
var aball = (node as Ball2);
if (aball.initialSelect == true) {
aball.initialSelect = false;
aball.effect = null;
aball.score = "";
}
}
}
if (initialSelect == false) {
initialSelect = true;
findNeighbors(this);
for (node in group.content) {
var tball = (node as Ball2);
if (tball.effect != null) {
score_count = score_count + 1;
}
if (tball.checked == true) {
tball.checked = false;
}
}
if (score_count > 9) {
score_count = score_count * 9
}
if (score_count == 8 ) {
score_count = score_count * 7
}
if (score_count == 7) {
score_count = score_count * 6
}
if (score_count == 6) {
score_count = score_count * 5
}
if (score_count == 5) {
score_count = score_count * 5
}
if (score_count == 4) {
score_count = score_count * 3
}
if (score_count == 3) {
score_count = score_count * 2
}
displayScore();
}
}
}
Text {
font: Font {size: 12
}
x: bind vx - 5,
y: bind vy
textAlignment: TextAlignment.LEFT
content: bind "{score}";
}
]
}
}
}
var button = Group {
translateY: 610
translateX: 245
content: [
SwingButton {
text: "New Game"
action: function () {
initGroup()
}
}
]
}
var x = Stage {
title: "Bubble Breaker"
width: 600
height: 700
scene: Scene {
fill: Color.GREY;
content: bind [
button,
Text {
x: 220
y: 50
fill: Color.ORANGE
effect: Glow {
level: .8
input: InnerShadow {
choke: 0.05
radius: 2
color: Color.BLACK
}
}
font: Font {size: 30
}
content: "Score {totalScore}"
}
group
]
}
}Find the code on GitHub here
| Print article | This entry was posted by Eric Warriner on December 18, 2009 at 7:32 pm, and is filed under JavaFX. Follow any responses to this post through RSS 2.0. You can leave a response or trackback from your own site. |
