`

JavaFX游戏开发--第一课 精灵动画

 
阅读更多

一直在关注JavaFX的发展,最近想试试使用JavaFX开发游戏是什么样的情况。可惜令我汗颜的是--没有找到类似于Java 2D中Graphics/Graphics2D之类的类。自己单纯的继承Node的话,也没办法自己进行绘制。看来目前使用JavaFX进行游戏开发,只能使用JavaFX的Shape和ImageView了。

今天花时间写了个JavaFX的精灵的动画的例子,让我们看看在JavaFX中如何操作精灵的动画吧。

首先创建一个JavaFX项目。

暂时不进行Scene的创建,因为我们要使用自定义的Parent。


我们先进行创建一个Sprite类,继承Parent。 这就是我们的精灵类了。

下面来看看代码:

import javafx.geometry.Rectangle2D;
import javafx.scene.Parent;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
/**
 * 精灵类
 * @author wing
 * @date 2012/7/17
 */
public class Sprite extends Parent {
	private enum Direction {
		Left, Right, Up, Down
	};

	private Direction direction = Direction.Left;
	private Direction lastDirection;
	private int x, y, width, height;
	private int index = 0;
	private int indexDiv = 5;
	private ImageView mImageView;
	private int speed = 4;

	public Sprite(int x, int y, int width, int height, String url) {
		this.x = x;
		this.y = y;
		this.width = width;
		this.height = height;
		Image actor = new Image(getClass().getResourceAsStream(url));
		mImageView = new ImageView(actor);
		mImageView.setViewport(new Rectangle2D(0, 0, width, height));
		mImageView.setLayoutX(x);
		mImageView.setLayoutY(y);
		getChildren().add(mImageView);
	}
	
	/**
	 * 像下移动
	 */
	public void moveDown() {
		direction = Direction.Down;
		if(lastDirection != direction){
			index = 0;
		}
		index++;
		if (index / indexDiv > 2) {
			index = 0;
		}
		mImageView.setViewport(new Rectangle2D(((index / indexDiv) % 3) * width, ((index / indexDiv) / 3) * height, width,
				height));
		mImageView.setLayoutY(mImageView.getLayoutY() + speed);
		
		lastDirection = direction;
	}
	
	/**
	 * 像左移动
	 */
	public void moveLeft() {
		direction = Direction.Left;
		if(lastDirection != direction){
			index = 3 * indexDiv;
		}
		index++;
		if (index / indexDiv > 5) {
			index = 3 * indexDiv;
		}
		mImageView.setViewport(new Rectangle2D(((index / indexDiv) % 3) * width, ((index / indexDiv) / 3) * height, width,
				height));
		mImageView.setLayoutX(mImageView.getLayoutX() - speed);
		
		lastDirection = direction;
	}
	
	/**
	 * 像右移动
	 */
	public void moveRight() {
		direction = Direction.Right;
		if(lastDirection != direction){
			index = 6 * indexDiv;
		}
		index++;
		if (index / indexDiv > 8) {
			index = 6 * indexDiv;
		}
		mImageView.setViewport(new Rectangle2D(((index / indexDiv) % 3) * width, ((index / indexDiv) / 3) * height, width,
				height));
		mImageView.setLayoutX(mImageView.getLayoutX() + speed);
		
		lastDirection = direction;
	}
	
	/**
	 * 像右移动
	 */
	public void moveUp() {
		direction = Direction.Up;
		if(lastDirection != direction){
			index = 9 * indexDiv;
		}
		index++;
		if (index / indexDiv > 11) {
			index = 9 * indexDiv;
		}
		mImageView.setViewport(new Rectangle2D(((index / indexDiv) % 3) * width, ((index / indexDiv) / 3) * height, width,
				height));
		mImageView.setLayoutY(mImageView.getLayoutY() - speed);
		
		lastDirection = direction;
	}
	
	
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public int getWidth() {
		return width;
	}
	public void setWidth(int width) {
		this.width = width;
	}
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}
}

1.首先定义了一个枚举类型,用来标明当前精灵的方向。

2.x, y, width, height这几个参数顾名思义,就是表明精灵的X,Y坐标和宽,高。

3.我们创建了一个Image,然后基于Image创建了一个ImageView。Image的图片加载是通过getClass().getResourceAsStream(String str)来进行。

4.ImageView有个setViewport(Rectangle2D rect2D)是个很重要的方法,就是显示这个ImageView中图片以rect2D的x,y为起点,width,height为宽高的一部分。 其实就是切割显示。这在所有的精灵动画中都是很常用的。


至于indexDiv大家暂时可以不用看,这个只是为了减慢精灵动画的(太快看起来不协调)。所以你们可以把index /

indexDiv都当作index来看待。


精灵动画,我这里暂且使用很常见的RPGMaker VX中的默认的精灵图片。

我们以这个精灵为标准,从左上到右下,索引也就是Sprite中的index是从0-11。


那么我们在使用ImageView.setViewport()时就要进行相应的处理。最简单的就是X方向(index % 3) * width, Y方向(index / 3 ) * height。 当index到3时,就进入第二行动画。相应的从0, 0,width, height 也变为了0, height, width, height。

然后通过setLayoutX()进行改变精灵的坐标,产生正在行走的效果。


为了避免精灵方向切换的时候,动画出现异常问题(可能会停留一帧上一个方向的动画帧)。我们又创建了一个lastDirection的方向枚举类型。用来标识上一次的方向。如果方向相同,则不做处理,如果方向不同,则要把当前帧切换到当前方向的第一帧。

	/**
	 * 像下移动
	 */
	public void moveDown() {
		direction = Direction.Down;
		if(lastDirection != direction){
			index = 0;
		}
		index++;
		if (index / indexDiv > 2) {
			index = 0;
		}
		mImageView.setViewport(new Rectangle2D(((index / indexDiv) % 3) * width, ((index / indexDiv) / 3) * height, width,
				height));
		mImageView.setLayoutY(mImageView.getLayoutY() + speed);
		
		lastDirection = direction;
	}

另外,由于只有3帧,如果当index 大于当前方向动画帧数的最大值,得重置为最小。我这里只是简单的标注了数字 2 ,5, 8, 11。


然后创建一个类GamePanel,用来添加我们的所有精灵和地图绘制(以后课程)。

import javafx.event.EventHandler;
import javafx.scene.Parent;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
/**
 * @author wing
 * @date 2012/7/17
 */
public class GamePanel extends Parent {
    private Sprite sprite;
	public GamePanel() {
	}

	public void load(){
        sprite = new Sprite(50, 50, 32, 32, "actor.png");
        getChildren().add(sprite);
        getScene().setOnKeyPressed(new EventHandler<KeyEvent>() {
 			@Override
 			public void handle(KeyEvent event) {
 				onKeyPressed(event);
 			}
 		});
	}
	
	
	public void onKeyPressed(KeyEvent event){
		if(event.getCode() == KeyCode.LEFT){
		  sprite.moveLeft();
	   }else if(event.getCode() == KeyCode.RIGHT){
		  sprite.moveRight();
	   }else if(event.getCode() == KeyCode.UP){
		  sprite.moveUp();
	   }else if(event.getCode() == KeyCode.DOWN){
		  sprite.moveDown();
	   }
	}
	
	
	public void update(long now){
		
	}

}

这个类现在很简单,只是单纯的在50,50坐标处,创建了一个Sprite。然后给Scene添加了一个按键事件,在按Left right up 和 down的时候,将会控制精灵进行各个方向的移动。


下面来写我们的主类。

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.stage.Stage;

public class MainClass extends Application {

	@Override
	public void start(Stage stage) throws Exception {
          GamePanel mPanel = new GamePanel();
          final Scene scene = new Scene(mPanel,800, 600);
          mPanel.load();
          scene.setFill(Color.BLACK);
          stage.setScene(scene);
          stage.setTitle("JavaFX游戏开发--第一课  精灵动画");
          stage.show();
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
        launch(MainClass.class, args);
	}

}

我们在主类中创建了GamePanel,根据GamePanel创建了一个Scene,调用了GamePanel的load方法,进行加载精灵和添加事件。然后将Scene背景设为了黑色。

下面我们来看看运行效果吧~

向右走:


向下走:


那么JavaFX游戏开发的第一课就讲到这里了。其实很简单,就是单纯的一个精灵动画的实现而已。所以我们并没有创建精灵的基类等工作。


后面的课程中,我们将会进行游戏地图,对话框等的加入。

本人水平不佳,望大家指正。一起进步。


转载请注明出处:http://blog.csdn.net/ml3947

分享到:
评论

相关推荐

    javafx-sdk-11.0.2

    JavaFX SDK 11.0.2 是一个用于开发富客户端应用程序的工具包,它在Java 11及更高版本中不再作为标准JDK的一部分。这个独立的SDK提供了必要的库和工具,使得开发者能够在Java平台上构建具有丰富图形用户界面(GUI)的...

    openjfx-jar.zip

    javafx.base-11.0.0-SNAPSHOT-linux.jar,javafx.base-11.0.0-SNAPSHOT-mac.jar,javafx.base-11.0.0-SNAPSHOT-win.jar,javafx-base-11.jar,javafx-base-11-win.jar,javafx-graphics-11.jar,javafx-graphics-11-win....

    javafx-sdk-17.0.2-lts-windows-x64

    JavaFX SDK 17.0.2 LTS 是一个用于创建桌面和基于浏览器的富客户端应用程序的工具包,专为Windows x64平台设计。这个版本是长期支持(LTS)版本,意味着它将提供更长期的维护和支持,适合于那些需要稳定开发环境的...

    javafx18sdk,javafx-sdk-18,的次源包,javafx运行库,可以向下兼容,linux系统下可附加使用

    linux系统下,可用如下两...java --module-path /home/ubuntu20/javafx-sdk-18/lib --add-modules javafx.controls,javafx.fxml -jar EQMSAny_jar.jar 其中 /home/ubuntu20/javafx-sdk-18 是上包所解压后的你放置的路径

    javaFX-jps-plugin.jar

    javaFX-jps-plugin.jar

    javafx动画---风扇图

    利用javafx绘制动画风扇图,提供pause、reverse、resume按钮

    javafx-11.0.2-windows.rar

    在"javafx-sdk-11.0.2"这个压缩包中,包含了运行和开发JavaFX应用所需的所有资源。 3. **打包工具**:为了便于部署,JavaFX 11提供了新的打包工具,如`jlink`和`jpackage`,可以创建自包含的运行时环境,减小最终...

    javaFx 学习--之布局菜单

    javaFx 学习--之布局菜单

    学习JavaFX脚本语言--中文PDF版

    总之,JavaFX为Java开发者提供了一个强大且灵活的工具,使得开发具有丰富图形界面的应用程序变得更加容易。如果你对桌面应用开发有兴趣,或者希望提升你的UI设计技能,那么学习JavaFX无疑是值得投入的。这个中文PDF...

    javafx-11.0.2 jar.rar

    标题中的"javafx-11.0.2 jar.rar"指的是JavaFX 11.0.2版本的库文件,这些文件被压缩在RAR格式的压缩包中。这个压缩包包含了JavaFX的不同模块,如base、controls、media、graphics、swing、web以及awt等,同时也包含...

    javafx_sdk-2_2_21-windows-i586

    javafx_sdk-2_2_21-windows-i586

    javafx使用指南-目录版.pdf

    1. 桌面应用程序:JavaFX 可以用于开发桌面应用程序,例如图形编辑器、视频播放器和游戏等。 2. 移动应用程序:JavaFX 可以用于开发移动应用程序,例如智能手机和平板电脑上的应用程序。 3. 网络应用程序:JavaFX ...

    luke-javafx-7.4.0-luke-release

    JavaFX支持2D和3D图形,动画效果,以及跨平台兼容性,使得Luke可以在多种操作系统上运行,包括Windows 7。在Luke 7.4.0中,用户可以期待一个更加直观且响应迅速的界面,便于浏览和查询索引中的文档和字段。 在...

    luke-javafx-7.3.1-luke-release.zip

    总的来说,"luke-javafx-7.3.1-luke-release.zip"是一个结合了JavaFX的最新技术与Lucene的强大搜索功能的工具包,对于Lucene开发者和信息检索领域的专业人士来说,它是一个不可或缺的辅助工具,帮助他们深入理解、...

    javafx-textfield-change-demo

    本示例"javafx-textfield-change-demo"就是关于如何实现这一功能的演示。 JavaFX提供了事件处理机制,我们可以使用ChangeListener接口来监听TextField的文本变化。当TextField中的文本发生改变时,ChangeListener的...

    javafx_samples-8u102-ea-b04-windows-25_apr_2016

    在压缩包中,`javafx-samples-8u102-ea`这个子目录可能包含了各种示例项目,每个项目都展示了JavaFX的不同功能。开发者可以通过查看源码学习如何使用JavaFX API来实现特定功能,也可以直接运行jar文件查看运行效果。...

    javafx-commons-2.0.1

    javafx-commons-2.0.1

    javafx-rest-archetype-1.1.zip

    这个压缩包文件"javafx-rest-archetype-1.1.zip"包含了项目的核心源代码,帮助开发者快速启动一个新的JavaFX应用,该应用能够与RESTful Web服务进行交互。 JavaFX是Oracle提供的一个用于创建桌面应用的富客户端平台...

    javafx-sdk-18.zip

    javafx-sdk-18.zip

    javafx-maven-archetypes:各种JavaFX项目的Maven原型

    先决条件JDK 11 Maven 3在本地安装原型要将所有原型安装在本地存储库中,请执行以下命令: git clone https://github.com/openjfx/javafx-maven-archetypes.gitcd javafx-maven-archetypesmvn clean install这将在...

Global site tag (gtag.js) - Google Analytics