模拟纸飞机运动动画 PaperPlaneAnim

项目需要模拟一个纸飞机飞到目的地的动画,用cocos的moveto动画不能满足需求,因为纸飞机总是向着飞机头朝向移动。

所以需要考虑飞机头的朝向,计算目标点和飞机的夹角,飞机前进的过程中按转向角速度this.angularSpeed修改飞机的角度angle
fly函数 传入飞机的目的地位置targetPos,初始化数据

public fly(targetPos: cc.Vec2, cb?: () => void, circleAngle?) {this._targetCallBack = cb;targetPos = this.flyNd.parent.convertToNodeSpaceAR(targetPos);this._targetPos = targetPos;this._speed = 0;this._circleAngleCnt = 0;this._circleFactor = 0;this.circleAngle = circleAngle == null ? this.circleAngle : circleAngle;this._flyStatus = FlyStatus.AccCircle;
}

update里根据飞机的位置this.flyNd.positiontargetPos计算得到夹角this._targetAngle

//计算目标位置在飞机的方位。let radian = Math.atan2(this.flyNd.y - this._targetPos.y, this.flyNd.x - this._targetPos.x);
this._targetAngle = 180 / Math.PI * radian;
this._targetAngle = (360 + this._targetAngle) % 360;

计算飞机当前角度 curAngle 并计算curAnglethis._targetAngle的差diffAngle

let curAngle = (360 + (this.flyNd.angle + this.defaultPlaneAngleOffset) % 360) % 360;
let diffAngle = this._targetAngle - curAngle;

根据设置的角速度angularSpeed修改飞机的角度

            if (Math.abs(diffAngle) > 1) {let factorAngle = this._targetAngle - curAngle > 0 ? 1 : -1;if (Math.abs(this._targetAngle - curAngle) > 180) {factorAngle *= -1;}this.flyNd.angle += factorAngle * this.angularSpeed;}

飞机总是向着飞机头的方向前进,根据飞机角度curAngle计算飞机x y上的速度分量因素factor

 let factor = this._getDirection(curAngle);private _getDirection(curAngle: number): cc.Vec2 {let factorX = 0;let factorY = 0;if (curAngle > 90 && curAngle < 270) {let deacc = (90 - (Math.abs(180 - curAngle))) / 90;factorX = 1 * deacc;} else if (curAngle < 90 || curAngle > 270) {let deacc = 1;if (curAngle < 90) {deacc = (90 - curAngle) / 90} else if (curAngle > 270) {deacc = (90 - (360 - curAngle)) / 90}factorX = -1 * deacc;}if (curAngle > 180) {let deacc = (90 - (Math.abs(270 - curAngle))) / 90;factorY = 1 * deacc;} else if (curAngle < 180) {let deacc = (90 - (Math.abs(90 - curAngle))) / 90;factorY = -1 * deacc;}return cc.v2(factorX, factorY);}

根据factor修改飞机位置,这里还设置了飞机的加速减速运动

            //加速this._speed = cc.misc.clampf(this._speed - this.acc, this.speed * 0.9, this.speed*1.5);//移动posthis.flyNd.x += factor.x * this._speed;this.flyNd.y += factor.y * this._speed;

最后达到目的地判断 ,并执行完成回调

            //判断到达let distance = Math.abs(this.flyNd.getPosition().sub(this._targetPos).mag());if (distance <= 15) {this._flyStatus = FlyStatus.Idle;if (this._targetCallBack! = null) {this._targetCallBack();this._targetCallBack = null;}}

最终效果就是飞机先转一圈,让后自己调整角度朝着目的地前进

完整代码

const { ccclass, property } = cc._decorator;enum FlyStatus {Idle = 0,TargetMoving = 1,AccCircle = 2 //加速
}@ccclass
export default class PaperPlaneAnim extends cc.Component {@property(cc.Node)flyNd: cc.Node = null;@property({tooltip: "定义9点方向为初始方向, 逆时针方向为正 飞机图片在angle为0时,飞机头和初始方向的角度偏差."})defaultPlaneAngleOffset: number = 0;@property({tooltip: "飞到目的地过程中要做转圈表演的角度."})circleAngle: number = 0;@property({tooltip: "飞行速度."})speed: number = 12;@property({tooltip: "掉头角速度."})angularSpeed: number = 6;@property({tooltip: "加速度."})acc: number = 0.15;private _flyStatus: FlyStatus = FlyStatus.Idle;private _targetAngle: number = 0; //飞机到目标的最终角度private _targetPos: cc.Vec2 = cc.v2(0, 0);private _targetCallBack: Function = null;private _circleAngleCnt: number = 0;private _speed: number = 0;private _circleFactor: number = 0;// LIFE-CYCLE CALLBACKS:start() {//test// let canvas = cc.find("Canvas/testnod");// canvas.on(cc.Node.EventType.TOUCH_END, (t) => {//     let pos = t.touch._point;//     this.fly(pos);// }, this);}lateUpdate(dt) {//模拟飞机只能像飞机头朝向前进,到达目的地的方式就是不断修改飞机头朝向。if (this._flyStatus == FlyStatus.TargetMoving) {//计算目标位置在飞机的方位。let radian = Math.atan2(this.flyNd.y - this._targetPos.y, this.flyNd.x - this._targetPos.x);this._targetAngle = 180 / Math.PI * radian;this._targetAngle = (360 + this._targetAngle) % 360;//判断飞机头在哪个象限let curAngle = (360 + (this.flyNd.angle + this.defaultPlaneAngleOffset) % 360) % 360;let factor = this._getDirection(curAngle);//修改anglelet diffAngle = this._targetAngle - curAngle;if (Math.abs(diffAngle) > 1) {let factorAngle = this._targetAngle - curAngle > 0 ? 1 : -1;if (Math.abs(this._targetAngle - curAngle) > 180) {factorAngle *= -1;}this.flyNd.angle += factorAngle * this.angularSpeed;}//加速this._speed = cc.misc.clampf(this._speed - this.acc, this.speed * 0.9, this.speed*1.5);//移动posthis.flyNd.x += factor.x * this._speed;this.flyNd.y += factor.y * this._speed;//判断到达let distance = Math.abs(this.flyNd.getPosition().sub(this._targetPos).mag());if (distance <= 15) {this._flyStatus = FlyStatus.Idle;if (this._targetCallBack! = null) {this._targetCallBack();this._targetCallBack = null;}}} else if (this._flyStatus == FlyStatus.AccCircle) {//转圈表演if (this._circleAngleCnt >= this.circleAngle) {this._flyStatus = FlyStatus.TargetMoving;}let curAngle = (360 + (this.flyNd.angle + this.defaultPlaneAngleOffset) % 360) % 360;let factor = this._getDirection(curAngle);if (this._speed > this.speed * 0.3) {if (this._circleFactor == 0) {this._circleFactor = this._targetAngle - curAngle > 0 ? 1 : -1;if (Math.abs(this._targetAngle - curAngle) > 180) {this._circleFactor *= -1;}}this.flyNd.angle += this._circleFactor * this.angularSpeed;this._circleAngleCnt += this.angularSpeed;}//加速this._speed = cc.misc.clampf(this._speed + this.acc, this.speed * 0.2, this.speed*1.5);//移动posthis.flyNd.x += factor.x * this._speed;this.flyNd.y += factor.y * this._speed;}}private _getDirection(curAngle: number): cc.Vec2 {let factorX = 0;let factorY = 0;if (curAngle > 90 && curAngle < 270) {let deacc = (90 - (Math.abs(180 - curAngle))) / 90;factorX = 1 * deacc;} else if (curAngle < 90 || curAngle > 270) {let deacc = 1;if (curAngle < 90) {deacc = (90 - curAngle) / 90} else if (curAngle > 270) {deacc = (90 - (360 - curAngle)) / 90}factorX = -1 * deacc;}if (curAngle > 180) {let deacc = (90 - (Math.abs(270 - curAngle))) / 90;factorY = 1 * deacc;} else if (curAngle < 180) {let deacc = (90 - (Math.abs(90 - curAngle))) / 90;factorY = -1 * deacc;}return cc.v2(factorX, factorY);}public fly(targetPos: cc.Vec2, cb?: () => void, circleAngle?) {this._targetCallBack = cb;targetPos = this.flyNd.parent.convertToNodeSpaceAR(targetPos);this._targetPos = targetPos;this._speed = 0;this._circleAngleCnt = 0;this._circleFactor = 0;this.circleAngle = circleAngle == null ? this.circleAngle : circleAngle;this._flyStatus = FlyStatus.AccCircle;}
}

github 链接

cocos creator 模拟纸飞机运动动画相关推荐

  1. 用 Cocos Creator 模拟书本翻页效果

    本篇文章作者:乐府-贝塔 乐府-贝塔:乐府前端核心开发,从事游戏开发多年,从 Cocos2d-x 做到 Cocos Creator,擅长渲染技术的相关优化.多年的前端开发经验激发了对技术研究的深厚兴趣 ...

  2. Cocos Creator - 制作精灵帧动画

    本文档主要根据官方文档上的图集资源.动画系统.音乐和音效等章节内容进行综合使用. 1.制作图集 制作图集有两种工具: TexturePacker Zwoptex(只能在Windows上使用) 我这里使 ...

  3. 进击3D游戏界!Cocos Creator快速实现骨骼动画交互!

    文章目录 前言 一.Cocos Creator简介? 二.快速上手Cocos Creator 1.任何语言学习,先概览一遍文档 2.跟随官方Demo,进行游戏的制作 三.如何自己实现骨骼模型和界面交互 ...

  4. 用Cocos Creator 模拟书本翻页效果

    1.简介 本文主要探讨了如何使用CocosCreator来模拟书本翻页效果,分别介绍了通过使用贝塞尔曲线和verlet积分算法来模拟书页底边在翻页过程中的弯曲形变,最后通过自定义assembler传入 ...

  5. Cocos Creator 优化,帧动画优化

    需求背景·:在游戏中使用了大量的帧动画,并且为了drawcall的优化使用了 cocos的自动合集功能,因为帧动画的动作效果需要统一 所以图片会有大量空白部分,虽然cocos有自己的trim,但在自动 ...

  6. Cocos Creator模拟砸金蛋3d旋转效果 | 附代码

    1 获取代码 关注微信公众号,发送[砸蛋]获取代码 2 效果预览 3 使用说明 点击add,添加蛋到盘子上,蛋的数量后台可配置: 点击move,让蛋在盘子上转动起来: 点击stop,让蛋停止转动. 4 ...

  7. cocos creator 模拟重力爆炸效果

    最近在写一个用collider和rigidbody来模拟爆炸一下掉落的效果.(因为是测试版,所以素材很low.仅供参考) 先上层级关系图 场景视图 pot是中间的那个小的图.也是模拟爆炸的中心点随便用 ...

  8. Cocos Creator模拟射箭效果 | 附代码

    1 获取代码 感谢「一枚小工」的投稿,关注他的微信公众号,发送[射箭]获取代码 2 效果预览 3 操作方法 点击屏幕,屏幕出现起始位置标志的圆点,不松开手指,滑动屏幕,控制力度和方向,移动距离越大,弓 ...

  9. Cocos Creator中的动画支持技术

    Cocos Creator主要亮点 官方的权威描述是:Cocos Creator是以内容创作为核心的一体化游戏开发工具,这个引擎基于Cocos2d-x,组件化,脚本化,数据驱动,跨平台发布. 本人使用 ...

最新文章

  1. 关联规则挖掘算法_#数据挖掘初体验 使用weka做关联规则
  2. 深度学习100问:图像语义分割有哪些经典的上采样方法?
  3. .net页面数据传递
  4. [原]关于鼠标滚轮的编程
  5. Android在ListView滑动数据混乱
  6. Error:Execution failed for task ':app:clean'.
  7. DRF数据验证+数据存储
  8. 开课吧Java课堂:线程间是如何实现通信
  9. dblink 同步数据_使用DBLINK同步TC数据库
  10. 实体类转换为XML字符串
  11. 遗传算法原理及应用二(交叉算子、变异算子与运行参数选择)
  12. FreeCAD源码分析:FreeCADApp模块
  13. Android 学习过程中遇到的知识点
  14. 计算机病毒互助百科,病毒百科——计算机病毒分类
  15. [201011][Maven 实战][许晓斌][著]
  16. 计算机笔记检讨,上课没做笔记的反省检讨书
  17. 明日之后android和ios,明日之后互通区有哪些 明日之后ios和安卓互通区一览
  18. vue导出word纯前端实现
  19. 从GraalVM到Quarkus系列-B002篇-Quarkus中的字节码框架gizmo
  20. 编写操作norflash的裸机程序

热门文章

  1. 3dMax 放样(牙膏)
  2. iOS8 CIGlassDistortion滤镜的使用
  3. 第十一章:django之后台管理
  4. 如何解决iCloud空间被Mac桌面和文稿占用太多的问题?
  5. 《Python》Python教程
  6. 这是一份全面详细的数据结构、算法学习指南
  7. Spring常用注解你知道有哪些吗?
  8. QuestMobile:2017年在线音乐应用行业洞察报告
  9. continue语句可以用在switch语句和3种循环语句中_Java基础复习笔记P20——break和continue...
  10. 小米前端实习面试题和一些经验