Skip to content

Tag: netbeans

Inkscape and JavaFX working together

Inkscape is a open source cross-platform vector graphics editor application that I use daily to create draws.

When Project Nile was launched, me and some others guys complained about lack of open source alternatives in the workflow of creation with JavaFX. So we developed a module inside Inkscape that converts your SVG drawings to JavaFX code.

Features

  • Both are free and open source technologies, providing more tools on a powerful workflow for programmers and designers to develop Rich Internet Applications.
  • Comes natively with Inkscape. Install Inkscape an have JavaFX exporting out-of-the-box. No needing to install external plugins.
  • Provides a way to Inkscape users to make RIA applications reusing their work at drawing tool.
  • Provides a way to JavaFX programmers a tool for designers their graphics and interfaces.
  • Keep separated the JavaFX programming logic from the graphics resources but also provide a way to connect them.
  • They work on Windows, Mac OS, Linux, OpenSolaris and FreeBSD.

Workflow Example

I’ll show here step by step how would be a designer-developer workflow from designing graphical elements, such interfaces, to integrating it to a JavaFX Script code in NetBeans. In this example I’m using Inkscape 0.46-devel, build from the unstable sources and NetBeans 6.1 with the JavaFX module. See here how to build Inkscape from sources and here how to do some optimizations on the build.

Here’s a artwork (a modified version from another one I did in another post) made with Inkscape.

Doesn’t matter the complexity of the drawing it is made of discrete elements such circles, rectangles, paths and others. What the exporting module does is converting these SVG elements into JavaFX Scene Graph API elements.

To do that just click on File → Save As… or Shift+Ctrl+S.

Select JavaFx as the output format.

And chose a name. I’m saving the drawing as Girl.fx.

Now the drawing is a JavaFX class that extends from CustomNode. Once in your classpath (in this case the same directory of your main code) you can call it.

Girl{}

Another example, the famous SVG tiger.

Tiger{}

Actually, you can get the elements of your drawing as attributes nodes of the main node. We use the name you gave to your object to name the attributes.

import javafx.scene.paint.Color;
var girl = Girl{}
girl.rightiris.fill = Color.LIME;
girl.fringe.fill = Color.WHITE;
girl.backhair.fill = Color.DARKGRAY;
girl.hair.fill = Color.GRAY;

import javafx.scene.paint.Color;
var girl = Girl{}
girl.rightiris.fill = Color.GREEN;
girl.backhair.fill = Color.DARKRED;
girl.hair.fill = Color.RED;

You can also put event handling by code.

import javafx.input.MouseEvent;
var p = Player{}
p.x.onMouseClicked = function( e: MouseEvent ):Void {
java.lang.System.exit(0);
}

As a ordinary JavaFX Node, you can do whatever you do with a Node, like using it inside a application or applying effects or transformations.

import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.effect.SepiaTone;

var girl = Girl{
   scaleX: 0.5
   scaleY: 0.5
   effect: SepiaTone{}
}

Frame {
   visible: true
   stage: Stage {
      content: [girl]
   }
}

Using this approach you can have the reference and total control under all those elements that compose your drawing. You can design complete interfaces and attach event handling by code.

Source code

The module is already on the main Inkscape dev tree and working properly. I guess it will be officially released to all users in the next Inkscape release.

Still to do

  • Fix some problems with strokes.
  • Fix some problems in the gradients.
  • Use Zlib to create jfd files when the structure is too big.
  • Provide a dynamic method like getElementById in JavaScript.
  • Convert effects like blur to JavaFX effects.
  • There are some i18n errors in the module to be fixed.
  • Finish the adaption from Paths to SVGPaths.
  • Finish the adaption to the new JavaFX 1.0 syntax (coming December, 2).

Thanks!

Thanks for all guys that worked on this module and also on the projects Inkscape and JavaFX. Specially thanks for Bob Jamison, Jim Clarke, Joshua Marinacci and others. That’s my first contribution to a big free software, I’m very glad and I want to do much more. :D

JavaFX, Defuse the Bomb

I continue to develop simple games demos to feel better the strengths and weakness of JavaFX for game development.

Preview:

[youtube]hR2LiKiBUgE[/youtube]

Click to play via Java Web Start:

There’s a little JavaFX game demo where you have to transport a bomb to a defuse point without touching in the walls. I’m using the collision detection methods I described early in this post to detect when the bomb hits a wall and then explode or when a bomb is inside the defuse point and the game ends. As it’s only a demo, it’s just one single level, but adding more levels would be easy.

Basically we have this four images:


bomb.png


goal.png


floor.png


wall.png

The code is petty simple. A little bit more than 300 lines with even with all comments and declarations. I transform the bomb image into a draggable node, create a list of collidable nodes and a especial node, the goal. I check the collisions when the bomb is dragged by mouse, if it hits something, it blows up.

I use extensively the TimeLine class from the animation framework (javafx.animation) to create chained animations and even to control some game logic.

As I focused in the simplicity, I don’t declared any classes to after instantiate their objects. I just was using common classes from JavaFX and putting logic on ir throught event and binding to external variables.

import javafx.application.Frame;
import javafx.application.Stage;
import javafx.animation.Timeline;
import javafx.animation.KeyFrame;
import javafx.animation.Interpolator;
import javafx.scene.image.ImageView;
import javafx.scene.image.Image;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.geometry.Circle;
import javafx.scene.geometry.Rectangle;
import javafx.scene.geometry.Shape;
import javafx.scene.text.Text;
import javafx.scene.Font;
import javafx.scene.FontStyle;
import javafx.input.MouseEvent;

/* Fade variable modified in some animations and used in the fadescreen */
var fade = 0.0;

/* The Bomb */
var lock = false;
var tx = 0.0;
var ty = 0.0;
var bomb:Node = Group{
    opacity: bind bombfade;
    content: [
        ImageView {
            image: Image {
                url: "{__DIR__}/bomb.png"
            }
        },
        Circle {
            centerX: 45, centerY: 21, radius: 7, fill: Color.LIME
            opacity: bind led
        },
        Circle {
            centerX: 30, centerY: 30, fill: Color.WHITE
            radius: bind fireradius
        },
    ],
    var startX = 0.0;
    var startY = 0.0;
    translateX: bind tx
    translateY: bind ty

    onMousePressed: function( e: MouseEvent ):Void {
        if (lock) {return;}
        startX = e.getDragX() - tx;
        startY = e.getDragY() - ty;
    }

    onMouseDragged: function(e:MouseEvent):Void {
        if (lock) {return;}
        tx = e.getDragX() - startX;
        ty = e.getDragY() - startY;
        checkcollissions();
    }
}

/* Big rectangle that covers all the screen (bomb explosion or game end) */
var fadescreen = Rectangle {
    x: 0, y: 0, width: 640, height: 480, fill: Color.WHITE
    opacity: bind fade
}

/* The wood floor image for the scenario. */
var floor = ImageView {
    image: Image {
        url: "{__DIR__}/floor.png"
    }
}

/* The goal image where the bomb should be placed. */
var goal = ImageView {
    x: 470, y: 360
    image: Image {
        url: "{__DIR__}/goal.png"
    }
}

/* List of obstacles nodes that the bomb can collide with. */
var obstacles = [
    Rectangle { x: 120, y: 0, width: 100, height: 300, fill: Color.BLACK},
    Rectangle { x: 350, y: 200, width: 100, height: 300, fill: Color.BLACK},
    Rectangle { x: 370, y: 50, width: 50, height: 50, fill: Color.BLACK},
    Rectangle {
        x: 250, y: 120, translateX: bind move, width: 100, height: 50
        fill: Color.BLACK
    },
];

/* Visible representations of obstacles */
var wallimage = Image {
    url: "{__DIR__}/wall.png"
}
var walls = for(obs in obstacles){
    ImageView {
        x: obs.x, y: obs.y, translateX: bind obs.translateX
        clip: obs, image: wallimage
    }
}

/* Animation for a blinking green led */
var led = 0.0;
var bombclock = Timeline {
    repeatCount: Timeline.INDEFINITE
    autoReverse: true
    keyFrames : [
        KeyFrame {
            time : 0s
            values : led => 0.0 tween Interpolator.LINEAR
        },
        KeyFrame {
            time : 1s
            values : led => 1.0 tween Interpolator.LINEAR
        }
    ]
}

/* Animation for the bomb explosion and game reset */
var fireradius = 0.0;
var explosion:Timeline = Timeline {
    repeatCount: 1
    keyFrames : [
        KeyFrame {
            time : 0s
            values : [
                fireradius => 0.0,
                fade => 0.0
            ]
        },
        KeyFrame {
            time : 2s
            values : [
                fireradius => 200.0 tween Interpolator.LINEAR,
                fade => 1.0 tween Interpolator.LINEAR
            ]
            action: gamereset
        },
        KeyFrame {
            time : 3s
            values: fade => 0.0 tween Interpolator.LINEAR
        },
    ]
}

/* Reset variables for initial values */
function gamereset(){
    lock = false;
    fireradius = 0.0;
    tx = 0.0;
    ty = 0.0;
    bombfade = 1.0;

    moveblock.start();
    specialcollison.start();
    bombclock.start();
}

/* Animation when the bomb reaches the goal. Bomb disapear. */
var bombfade = 1.0;
var bomdisapear = Timeline {
    repeatCount: 1
    keyFrames : [
        KeyFrame {
            time : 1s
            values: [
                        bombfade => 0.0 tween Interpolator.EASEBOTH,
                        fade => 0.0
            ]
        },
        KeyFrame {
            time : 2s
            values:
                    fade => 1.0 tween Interpolator.LINEAR;
            action: gamereset
        },
        KeyFrame {
            time : 3s
            values:
                    fade => 0.0 tween Interpolator.LINEAR;
        },
    ]
}

/* Animation for a moving block. */
var move = 0.0;
var moveblock = Timeline {
    repeatCount: Timeline.INDEFINITE
    autoReverse: true
    keyFrames : [
        KeyFrame {
            time : 0s
            values :
                    move => 0.0
        },
        KeyFrame {
            time : 3s
            values :
                    move => 200.0 tween Interpolator.EASEBOTH
        },
    ]
}

/* Check and handle possible collisions. */
function checkcollissions(): Void {
    if(checkobstacles()){
        lock = true;
        specialcollison.stop();
        moveblock.stop();
        explosion.start();
    }

    if (insidenode(bomb,goal)) {
        lock = true;
        moveblock.stop();
        bomdisapear.start();
    }
}

/* There was a bug, when the bomb is stopped, not been gragged, in front of
the moving block, it could pass through it because checkcollissions() was
only called on mouse moving. This make sure checking this special case. */
var specialcollison:Timeline = Timeline {
    repeatCount: Timeline.INDEFINITE
    keyFrames : [
        KeyFrame {
            time : 1s/5
            action: function(){
                if(hitnode(obstacles[sizeof obstacles-1], bomb)){
                    lock = true;
                    moveblock.stop();
                    explosion.start();
                    specialcollison.stop();
                }
            }
        }
    ]
}

/*
* The next four functions are for collision detection.
* @See https://silveiraneto.net/2008/10/30/javafx-rectangular-collision-detection/
*/

/*
 * Check collision between two rectangles.
 */
function collission(ax, ay, bx, by, cx, cy, dx, dy): Boolean {
    return not ((ax > dx)or(bx < cx)or(ay > dy)or(by < cy));
}

/*
 * Check if the first rectangle are inside the second.
 */
function inside (ax, ay, bx, by, cx, cy, dx, dy):Boolean{
    return ((ax > cx) and (bx < dx) and (ay > cy) and (by < dy));
}

function hitnode(a: Node, b:Node): Boolean {
    return (collission(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getBoundsX(), b.getBoundsY(),
        b.getBoundsX() + b.getWidth(), b.getBoundsY() + b.getHeight()
    ));
}

function insidenode(a:Node,b:Node):Boolean {
    return (inside(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getBoundsX(), b.getBoundsY(),
        b.getBoundsX() + b.getWidth(), b.getBoundsY() + b.getHeight()
    ));
}

/*
* Check collision of bomb against each obstacle.
*/
function checkobstacles(): Boolean{
    for(obst in obstacles){
        if (hitnode(obst, bomb)){
            return true;
        }
    }
    return false;
}

/* Pack visual game elements in a Frame's Stage, unresizable. */
Frame {
    title: "Defuse the Bomb"
    width: 640
    height: 480
    resizable: false
    closeAction: function() {
        java.lang.System.exit( 0 );
    }
    visible: true

    stage: Stage {
        content: bind [floor, goal, walls, bomb, fadescreen]
    }
}

/* Call gamereset to set initial values and start animations */
gamereset();

Downloads:

JavaFX, rectangular collision detection

[youtube]NRwRTHPGg6M[/youtube]

In a game I wrote some years ago we handled simple rectangular collisions. Given the points:

We did:

// returning 0 means collision
int collision(int ax, int ay, int bx, int by, int cx, int cy, int dx, int dy){
	return ((ax > dx)||(bx < cx)||(ay > dy)||(by < cy));
}

I'll show here a little demo about how implement simple rectangular collisions on JavaFX.
First I created a movable rectangle using the same idea of draggable nodes I already had posted before.

import javafx.input.MouseEvent;
import javafx.scene.geometry.Rectangle;

public class MovableRectangle extends Rectangle {
    private attribute startX = 0.0;
    private attribute startY = 0.0;

    public attribute onMove = function(e:MouseEvent):Void {}

    override attribute onMousePressed = function(e:MouseEvent):Void {
        startX = e.getDragX()-translateX;
        startY = e.getDragY()-translateY;
        onMove(e);
    }

    override attribute onMouseDragged = function(e:MouseEvent):Void {
        translateX = e.getDragX()-startX;
        translateY = e.getDragY()-startY;
        onMove(e);
    }
}

In the main code I some important things:

  • colide, a color that represents the collision effect. White means no collision and gray means collision.
  • rec1 and rec2, the two rectangles that can collide.
  • checkcollision() the function that checks and handles a possible collision.

Here is the main code:

import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.geometry.Rectangle;
import javafx.scene.paint.Color;
import javafx.input.MouseEvent;

var colide = Color.WHITE;

function checkcollision():Void {
    if (
        (rec1.getBoundsX() > rec2.getBoundsX() + rec2.getWidth()) or
        (rec1.getBoundsX() + rec1.getWidth() < rec2.getBoundsX()) or 
        (rec1.getBoundsY() > rec2.getBoundsY() + rec2.getHeight()) or 
        (rec1.getBoundsY() + rec1.getHeight() < rec2.getBoundsY())
    ) {
        colide = Color.WHITE
    } else {
        colide = Color.LIGHTGRAY
    }
}

var rec1: MovableRectangle = MovableRectangle {
    x: 10, y: 10, width: 50, height: 60, fill: Color.RED
    onMove: function(e:MouseEvent):Void {
        checkcollision()
    }
}

var rec2: MovableRectangle = MovableRectangle {
    x: 100, y: 100, width: 70, height: 30, fill: Color.BLUE
    onMove: function(MouseEvent):Void {
        checkcollision()
    }
}
Frame {
    title: "Rectangular Collisions", width: 300, height: 300
    closeAction: function() { 
        java.lang.System.exit( 0 ); 
    }
    visible: true

    stage: Stage {
        fill: bind colide
        content: [rec1, rec2]
    }
}

Try it via Java Web Start:

Java Web Start

Some considerations:

  • You can use rectangular collisions to create bounding boxes to handle collisions in more complex shapes or sprites. Is a common approach in 2d games to avoid more expensive calculations.
  • There are space for optimizations.
  • In this case I'm using only two objects. Some problems raises when I have N objects to handle.

More generally, we can code:

function collission(ax, ay, bx, by, cx, cy, dx, dy): Boolean {
    return not ((ax > dx)or(bx < cx)or(ay > dy)or(by < cy));
}

function hitnode(a: Node, b:Node): Boolean{
    return (collission(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getX(), b.getY(),
        b.getX() + b.getWidth(), b.getY() + b.getHeight()
    ));
}

This way we can pass just two bounding boxes to hitnode and easily check collision of a node against a list of bounding boxes nodes.
Using the same approach I also wrote this function to test if a Node is inside another Node:

function inside (ax, ay, bx, by, cx, cy, dx, dy):Boolean{
    return ((ax > cx) and (bx < dx) and (ay > cy) and (by < dy));
}

function insidenode(a:Node,b:Node):Boolean{
    return (inside(
        a.getBoundsX(), a.getBoundsY(),
        a.getBoundsX() + a.getWidth(), a.getBoundsY() + a.getHeight(),
        b.getBoundsX(), b.getBoundsY(),
        b.getBoundsX() + b.getWidth(), b.getBoundsY() + b.getHeight()
    ));
}

Soon I'll post game examples showing how to use this method and others collission detection methods.

Downloads:

Ainda essa semana

Ainda essa semana eu vou fazer três palestras. Olhe aí se você não vai estar por perto. ;)

  • 29/10 – Quarta-feira 20:30 – Palestra sobre NetBeans no na VII Semana de TI e Telecomunicações da FIC.
  • 30/10 – Sexta-feira 09:30 – Palestra sobre OpenSolaris também na VII Semana de TI e Telecomunicações da FIC.
  • 01/11Sábado 15:20 – Palestra Apresentando o CEJUG e o poder do Java em Iguatu no Encontro PHP & Java.

SCSNI Study Guide

This is a draft of study guide based on SCSNI (Sun Certified Specialist Netbeans IDE) exam objectives.

SCSNI Study Guide
Exam Objetive Resources
Section 1: IDE Configuration
1.1 Demonstrate the ability to configure the functionality available in the IDE, including using enabling and disabling functionality and using the Plugin Manager.
1.2 Explain the purpose of the user directory and the netbeans.conf file and how these can be used to configure the IDE.
1.3 Demonstrate the ability to work with servers in the IDE, such as registering new server instances and stopping and starting servers.
1.4 Describe how to integrate external libraries in the IDE and use them in coding and debugging your project.
1.5 Demonstrate knowledge of working with databases in the IDE, including registering new database connections and tables running SQL scripts.
1.6 Describe how to integrate and use different versions of the JDK in the IDE for coding, debugging, and viewing Javadoc documentation.
Section 2: Project Setup
2.1 Describe the characteristics and uses of a free-form project.
2.2 Demonstrate the ability to work with version control systems and the IDE. (Which VCS’s are available, which ones you need an external client for, how to pull sources out of a repository, view changes, and check them back in).
2.3 Describe the ways in which you can change the build process for a standard project, such as configuring project properties and modifying the project’s Ant build script.
2.4 Configure your project to compile against and run on a specific version of the JDK.
Section 3: Java SE Development
3.1 Demonstrate the ability to create NetBeans projects from the source code of an existing Java SE program.
3.2 Describe how to manage the classpath of a Java SE project, including maintaining a separate classpath for compiling and debugging.
3.3 Demonstrate the knowledge of the NetBeans GUI Builder and the ability to lay out and hook up basic forms using it.
3.4 Demonstrate the ability to package and distribute a built Java Desktop project for use by another user.
Section 4: Java EE Web Development
4.1 Describe how to create a NetBeans project from the source code of an existing Web application.
4.2 Distinguish between a visual web application and web application.
4.3 Demonstrate knowledge of which web frameworks are available in NetBeans IDE and how they are added to and used in a web application.
4.4 Describe how to monitor HTTP requests when running a web application.
4.5 Demonstrate a knowledge of basic tasks related to building and deploying web applications to a server, such as changing the target server and undeploying an application.
Section 5: Editing
5.1 Describe the purpose and uses of refactoring and demonstrate the ability to perform basic refactoring on Java source code.
5.2 Describe how to use the Options window to change the default appearance and behavior of the Source Editor.
5.3 Describe the ways that the IDE highlights errors in source code and the tools the IDE offers for correcting those errors.
5.4 Demonstrate the ability to use editor hints, such as implementing all the methods for an implemented interface
5.5 Demonstrate the ability to use live code templates such as automatic generation of constructors, try/catch loops, and getters and setters.
Section 6: Testing, Profiling, and Debugging
6.1 Demonstrate the ability to work with JUnit tests in the IDE, such as creating JUnit tests and interpreting JUnit test output.
6.2 Describe how to debug a local (desktop) application, including setting breakpoints and stepping through code.
6.3 Describe the difference between local and remote debugging and describe how to debug a remote (web) application.
6.4 Describe the purpose of profiling applications and how to profile a local desktop application in the IDE.

More useful resources:

Please, collaborate in the comments with others resource links (with section number). Let’s complete this guide.

JavaFX Overview Slides

My slides about a overview on JavaFX at our last CEJUG event.

JavaFX Overview

View SlideShare presentation or Upload your own. (tags: javafx ria)

Downloads:

Café com Tapioca na Christus

Café com Tapioca na Christus

Here a little screncast showing the live preview feature on the NetBeans JavaFX Plugin.

[youtube]vCWQtQgdpUA[/youtube]

You can also download the orignal screencast in higher resolution netbeans_javafx_preview.ogg (15 Mb). Photos of the presentation at my Flickr album.