cocos creator实现浏览星球的功能,附源码
预览效果:
技术要点:
- 主摄像机的视场轴需要设置为水平。
- 在场景下创建一个空节点用于挂载控制器脚本
图片已进行各概念的说明
在“collisionNodeArray”属性下,放置需要点击的星球节点,系统会自己绑定碰撞器。
也可自己提前绑定。
- 布局场景,星球围绕相机。参考如下:
注意相机的属性。可以根据自己的需要调整相机的z值。只要保证星球绕着相机布局则行。
- 关于摄像机旋转的上下限制。
可以通过设置
这两个参数进行调节,是个经验数值。
系统本身会进行基础的上下限制。这两个参数属于额外的限制。即顶部往下,底部往上。
控制器(planet_view_controller)代码:
直接拷贝到项目的一个空代码文件即可:
import { _decorator, Component, Node, Camera, Input, input, EventTouch, Vec2, Quat, Vec3, screen, tween, Tween, Collider, SphereCollider, geometry, PhysicsSystem, EventHandler } from "cc";
const { ccclass, property } = _decorator;
@ccclass("PlanetViewController")
export class PlanetViewController extends Component {start() {this.bindInputEvent();this.setLimitEuler();this.clickManagerStart();}//浏览功能区@property({ displayName: "顶部额外限制角度",})private upLimitAngle = 0;@property({ displayName: "底部额外限制角度",})private downLimitAngle = 0;@property(Camera)private centerCamera!: Camera;private bindInputEvent() { input.on(Input.EventType.TOUCH_START, this.onTouchStart, this);
input.on(Input.EventType.TOUCH_MOVE, this.onTouchMove, this);
input.on(Input.EventType.TOUCH_END, this.onTouchEnd, this);}private limitEdgeEuler = 0;private setLimitEuler() {this.limitEdgeEuler = (180 * Math.atan(Math.tan((this.centerCamera.fov * Math.PI) / 360) / this.centerCamera.camera.aspect)) / Math.PI;}private startLocation = new Vec2();private onTouchStart(e: EventTouch) { e.getLocation(this.startLocation);
Tween.stopAllByTarget(this.lastRotaionSpeed);}private lastRotaionSpeed = new Vec2();private onTouchMove(e: EventTouch) { e.getDelta(this.lastRotaionSpeed);this.rotateCenterCamera(this.lastRotaionSpeed);}private clickLocation = new Vec2();private onTouchEnd(e: EventTouch) { e.getLocation(this.clickLocation);const dis = Vec2.squaredDistance(this.startLocation, this.clickLocation);if (dis <= 0.1) {this.node.emit("click", this.clickLocation);console.log("click");return;}tween(this.lastRotaionSpeed).to(0.5,{ x: 0,
y: 0,},{ easing: "sineOut",
onUpdate: () => {this.rotateCenterCamera(this.lastRotaionSpeed);},}).start();}private curRotateResultEuler = new Vec3();private rotateQuat = new Quat();private lastRotationQuat = new Quat();private rotateCenterCamera(volume: Vec2) { Quat.fromAxisAngle(this.rotateQuat, Vec3.UP, (volume.x * 0.785) / screen.windowSize.width);
Quat.rotateX(this.rotateQuat, this.rotateQuat, (-volume.y * 0.785) / screen.windowSize.height);this.lastRotationQuat.set(this.centerCamera.node.rotation);
Quat.multiply(this.lastRotationQuat, this.lastRotationQuat, this.rotateQuat);this.lastRotationQuat.getEulerAngles(this.curRotateResultEuler);this.centerCamera.node.rotate(this.rotateQuat);const isOverUp = this.curRotateResultEuler.x < -this.limitEdgeEuler + this.upLimitAngle;const isOverDown = this.curRotateResultEuler.x > this.limitEdgeEuler - this.downLimitAngle;if (isOverUp || isOverDown) {this.lastRotationQuat.set(this.centerCamera.node.rotation);this.lastRotationQuat.getEulerAngles(this.curRotateResultEuler);const { y, z } = this.curRotateResultEuler;const x = isOverUp ? -this.limitEdgeEuler + this.upLimitAngle : this.limitEdgeEuler - this.downLimitAngle;this.centerCamera.node.setRotationFromEuler(x, y, z);}const { x, y } = this.centerCamera.node.eulerAngles;this.centerCamera.node.setRotationFromEuler(x, y, 0);}//点击检测功能区@property([EventHandler])private collisionEventHandlerArray: EventHandler[] = [];@property([Node])private collisionNodeArray: Node[] = [];private clickManagerStart() {this.setCollisionNodeCollider();this.bindClickEvent();}private setCollisionNodeCollider() {this.collisionNodeArray.forEach((node) => {let collider = node.getComponent(Collider);if (!collider) { collider = node.addComponent(SphereCollider);}
collider.isTrigger = true;});}private clickRay = new geometry.Ray();private bindClickEvent() {this.node.on("click", ({ x, y }: Vec2) => {if (this.collisionNodeArray.length === 0) return;this.centerCamera.screenPointToRay(x, y, this.clickRay);
PhysicsSystem.instance.raycast(this.clickRay);if (PhysicsSystem.instance.raycastResults.length) {const firstColliderNode = PhysicsSystem.instance.raycastResults[0].collider.node;this.collisionEventHandlerArray.forEach((handler) => handler.emit([firstColliderNode]));}});}
}
cocos creator实现浏览星球的功能,附源码相关推荐
- Qt利用avilib实现录屏功能_openlayers6结合geoserver利用WFS服务实现图层编辑功能(附源码下载)...
内容概览 1.openlayers6结合geoserver利用WFS服务实现图层编辑功能 2.源代码demo下载 效果图如下: 本篇主要是参照openlayers6结合geoserver利用WFS服务 ...
- arcgis xml 下载 切片_openlayers6结合geoserver利用WFS服务实现图层编辑功能(附源码下载)...
内容概览 1.openlayers6结合geoserver利用WFS服务实现图层编辑功能 2.源代码demo下载 效果图如下: 本篇主要是参照openlayers6结合geoserver利用WFS服务 ...
- VC++利用笔记本自带摄像头扫二维码功能(附源码demo)
VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 第8章:VC++利用笔记本自带摄像头扫二维码功能(附源码demo) 源代码demo已上传到百度网盘:永久生效 ,代码实现了打开笔记本 ...
- srs可以用java开发吗,为SRS流媒体服务器添加HLS加密功能(附源码)
#为SRS流媒体服务器添加HLS加密功能(附源码)# 之前测试使用过nginx的HLS加密功能,会使用到一个叫做nginx-rtmp-module的插件,但此插件很久不更新了,网上搜索到一个中国制造的 ...
- VC++实现的软键盘功能(附源码)
VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 软键盘界面如下: 置于桌面窗口最顶层: 置顶介绍: if (hwnd = FindWindow(NULL, szTitle)){// ...
- IoC容器Autofac(3) - 理解Autofac原理,我实现的部分Autofac功能(附源码)
上篇文章中,举了一个Autofac的简单例子,园友eflay反应: "虽然对autofac架构原理还是完全不懂,不过基本是明白ioc的用途了,会从已注册的类中找出符合接口的类来调用构造函数进 ...
- cocos creator经典游戏英文版《俄罗斯方块》源码H5+安卓+IOS三端源码
cocos creator2.2.2经典游戏英文版<俄罗斯方块>源码H5+安卓+IOS三端源码,开发脚本为typeScript方便扩展和阅读,支持cocos creator2.X版本,完整 ...
- java基于Redis实现排行榜功能-附源码
java基于Redis Zset实现排行榜功能 前言 做之前要思考的问题? Zset怎么存储需要的多个字段? 话不多说先上效果图 数据存储格式 代码 源码下载 闲暇之余,整理了一下之前利用Redis ...
- 微信小程序实现天气预报功能(附源码)
目录 前言 效果图 天气API获取 微信小程序后台域名配置 页面代码 注意问题(必看) 留言 前言 最近在学小程序开发,刚好学到天气预报功能的制作,于是给大家分享下. 效果图 天气API获取 这里我用 ...
最新文章
- 总结:DCIC算法分析赛完整方案分享!
- NBT:PICRUSt2预测宏基因组功能
- “春色满园”!谷歌新数据中心有望实现100%可再生能源
- [再学Python] - 2 - math库和random库
- Software Defined Networking(Week 2, part 2)
- 请求发送者与接收者解耦——命令模式(五)
- 关于Symantec企业级防病毒软件的版本历史
- [机器学习与scikit-learn-20]:算法-逻辑回归-线性逻辑回归linear_model.LogisticRegression与代码实现
- java 登陆邮箱_java如何登陆163邮箱,获取登陆用户的好友列表(1)
- STM8 时钟寄存器
- 基于Python实现的黑白棋强化学习模型
- 解决方案:SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to
- BX9054: 各浏览器对 document.execCommand 方法的首参数可选值范围存在差异
- Speedoffice(PPT)如何做动画演示效果
- 学雷前辈暑期小学期课简单视频播放器制作笔记(二)
- 偏差-方差均衡(Bias-Variance Tradeoff)
- [机缘参悟-30]:鬼谷子-内揵篇-同理心,站在对方的立场,拉近与对方的心理距离
- telnet中使用IMAP协议查看收件箱
- 【三栏式布局、双飞翼布局、圣杯布局】09
- Python 获取目录下的文件列表,并自然排序