egret p2物理引擎學習記錄
p2(physics)下載地址:https://download.csdn.net/download/qq_31189489/79552684
引入物理引擎
下載p2 物理引擎包
\physics\libsrc\bin\physics目錄下所有檔案拷貝到根目錄/../p2Physics目錄下- 修改專案根目錄組態檔
egretProperties.json 修改項如下
{ "name":"physics", "path":"../physics" }編譯 打開
egret編輯器wing找到插件egret專案工具編譯引擎

查看是否編譯成功

如果
libs/modules/目錄下出現了physics檔案夾則表示編譯成功
使用物理引擎
基本概念

- 世界: 設定世界內部的
重力加速度添加元素添加世界相關設定等功能,比如設定材質之間的摩擦和相關系數
- 形狀:繪制物體的基本形狀,每一個剛體都需要添加形狀,設定
形狀相關屬性比如: - 剛體:設定剛體,
物理相關屬性,比如剛體型別 重量位置,角速度,位置等等 - 貼圖:displays,通過貼圖展示
egret相關顯示元素,系結顯示
- 世界: 設定世界內部的
- 基本步驟
創建世界
// 實體化一個world物件 this.world = new p2.World(); //設定world為睡眠狀態 this.world.sleepMode = p2.World.BODY_SLEEPING; this.world.gravity = [0,9.8] console.log('create world success')

創建一個地板
// 繪制地面,也是通過shape和body 兩個基礎物件進行合成 let stageHeight = egret.MainContext.instance.stage.stageHeight var groundShape:p2.Plane = new p2.Plane() var groundBody:p2.Body = new p2.Body({ type:p2.Body.STATIC, position:[0,stageHeight -100] }) groundShape.material = this.steelMaterial groundBody.angle = Math.PI groundBody.addShape(groundShape) groundBody.displays = [] this.world.addBody(groundBody) // 由于沒有系結材質,直接繪制一條的線條 let groundLine:egret.Shape = new egret.Shape groundLine.graphics.lineStyle(2,0x00ff00) groundLine.graphics.moveTo(0,stageHeight-90) groundLine.graphics.lineTo(egret.MainContext.instance.stage.stageWidth,stageHeight-90) this.addChild(groundLine)

創建一個可視小球

private display:egret.Shape; private createBody():void{ var boxShape:p2.Shape = new p2.Box({width:20,height:20}) var boxBody:p2.Body = new p2.Body({ mass: 2, position: [200, 200],velocity:[30,5]}) boxShape.material = this.iceMaterial this.display = new egret.Shape() this.display.x = 100 this.display.graphics.beginFill(0xff0000,1) this.display.graphics.drawCircle(0,0,(<p2.Box>boxShape).width) this.display.graphics.endFill() // this.display.width = (<p2.Box>bfoxShape).width // this.display.height = (<p2.Box>boxShape).height boxBody.displays = [this.display] boxBody.addShape(boxShape) this.world.addBody(boxBody) this.addChild(this.display) // var boxShape:p2.Shape = new p2.Shape() // var boxBody:p2.Body = new p2.Body({ mass: 1, position: [200, 180],angularVelocity:1 }) // boxBody.addShape(boxShape) // this.world.addBody(boxBody) console.log('create body success') }更新視圖
world創建出來,并不會自動執行運動邏輯,需要通過world.step()進行步進運動

this.world.step(1); var l = this.world.bodies.length; for (var i:number = 0; i < l; i++) { var boxBody:p2.Body = this.world.bodies[i]; var box:egret.DisplayObject = boxBody.displays[0]; if (box) { //將剛體的坐標和角度賦值給顯示物件 box.x = boxBody.position[0]; box.y = boxBody.position[1]; //如果剛體當前狀態為睡眠狀態,將圖片alpha設為0.5,否則為1 if (boxBody.sleepState == p2.Body.SLEEPING) { box.alpha = 0.5; } else { box.alpha = 1; } } }在主程式中執行所有方法,并且通過時鐘函式不斷呼叫update函式,最終代碼如下
main.ts

class HelloWorld extends eui.UILayer{ // 定義一個world變數 private world:p2.World // 定義一個除錯畫布 private debugDraw:any // 定義兩種材質 private iceMaterial = new p2.Material(1); private steelMaterial = new p2.Material(2); private async runGame(){ console.log('加載資源') // 入口方法 await this.loadResource() // console.log('創建背景') // this.createBg() console.log('創建灰色遮罩') this.createMask() // console.log('繪制movieClips') // this.createClips() this.createWorld() this.createGround() this.createBody() this.addEventListener(egret.Event.ENTER_FRAME,this.update,this); } private createClips(){ let data = https://www.cnblogs.com/zm-blogs/p/RES.getRes("chara_json") let textr = RES.getRes('chara_png') let factorys:egret.MovieClipDataFactory = new egret.MovieClipDataFactory(data,textr) let paimeng:egret.MovieClip = new egret.MovieClip(factorys.generateMovieClipData('paimeng')) this.addChild(paimeng) paimeng.gotoAndPlay("main",-1) } // 入口函式 protected createChildren(): void { super.createChildren() this.runGame() } // 創建背景圖片 private createBg(){ let bg = new Util().createBitMap('bg_jpg') console.log(bg) this.addChild(bg) bg.width = this.stage.stageWidth bg.height = this.stage.stageHeight } // 加載資源 private async loadResource() { try { const loadingView = new LoadingUI(); this.stage.addChild(loadingView); // 暫時注釋預加載資源 // await RES.loadConfig("resource/default.res.json", "resource/"); // await RES.loadGroup("preload", 0, loadingView); this.stage.removeChild(loadingView); } catch (e) { console.error(e); } } // 創建遮罩 private createMask(){ let mask = new egret.Shape() mask.graphics.beginFill(0xffffff,1) mask.graphics.drawRect(0,0,this.stage.stageWidth,this.stage.stageHeight) mask.graphics.endFill() mask.y = 0 this.addChild(mask) } // 創建剛體 private createWorld():void{ // 實體化一個world物件 this.world = new p2.World(); //設定world為睡眠狀態 this.world.sleepMode = p2.World.BODY_SLEEPING; this.world.gravity = [0,9.8] console.log('create world success') } //生成地板Plane private planeBody:p2.Body; private createGround():void{ // 繪制地面,也是通過shape和body 兩個基礎物件進行合成 let stageHeight = egret.MainContext.instance.stage.stageHeight var groundShape:p2.Plane = new p2.Plane() var groundBody:p2.Body = new p2.Body({ type:p2.Body.STATIC, position:[0,stageHeight -100] }) groundShape.material = this.steelMaterial groundBody.angle = Math.PI groundBody.addShape(groundShape) groundBody.displays = [] this.world.addBody(groundBody) // 由于沒有系結材質,直接繪制一條的線條 let groundLine:egret.Shape = new egret.Shape groundLine.graphics.lineStyle(2,0x00ff00) groundLine.graphics.moveTo(0,stageHeight-90) groundLine.graphics.lineTo(egret.MainContext.instance.stage.stageWidth,stageHeight-90) this.addChild(groundLine) // //建立一個shape形狀 // let planeShape:p2.Plane = new p2.Plane(); // //建立body剛體 // this.planeBody= new p2.Body({ // //剛體型別 // type:p2.Body.STATIC, // //剛體的位置 // position:[0,this.stage.stageHeight] // }); // this.planeBody.angle = Math.PI; // this.planeBody.displays = []; // this.planeBody.addShape(planeShape); // this.world.addBody(this.planeBody); console.log(' create ground success') } private display:egret.Shape; private createBody():void{ var boxShape:p2.Shape = new p2.Box({width:20,height:20}) var boxBody:p2.Body = new p2.Body({ mass: 2, position: [200, 200],velocity:[30,5]}) boxShape.material = this.iceMaterial this.display = new egret.Shape() this.display.x = 100 this.display.graphics.beginFill(0xff0000,1) this.display.graphics.drawCircle(0,0,(<p2.Box>boxShape).width) this.display.graphics.endFill() // this.display.width = (<p2.Box>bfoxShape).width // this.display.height = (<p2.Box>boxShape).height boxBody.displays = [this.display] boxBody.addShape(boxShape) this.world.addBody(boxBody) this.addChild(this.display) // var boxShape:p2.Shape = new p2.Shape() // var boxBody:p2.Body = new p2.Body({ mass: 1, position: [200, 180],angularVelocity:1 }) // boxBody.addShape(boxShape) // this.world.addBody(boxBody) console.log('create body success') } //幀事件,步函式 private update() { this.world.step(1); var l = this.world.bodies.length; for (var i:number = 0; i < l; i++) { var boxBody:p2.Body = this.world.bodies[i]; var box:egret.DisplayObject = boxBody.displays[0]; if (box) { //將剛體的坐標和角度賦值給顯示物件 box.x = boxBody.position[0]; box.y = boxBody.position[1]; //如果剛體當前狀態為睡眠狀態,將圖片alpha設為0.5,否則為1 if (boxBody.sleepState == p2.Body.SLEEPING) { box.alpha = 0.5; } else { box.alpha = 1; } } } } // private createDebug():void{ // } // private createTestPhysic():void{ // console.log('create begin') // const body = new p2.Body() // //創建寬4單位、高2單位的矩形形狀 // const shpRect: p2.Shape = new p2.Shape({angle:1,position: [200, 180]}); // //創建平面形狀 // const shpPlane: p2.Plane = new p2.Plane(); // } }
遇到的坑:詳見這個博客:https://www.cnblogs.com/zm-blogs/p/15869701.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423464.html
標籤:其他
