预览效果:

技术要点:

  1. 主摄像机的视场轴需要设置为水平。

  1. 在场景下创建一个空节点用于挂载控制器脚本

图片已进行各概念的说明

在“collisionNodeArray”属性下,放置需要点击的星球节点,系统会自己绑定碰撞器。

也可自己提前绑定。

  1. 布局场景,星球围绕相机。参考如下:

注意相机的属性。可以根据自己的需要调整相机的z值。只要保证星球绕着相机布局则行。

  1. 关于摄像机旋转的上下限制。

可以通过设置

这两个参数进行调节,是个经验数值。

系统本身会进行基础的上下限制。这两个参数属于额外的限制。即顶部往下,底部往上。

控制器(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实现浏览星球的功能,附源码相关推荐

  1. Qt利用avilib实现录屏功能_openlayers6结合geoserver利用WFS服务实现图层编辑功能(附源码下载)...

    内容概览 1.openlayers6结合geoserver利用WFS服务实现图层编辑功能 2.源代码demo下载 效果图如下: 本篇主要是参照openlayers6结合geoserver利用WFS服务 ...

  2. arcgis xml 下载 切片_openlayers6结合geoserver利用WFS服务实现图层编辑功能(附源码下载)...

    内容概览 1.openlayers6结合geoserver利用WFS服务实现图层编辑功能 2.源代码demo下载 效果图如下: 本篇主要是参照openlayers6结合geoserver利用WFS服务 ...

  3. VC++利用笔记本自带摄像头扫二维码功能(附源码demo)

      VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 第8章:VC++利用笔记本自带摄像头扫二维码功能(附源码demo) 源代码demo已上传到百度网盘:永久生效  ,代码实现了打开笔记本 ...

  4. srs可以用java开发吗,为SRS流媒体服务器添加HLS加密功能(附源码)

    #为SRS流媒体服务器添加HLS加密功能(附源码)# 之前测试使用过nginx的HLS加密功能,会使用到一个叫做nginx-rtmp-module的插件,但此插件很久不更新了,网上搜索到一个中国制造的 ...

  5. VC++实现的软键盘功能(附源码)

      VC++开发常用功能一系列文章 (欢迎订阅,持续更新...) 软键盘界面如下: 置于桌面窗口最顶层: 置顶介绍: if (hwnd = FindWindow(NULL, szTitle)){// ...

  6. IoC容器Autofac(3) - 理解Autofac原理,我实现的部分Autofac功能(附源码)

    上篇文章中,举了一个Autofac的简单例子,园友eflay反应: "虽然对autofac架构原理还是完全不懂,不过基本是明白ioc的用途了,会从已注册的类中找出符合接口的类来调用构造函数进 ...

  7. cocos creator经典游戏英文版《俄罗斯方块》源码H5+安卓+IOS三端源码

    cocos creator2.2.2经典游戏英文版<俄罗斯方块>源码H5+安卓+IOS三端源码,开发脚本为typeScript方便扩展和阅读,支持cocos creator2.X版本,完整 ...

  8. java基于Redis实现排行榜功能-附源码

    java基于Redis Zset实现排行榜功能 前言 做之前要思考的问题? Zset怎么存储需要的多个字段? 话不多说先上效果图 数据存储格式 代码 源码下载 闲暇之余,整理了一下之前利用Redis ...

  9. 微信小程序实现天气预报功能(附源码)

    目录 前言 效果图 天气API获取 微信小程序后台域名配置 页面代码 注意问题(必看) 留言 前言 最近在学小程序开发,刚好学到天气预报功能的制作,于是给大家分享下. 效果图 天气API获取 这里我用 ...

最新文章

  1. 总结:DCIC算法分析赛完整方案分享!
  2. NBT:PICRUSt2预测宏基因组功能
  3. “春色满园”!谷歌新数据中心有望实现100%可再生能源
  4. [再学Python] - 2 - math库和random库
  5. Software Defined Networking(Week 2, part 2)
  6. 请求发送者与接收者解耦——命令模式(五)
  7. 关于Symantec企业级防病毒软件的版本历史
  8. [机器学习与scikit-learn-20]:算法-逻辑回归-线性逻辑回归linear_model.LogisticRegression与代码实现
  9. java 登陆邮箱_java如何登陆163邮箱,获取登陆用户的好友列表(1)
  10. STM8 时钟寄存器
  11. 基于Python实现的黑白棋强化学习模型
  12. 解决方案:SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to
  13. BX9054: 各浏览器对 document.execCommand 方法的首参数可选值范围存在差异
  14. Speedoffice(PPT)如何做动画演示效果
  15. 学雷前辈暑期小学期课简单视频播放器制作笔记(二)
  16. 偏差-方差均衡(Bias-Variance Tradeoff)
  17. [机缘参悟-30]:鬼谷子-内揵篇-同理心,站在对方的立场,拉近与对方的心理距离
  18. telnet中使用IMAP协议查看收件箱
  19. 【三栏式布局、双飞翼布局、圣杯布局】09
  20. Python 获取目录下的文件列表,并自然排序

热门文章

  1. 中考计算机试题,中考微机考试试题.docx
  2. Android Sqlite数据库详解
  3. RestTemplate
  4. 全球及中国BOPET盖膜行业研究及十四五规划分析报告
  5. avx指令集 matlab,最新版Matlab 2020a修复处理器识别bug 将默认调用最新指令集
  6. 从草根到百万年薪程序员的十年风雨之路,年薪50W
  7. TinyFrame框架中的UOW使用方式纠正
  8. Houdini:最小白的路径动画
  9. 蓝桥杯第六届省赛试题——温度记录器
  10. 【花雕动手做】有趣好玩的音乐可视化系列项目(32)--P10矩阵LED单元板