Mostrando entradas con la etiqueta graficos. Mostrar todas las entradas
Mostrando entradas con la etiqueta graficos. Mostrar todas las entradas

martes, 16 de junio de 2009

Pastello... JavaFX crayon phyics


Me suscribi para seguir el Twitter de JavaFX y el primer post que encontré me pareció entretenido. Se llama Pastello. Es un juego de "puzzle" en que debes dibujar la solución para que una bolita llegue hasta donde está la estrella.

Lo interesante del proyecto es la FISICA de los elementos. Así, por ejemplo, puedes dejar caer bolitas sobre la bola principal, de manera que esta gire subiendo por una rampa que dibujaste con un triangulo. También puedes agregar contrapesos, etc. Un tanto adictivo! ;D

Jugar Pastello

Sitio del proyecto Pastello

viernes, 5 de junio de 2009

JavaFX 1.2 incluye APIs para gráficos (charts)


Este es el código para agregar un gráfico de Pie en JavaFX

package piechartsample;

import javafx.scene.chart.*;
import javafx.scene.Scene;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;

var name = ["Java", "JavaFX", "MySQL", "Netbeans", "Others"];
var val = [20, 12, 25, 22, 30];


var r : PieChart.Data[] = [];
for(i in [0..4]) {
insert PieChart.Data {
action: function() {
print("Name :: {name[i]}");
}
label : name[i] value : val[i] } into r; }


var chart = PieChart3D {
data : r
pieLabelFont: Font.font("dialog", FontWeight.REGULAR, 8);
pieLabelVisible: true
pieValueVisible: true
pieToLabelLineOneLength: 3
pieToLabelLineTwoLength : 6

}

var st = Stage {
height: 420
width: 480
title:"Pie Chart 3D"
scene: Scene {
content: [
chart
]
}
}

Este es el código para un gráfico de "burbujas":


package bubblechart;

import javafx.scene.chart.*;
import javafx.scene.chart.part.*;
import javafx.scene.paint.Color;
import javafx.scene.Scene;
import javafx.stage.Stage;
var x: Number[] = [30, 60, 10, 100,50];
var y: Number[] = [40,20,90,40,23];
var radius: Number[] = [10,13,7,10,5];

var x1: Number[] = [13, 20, 100, 30,50];
var y1: Number[] = [100,80,60,40,20];
var radius1: Number[] = [7,13,10,6,12];

var r : BubbleChart.Data[] = [];
var r1: BubbleChart.Data[] = [];
for(i in [0..4]) {
insert BubbleChart.Data {fill: Color.YELLOWGREEN xValue : x[i] yValue : y[i] radius: radius[i] }into r;
insert BubbleChart.Data {fill: Color.RED xValue : x1[i] yValue : y1[i] radius: radius1[i] }into r1;

}
var s1 : BubbleChart.Series = BubbleChart.Series{data: [r,r1]};
var BubbleChartData : BubbleChart.Series[] = [s1];
var chart = BubbleChart {
title : "BubbleChart"
xAxis : NumberAxis{
lowerBound: 0
upperBound : 150
label: "SomeX"
visible: true
axisStrokeWidth: 1
tickUnit : 20
tickLabelsVisible: true

}
yAxis : NumberAxis{
lowerBound: 0
upperBound : 150
tickUnit: 20
label: "SomeY"
visible: true
tickLabelsVisible: true
}
data : BubbleChartData
}

var st = Stage {
height: 520
width: 640
title:"Bubble Chart"
scene: Scene {
content: [
chart
]
}
}


sábado, 31 de enero de 2009

JavaFX: ¿Cuantas bolitas? (test de rendimiento gráfico)


Este ejercicio contiene 3 controles de barra que permiten ajustar:

1) El número de bolas rebotando en la ventana;
2) La transparencia de las bolas;
3) El radio de las bolas.



Cada nueva bola que se agrega, lo hace con un efecto (cambia el radio un par de veces) y luego continua rebotando entre los márgenes de la ventana. Si se aumenta el tamaño de la ventana, el area de desplazamiento aumenta, si se reduce, las bolas que se encuentran más alla del nuevo margen, regresan al centro de la ventana.

Un area de texto muestra el número de bolas en la ventana, el porcentaje de transparencia y el radio de los círculos.

Una instrucción importante es "canSkip:true", en el Timeline que actualiza la posicion de las bolas (y que por lo tanto, las redibuja). Esta instrucción evita que la CPU se sobrecargue de trabajo y solo realiza la actualización de las bolas si hay capacidad de procesamiento disponible. Intenten con unas 200 bolas y quiten el canSkip y veran como el programa se "pega".

Archivo Maix.fx
package howmany;

import javafx.scene.*;
import javafx.stage.Stage;
import javafx.ext.swing.SwingSlider;
import javafx.scene.layout.VBox;
import javafx.scene.text.*;

// si cambia tamaño de la ventana
// reposiciona los circulos mas alla del margen
var maxX=250.0 on replace { circles.resetPos() };
var maxY=250.0 on replace { circles.resetPos() };

// seleccion numero de bolas
var selector = SwingSlider {
minimum: 0
maximum: 100
value: 0
vertical: false
};

// transparencia de las bolas
var transparency = SwingSlider {
minimum: 0
maximum: 100
value: 50
vertical: false
};

// radio de las bolas
var radius = SwingSlider {
minimum: 0
maximum: 40
value: 20
vertical: false
};

// texto para desplegar valores
var total = Text {
font: Font { size: 18 }
textOrigin:TextOrigin.TOP;
};

// componente que contiene los circulos
var circles = element {
balls:bind selector.value;
radius:bind radius.value;
level:bind transparency.value / 100.0;
display: total
maxX:bind maxX
maxY:bind maxY
};

Stage {
// si cambia tamaño de la ventana
// actualiza variables con dimensiones
width: bind maxX with inverse
height: bind maxY with inverse

scene: Scene { content: [
circles,
VBox { content: [
selector,
transparency,
radius,
total ]
} ]
}
}


Archivo element.fx

package howmany;

import javafx.stage.Stage;
import javafx.scene.*;
import javafx.scene.text.*;
import javafx.scene.shape.Circle;
import javafx.scene.paint.Color;
import javafx.animation.*;
import java.lang.Math;


// clase que extiende circulos
class ball extends Circle {

// "sobreescribe" los parametros del circulo normal,
// de manera de tener los valores en la nueva clase
override var stroke = null;
override var fill = Color.RED;
override var centerX = 100;
override var centerY = 100;
override var radius = 10;
override var scaleX;
override var scaleY;

public var incx;
public var incy;

// mueve el circulo en los incrementos de la instancia
function move():Void {
centerX += incx;
centerY += incy;
if (centerX<0 or centerX>maxX) then
incx = -incx;
if (centerY<0 or centerY>maxY) then
incy = -incy;
};

// efecto para cuando crea el circulo
// cambia un par de veces de tamaño (como rebote)
var dropIn = Timeline {
repeatCount:5
autoReverse:true
keyFrames: [
at (0s) { scaleX => 2.0; scaleY => 2.0 }
at (0.3s) { scaleX => 1.0; scaleY => 1.0 }
]
};

// al crear el circulo, dispara el efecto de rebote
postinit {
dropIn.play();
};

};


// clase que contiene a todos los circulos
public class element extends CustomNode {

public var balls = 50.0;
public var display = Text { };
public var maxX;
public var maxY;
// si cambia la transparencia
public var level = 1.0 on replace {
// actualiza la opacidad de todos los circulos
for (obj in objs) obj.opacity = level; };
// si cambia el radio
public var radius = 10.0 on replace {
// actualiza el radio de todos los circulos
for (obj in objs) obj.radius = radius; };

// arreglo que contiene todos los circulos
var objs:ball[];
// colores que asigna a los circulos
var colors:Color[]=[
Color.RED, Color.BLUE, Color.YELLOW,
Color.PURPLE, Color.CYAN];

var i=0;

// agrega nuevo circulo al componente
function addBall():Void {
var ix=Math.random()*15 - 7;
var iy=Math.random()*15 - 7;
var circ = ball {
centerX:maxX/2
centerY:maxY/2
incx: ix
incy:iy
radius:radius
fill: colors[i mod sizeof colors]
opacity:level
};
insert circ into objs;
};


// crea el componente con los circulos
override function create():Node {

// chequea si debe agregar o quitar circulos
Timeline {
repeatCount:Timeline.INDEFINITE
keyFrames: [
KeyFrame {
time: 0.2s
action: function():Void {
display.content=
"{sizeof objs} / {(level*100) as Integer}% / {radius}";
if (sizeof objs < balls) then {
addBall();
i++;
}
if (sizeof objs > balls) then
delete objs[0];
}
}
]
}.play();

// mueve los circulos
Timeline {
repeatCount:Timeline.INDEFINITE
keyFrames: [
KeyFrame {
time: 0.04s
// para evitar que se sobrecargue de trabajo
canSkip: true
action: function():Void {
for (obj in objs)
obj.move();
}
}
]
}.play();

// retorna el componente con los circulos
Group {
content: bind objs
};

};

// reposicion los circulos si excende el margen
public function resetPos():Void {
for (obj in objs) {
var pos = obj.boundsInScene;
if (pos.maxX > maxX) then
obj.centerX = maxX/2 ;
if (pos.maxY > maxY) then
obj.centerY = maxY/2 ;
}
};

}

miércoles, 21 de enero de 2009

JavaFX: Integración con recursos Adobe Illustrator


JavaFX permite integrar fácilmente recursos gráficos en el código, permitiendo dar una apariencia más rica y atractiva a las aplicaciones y juegos desarrollados con JavaFX.



Para traspasar recursos de Adobe Illustrator a JavaFX, tienes que instalar el JavaFX Production Suite.

Una copia completa del proyecto Netbeans -con los recursos Adobe Illustrator- está aquí ... (Download Complete Project)


archivo CDartUI.fx


package animatecd;

import javafx.scene.Node;
import javafx.fxd.UiStub;
import javafx.scene.Group;

public class CDartUI extends UiStub {

override public var url = "{__DIR__}CDart.fxz";
public var Artwork: Node;

override protected function update() {

Artwork=getNode("Artwork");
}

}

Archivo Main.fx

package animatecd;

import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.text.Text;
import javafx.scene.text.Font;
import javafx.scene.Group;
import javafx.animation.Timeline;

// carga imagenes de Illustrator
var ui = CDartUI {};
var scale:Number;

Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: true
keyFrames: [
at(0s) { scale => 0.1 }
at(10s) { scale => 12.0 }
]
}.play();

Stage {
width: 400
height: 400
scene: Scene {
content: Group {
content:ui
scaleX:bind scale
scaleY:bind scale
translateX:bind scale*80
translateY:bind scale*80
rotate:bind scale*36
}
}
}

{__DIR__} indica que el archivo CDart.fxz está en el mismo directorio que las clases compiladas (basta poner el archivo CDart.fxz en el directorio que contiene el código fuente para que Netbeans lo copie al directorio correspondiente con la copia para distribuir).

Si el archivo de Adobe Illustrator contiene mas de un elemento (layers identificados con la etiqueda "jfx:" y el nombre del elemento), puede acceder a las propiedades usando (en este caso) ui.Artwork.nombre_de_la_propiedad. Esto le permitirá mover los elementos contenido en el archivo Adobe, de manera independiente. Otras propiedades que puede alterar son... cambiar su opacidad (transparencia), rotarlo, escalarlo, etc.

sábado, 6 de diciembre de 2008

JavaFX: La rueda de la fortuna


Este ejemplo genera una "rueda" de colores de distinta intensidad y que gira... el ejemplo original viene incluido con Netbeans 6.5, yo sólo le agregué el giro. Pueden modificar la velocidad del giro cambiando el tiempo en el Timeline (0.5s, o medio segundo para una vuelta completa).

Básicamente, lo único que agregué fue un rotate: bind angle; asociado a la rueda ya generada incluida en la escena (Scene) y una "linea de tiempo" (Timeline) que incrementa el ángulo entre 0º y 360º, en el tiempo especificado. Una vez que llega a 360º, comienza por el ángulo 0º. Así queda la impresión que la ruega gira indefinidamente.



package color;

import javafx.scene.Group;
import javafx.scene.CustomNode;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.shape.Arc;
import javafx.scene.shape.ArcType;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.animation.Timeline;
import javafx.lang.FX;

class ColorWheelNode extends CustomNode {

var segments : Number = 12;
var steps : Number = 6;
var radius : Number = 95;
var stripes : Arc[];

override function create() : Node {
return Group {
content: bind stripes
};
}

init {
// Set radius
var r = radius;
var rStep = radius / steps;
var colors : Color[];
for( i in [1..
segments + 1] ) {
insert Color.rgb( 255, 255, 0 ) into colors;
}
for( i in [0..
steps - 1] ) {
colors[1] = Color.rgb( 255 - ( 255 / steps * i ), 255 - ( 255 / steps * i ), 0 );
colors[2] = Color.rgb( 255 - ( 255 / steps ) * i, ( 255 / 1.5 ) - (( 255 / 1.5 ) / steps ) * i, 0 );
colors[3] = Color.rgb( 255 - ( 255 / steps ) * i, ( 255 / 2 ) - ( ( 255 / 2 ) / steps ) * i, 0 );
colors[4] = Color.rgb( 255 - ( 255 / steps ) * i, ( 255 / 2.5 ) - (( 255 / 2.5 ) / steps ) * i, 0 );
colors[5] = Color.rgb( 255 - ( 255 / steps ) * i, 0, 0 );
colors[6] = Color.rgb( 255 - ( 255 / steps ) * i, 0, ( 255 / 2 ) - (( 255 / 2 ) / steps ) * i );
colors[7] = Color.rgb( 255 - ( 255 / steps ) * i, 0, 255 - ( 255 / steps ) * i );
colors[8] = Color.rgb(( 255 / 2 ) - (( 255 / 2 ) / steps ) * i, 0, 255 - ( 255 / steps ) * i );
colors[9] = Color.rgb( 0, 0, 255 - ( 255 / steps ) * i );
colors[10] = Color.rgb( 0, 255 - ( 255 / steps ) * i, ( 255 / 2.5 ) - (( 255 / 2.5 ) / steps ) * i );
colors[11] = Color.rgb( 0 , 255 - ( 255 / steps ) * i, 0 );
colors[12] = Color.rgb(( 255 / 2 ) - (( 255 / 2 ) / steps ) * i, 255 - ( 255 / steps ) * i, 0 );
for( j in [1..segments] ) {
var c = colors[
j.intValue()];
insert Arc {
centerX: 100,
centerY: 100
radiusX: r ,
radiusY: r
startAngle: 360 / segments * ( segments - j - 0.5)
length: 360 / segments
fill: c
type: ArcType.ROUND
} into stripes;
}
r -= rStep;
}
}
}


var angle:Integer;

Timeline {
repeatCount: Timeline.INDEFINITE
autoReverse: false
keyFrames: [
at (0s) {angle => 0},
at (0.5s) {angle => 360},
]
}.play();



Stage {
scene: Scene {
fill: Color.GRAY
content: ColorWheelNode {
rotate: bind angle;
}
}

width: 216
height: 232
title: "Color Wheel"
}