This is my entry to dude where's my pass contest for javaone
since this post came up as no.1 in Google blog search for javafx for no particular reason I now am obliged to convert it to a full fledged code, here's my step by step guide to what I had done
1. Motivation
I want to roll out an entry to Sun's dude where's my pass contest, I had no intention to really winning it(I am very very bad at it), but everything is worth a try ,It was supposed to be a simple video , but I am not an entertainer(see video if you have any doubts), I was browsing through dzone and came across this post
I never had developed even a simplest of game but it really fascinates me specially the storytelling, so here it goes , when I came to know about the free mario sprites(read GIFs if you please) and one thing led to another and this whole thing was conceptualized here is the screen-shot of directory structure, nothing fancy but it get the work done, and all I can come up given the time constraint.
here is description of images- castleone : the png of castle with javaone banner above it , created via GIMP
- code.png : the image of code when Mr. gosling try to find princess , created with JDarkroom and Paint
- jag.png : image of Mr.gosling animated
- jagback : back of of mr. Gosling , created with GIMP(although it doesn't look like a back image)
- others are self explanatory
since you have seen the video (I assume ) it is easy to present different snippets
I decided to use absolute positioning since it is a really quick and dirty work so no pre-planning
as for the scene I use LinearGradient to fill it t o give green ground and blue sky feel here is code of gradient
fill:LinearGradient {
startX : 0.0
startY : 0.0
endX : 0.0
endY : 1.0
stops: [
Stop {
color : Color.LIGHTBLUE
offset: 0.0
},
Stop {
color : Color.BLUE
offset: 0.8
},
Stop {
color : Color.LIGHTGREEN
offset: 0.81
},
Stop {
color : Color.GREEN
offset: 1.0
},
]
}
the code is self- explanatory , nothing fancy here
images used
The scene consist of few images, here are there code and details
- The castle , it's visible variable is bind to castleView boolean variable and set to true when Mr.Gosling said that one
- The mario image, xposition is binded to make it move
- Mr. gosling image , x: position is bind to make it move and image variable is bind to allow to switch between front and back view
- Code image which is displayed when Mr. Gosling tried to search for princess
ImageView {
fitHeight:200 fitWidth:200
translateX:350
translateY:40
visible:bind castleView
image: Image {
url: "{__DIR__}resources/castleone.png"
}
}
image = ImageView{
visible: bind marioV
x:bind marioX;
y:200
scaleX:2.0
scaleY:2.0
image: bind currentMarioImage
}
imageGos = ImageView {
x:bind gosX y:180
fitWidth:40 fitHeight:60
image :bind jagimg
}
ImageView {
visible :bind consoleV
translateX:20
translateY:20
fitHeight:150 fitWidth:300
image: Image {
url: " resources="" png="">
},
}
and the two mediafile which I accesed from my local WAMP server through http,
caution : don't place them in resources folder , mediafiles under jar are not yet supported
here's the code
// two mediafile recorded by me and played in the beginning and end
MediaView {
translateX:40 translateY:20
fitWidth:250 fitHeight:160
preserveRatio: true
visible:bind mediaV
mediaPlayer : playMedia = MediaPlayer {
autoPlay:false
media : Media {
source : "http://localhost/video.avi"
}
}
}
MediaView {
translateX:40 translateY:20
fitWidth:250 fitHeight:160
preserveRatio: true
visible:bind dudeV
mediaPlayer : playDude = MediaPlayer {
autoPlay:false
media : Media {
source : "http://localhost/pass.avi";
}
}
}
for some region my college profile server does not allow to fetch these files so attached jnlp won't play it
the magic
here is the timeline where all the magic happen
var marioMoveRight = Timeline {
repeatCount: 1
keyFrames : [
KeyFrame {
time: 3s
canSkip: true
values: [marioX=>280, gosX=>230]
action: function(){
currentMarioImage =marioStanding;
jagDialog=true;
marioDialog = false;
println("3s over")
}
}
KeyFrame {
time: 4s
action: function(){
marioDialog = true;
jagDialog=false;
println("4s over")
}
}
KeyFrame {
time: 5s
action: function(){
marioTalk = "{marioTalk}\n my princess is lost";
}
}
KeyFrame {
time: 6s
action: function () {
marioTalk = "She is in the Castle";
}
}
KeyFrame {
time: 7s
action: function () {
jagTalk = "Which castle";
jagDialog = true;
marioDialog = false;
}
}
KeyFrame {
time: 8s
action: function () {
jagTalk = "{jagTalk} \nThat one";
jagDialog = true;
marioDialog = false;
castleView = true;
}
}
KeyFrame {
time: 9s
action: function () {
jagTalk = "let me find her";
jagimg = jagbimg;
}
}
KeyFrame {
time: 10s
action: function () {
consoleV=true;
jagDialog = false
}
}
KeyFrame {
time: 12s
action: function () {
consoleV=false;
jagDialog = false;
mediaV=true;
playMedia.play();
}
}
KeyFrame {
time: 17s
action: function () {
marioDialog=true;
marioTalk = "Aw! man she is ugly , bulls";
playMedia.pause();
mediaV = false;
jagimg=jagfimg;
}
}
KeyFrame {
time: 18.5s
action: function () {
marioTalk = "perhaps, I \nshould go to javaone,";
}
}
KeyFrame {
time: 20s
action: function () {
marioTalk = "great minds \n'll ease me up";
}
}
KeyFrame {
time: 21.5s
action: function () {
marioTalk = "I wasted lifetime , hunting castles";
}
}
KeyFrame {
time: 23s
action: function () {
marioDialog = true;
jagDialog =false;
mediaV= false;
marioTalk = "Now I should do something worthwhile";
}
}
KeyFrame {
time: 24.5s
action: function () {
marioDialog = false;
jagDialog = true;
jagTalk = "Sorry dude, that one goes to your fake princess";
}
}
KeyFrame {
time: 26s
action: function () {
jagTalk = "he agreed to become \nthat, for it";
}
}
KeyFrame {
time: 27.5s
action: function () {
marioDialog = true;
jagDialog = false;
marioTalk = "yeah sure he deserve, 'll \nsee ya next year";
}
}
KeyFrame {
time: 29s
values: marioX =>280
action:function(){
marioDialog = false;
currentMarioImage = marioImage;
}
}
KeyFrame {
time: 30.5s
values: gosX => 230
action:function(){
jagimg=jagfimg;
}
}
KeyFrame{
time:32s
values: [marioX =>0 , gosX=>300]
action:function(){
dudeV=true;
playDude.play();
}
}
KeyFrame{
time:35s
action:function(){
stage.scene=newScene;
}
}
]
}
sorry for badly named variable
here is the complete code
/*
* Main.fx
*
* Created on 12 May, 2009, 10:58:17 AM
*/
package javaone;
import java.lang.Object;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.scene.Group;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.paint.*;
import javafx.scene.Scene;
import javafx.scene.shape.*;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.scene.effect.Glow;
/**
* @author Vaibhav Mishra
*/
var console="";
var marioV = true;;
var mediaV = false;
var image:ImageView;
var gosX=50;
var imageGos:ImageView;
var marioX=500;
var marioImage:Image = Image {
url:"{__DIR__}resources/mario_walkleft.gif"
};
var jagfimg= Image {
url: "{__DIR__}resources/jag.png";
}
var jagimg = jagfimg;
var jagbimg =Image {
url: "{__DIR__}resources/jagback.png";
}
var marioDialog = false;
var jagDialog = false;
var marioTalk = "Hi Mr. Gosling";
var jagTalk = "Hi Mario";
var videoSource = "http://localhost/video.avi";
var playMedia:MediaPlayer;
var marioStanding:Image = Image{
url:"{__DIR__}resources/mario_standleft.png";
}
var dudeV=false;
var castleView = false;
var consoleV = false;
var playDude:MediaPlayer ;
var currentMarioImage = marioImage;
var stage = Stage {
title: "JavaONE Podium"
width: 600
height: 300
scene: Scene {
fill:LinearGradient {
startX : 0.0
startY : 0.0
endX : 0.0
endY : 1.0
stops: [
Stop {
color : Color.LIGHTBLUE
offset: 0.0
},
Stop {
color : Color.BLUE
offset: 0.8
},
Stop {
color : Color.LIGHTGREEN
offset: 0.81
},
Stop {
color : Color.GREEN
offset: 1.0
},
]
}
content: [
ImageView {
fitHeight:200 fitWidth:200
translateX:350
translateY:40
visible:bind castleView
image: Image {
url: "{__DIR__}resources/castleone.png"
}
}
image = ImageView{
visible: bind marioV
x:bind marioX;
y:200
scaleX:2.0
scaleY:2.0
image: bind currentMarioImage
}
// gosling's image
imageGos = ImageView {
x:bind gosX y:180
fitWidth:40 fitHeight:60
image :bind jagimg
}
//goslings bubble which with inbound text, note text if more than avilable may overflow
Group{
visible :bind jagDialog
translateX:130
translateY:100
content:[
Rectangle {
width: 100, height: 60
arcWidth:20 arcHeight:20
fill: Color.LIGHTGRAY
}
Text {
translateX:10
translateY:20
wrappingWidth:100
font : Font {
size: 12
}
content: bind jagTalk
}
Polyline {
points : [70,50, 60,50,85, 75,70,50 ]
fill:Color.LIGHTGRAY
stroke:Color.LIGHTGRAY
}
]
}
//mario bubble constraint same as gosling's
Group{
visible :bind marioDialog
translateX:300
translateY:100
content:[
Rectangle {
width: 100, height: 60
arcWidth:20 arcHeight:20
fill: Color.LIGHTGRAY
}
Text {
translateX:10
translateY:20
wrappingWidth:100
font : Font {
size: 12
}
content: bind marioTalk
}
Polyline {
points : [30,50, 40,50,15, 75,30,50 ]
fill:Color.LIGHTGRAY
stroke:Color.LIGHTGRAY
}
]
}
ImageView {
visible :bind consoleV
translateX:20
translateY:20
fitHeight:150 fitWidth:300
image: Image {
url: "{__DIR__}resources/code.png"
},
}
// two mediafile recorded by me and played in the beginning and end
MediaView {
translateX:40 translateY:20
fitWidth:250 fitHeight:160
preserveRatio: true
visible:bind mediaV
mediaPlayer : playMedia = MediaPlayer {
autoPlay:false
media : Media {
source : "http://localhost/video.avi"
}
}
}
MediaView {
translateX:40 translateY:20
fitWidth:250 fitHeight:160
preserveRatio: true
visible:bind dudeV
mediaPlayer : playDude = MediaPlayer {
autoPlay:false
media : Media {
source : "http://localhost/pass.avi";
}
}
}
]
}
}
var newScene:Scene = Scene{
fill:Color.WHITE
content:[
Text {
translateX:200 translateY:130
font : Font {
size: 24
}
x: 10, y: 30
content: "Created in JavaFX"
fill:Color.BLUE
effect:Glow {
level: 1
}
}
]
}
var marioMoveRight = Timeline {
repeatCount: 1
keyFrames : [
KeyFrame {
time: 3s
canSkip: true
values: [marioX=>280, gosX=>230]
action: function(){
currentMarioImage =marioStanding;
jagDialog=true;
marioDialog = false;
println("3s over")
}
}
KeyFrame {
time: 4s
action: function(){
marioDialog = true;
jagDialog=false;
println("4s over")
}
}
KeyFrame {
time: 5s
action: function(){
marioTalk = "{marioTalk}\n my princess is lost";
}
}
KeyFrame {
time: 6s
action: function () {
marioTalk = "She is in the Castle";
}
}
KeyFrame {
time: 7s
action: function () {
jagTalk = "Which castle";
jagDialog = true;
marioDialog = false;
}
}
KeyFrame {
time: 8s
action: function () {
jagTalk = "{jagTalk} \nThat one";
jagDialog = true;
marioDialog = false;
castleView = true;
}
}
KeyFrame {
time: 9s
action: function () {
jagTalk = "let me find her";
jagimg = jagbimg;
}
}
KeyFrame {
time: 10s
action: function () {
consoleV=true;
jagDialog = false
}
}
KeyFrame {
time: 12s
action: function () {
consoleV=false;
jagDialog = false;
mediaV=true;
playMedia.play();
}
}
KeyFrame {
time: 17s
action: function () {
marioDialog=true;
marioTalk = "Aw! man she is ugly , bulls";
playMedia.pause();
mediaV = false;
jagimg=jagfimg;
}
}
KeyFrame {
time: 18.5s
action: function () {
marioTalk = "perhaps, I \nshould go to javaone,";
}
}
KeyFrame {
time: 20s
action: function () {
marioTalk = "great minds \n'll ease me up";
}
}
KeyFrame {
time: 21.5s
action: function () {
marioTalk = "I wasted lifetime , hunting castles";
}
}
KeyFrame {
time: 23s
action: function () {
marioDialog = true;
jagDialog =false;
mediaV= false;
marioTalk = "Now I should do something worthwhile";
}
}
KeyFrame {
time: 24.5s
action: function () {
marioDialog = false;
jagDialog = true;
jagTalk = "Sorry dude, that one goes to your fake princess";
}
}
KeyFrame {
time: 26s
action: function () {
jagTalk = "he agreed to become \nthat, for it";
}
}
KeyFrame {
time: 27.5s
action: function () {
marioDialog = true;
jagDialog = false;
marioTalk = "yeah sure he deserve, 'll \nsee ya next year";
}
}
KeyFrame {
time: 29s
values: marioX =>280
action:function(){
marioDialog = false;
currentMarioImage = marioImage;
}
}
KeyFrame {
time: 30.5s
values: gosX => 230
action:function(){
jagimg=jagfimg;
}
}
KeyFrame{
time:32s
values: [marioX =>0 , gosX=>300]
action:function(){
dudeV=true;
playDude.play();
}
}
KeyFrame{
time:35s
action:function(){
stage.scene=newScene;
}
}
]
}
override function run():Void{
stage;
marioMoveRight.play();
}
here is the link to jnlp for launch
same video on vimeo
dudepass from vaibhav mishra on Vimeo.
edit1: I removed blogger embedded video, because it scaled downthe video big-time and it totally sucks, added youtube link
edit2: don't know about quality , added vimeo link
edit3: 7 votes(2 of which are negative but still, it counts) thanks anyone who bothered enough
edit4: I modified post to make it more fulfilling and jsut realized my code ran 423 lines...

0 comments:
Post a Comment