FXGL 04.动画 (可爱的乌贼娘)

我们在之前的文章中简单创建了一个png格式的图片展示的实体,这里我们要更换换这个实体的展示模式,让一个活灵活现的乌贼娘出现在我们的游戏世界中!

1.实体的展示过程

这样的一个实体创建过程我们并不陌生,如果需要将某个素材作为展示内容,我们只需要在创建中的view方法中加入其中。

   Entity entity = FXGL.entityBuilder().with(new MoveComponent()).build();

那我们来探究下view方法的本质。(我并不太懂Kotlin)
但是还是找到了以下源码

 fun view(node: Node) = this.also {entity.viewComponent.addChild(node)}fun view(textureName: String) = this.also {view(FXGL.texture(textureName))}

Node 类是大多数javafx的形状图形的顶级抽象类,我们熟悉的shape,box等类都继承自该类。明显可以理解viewcomponent是实体的实际展示控制类。
那如果想要在程序运行时修改实体的动画内容,很容易就能想到需要做就是修改entity中的viewcomponent

2.从素材网站中下载素材

这里我推荐使用爱给网,免费且资源众多。
在其中可以下载需要的各种素材。

3.修改之前的实体展示

我这里下载了一张乌贼娘的行走图

首先对于实体静态工厂,我将其中的view部分移除

    public static Entity createEntity(EntityType type){switch (type) {case PLANE -> {Entity entity = FXGL.entityBuilder().with(new MoveComponent()).build();entity.setType(EntityType.PLANE);return entity;}default -> {return null;}}
}

然后修改移动组件,为其增加动画内容

package com.dam.wonder.component;import com.almasb.fxgl.core.math.Vec2;
import com.almasb.fxgl.entity.component.Component;
import com.almasb.fxgl.texture.AnimatedTexture;
import com.almasb.fxgl.texture.AnimationChannel;
import javafx.scene.image.Image;
import javafx.util.Duration;
import lombok.extern.slf4j.Slf4j;@Slf4j
public class MoveComponent extends Component {private double speedX = 0d;private double speedY = 0d;/*** Called after the component is added to entity.*/@Overridepublic void onAdded() {entity.getViewComponent().addChild(texture);}private double maxSpeed = 4d;private double aTime = 1d;private boolean speedXAdd;private boolean speedYAdd;//这里增加一个面向属性,用来判断实体在各种速度下的面向问题private int face = 1;//动画频道 对应四个方向的动画private final AnimationChannel up;private final AnimationChannel down;private final AnimationChannel right;private final AnimationChannel left;//动画素材private final AnimatedTexture texture;@Overridepublic void onUpdate(double tpf) {//        log.info("当前状态下  x速度为=[{}], Y速度为=[{}]  x加速状态为=[{}] Y加速状态为 =[{}]",speedX,speedY,speedXAdd,speedYAdd);int tempFace = face;if (speedX != 0d) {Vec2 dir = Vec2.fromAngle(entity.getRotation() - 360).mulLocal(speedX);entity.translate(dir);if (speedX>0) {tempFace = 1;}else {tempFace = 2;}}if (speedY != 0d) {Vec2 dir = Vec2.fromAngle(entity.getRotation() - 90).mulLocal(speedY);entity.translate(dir);if (speedY > 0) {tempFace = 3;}else {tempFace = 4;}}if (!speedXAdd) {slowDownSpeed(true);}if (!speedYAdd) {slowDownSpeed(false);}if (tempFace != face) {if (tempFace == 1) {this.texture.loopAnimationChannel(left);}else if (tempFace == 2){this.texture.loopAnimationChannel(right);}else if (tempFace == 3) {this.texture.loopAnimationChannel(up);}else {this.texture.loopAnimationChannel(down);}face = tempFace;}}public MoveComponent () {//在构造方法中增加加载动画的方法Image image = new Image("assets/textures/player.png");//这里通过对图片的规划,每一行的动画个数,每个帧的宽度高度,整个动画的跨度时间,跨度几个动画down = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 0, 3);right = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 4, 7);left = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 8, 11);up = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 12, 15);texture = new AnimatedTexture(up);//播放动画texture.loop();}public void up() {changeSpeed(true,false);}public void left() {changeSpeed(false,true);}public void right() {changeSpeed(true,true);}public void down(){changeSpeed(false,false);}public void stop() {speedX = 0d;speedY = 0d;}public void stopX() {speedXAdd = false;}public void stopY() {speedYAdd = false;}/*** 改变移动速度 主动改变* @param upOrDown* @param xOrY*/private  void changeSpeed(boolean upOrDown,boolean xOrY) {if (xOrY) {speedXAdd = true;if (upOrDown) {if (speedX < maxSpeed) {speedX = speedX + (float)maxSpeed/(10*aTime) + 0.01;}}else {if (speedX > -maxSpeed) {speedX = speedX - (float)maxSpeed/(10f*aTime) - 0.01;}}}else {speedYAdd = true;if (upOrDown) {if (speedY < maxSpeed) {speedY = speedY + (float)maxSpeed/(10f*aTime) + 0.01;}}else {if (speedY > -maxSpeed) {speedY = speedY - (float)maxSpeed/(10f*aTime) - 0.01;}}}
//        log.info("实体当前状态为 位置=[{}],速度Y=[{}],速度X =[{}]",entity.getPosition(),this.speedY,this.speedX);}/*** 速度减少 被动减速* @param xOrY*/private void slowDownSpeed(boolean xOrY) {if (xOrY) {if (speedX > 0.5) {speedX = speedX - (float)speedX/10 -0.01;}else if (speedX< -0.5){speedX = speedX - (float)speedX/10 +0.01;}else {speedX = 0d;}}else {if (speedY > 0.5) {speedY = speedY - (float)speedY/10 -0.01;}else if (speedY< -0.5){speedY = speedY - (float)speedY/10 +0.01;}else {speedY = 0d;}}}public double getSpeedX() {return speedX;}public void setSpeedX(double speedX) {this.speedX = speedX;}public double getSpeedY() {return speedY;}public void setSpeedY(double speedY) {this.speedY = speedY;}public double getMaxSpeed() {return maxSpeed;}public void setMaxSpeed(double maxSpeed) {this.maxSpeed = maxSpeed;}public double getaTime() {return aTime;}public void setaTime(double aTime) {this.aTime = aTime;}
}

简简单单的启动项目,一个乌贼娘跃然纸上啦!

当然,只到这一步我是不满足的,因为这个乌贼娘在速度为零的时候依然保持着移动动画。进行一点点小小的修改。
很容易想到,简单的添加四个全新的信道。

    private final AnimationChannel up;private final AnimationChannel upHold;private final AnimationChannel down;private final AnimationChannel downHold;private final AnimationChannel right;private final AnimationChannel rightHold;private final AnimationChannel left;private final AnimationChannel leftHold;private final AnimatedTexture texture;

简单的初始化他们

        down = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 0, 3);downHold = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 1, 1);right = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 4, 7);rightHold = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 5, 5);leftHold = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 9, 9);left = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 8, 11);up = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 12, 15);upHold = new AnimationChannel(image, 4, 32, 38, Duration.seconds(1), 13, 13);

再简单的判断速度为零时修改为静止信道

 @Overridepublic void onUpdate(double tpf) {//        log.info("当前状态下  x速度为=[{}], Y速度为=[{}]  x加速状态为=[{}] Y加速状态为 =[{}]",speedX,speedY,speedXAdd,speedYAdd);int tempFace = face;if (speedX != 0d) {Vec2 dir = Vec2.fromAngle(entity.getRotation() - 360).mulLocal(speedX);entity.translate(dir);if (speedX>0) {tempFace = 1;}else if (speedX<0){tempFace = 2;}}else {//转变面向if (tempFace == 1) {tempFace = 5;}else if (tempFace == 2) {tempFace = 6;}}if (speedY != 0d) {Vec2 dir = Vec2.fromAngle(entity.getRotation() - 90).mulLocal(speedY);entity.translate(dir);if (speedY > 0) {tempFace = 3;}else {tempFace = 4;}}else {if (tempFace == 3) {tempFace = 7;}else if (tempFace == 4) {tempFace = 8;}}if (!speedXAdd) {slowDownSpeed(true);}if (!speedYAdd) {slowDownSpeed(false);}if (tempFace != face) {if (tempFace == 1) {this.texture.loopAnimationChannel(left);}else if (tempFace == 2){this.texture.loopAnimationChannel(right);}else if (tempFace == 3) {this.texture.loopAnimationChannel(up);}else if (tempFace == 4){this.texture.loopAnimationChannel(down);}else if (tempFace == 5) {this.texture.loopAnimationChannel(leftHold);}else if (tempFace == 6) {this.texture.loopAnimationChannel(rightHold);}else if (tempFace == 7){this.texture.loopAnimationChannel(upHold);}else if (tempFace == 8) {this.texture.loopAnimationChannel(downHold);}face = tempFace;}}

非常容易啊,啪的一下,这个完整的动画过程就做完了。

当然除了动态素材动画信道的方法,还有一个使用的更多的动画建造器方式
(animationBuilder)
这个方法能自定义很多动画,例如各种变形动画,粒子特效等,也能设置回调用于控制动画。在官方wiki中有详细介绍,这里就不多赘述了。

FXGL JAVA游戏引擎 教程 .04 动画 (可爱乌贼娘)相关推荐

  1. FXGL JAVA游戏引擎 教程 03.游戏UI

    当我们拥有一个实体并且对其绑定了可移动的组件之后,我们拥有了一个可以自由操控控制的角色.但是距离成为一个真正的游戏还有几个必不可少的组件需要实现.其中游戏ui就是不可或缺的一个组件. 坐标系 对于所有 ...

  2. FXGL JAVA游戏引擎 教程 05.场景 (萌妹在线哭泣)

    上文中,我们已经有了一个漂亮的人物角色,但是对于一个游戏而言,除了可操控的游戏角色,各种弹出框也是必须设计考虑的一部分. 比如你希望播放一个过场动画,弹出一个对话框,打开背包栏目等等. 为了实现以上功 ...

  3. JAVA游戏引擎!FXGL 教程 总目录

    喜欢打游戏也喜欢编程,总想开发一款自己的游戏,圆自己儿时的一个梦. 我并非要编写一个游戏引擎,故而也用不到LWJGL这种层级的引擎,如果你也是一个和我一样单纯想做一款游戏的javaer,那你也可以和我 ...

  4. [转]Java游戏引擎

    JME(jMonkey Engine): JME是一个高性能的3D图形API,采用LWJGL作为底层支持.它的后续版本将支持JOGL.JME和Java 3D具有类似的场景结构,开发者必须以树状方式组织 ...

  5. 各种Java游戏引擎简介

    各种Java游戏简介 JME(jMonkey Engine): JME是一个高性能的3D图形API,采用LWJGL作为底层支持.它的后续版本将支持JOGL.JME和Java 3D具有类似的场景结构,开 ...

  6. Unity3d动画脚本 Animation Scripting(深入了解游戏引擎中的动画处理原理--旧的动画系统)

    (来自:http://blog.sina.com.cn/s/blog_409cc4b00100qmgz.html) 也许这一篇文章的内容有点枯燥,但我要说的是如果你想深入的了解游戏引擎是如何处理动画片 ...

  7. python和java的格斗动画_《Genesis-3D开源游戏引擎--横版格斗游戏制作教程04:技能的输入与检测》...

    4.技能的输入与检测 概述: 技能系统的用户体验,制约着玩家对整个游戏的体验.游戏角色的技能华丽度,连招的顺利过渡,以及逼真的打击感,都作为一款游戏的卖点吸引着玩家的注意.开发者在开发游戏初期,会根据 ...

  8. java游戏开发(java游戏开发教程)

    Java游戏开发绘图器是什么呢? 众所周知,Java GUI以paint进行绘图,以repaint进行图像刷新,而完成repaint及paint这一连贯过程中所用到绘图组件,我将其称为绘图器.就我个人 ...

  9. Java游戏引擎libgdx的简介

    最近想做点小应用,但界面方面是非常不在行,自然想 借助游戏引擎来处理这部分工作.本打算在flex中找一 个比较好的,但找到pushbotton的时候发现官方主页留 下的只有goodbye的页面,留言的 ...

  10. 55ide游戏引擎教程2:新建项目Hello World

    首先我们打开引擎,引擎窗口--文件--新建--55ide客户端--新建一个工程 一般新建在引擎根目录下面的,游戏作品里面.当然,你要放到其他位置,也可以,谁叫你这么叼 这就是进入主程序的界面. 加载: ...

最新文章

  1. 工程管理专业就业前景_网络工程师就业前景如何?
  2. 实现SQL Server 2012 镜像
  3. oracle12c分页,ArcSDE10.2.1使用Oracle12c新特性分页
  4. python 图像像素的坐标系方向, PIL库中Image.getpixel()方法, 相机标定之四个坐标系及其关系
  5. 数据智能构建管理平台Dataphin V2.9.4.3版本发布
  6. JZOJ 2678. 树B
  7. 记一次调用API遇到的问题
  8. 分布式精华问答 | 如何实现分布式系统的高可用性?
  9. h5弹框滑动 ios_微信 iOS 版更新:细节大更新,你值得拥有
  10. 题目1452:搬寝室(dp题目)
  11. HTML5技术的调研以及贴吧应用总结
  12. python制作简单文本编辑器
  13. iptv组播和单播的区别
  14. GTD工具 Wunderlist使用心得总结
  15. 成都国税打造全能“电子税务局”
  16. 计算机配置35%卡住不动了,win7配置更新35%不动怎么回事_win7配置windows update完成35卡住不动了如何解决...
  17. OCPC不起量该怎么办?从这四个方面着手,轻松起量
  18. Oracle数据库,创建表并给表、字段添加注释
  19. 程序猿如何高效的学习英语
  20. Couldn‘t terminate the existing process for com.hopechart.gallery

热门文章

  1. 动态本体 palantir
  2. Faster-RCNN的关键点总结
  3. 《Neural Architectures for Nested NER through Linearization》
  4. [软件测试] - No.1 Fault Error Failure 区别
  5. DVB-S/S2天线及信号相关知识
  6. Elasticsearch怎样实现自定义分词
  7. coreldraw怎样定数等分_coreldraw 里怎么将线段等分?
  8. XMLHttpRequest.readyState 状态
  9. Shopee上货软件,新手小白必备神器
  10. 你PICK的球队可能没赢,但PICK以下拍摄技巧绝对稳赚不赔!