亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

【Cocos Creator實戰教程(7)】——猴子摘月亮(平臺動作,碰撞檢測詳解)

2019-11-09 14:26:38
字體:
來源:轉載
供稿:網友

最后一個寒假說沒就沒。。。


話說我等Creator 的物理引擎等了好久好久,終于。。。。。。還是沒等到。。。。。。

我們今天就用碰撞檢測系統和一些算法簡單的模擬一下2D平臺動作的物理特性吧


先來看一下我們的主角 這里寫圖片描述

是不是很可愛啊

所以我們要給她起一個可愛的名字,

就叫她大馬猴吧。。。

水平移動:

我們先來實現一下按鍵控制大馬猴左右移動的效果

用渲染節點里的單色SPRite(后面的平臺也用這個)制作一個地面平臺,把大馬猴放在地面上 這里寫圖片描述

新建MonkeyControl腳本,掛載在大馬猴節點上

MonkeyControl.js

cc.Class({ extends: cc.Component, properties: { speed: 0, maxSpeed:0, acce: 0, direction: 0 }, onLoad: function () { cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); }, onDestroy() { cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); }, onKeyDown(event) { switch (event.keyCode) { case cc.KEY.a: case cc.KEY.left: this.direction = -1; break; case cc.KEY.d: case cc.KEY.right: this.direction = 1; break; } }, onKeyUp(event) { switch (event.keyCode) { case cc.KEY.a: case cc.KEY.left: case cc.KEY.d: case cc.KEY.right: this.direction = 0; break; } }, update: function (dt) { if (this.direction === 0) { if (this.speed > 0) { this.speed -= this.acce * dt; if (this.speed <= 0) this.speed = 0; } else if (this.speed < 0) { this.speed += this.acce * dt; if (this.speed >= 0) this.speed = 0; } } else { this.speed += (this.direction > 0 ? 1 : -1) * this.acce * dt; if (Math.abs(this.speed) > this.maxSpeed) { this.speed = this.speed > 0 ? this.maxSpeed : -this.maxSpeed; } } this.node.x += this.speed * dt; },});

我們在大馬猴的控制腳本里加了四個屬性 speed:x軸的速度 maxSpeed:x軸的最大速度,避免大馬猴越跑越快 acce:x軸加速度 direction:按鍵控制方向,-1:左(按下左鍵),1:右(按下右鍵),0:不動(松開按鍵)

通常對物體運動的位置計算會放在update函數里,核心邏輯就是:位移=速度x時間,速度=加速度x時間

update這個函數是一個循環周期函數,每隔一個固定的時間(dt)就會調用一次

這里的if,else部分就是為了得出本次update的速度,然后根據速度乘時間更新本次大馬猴的位置

如果感覺不好理解,是時候拿出高中物理課本復習一遍了

設置一下參數:

這里寫圖片描述

效果如下:

這里寫圖片描述

跳躍運動

突然腦子里響起了廣播體操的音樂。。。

修改MonkeyControl.js

cc.Class({ extends: cc.Component, properties: { speed: cc.v2(0, 0), maxSpeed: cc.v2(0, 0), acce: 0, direction: 0, jumpSpeed:0, gravity:0, groundY: 0 }, onLoad: function () { this.groundY = this.node.y; this.jumping = false; cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); }, onDestroy() { cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); }, onKeyDown(event) { switch (event.keyCode) { case cc.KEY.a: case cc.KEY.left: this.direction = -1; break; case cc.KEY.d: case cc.KEY.right: this.direction = 1; break; case cc.KEY.w: case cc.KEY.up: if(!this.jumping){ this.jumping = true; this.speed.y = this.jumpSpeed; } } }, onKeyUp(event) { switch (event.keyCode) { case cc.KEY.a: case cc.KEY.left: case cc.KEY.d: case cc.KEY.right: this.direction = 0; break; } }, update: function (dt) { if (this.jumping) { this.speed.y += this.gravity * dt; if (Math.abs(this.speed.y) > this.maxSpeed.y) { this.speed.y = this.speed.y > 0 ? this.maxSpeed.y : -this.maxSpeed.y; } } if (this.direction === 0) { if (this.speed.x > 0) { this.speed.x -= this.acce * dt; if (this.speed.x <= 0) this.speed.x = 0; } else if (this.speed.x < 0) { this.speed.x += this.acce * dt; if (this.speed.x >= 0) this.speed.x = 0; } } else { this.speed.x += (this.direction > 0 ? 1 : -1) * this.acce * dt; if (Math.abs(this.speed.x) > this.maxSpeed.x) { this.speed.x = this.speed.x > 0 ? this.maxSpeed.x : -this.maxSpeed.x; } } this.node.x += this.speed.x * dt; this.node.y += this.speed.y * dt; if(this.node.y <= this.groundY){ this.node.y = this.groundY; this.jumping = false; } },});

這里我們給大馬猴又加了幾個屬性

jumpSpeed:起跳速度 gravity:重力 groundY:大馬猴落到地面時的Y軸位置 同時把speed和maxSpeed都變成了二維的

測試參數: 這里寫圖片描述

效果如下: 這里寫圖片描述

利用碰撞檢測實現平臺動作

首先我們再添加一個平臺節點,然后給地面,平臺和大馬猴都添加碰撞組件

這里寫圖片描述

修改MonkeyControl.js

cc.Class({ extends: cc.Component, properties: { speed: cc.v2(0, 0), maxSpeed: cc.v2(0, 0), acce: 0, direction: 0, jumpSpeed: 0, gravity: 0, }, onLoad: function () { cc.director.getCollisionManager().enabled = true; cc.director.getCollisionManager().enabledDebugDraw = true; cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); this.jumping = false; this.collisionX = 0;//x軸是否碰撞,0:沒有碰撞,-1:左方有碰撞,1:右方有碰撞 this.collisionY = 0; this.touchingNumber = 0;//同時碰撞物體的個數 }, onDestroy() { cc.director.getCollisionManager().enabled = false; cc.director.getCollisionManager().enabledDebugDraw = false; cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN, this.onKeyDown, this); cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP, this.onKeyUp, this); }, onKeyDown(event) { switch (event.keyCode) { case cc.KEY.a: case cc.KEY.left: this.direction = -1; break; case cc.KEY.d: case cc.KEY.right: this.direction = 1; break; case cc.KEY.w: case cc.KEY.up: if (!this.jumping) { this.jumping = true; this.speed.y = this.jumpSpeed; } } }, onKeyUp(event) { switch (event.keyCode) { case cc.KEY.a: case cc.KEY.left: case cc.KEY.d: case cc.KEY.right: this.direction = 0; break; } }, onCollisionEnter: function (other, self) { this.node.color = cc.Color.RED; this.touchingNumber++; // 1st step // get pre aabb, go back before collision var otherAabb = other.world.aabb; var otherPreAabb = other.world.preAabb.clone(); var selfAabb = self.world.aabb; var selfPreAabb = self.world.preAabb.clone(); // 2nd step // forward x-axis, check whether collision on x-axis selfPreAabb.x = selfAabb.x; otherPreAabb.x = otherAabb.x; if (cc.Intersection.rectRect(selfPreAabb, otherPreAabb)) { if (this.speed.x < 0 && (selfPreAabb.xMax > otherPreAabb.xMax)) { this.node.x = otherPreAabb.xMax - this.node.parent.x; this.collisionX = -1; } else if (this.speed.x > 0 && (selfPreAabb.xMin < otherPreAabb.xMin)) { this.node.x = otherPreAabb.xMin - selfPreAabb.width - this.node.parent.x; this.collisionX = 1; } this.speed.x = 0; other.touchingX = true; return; } // 3rd step // forward y-axis, check whether collision on y-axis selfPreAabb.y = selfAabb.y; otherPreAabb.y = otherAabb.y; if (cc.Intersection.rectRect(selfPreAabb, otherPreAabb)) { if (this.speed.y < 0 && (selfPreAabb.yMax > otherPreAabb.yMax)) { this.node.y = otherPreAabb.yMax - this.node.parent.y; this.jumping = false; this.collisionY = -1; } else if (this.speed.y > 0 && (selfPreAabb.yMin < otherPreAabb.yMin)) { this.node.y = otherPreAabb.yMin - selfPreAabb.height - this.node.parent.y; this.collisionY = 1; } this.speed.y = 0; other.touchingY = true; } }, onCollisionExit: function (other) { this.touchingNumber--; if (this.touchingNumber === 0) { this.node.color = cc.Color.WHITE; } if (other.touchingX) { this.collisionX = 0; other.touchingX = false; } else if (other.touchingY) { other.touchingY = false; this.collisionY = 0; this.jumping = true; } }, update: function (dt) { if (this.collisionY === 0) {//如果Y軸沒有碰撞 this.speed.y += this.gravity * dt; if (Math.abs(this.speed.y) > this.maxSpeed.y) { this.speed.y = this.speed.y > 0 ? this.maxSpeed.y : -this.maxSpeed.y; } } if (this.direction === 0) { if (this.speed.x > 0) { this.speed.x -= this.acce * dt; if (this.speed.x <= 0) this.speed.x = 0; } else if (this.speed.x < 0) { this.speed.x += this.acce * dt; if (this.speed.x >= 0) this.speed.x = 0; } } else { this.speed.x += (this.direction > 0 ? 1 : -1) * this.acce * dt; if (Math.abs(this.speed.x) > this.maxSpeed.x) { this.speed.x = this.speed.x > 0 ? this.maxSpeed.x : -this.maxSpeed.x; } } if (this.speed.x * this.collisionX > 0) { this.speed.x = 0; } this.node.x += this.speed.x * dt; this.node.y += this.speed.y * dt; },});

碰撞檢測系統有三個檢測碰撞的函數,分別是:

onCollisionEnter(other,self):碰撞體剛碰撞時觸發

onCollisionStay(other,self):碰撞體持續碰撞時觸發

onCollisionExit(other):碰撞體分開時觸發

他們傳入的參數other和self指的是什么呢?

指的就是他們的碰撞組件

比如我們在onCollisionEnter函數里寫上這樣兩行代碼

other.node.color = cc.Color.RED; self.node.color = cc.Color.GREEN;

就可以實現讓兩個碰撞組件的節點變色的效果

那碰撞組件(這里用的是cc.BoxCollider)里還有什么屬性方法呢?

通常我們遇到這種問題時,第一反應就是去查一下api,可是人生充滿意外,Creator的api并不全,很多東西都沒有

這里我給新手介紹一個查看屬性的方法

我們這次不用模擬器,選擇瀏覽器(谷歌瀏覽器)運行,按下F12啟動調試窗口,然后在onCollisionEnter函數的第一行代碼旁邊單擊設置一個斷點,然后刷新瀏覽器

這樣我們的程序就會運行到斷點的位置,如下圖

這里寫圖片描述

這時就可以進行相應的變量查看、測試

在控制臺輸入other,敲回車,就可以得到other組件的全部屬性方法,真的是全部哦,一點都不會少(有時候函數名忘了,不查api,通過這種方式獲得提示也是一種方法)

這里寫圖片描述

這里我們用到的屬性主要是world里的幾個 aabb:axis-aligned bounding box,軸對齊包圍盒,也就是碰撞檢測的區域 aabb.x、aabb.y:碰撞盒的位置,矩形的中心位置 aabb.xMin、aabb.xMax、aabb.yMin、aabb.yMax:碰撞盒的邊緣位置,矩形的四個邊

preAabb的屬性跟aabb相同,代表著碰撞盒的上一次位置,我們利用這個”上一次位置”就可以實現“前面有障礙物,大馬猴走不過去”的效果了

簡單的思路就是:如果發生了不可移動的碰撞(障礙物),就退回到“上一次位置”

現在我們再來看MonkeyContro.js的代碼

onCollisionEnter里我們做的事情就是保存上一次計算碰撞組件的位置,如果發生碰撞了就返回上一次位置,分別進行了x軸檢測和y軸檢測,如果想加深理解,可以嘗試自己畫個圖

算了,我知道你也不會畫

這里寫圖片描述

上圖就是X軸碰撞的情況,Y軸碰撞的情況類似

最后來看一下效果吧

這里寫圖片描述

跟隨平臺移動

鏡頭跟隨

添加觸摸按鍵

虛擬搖桿

找個天氣好的日子再寫


上一篇:GreeDao 3.0 的基礎使用

下一篇:Tango概念

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
97视频在线免费观看| 亚洲第一av网站| 亚洲激情国产精品| 国产成人精品免费久久久久| 午夜美女久久久久爽久久| 国产成人精品久久亚洲高清不卡| 亚洲男人第一av网站| 97超碰色婷婷| 色综合亚洲精品激情狠狠| 91av免费观看91av精品在线| 欧美日韩国产中文精品字幕自在自线| 精品网站999www| 中文字幕精品久久久久| 91精品久久久久久久久久久| 上原亚衣av一区二区三区| 欧美日韩成人在线观看| 日韩经典中文字幕在线观看| 亚洲精品成人网| 久久精品国产亚洲一区二区| 亚洲а∨天堂久久精品9966| 亚洲美女性生活视频| 欧美黄网免费在线观看| 日韩激情片免费| 97香蕉久久夜色精品国产| 日韩在线观看网址| 久久久女人电视剧免费播放下载| 国产91精品久久久| 亚洲成人网久久久| 亚洲女同精品视频| 98视频在线噜噜噜国产| 久久久亚洲影院| 亚洲精品福利视频| 久久综合九色九九| 欧美在线视频观看| 91精品久久久久久久久| 日韩视频―中文字幕| 欧美午夜宅男影院在线观看| 久久精品99国产精品酒店日本| 国产91ⅴ在线精品免费观看| 日韩久久精品电影| 日韩精品在线免费观看视频| 欧美日韩午夜视频在线观看| 插插插亚洲综合网| 欧美在线国产精品| 91国内产香蕉| 亚洲精品资源美女情侣酒店| 欧美日韩中文字幕在线| 亚洲国产三级网| 成人精品一区二区三区| 亚洲精品久久7777777| 精品成人国产在线观看男人呻吟| 国产精品电影观看| 一区二区中文字幕| 欧美www在线| 91丝袜美腿美女视频网站| 久久99久久99精品中文字幕| 一本一本久久a久久精品综合小说| 国产成人高清激情视频在线观看| 亚洲免费视频在线观看| 成人欧美在线视频| 中文字幕在线观看亚洲| 日韩美女在线看| 成人a视频在线观看| 欧美日本中文字幕| 国产精品美女www爽爽爽视频| 成人高h视频在线| 日韩av电影国产| 日韩视频在线观看免费| 亚洲欧美日本伦理| 国产成人精品a视频一区www| 亚洲天堂第二页| 一本色道久久88综合日韩精品| 国产手机视频精品| 国产成人精品久久亚洲高清不卡| 777国产偷窥盗摄精品视频| 久久久欧美一区二区| 国产精品黄色影片导航在线观看| 亚洲性无码av在线| 91亚洲精品一区二区| 日韩中文字幕av| 欧美福利视频在线观看| 国产成人精品免高潮在线观看| 日韩精品中文字幕在线播放| 精品久久久久久久久久久久久| 亚洲级视频在线观看免费1级| 美女视频久久黄| 97在线视频免费看| 国产成人精品久久亚洲高清不卡| 亚洲人成网站在线播| 国产精品一区二区久久久久| 精品国产福利视频| 欧美午夜宅男影院在线观看| 97视频人免费观看| 国产一区二区黄| 久久91亚洲精品中文字幕奶水| 国产精品91久久久久久| 久久天天躁夜夜躁狠狠躁2022| 国产精品久久国产精品99gif| 91久久久在线| 日韩一区二区久久久| 亚洲aⅴ男人的天堂在线观看| 欧美中文在线观看| 91成人精品网站| 亚洲欧美日韩中文视频| 欧美不卡视频一区发布| 91福利视频网| 北条麻妃一区二区在线观看| 丝袜亚洲另类欧美重口| 色一区av在线| 国产精品成人播放| 91嫩草在线视频| 中文字幕亚洲欧美在线| 亚洲永久在线观看| 成人福利视频网| 国产精品视频大全| 亚洲欧美日韩精品久久亚洲区| 国产成人精品在线观看| 中文字幕亚洲欧美在线| 国产精品va在线播放我和闺蜜| 欧美放荡办公室videos4k| 久久久国产一区二区三区| 亚洲精品女av网站| 欧美日韩国产成人高清视频| 日韩视频一区在线| 国产精品入口福利| 欧美大片大片在线播放| 亚洲视频综合网| 久久av资源网站| 81精品国产乱码久久久久久| 亚洲成人av资源网| 97视频在线看| 欧美性猛交xxxx乱大交极品| 久久久久久久久久亚洲| 亚洲的天堂在线中文字幕| 日韩精品高清在线观看| 欧美亚洲另类视频| 欧美又大又硬又粗bbbbb| 久久综合伊人77777尤物| 亚洲高清在线观看| 欧美重口另类videos人妖| 欧美精品在线视频观看| 午夜精品久久久久久久99热浪潮| 成人精品久久久| 欧美有码在线观看| 九九精品在线播放| 国产人妖伪娘一区91| 久久久综合免费视频| 欧美丰满少妇xxxx| 国产精品成人av在线| 久久久精品中文字幕| 国产精品入口日韩视频大尺度| www.日韩系列| 色无极影院亚洲| 久久理论片午夜琪琪电影网| 中文欧美在线视频| 亚洲欧美中文日韩v在线观看| 日本精品性网站在线观看| 国产有码在线一区二区视频| 欧美亚洲国产精品| 欧美日韩第一视频| 亚洲黄色av女优在线观看| 亚洲精品丝袜日韩| 国产主播在线一区| 久久精品中文字幕免费mv|