<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>

          轉(zhuǎn)向行為! steering behaviors !

          共 7781字,需瀏覽 16分鐘

           ·

          2021-05-29 14:12

          尋找 seek 避開 flee 到達(dá) arrive 追逐 purse 躲避 evade 群落 flock !

          效果

          轉(zhuǎn)向行為旨在通過使用簡單的力來幫助自主角色以逼真的方式運(yùn)動(dòng),這些簡單的力結(jié)合起來可以圍繞角色的環(huán)境產(chǎn)生逼真的,即興的導(dǎo)航。它們不是基于涉及路徑規(guī)劃或全局計(jì)算的復(fù)雜策略,而是使用本地信息,例如鄰居的部隊(duì)。這使它們易于理解和實(shí)施,但仍然能夠產(chǎn)生非常復(fù)雜的運(yùn)動(dòng)模式。

          群落效果:

          追逐偏移:

          視頻預(yù)覽[歡迎關(guān)注,獲得最新研究成果]:

          實(shí)現(xiàn)

          實(shí)現(xiàn)轉(zhuǎn)向行為抓住以下兩個(gè)點(diǎn):

          • 轉(zhuǎn)向力
          • 周圍角色對(duì)象

          角色類需要包含以下幾個(gè)基本屬性:

          • 位置
          • 速度
          • 轉(zhuǎn)向力

          每幀根據(jù)合力與加速度,速度與位置的關(guān)系,更新位置。

          this._steeredForce.multiplyScalar(1 / this.mass)
          this.velocity.add(this._steeredForce)
          this._steeredForce.set(00)
          this._position.add(this.velocity)

          每種行為,都會(huì)算出有個(gè)期望速度,根據(jù)這個(gè)期望速度算出一個(gè)轉(zhuǎn)向力加上去即可。

          尋找 seek 與 避開 flee

          尋找的期望速度直接指向目標(biāo)點(diǎn),轉(zhuǎn)向力是期望速度減去當(dāng)前速度。避開正好相反。

          seek(target: Vec2): void {
              const desiredVelocity: Vec2 = Vec2.subtract(temp_v2, target, this._position).normalize()
              desiredVelocity.multiplyScalar(this.maxSpeed);
              const force: Vec2 = desiredVelocity.subtract(this.velocity);
              this._steeredForce.add(force);
          }

          flee(target: Vec2): void {
              const desiredVelocity: Vec2 = Vec2.subtract(temp_v2, target, this._position).normalize()
              desiredVelocity.multiplyScalar(this.maxSpeed);
              const force: Vec2 = desiredVelocity.subtract(this.velocity);
              this._steeredForce.subtract(force);
          }

          到達(dá) arrive

          與尋找的期望速度類似,方向是一樣的,區(qū)別是快到的時(shí)候速度會(huì)減少。

          可以加一個(gè)距離控制,在還沒達(dá)到這個(gè)距離時(shí),先以最快的速度過去,比較近的時(shí)候減緩速度。

          arrive(target: Vec2): void {
              const desiredVelocity: Vec2 = Vec2.subtract(temp_v2, target, this._position).normalize()
              const dist: number = Vec2.distance(this._position, target)
              if (dist > this.arrivalThreshold) {
                  desiredVelocity.multiplyScalar(this.maxSpeed);
              } else {
                  desiredVelocity.multiplyScalar(this.maxSpeed * dist / this.arrivalThreshold);
              }
              const force: Vec2 = desiredVelocity.subtract(this.velocity);
              this._steeredForce.add(force);
          }

          追逐 purse 與 躲避 evade

          追逐與躲避會(huì)預(yù)測(cè)目標(biāo)將會(huì)移動(dòng)到的位置,最后再調(diào)用尋找和避開。

          其中,追逐時(shí),如果剛好在正前方,就不用預(yù)測(cè)目標(biāo)移動(dòng)的位置,直接飛過去就好。

          pursue(target: Vehicle): void {
              const toTarget = Vec2.subtract(temp_v2, target.position, this._position)
              if (toTarget.dot(this.heading) > 0 && this.heading.dot(target.heading) < -0.95) {
                  // 如果面對(duì)面,正好在前面,就直接飛過去
                  this.seek(target.position)
              } else {
                  const lookAheadTime: number = Vec2.distance(this._position, target.position) / (this.maxSpeed + target.velocity.length());
                  const predictedTarget: Vec2 = Vec2.add(temp2_v2, target.position, Vec2.multiplyScalar(temp_v2, target.velocity, lookAheadTime));
                  this.seek(predictedTarget)
              }
          }

          evade(target: Vehicle): void {
              const lookAheadTime: number = Vec2.distance(this._position, target.position) / (this.maxSpeed + target.velocity.length())
              const predictedTarget: Vec2 = Vec2.add(temp2_v2, target.position, Vec2.multiplyScalar(temp_v2, target.velocity, lookAheadTime));
              this.flee(predictedTarget)
          }    

          追逐偏移 pursueOffset

          追逐偏移使得角色之間保持指定位置的偏移。

          先初始算出偏移位置,再算偏移預(yù)期位置,最后調(diào)用到達(dá)。

          pursueOffset(target: Vehicle, offset: Vec2): void {
              const localOffset = temp_v2.set(
                  target.side.x * offset.x + target.side.y * offset.y,
                  target.heading.x * offset.x + target.heading.y * offset.y
              )
              const offsetTargetPos = Vec2.add(temp_v2, target.position, localOffset)
              const lookAheadTime: number = Vec2.distance(this._position, offsetTargetPos) / (this.maxSpeed + target.velocity.length())
              const predictedTarget: Vec2 =
                  Vec2.add(
                      temp2_v2,
                      offsetTargetPos,
                      Vec2.multiplyScalar(temp2_v2, target.velocity, lookAheadTime),
                  );
              this.arrive(predictedTarget)
          }

          群落 flock

          群落行為是由分離、凝聚和隊(duì)列組成。

          • 分離(separation):每個(gè)角色都試著和相鄰角色保持一定的距離。
          • 凝聚(cohesion):每個(gè)角色盡量不掉隊(duì),不落下太遠(yuǎn)。
          • 隊(duì)列(alignment):每個(gè)角色盡可能與相鄰角色行動(dòng)于同一方向。

          近了就離開,在一定范圍內(nèi)就靠近,速度取平均值。

          flock(vehicles: Vehicle[]): void {
              let averageVelocity: Vec2 = temp3_v2.set(this.velocity)
              let averagePosition: Vec2 = temp4_v2.set(00)
              let inSightCount = 0;
              for (let i = 0; i < vehicles.length; i++) {
                  let vehicle: Vehicle = vehicles[i] as Vehicle;
                  if (vehicle != this && this.inSight(vehicle)) {
                      averageVelocity = averageVelocity.add(vehicle.velocity);
                      averagePosition = averagePosition.add(vehicle.position);
                      if (Vec2.squaredDistance(this.position, vehicle.position) < this.tooCloseDist * this.tooCloseDist) this.flee(vehicle.position);
                      inSightCount++;
                  }
              }
              if (inSightCount > 0) {
                  averageVelocity.multiplyScalar(1 / inSightCount);
                  averagePosition.multiplyScalar(1 / inSightCount);
                  this.seek(averagePosition);
                  const force = averageVelocity;
                  this._steeredForce.subtract(force);
              }
          }

          小結(jié)

          轉(zhuǎn)向行為的實(shí)現(xiàn)可分解為模擬各個(gè)行為的力,再計(jì)算合力,接著算加速度和速度,最后更新位置!

          以上為白玉無冰使用 Cocos Creator 3.1.0 實(shí)現(xiàn) "轉(zhuǎn)向行為!" 的技術(shù)分享。

          Cocos Store 鏈接:   http://store.cocos.com/app/detail/2893

          參考資料

          https://www.red3d.com/cwr/steer/
          《Flash ActionScript 3.0 動(dòng)畫高級(jí)教程》

          《游戲人工智能編程案例精粹》

          keep hungry! keep foolish!

          更多

          折紙效果
          豎直布局的文本
          彈性跟隨相機(jī)!
          標(biāo)志板!
          2D 素材 3D 效果!
          2020 原創(chuàng)精選!


          更多精彩歡迎關(guān)注微信公眾號(hào)



          瀏覽 67
          點(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>
                  操操操操操操操操操操操逼 | 亚洲精品久久久蜜桃 直播 | 豆花国产在线 | 国产精品久久久久久无码牛牛章艳 | 国产精品伊人 |