Box2d 物理画线,Cocos Creator 3.8

news2024/11/27 21:00:50

一个简易的画线刚体Demo

效果

8f47de634e1b0ed99c34556f5d6d6bce.gif

抱歉,放错图了,以上是 孙二喵 iwae https://forum.cocos.org/t/topic/142673[1] 的效果图。本Demo是根据文章的思路,合成的代码。首先,感谢孙二喵的技术分享。

以下是最终效果图

02574b9799258f43a7ab84bce6bc59cf.gif

使用

版本 Cocos Creator 3.8.1

  1. 创建一个 Empty(2D) 项目

f080e303ac7117572eee3075628d1c09.png
  1. 保存场景,新建一个 Game.ts 脚本,把代码复制进去(代码在最后面)

bf29203dee0e723e495237a74ec56580.png
  1. 拖入Game.ts脚本至场景中

697e7c5f2482ba82e398caca0bf8602c.png
  1. (可选)在场景中添加一些静态刚体和碰撞体

0a3c17841e62746acc9b6bd2772787ba.png
  1. 运行预览

原理

坐标转换

触点坐标转到节点坐标

  • getUILocation

  • UITransform.convertToNodeSpaceAR

推荐阅读纯干货!一文搞懂 Cocos Creator 3.0 坐标转换原理

https://mp.weixin.qq.com/s/mV5EY4NMrpgCP9XFocrcGA

计算碰撞体

首先问题分解:已知:

  • 两个点的坐标

  • 线宽

求:

  • 围成该线段的四个点的坐标

297ccd958184676ae53e8db378ac5426.png

回顾一下,2D中的旋转的矩阵是:

旋转90度的矩阵为

旋转-90度的矩阵为

先计算方向向量,然后2个垂直方向的向量,分别乘以我们线段一半的宽度,最后起始点和结束点分别加上这2个向量,4个路径点

//方向向量
d = (end - start).normalize();
//垂直向量1
d1 = R_1 * d = (d.y,-d.x)
//垂直向量2
d2 = R_2 * d = (-d.y,d.x)
//求4个点
p1 = start + d1 * widhtHalf
p2 = start + d2 * widhtHalf
p3 = end + d1 * widhtHalf
p4 = end + d2 * widhtHalf
6fc75ae2fe13d5d1f91cdd916452f5d3.png

代码

import { _decorator, Component, EventTouch, find, Node, macro, Graphics, v2, Vec2, UITransform, v3, Color, RigidBody2D, PolygonCollider2D, PhysicsSystem2D } from 'cc';
const { ccclass, property } = _decorator;

const __tempV2 = v2()
const __tempV3 = v3()

type TypePoint = {
    x: number,
    y: number
}

@ccclass('Game')
export class Game extends Component {

    private _canvasNode: Node
    start() {
        macro.ENABLE_MULTI_TOUCH = false;
        PhysicsSystem2D.instance.debugDrawFlags = 1;
        this._canvasNode = find("Canvas")
        this._canvasNode.on(Node.EventType.TOUCH_START, this.onTouchStart, this)
        this._canvasNode.on(Node.EventType.TOUCH_MOVE, this.onTouchMove, this)
        this._canvasNode.on(Node.EventType.TOUCH_END, this.onTouchEnd, this)
        this._canvasNode.on(Node.EventType.TOUCH_CANCEL, this.onTouchEnd, this)
    }

    private getUIPos(pos: Vec2) {
        __tempV3.set(pos.x, pos.y, 0)
        this._curGraphics.node.getComponent(UITransform).convertToNodeSpaceAR(__tempV3, __tempV3)
        pos.set(__tempV3.x, __tempV3.y)
        return pos;
    }

    private _curGraphics: Graphics;
    private onTouchStart(evt: EventTouch) {
        evt.getUILocation(__tempV2)
        this._pointList.length = 0;
        const node = new Node()
        node.layer = this._canvasNode.layer;
        this._canvasNode.addChild(node);
        this._curGraphics = node.addComponent(Graphics)
        this._curGraphics.strokeColor = Color.WHITE;
        this._curGraphics.lineWidth = 10;
        const { x, y } = this.getUIPos(__tempV2)
        this._curGraphics.moveTo(x, y)
        this._pointList.push({ x, y })
    }

    private _preK: number = 0
    private _pointList: TypePoint[] = []
    private onTouchMove(evt: EventTouch) {
        evt.getUILocation(__tempV2)
        const { x, y } = this.getUIPos(__tempV2)
        const { x: preX, y: preY } = this._pointList[this._pointList.length - 1];
        const diffX = x - preX;
        const diffY = y - preY;
        const dis = (Math.abs(diffX) + Math.abs(diffY))
        if (dis >= this._curGraphics.lineWidth) {
            const d = 0.001
            const curK = Math.abs(diffX) < d ? (Number.MAX_SAFE_INTEGER * Math.sign(diffX) * Math.sign(diffY)) : (diffY / diffX)
            if (this._pointList.length > 1) {
                const diffK = curK - this._preK;
                if (Math.abs(diffK) < d) {
                    // 斜率相同去掉前一个点
                    this._pointList.pop()
                }
            }
            this._pointList.push({ x, y })
            this._curGraphics.lineTo(x, y)
            this._curGraphics.stroke();
            this._preK = curK;
        }
    }

    private onTouchEnd(evt: EventTouch) {
        console.log(this._pointList.length)
        if (this._pointList.length > 1) {
            this._curGraphics.addComponent(RigidBody2D);
            for (let index = 0; index < this._pointList.length - 1; index++) {
                const start = this._pointList[index];
                const end = this._pointList[index + 1];
                const poly = this._curGraphics.addComponent(PolygonCollider2D);
                const d = v2(end.x - start.x, end.y - start.y).normalize();
                const widhtHalf = this._curGraphics.lineWidth / 2;
                const p1 = v2(d.y, -d.x).multiplyScalar(widhtHalf).add2f(start.x, start.y)
                const p2 = v2(-d.y, d.x).multiplyScalar(widhtHalf).add2f(start.x, start.y)
                const p3 = v2(d.y, -d.x).multiplyScalar(widhtHalf).add2f(end.x, end.y)
                const p4 = v2(-d.y, d.x).multiplyScalar(widhtHalf).add2f(end.x, end.y)
                poly.points = [p1, p2, p4, p3];
                poly.apply()
            }
        } else {
            this._curGraphics.node.destroy();
        }
        this._curGraphics = null;
    }
}

小结

简单来说,画线刚体就是根据路径点和线宽去生成碰撞体。

参考资料

[1]

https://forum.cocos.org/t/topic/142673: https://forum.cocos.org/t/topic/142673

364b098e6a67479f94abef30c5acf83b.jpeg

“点赞“ ”在看” 鼓励一下a36b1ea4fe56c51237831f5013d4211a.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1172787.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Cube MX 开发高精度电流源跳坑过程/SPI连接ADS1255/1256系列问题总结/STM32 硬件SPI开发过程

文章目录 概要整体架构流程技术名词解释技术细节小结 概要 1.使用STM32F系列开发一款高精度恒流电源&#xff0c;用到了24位高精度采样芯片ADS1255/ADS1256系列。 2.使用时发现很多的坑&#xff0c;详细介绍了每个坑的具体情况和实际的解决办法。 坑1&#xff1a;波特率设置…

【C++初阶】第一站:C++入门基础(上) -- 良心详解

前言: 从这篇文章开始,将进入C阶段的学习&#xff0c;此篇文章是c的第一站的上半篇&#xff0c;讲述C初阶的知识 目录 什么是C C的发展史 C关键字(C98) 命名空间 命名空间定义 命名空间使用 1.加命名空间名称及作用域限定符 2.使用using将命名空间中某个成员引入 3.使…

PTA:前序序列创建二叉树

前序序列创建二叉树 题目输入格式输出格式输入样例&#xff08;及其对应的二叉树&#xff09;输出样例 代码 题目 编一个程序&#xff0c;读入用户输入的一串先序遍历字符串&#xff0c;根据此字符串建立一个二叉树&#xff08;以二叉链表存储&#xff09;。 例如如下的先序遍…

火狐浏览器导入burpsuite CA 证书无法正常上网

当我们给火狐浏览器设置burpsuite代理&#xff0c;并给火狐导入了burpsuite的CA证书后&#xff0c;仍然无法上网的解决方法。 当我们把浏览器的代理配置好之后&#xff0c;浏览器导入证书&#xff0c;burpsuite设置好代理后&#xff0c;如上图&#xff0c;仍然无法上网&…

精品Python手机数据收集软件-爬虫可视化大屏

《[含文档PPT源码等]精品基于Python的数据收集软件-爬虫》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;python 使用框架&#xff1a;Django 前端技术&#xff…

【教3妹学编程-算法题】重复的DNA序列

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开心呀。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;阳光明媚、万里无云、秋高气爽&#xff0c;适合秋游。 2哥&…

STM32WB55开发(6)----FUS更新

STM32WB55开发.6--FUS更新 概述视频教学硬件准备存储器映射FLASH安全区设置SRAM安全区设置通过USB进行下载注意事项 概述 在 STM32WB 微控制器中&#xff0c;FUS&#xff08;Firmware Upgrade Services&#xff09;是用于固件升级的一种服务。这项服务可以让你更新设备上的无…

回归预测 | Matlab实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机的多输入单输出回归预测

回归预测 | Matlab实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机的多输入单输出回归预测 目录 回归预测 | Matlab实现SSA-CNN-SVM麻雀算法优化卷积神经网络-支持向量机的多输入单输出回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.SSA-CNN-SVM麻雀算法…

Jupyter Notebook交互式开源笔记本工具

1、官网 http://jupyter.org/ 2、什么是Jupyter Notebook Jupyter Notebook一个交互式的开源笔记本工具&#xff0c;可以用于编写、运行、和共享代码、文本、图形等内容。 如下文本、代码、图形 支持多种编程语言&#xff0c;包括python、R和Julia等&#xff0c;可以走一个…

计算机服务器中了locked勒索病毒怎么办,勒索病毒解密,数据恢复

随着网络技术的不断成熟&#xff0c;网络中存在的病毒威胁也不断增多&#xff0c;近期&#xff0c;云天数据恢复中心陆续接到很多企业的求助&#xff0c;企业的计算机服务器数据库遭到了勒索病毒攻击&#xff0c;并且勒索病毒的攻击与加密形式也发生了许多变化。其中攻击次数较…

优化|求解非凸和无梯度lipschitz连续性的一阶算法在二次规划反问题中的应用(代码分享)

原文信息&#xff08;包括题目、发表期刊、原文链接等&#xff09;&#xff1a;First Order Methods Beyond Convexity and Lipschitz Gradient Continuity with Applications to Quadratic Inverse Problems 原文作者&#xff1a;Jrme Bolte, Shoham Sabach, Marc Teboulle, a…

Vue H5页面长按保存为图片

安装依赖&#xff1a;npm install html2canvas -d <template><div class"index"><div id"captureId" class"capture" v-show"firstFlag"><ul><li>1</li><li>2</li><li>3<…

数学概率 | 旋转矩阵、欧拉角、四元数

目录 一&#xff0c;旋转矩阵 二维旋转矩阵 三维旋转矩阵 二&#xff0c;欧拉角 三&#xff0c;四元数 四&#xff0c;矩阵、欧拉角、四元数相互转换 四元数转矩阵 矩阵转四元数 欧拉角转矩阵 矩阵转欧拉角 欧拉角转四元数 四元数转欧拉角 一&#xff0c;旋转矩阵 …

JavassmMYSQL宠物领养系统08465-计算机毕业设计项目选题推荐(附源码)

目 录 摘要 1 绪论 1.1课题背景及意义 1.2研究现状 1.3ssm框架介绍 1.3论文结构与章节安排 2 宠物领养系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 非功能性分析 2.4 系统用例分析 …

大数据Doris(十七):关于 Partition 和 Bucket 的数量和数据量的建议

文章目录 关于 Partition 和 Bucket 的数量和数据量的建议 关于 Partition 和 Bucket 的数量和数据量的建议 一个表的 Tablet 总数量等于 (Partition num * Bucket num)。一个表的 Tablet 数量,在不考虑扩容的情况下,推荐略多于整个集群的磁盘数量。单个 Tablet 的数据量理论…

MySQL第四讲·如何正确设置主键?

你好&#xff0c;我是安然无虞。 文章目录 主键&#xff1a;如何正确设置主键&#xff1f;业务字段做主键自增字段做主键手动赋值字段做主键 主键总结 主键&#xff1a;如何正确设置主键&#xff1f; 前面我们在讲解存储的时候&#xff0c;有提到过主键&#xff0c;它可以唯一…

CrossOver软件2024最新版本下载

我们都明白快速运行&#xff1a;无须再独立运行一个Win电脑操作系统&#xff0c;进而解决双启动的繁杂和vm虚拟机的卡屏。习惯上来说极速运行&#xff1a;CrossOver能够让Win软件全速全状态运行&#xff0c;不会有丝毫的性能影响&#xff0c;让你在MAC系统中使用熟悉的Win应用。…

【JMeter】后置处理器的分类以及场景介绍

1.常用后置处理器的分类 Json提取器 针对响应体的返回结果是json格式的会自动生成新的变量名为【提取器中变量名_MatchNr】,取到的个数由jsonpath expression取到的个数决定 可以当作普通变量调用,调用语法:${提取器中变量名_MatchNr}正则表达式提取器 返回结果是任何数据格…

2022年12月 Python(三级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试&#xff08;1~6级&#xff09;全部真题・点这里 一、单选题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 第1题 列表L1中全是整数&#xff0c;小明想将其中所有奇数都增加1&#xff0c;偶数不变&#xff0c;于是编写了如下图所示的代…

单链表经典算法

移除链表元素 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 思路&#xff1a;&#xff08;1&#xff09;创建三个结构体指针&#xff0c;分别代表一条新链表的头newhead&#xff0c;…