<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Box2d 物理畫線,Cocos Creator 3.8

          共 11781字,需瀏覽 24分鐘

           ·

          2023-11-09 09:19

          一個(gè)簡(jiǎn)易的畫線剛體Demo

          效果

          抱歉,放錯(cuò)圖了,以上是 孫二喵 iwae https://forum.cocos.org/t/topic/142673[1] 的效果圖。本Demo是根據(jù)文章的思路,合成的代碼。首先,感謝孫二喵的技術(shù)分享。

          以下是最終效果圖

          使用

          版本 Cocos Creator 3.8.1

          1. 創(chuàng)建一個(gè) Empty(2D) 項(xiàng)目
          1. 保存場(chǎng)景,新建一個(gè) Game.ts 腳本,把代碼復(fù)制進(jìn)去(代碼在最后面)
          1. 拖入Game.ts腳本至場(chǎng)景中
          1. (可選)在場(chǎng)景中添加一些靜態(tài)剛體和碰撞體
          1. 運(yùn)行預(yù)覽

          原理

          坐標(biāo)轉(zhuǎn)換

          觸點(diǎn)坐標(biāo)轉(zhuǎn)到節(jié)點(diǎn)坐標(biāo)

          • getUILocation
          • UITransform.convertToNodeSpaceAR

          推薦閱讀純干貨!一文搞懂 Cocos Creator 3.0 坐標(biāo)轉(zhuǎn)換原理

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

          計(jì)算碰撞體

          首先問題分解:已知:

          • 兩個(gè)點(diǎn)的坐標(biāo)
          • 線寬

          求:

          • 圍成該線段的四個(gè)點(diǎn)的坐標(biāo)

          回顧一下,2D中的旋轉(zhuǎn)的矩陣是:


          旋轉(zhuǎn)90度的矩陣為


          旋轉(zhuǎn)-90度的矩陣為


          先計(jì)算方向向量,然后2個(gè)垂直方向的向量,分別乘以我們線段一半的寬度,最后起始點(diǎn)和結(jié)束點(diǎn)分加上這2個(gè)向量,4個(gè)路徑點(diǎn)

          //方向向量
          d = (end - start).normalize();
          //垂直向量1
          d1 = R_1 * d = (d.y,-d.x)
          //垂直向量2
          d2 = R_2 * d = (-d.y,d.x)
          //求4個(gè)點(diǎn)
          p1 = start + d1 * widhtHalf
          p2 = start + d2 * widhtHalf
          p3 = end + d1 * widhtHalf
          p4 = end + d2 * widhtHalf

          代碼

          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) {
                              // 斜率相同去掉前一個(gè)點(diǎn)
                              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;
              }
          }

          小結(jié)

          簡(jiǎn)單來說,畫線剛體就是根據(jù)路徑點(diǎn)和線寬去生成碰撞體。

          參考資料

          [1]

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

          “點(diǎn)贊“ ”在看” 鼓勵(lì)一下

          瀏覽 778
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费成人一级片 | 九色伊人| 色吊丝最新永久网址大全 | 狼友最新网址 | 亚洲国产中文字幕啊啊啊扒开腿 |