cocos creator实现浏览星球的功能,附源码
创始人
2024-02-21 16:03:06

预览效果:

 

技术要点:

  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]));}});}
}

相关内容

热门资讯

上海宾馆预订(上海宾馆预订服务... 今天给各位分享上海宾馆预订的知识,其中也会对上海宾馆预订服务网站进行解释,如果能碰巧解决你现在面临的...
携程飞机票查询(携程飞机票查询... 今天给各位分享携程飞机票查询的知识,其中也会对携程飞机票查询网上订单怎么查进行解释,如果能碰巧解决你...
成都到重庆的火车时刻表(成都至... 今天给各位分享成都到重庆的火车时刻表的知识,其中也会对成都至重庆的高铁时刻表进行解释,如果能碰巧解决...
Mybatis框架源码笔记(八... 1、插件概述 引用一段官网的译文 MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。...
扶绥到南宁的火车(扶绥到南宁的... 本篇文章极速百科给大家谈谈扶绥到南宁的火车,以及扶绥到南宁的火车时间表对应的知识点,希望对各位有所帮...
ubuntu20.4源码安装最...         Ubuntu20.4自带的gcc为V9.4.0的版本,老版本的gcc存...
二次开发:基于ssm的流浪猫狗... 项目描述 该项目使用spring mvc,spring,mybatis框...
图像方向矫正和透视变换处理 文章目录一、前期工作二、当前进展1. PaddleSeg2. MobileSeg 模型3. 代码处理...
成都到巴中火车时刻表(北京至成... 本篇文章极速百科给大家谈谈成都到巴中火车时刻表,以及北京至成都的火车时刻表对应的知识点,希望对各位有...
南昌到向塘(南昌到向塘火车票查... 本篇文章极速百科给大家谈谈南昌到向塘,以及南昌到向塘火车票查询对应的知识点,希望对各位有所帮助,不要...
上海到苏州火车票价(南京到上海... 今天给各位分享上海到苏州火车票价的知识,其中也会对南京到上海火车票价进行解释,如果能碰巧解决你现在面...
洛阳如家快捷酒店(洛阳如家快捷... 本篇文章极速百科给大家谈谈洛阳如家快捷酒店,以及洛阳如家快捷酒店地址电话对应的知识点,希望对各位有所...
flinkcdc笔记        在之前的数据同步中,好比咱们想实时获取数据库的数据,通常采...
《程序员面试金典(第6版)》面... 题目描述 设计并实现一个算法,找出二叉树中某两个节点的第一个共同祖先。不得将其他的节点...
如何在外网http访问内网邮件... 不少公司选择用winmail搭建部署内部邮箱服务器,对于邮件管理员,不但...
java常用设计模式以及场景使... 背景 设计模式在面试中总是不能很好的回答出来,所以开一个专题,将每一个...
常州恐龙园门票价格(常州恐龙园... 本篇文章极速百科给大家谈谈常州恐龙园门票价格,以及常州恐龙园门票价格查询对应的知识点,希望对各位有所...
郑州清华园(郑州清华园小区房价... 今天给各位分享郑州清华园的知识,其中也会对郑州清华园小区房价进行解释,如果能碰巧解决你现在面临的问题...
郑州火车票查询(深圳到郑州火车... 今天给各位分享郑州火车票查询的知识,其中也会对深圳到郑州火车票查询进行解释,如果能碰巧解决你现在面临...
哈尔滨如家酒店(哈尔滨如家酒店... 今天给各位分享哈尔滨如家酒店的知识,其中也会对哈尔滨如家酒店住宿价格进行解释,如果能碰巧解决你现在面...
一、用户行为采集平台 第1章 数据仓库概念数据仓库( Data Warehouse )...
【嵌入式模块】MPU6050 文章目录0 前言1 MPU6050概述1.1 基本概述1.2 引脚和常用原理图2 代码3 姿态解算3...
湖南省博物馆网上订票(湖南省博... 今天给各位分享湖南省博物馆网上订票的知识,其中也会对湖南省博物馆网上订票怎么订进行解释,如果能碰巧解...
本溪到沈阳列车时刻表(本溪到沈... 今天给各位分享本溪到沈阳列车时刻表的知识,其中也会对本溪到沈阳列车时刻表最新查询进行解释,如果能碰巧...
南京仙林宾馆(南京仙林宾馆电话... 本篇文章极速百科给大家谈谈南京仙林宾馆,以及南京仙林宾馆电话对应的知识点,希望对各位有所帮助,不要忘...
合肥到杭州的火车时刻表(合肥到... 今天给各位分享合肥到杭州的火车时刻表的知识,其中也会对合肥到杭州火车时刻表查询结果进行解释,如果能碰...
C++STL 容器案例 员工分... STL容器 员工分组案例 文章目录STL容器 员工分组案例1 案例描述2 实现步骤3 案例代码与分析...
每日一题——最大网络秩 解答代码: class Solution { public:     int maxi...
哈利法塔门票(哈利法塔门票多少... 今天给各位分享哈利法塔门票的知识,其中也会对哈利法塔门票多少钱一张进行解释,如果能碰巧解决你现在面临...
台州火车票(阜阳到台州火车票)... 本篇文章极速百科给大家谈谈台州火车票,以及阜阳到台州火车票对应的知识点,希望对各位有所帮助,不要忘了...