• 重力的方向和地面的问题

    p2中默认的方向是从上到下,如果重力默认是正数的话,物体放到世界中是会从上面往下面飘的

    p2plane地面默认的方向是y轴的方向,而在p2y轴的方向默认是从上往下

    首先来看,重力gravity是正数,并且plane地面在视图中间,小球是怎么运动

    // 创建世界
    this.world = new p2.World()
    this.world.sleepMode = p2.World.BODY_SLEEPING
    this.world.gravity = [0,5]
    // 设置弹性属性
    this.world.defaultContactMaterial.restitution = 1; // 创建地面
    this.planeBody = new p2.Body({
    position:[egret.MainContext.instance.stage.stageWidth/2,egret.MainContext.instance.stage.stageHeight/2]
    })
    let plane = new p2.Plane()



    小球受重力的影响从上往下掉,没有问题,并且即使是在地面下面,地面的方向也是从上往下,小球下到地面之后依旧是从上往下运动

    下面把世界的重力改成从下往上,相当于漂浮的感觉



    可以看到plane下方,也就是在p2引擎中的y轴正方向地面上的小球依照物理定律,自由落地,从下往上落到地面上

    plane上方,也就是p2物理引擎中的地下世界,是会奇怪的往地面上跑

    总体来说:在p2物理世界中,地面上的物体,遵循自由落体和牛顿引力相关运动原理,但是默认方向是从上往下的Y轴方向,所以如果地面在最下面的话,需要将plane地面水平翻转180‘,并且此时重力可以设置为正数,达到从上往下的效果

    正确的效果是这样的:



    实现代码

    // 创建世界
    this.world = new p2.World()
    this.world.sleepMode = p2.World.BODY_SLEEPING
    this.world.gravity = [0,5]
    // 设置弹性属性
    this.world.defaultContactMaterial.restitution = 1; // 创建地面
    this.planeBody = new p2.Body({
    position:[egret.MainContext.instance.stage.stageWidth/2,egret.MainContext.instance.stage.stageHeight/2]
    })
    let plane = new p2.Plane()
    this.planeBody.angle = Math.PI // 地面需要旋转180度,不然是从上往下
  • 生成阻碍方块,并且不允许方块有重叠区域

    实现原理

    纵坐标可以设定在同一水平线上,横坐标位置随机,通过随机数生成位置,并且通过随机数确定方块的大小,生成第二个随机方块的时候判断时候与前面生成的所有方块有重叠部分` 半径 只差的绝对值 < 半径值和`, 如果有重叠部分的话,嵌套调用,如果没有的话,即生成新的方块

    实现代码

    private randomNum(minNum,maxNum):number{  // 生成随机数的方法,借鉴自菜鸟教程
    switch(arguments.length){
    case 1:
    return parseInt(Math.random() * minNum+1 + '',10);
    break;
    case 2:
    return parseInt(Math.random()*(maxNum-minNum+1)+minNum,10);
    break;
    default:
    return 0;
    break;
    }
    } private genereteBox():void{
    /**
    * 生成随机个障碍盒子
    */
    let stageHeight = egret.MainContext.instance.stage.stageHeight // 获取屏幕高度
    let stageWidth = egret.MainContext.instance.stage.stageWidth // 获取屏幕宽度 let count = this.randomNum(1,4) // 生成的障碍个数 let arr = [] let generatePosition = ()=>{ // 保证this指向问题
    let size = this.randomNum(30,70)
    let location = this.randomNum(size,stageWidth-size)
    if(arr.length === 0){
    arr.push({
    size:size,
    location:location
    })
    return [size,location]
    }else{
    for(let index = 0;index<arr.length;index++){
    if((Math.abs(location-arr[index].location)) < (size + arr[index].size)){
    console.log(size,location)
    return generatePosition()
    }
    }
    arr.push({
    size:size,
    location:location
    })
    return [size,location]
    }
    }
    for(let index = 0;index<count;index++){
    let [size,location] = generatePosition()
    let react:egret.Shape = this.createBox(size)
    let reactShape: p2.Shape = new p2.Box({
    width:size,
    height:size
    })
    let reactBody:p2.Body = new p2.Body({
    type:p2.Body.STATIC,
    position:[
    location,stageHeight-size
    ],
    })
    reactBody.addShape(reactShape)
    reactBody.displays = [react]
    this.world.addBody(reactBody)
    }
    }
  • 点击生成小球逻辑

    实现逻辑

    1.生成小球刚体,形状,及绑定贴图
    
    2.生成小球的位置为点击事件的位置
    
    3.绑定到`egret`的点击事件上

    实现代码

    //步骤1,2
    private generateBall(locationX:number,locationY:number):void{
    var ball:egret.Shape
    var ballShape:p2.Shape
    var ballBody:p2.Body ball = this.createBall()
    ballShape = new p2.Circle({
    radius:10
    })
    ballBody = new p2.Body({
    position:[locationX,locationY],
    mass:50,
    overlaps:false
    })
    ball.width = (<p2.Circle>ballShape).radius*2
    ball.height = (<p2.Circle>ballShape).radius*2
    ball.anchorOffsetX = ball.width/2
    ball.anchorOffsetY = ball.height/2
    ballBody.addShape(ballShape)
    ballBody.displays = [ball]
    this.world.addBody(ballBody)
    } // 步骤3 this.addEventListener(egret.TouchEvent.TOUCH_TAP,(e:egret.TouchEvent)=>{
    this.generateBall(e.localX,e.localY) // e.localX和e.localY 可以拿到点击事件的点击X或者y
    },this)
  • 小球碰撞出现锚点问题,即碰撞不是发生在边缘,而是感觉发生在球心或者什么位置

    原因分析

    1.可能是因为贴图的视觉中心和 刚体的中心没有设置在一起
    
    在`egret`贴图的中心,默认是在坐标左上角
    
    但是在`p2`物理引擎中,默认的图形锚点确是在刚体的中心
    
    所以在使用两个合并时需要将贴图的锚点中心设置到和刚体中心一样
    
    ![截图](attachment:8f15efc90e41b0d12e13731386c191a1)

    代码如下


    private createBox(width:number,angle:number):egret.Shape{
    var box = new egret.Shape()
    box.graphics.beginFill(0x0000ff)
    box.graphics.drawRect(0,0,width,width)
    box.graphics.endFill()
    box.anchorOffsetX = box.width/2
    box.anchorOffsetY = box.height/2
    box.rotation = angle * 180 / Math.PI;
    console.log('box rotation : ' + box.rotation)
    this.addChild(box)
    return box
    }
  • 小球和方块出现重叠的现象,而且碰撞中心感觉只是在小球的中心点,并不是小球的边缘碰撞

    问题现象

    ![3.gif](attachment:774c5f928557ca980283141254dba5f8)

    检查原因

    原来是小球贴图`egret.shape`和小球物理引擎中刚体的大小不一样`p2.body`
    
    小球的刚体结构实际上是在贴图内部的一个小区域

    代码如下

    //修改后
    private generateBall(locationX:number,locationY:number):void{
    var ball:egret.Shape
    var ballShape:p2.Shape
    var ballBody:p2.Body
    var size:number = 10
    ball = this.createBall(size*2) // size是刚体半径的大小,生成小球贴图的时候需要两倍大小,因为egret drawCirle是直径
    ballShape = new p2.Circle({
    radius:size
    })
    ballBody = new p2.Body({
    position:[locationX,locationY],
    mass:50
    })
    ball.width = (<p2.Circle>ballShape).radius*2 // 小球宽度也是直径
    ball.height = (<p2.Circle>ballShape).radius*2 // 小球高度页是直径
    ball.anchorOffsetX = ball.width/2 //参考下一个问题
    ball.anchorOffsetY = ball.height/2
    ballBody.addShape(ballShape)
    ballBody.displays = [ball]
    this.world.addBody(ballBody)
    }
  • 贴图的旋转和刚体的旋转数值明明设置的是一样的,但是旋转角度和碰撞反应感觉角度并不正确

    问题原因:

    `egret`中表示旋转的`rotate`属性是弧度制
    
    而 `p2`中表示旋转的`angle`属性是角度制,即在`p2`中写多少度就是旋转多少度,但是在`egret`的贴图中需要将角度转换为弧度
    
    转换公式如下

数学上是用弧度而非角度,因为360的容易整除对数学不重要,而数学使用弧度更方便。角度和弧度关系是:2π弧度=360°。从而1°≈0.0174533弧度,1弧度≈57.29578°。

  1. 角度转换为弧度公式:弧度=角度÷180×π

2)弧度转换为角度公式: 角度=弧度×180÷π


** 代码如下:** ```typescript
protected freshFrame():void{
this.world.step(1)
var len:number = this.world.bodies.length
for(let index = 0;index<len;index++){
var body:p2.Body = this.world.bodies[index]
var display: egret.DisplayObject = body.displays[0]
display.x = body.position[0]
display.y = body.position[1]
display.rotation = body.angle * 180/ Math.PI
}
}
  • 在两侧填上阻止的墙壁,形成密闭的环境

【h5游戏开发】egret引擎p2物理引擎 - 小球碰撞地面搞笑的物理现象的更多相关文章

  1. 最近这两天看了关于H5游戏开发的一个教程,实践很短暂,看了很多理论的东西,现在呢也只是想回忆回忆关于EUI的部分知识吧

    首先我了解了什么是Egret: Egret中文就是白鹭的意思,Egret是一套H5游戏开发的软件.(纯粹属于个人理解) 其次我对以下几款软件的相关知识做了些了解: Egret Engine(引擎),E ...

  2. 今天我看了一个H5游戏EUI的例子,我都快分不清我到底是在用什么语言编译了代码了,作为刚刚学习H5游戏开发的菜鸟只能默默的收集知识

    今天看了一个EUI的demo,也是接触H5游戏开发的第五天了,我想看看我能不能做点什么出来,哎,自己写果然还是有问题的.在看EUI哪一个demo的时候就遇见了一些摇摆不定的问题,我觉得提出来 1.to ...

  3. 关于h5游戏开发,你想了解的一切都在这儿!

    ​2020年,受疫情影响,线下产业红利褪去,线上迎来的新一轮的高峰.众多商家纷纷抓住了转型时机,开启了流量争夺战.H5游戏定制无疑是今年引流的大热门.如何开发一款有趣.有爆点.用户爱买单的好游戏呢? ...

  4. 为什么选择H5游戏开发定制?

    为什么选择H5游戏开发定制? 随着微信H5游戏推广带来的显著效果,越来越多的商家已经加入到游戏营销的队伍中来, 对H5小游戏有了解的商家都知道,[模板游戏]的价格往往低于[定制游戏]的价格,可是为什么 ...

  5. 2、Cocos2dx 3.0游戏开发找小三之引擎简单介绍

    尊重开发人员的劳动成果,转载的时候请务必注明出处:http://blog.csdn.net/haomengzhu/article/details/27094663 引擎简单介绍 Cocos2d-x 的 ...

  6. H5游戏开发之抓住小恐龙

    第一次写技术性博文,以前都只是写一些生活感想,记录一些生活发生的事情. 博主大三学生一枚,目前学习JS一年多,还处于学习阶段,有什么说的不好的希望大牛指点下,由于第一次写博文,排版什么的有待改进,希望 ...

  7. H5游戏开发:贪吃蛇

    贪吃蛇的经典玩法有两种: 积分闯关 一吃到底 第一种是笔者小时候在掌上游戏机最先体验到的(不小心暴露了年龄),具体玩法是蛇吃完一定数量的食物后就通关,通关后速度会加快:第二种是诺基亚在1997年在其自 ...

  8. H5游戏开发之多边形碰撞检测

    2D多边形碰撞检测介绍这是一篇论证如何在2D动作游戏中执行碰撞检测的文章(Mario,宇宙入侵者等),为了保证它的高效性和精确性,碰撞检测是以多边形为基础的,而不是以sprite为基础.这是两种不同的 ...

  9. cocos2d-x ios游戏开发初认识(八) 触摸事件与碰撞检測

    玩过植物大战僵尸都知道,要在草坪里放一朵向日葵或者其他的植物仅仅需触摸那个植物将其拖入到想要摆放的位置,这事实上就是这节要写的触摸事件.还能够发现当我们的僵尸出来的时候,我们的小豌豆会发子弹攻击僵尸, ...

随机推荐

  1. Spring Enable annotation – writing a custom Enable annotation

    原文地址:https://www.javacodegeeks.com/2015/04/spring-enable-annotation-writing-a-custom-enable-annotati ...

  2. ABP中使用OAuth2(Resource Owner Password Credentials Grant模式)

    ABP目前的认证方式有两种,一种是基于Cookie的登录认证,一种是基于token的登录认证.使用Cookie的认证方式一般在PC端用得比较多,使用token的认证方式一般在移动端用得比较多.ABP自 ...

  3. Windows 7 安装.net framework 4.0 失败,错误HRESULT 0xc8000222解决办法

    今天在客服那里发现一个比较奇怪的错误,在客服机子上安装.NET Framework4.0时,出现如下错误:HRESULT 0xc8000222 百度了下原因,原来是win7自动更新造成的.原文网址:h ...

  4. 跟我学android- 创建运行环境(二)

    Android程序 需要在Android手机上运行,因此 Android开发时 必须准备相关运行,调试环境. Android真机(建议使用真机,速度快,效果好) Android虚拟设备(AVD) 使用 ...

  5. HADOOP:WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable终于解决了

    WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin- ...

  6. Android中用友盟实现QQ的第三方登录

    //首先应该去友盟的官网注册你的账号,创建一个应用,获得它的APPkey,也可以用它的API上的appkey,下载SDK,下面根据API文档一步步实现就行了. //下面是友盟的APi文档 1.  产品 ...

  7. node.js报错throw err; // Rethrow non-MySQL errors e:\serverTest\node_modules\mysql\lib\protocol\Parser.js:79 解决方法

    今天在用node+angular做后台时,需要使用session保存登陆状态的时候,遇到了此问题,问题直译为非mysql问题,我也在后台取到的登陆用户名和密码,确实不是数据库问题.最后发现在使用ses ...

  8. poj2442 堆应用

    #include <cstdio> #include <cstring> #include <string> #include <vector> #in ...

  9. 最近用到的 sql 统计操作

    统计操作 1.分组统计group by select id,name,count(*) as '总数'  from test1 group by id,name     --group by   分组 ...

  10. C#和java之间的一些差异与共性

    C#与java之间的一些共性和差异整理 隐藏:与java中的重写几乎一致,但是需要添加new关键字让编译器知道,否则会有警告 虚方法:1.声明为virtual的方法就是虚方法,在子类中使用overri ...