Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFx 2.0 - an approach to game sprite animation

Wow... JavaFx 2 has thrown me for a loop when it comes to game programming. I am trying to etermine how best to approach player controlled sprite animation. (ie. making enemies and things and the player animate).

I know how to write code to read a spritesheet and set up a game loop in AS3 or Java swing... but it I'm having a real tough time wrapping my head around how the animation loop in my game should interact with whatever component of FX it is that renders.

I've studied the api. There is a TranslateTransition class. But it seems excessive compared to other languages. And eberything else looks completely interface based or just too limited.

I'm reading Pro JavaFx2 by Weaver... and man am I having trouble replicating that coding style. But I can read it find :) Don't know whether to love or hate this beast yet.

Any suggestions?

like image 359
Marc H Avatar asked Feb 20 '23 09:02

Marc H


2 Answers

Read this blog entry: http://blog.netopyr.com/2012/03/09/creating-a-sprite-animation-with-javafx/

This is best realization of JavaFX sprite animation ever :)

like image 198
Sergey Grinev Avatar answered Feb 23 '23 00:02

Sergey Grinev


I'm a little late to the party on this one, but figured I'd contribute my solution to sprite animation with JavaFX. Here's a class you can paste into your own projects to display a sprite animation using ImageView, the animation is frame-rate independent.

import javafx.animation.AnimationTimer;
import javafx.geometry.Rectangle2D;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;

public class ImageViewSprite extends AnimationTimer {


    private final ImageView imageView; //Image view that will display our sprite

    private final int totalFrames; //Total number of frames in the sequence
    private final float fps; //frames per second I.E. 24

    private final int cols; //Number of columns on the sprite sheet
    private final int rows; //Number of rows on the sprite sheet

    private final int frameWidth; //Width of an individual frame
    private final int frameHeight; //Height of an individual frame

    private int currentCol = 0;
    private int currentRow = 0;

    private long lastFrame = 0;

    public ImageViewSprite(ImageView imageView, Image image, int columns, int rows, int totalFrames, int frameWidth, int frameHeight, float framesPerSecond) {
        this.imageView = imageView;
        imageView.setImage(image);
        imageView.setViewport(new Rectangle2D(0, 0, frameWidth, frameHeight));

        cols = columns;
        this.rows = rows;
        this.totalFrames = totalFrames;
        this.frameWidth = frameWidth;
        this.frameHeight = frameHeight;
        fps = framesPerSecond;

        lastFrame = System.nanoTime();
    }

    @Override
    public void handle(long now) {
        int frameJump = (int) Math.floor((now - lastFrame) / (1000000000 / fps)); //Determine how many frames we need to advance to maintain frame rate independence

        //Do a bunch of math to determine where the viewport needs to be positioned on the sprite sheet
        if (frameJump >= 1) {
            lastFrame = now;
            int addRows = (int) Math.floor((float) frameJump / (float) cols);
            int frameAdd = frameJump - (addRows * cols);

            if (currentCol + frameAdd >= cols) {
                currentRow += addRows + 1;
                currentCol = frameAdd - (cols - currentCol);
            } else {
                currentRow += addRows;
                currentCol += frameAdd;
            }
            currentRow = (currentRow >= rows) ? currentRow - ((int) Math.floor((float) currentRow / rows) * rows) : currentRow;

            //The last row may or may not contain the full number of columns
            if ((currentRow * cols) + currentCol >= totalFrames) {
                currentRow = 0;
                currentCol = Math.abs(currentCol - (totalFrames - (int) (Math.floor((float) totalFrames / cols) * cols)));
            }

            imageView.setViewport(new Rectangle2D(currentCol * frameWidth, currentRow * frameHeight, frameWidth, frameHeight));
        }
    }
}

Implement this with the following:

ImageViewSprite anim = new ImageViewSprite(ImageView, new Image("/pathToImage"), columns, rows, totalNumberOfFrames, FrameWidth, FrameHeight, FPS);
anim.start();
like image 34
Tryder Avatar answered Feb 22 '23 22:02

Tryder