当前位置:网站首页>Egret engine P2 physics engine (2) - Funny physical phenomenon of small balls hitting the ground
Egret engine P2 physics engine (2) - Funny physical phenomenon of small balls hitting the ground
2022-06-30 06:59:00 【Zmmm Jun】
The direction of gravity and the problem of the ground
p2The default direction in is from top to bottom , If gravity defaults toPositive numbersWords , Objects in the world will float from top to bottomp2inplaneThe default direction of the ground isyAxis direction , And in thep2inyBy default, the direction of the axis is from top to bottomFirst of all to see , gravity
gravityPositive number , alsoplaneThe ground is in the middle of the view , How the ball moves// Create the world this.world = new p2.World() this.world.sleepMode = p2.World.BODY_SLEEPING this.world.gravity = [0,5] // Set elastic properties this.world.defaultContactMaterial.restitution = 1; // Create the ground this.planeBody = new p2.Body({ position:[egret.MainContext.instance.stage.stageWidth/2,egret.MainContext.instance.stage.stageHeight/2] }) let plane = new p2.Plane()[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-hE4elxQy-1644331551608)(attachment:6ad7466b4bf55bdac75e466848ec3194)]

The ball falls from top to bottom under the influence of gravity , No problem , And even under the ground , The direction of the ground is also from top to bottom , After the ball goes down to the ground, it still moves from top to bottom
Let's change the gravity of the world from bottom to top , Equivalent to the feeling of floating
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-BRbBoooN-1644331551613)(attachment:4b1e2d452b61e2367505b49469ee8092)]

You can see
planebelow , That is to sayp2In the engine y Affirmative directionOn the groundAccording to the laws of physics , Free landing , Fall to the ground from the bottom upplaneupper , That is to sayp2The underground world in the physics engine , It will be strange to run to the groundOn the whole : stay
p2In the physical world , Objects on the ground , Follow the motion principle of free falling body and Newton's gravity , But the default direction is from top to bottomYAxis direction , So if the ground is at the bottom , Need to putplaneThe ground flips horizontally180‘, And the gravity can be set toPositive numbers, Achieve a top-down effectThe correct effect is :
[ Failed to transfer the external chain picture , The origin station may have anti-theft chain mechanism , It is suggested to save the pictures and upload them directly (img-PwDkJ72t-1644331551614)(attachment:2763159bfe8260d8facda806e93144e0)]

Implementation code
// Create the world this.world = new p2.World() this.world.sleepMode = p2.World.BODY_SLEEPING this.world.gravity = [0,5] // Set elastic properties this.world.defaultContactMaterial.restitution = 1; // Create the ground 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 // The ground needs to be rotated 180 degree , Otherwise, it is from top to bottomGenerate blocks , And the square is not allowed to have overlapping areas
Realization principle :
The vertical coordinate can be set on the same horizontal line , The abscissa position is random , Generate positions by random numbers , And the size of the block is determined by random numbers , When generating the second random block, it is judged that there is an overlap with all the blocks previously generated ` radius Only the absolute value of the difference < Radius value and `, If there is any overlap , Nested calls , If not , That is, a new block is generatedImplementation code :
private randomNum(minNum,maxNum):number{ // The way to generate random numbers , Learn from the rookie tutorial 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{ /** * Generate random obstacle boxes */ let stageHeight = egret.MainContext.instance.stage.stageHeight // Get screen height let stageWidth = egret.MainContext.instance.stage.stageWidth // Get screen width let count = this.randomNum(1,4) // Number of obstacles generated let arr = [] let generatePosition = ()=>{ // Guarantee this Point to the problem 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) } }Click generate small ball logic
Implementation logic
1. Generate small ball rigid body , shape , And binding maps 2. The position of the generated ball is the position of the click event 3. Bound to the `egret` Click on the eventImplementation code
// step 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) } // step 3 this.addEventListener(egret.TouchEvent.TOUCH_TAP,(e:egret.TouchEvent)=>{ this.generateBall(e.localX,e.localY) // e.localX and e.localY You can get the click event X perhaps y },this)
The small ball collides with the anchor point , That is, the collision doesn't happen at the edge , It's about feeling at the center of the ball or somewhere
Cause analysis :
1. Maybe it's the visual center of the map and The centers of the rigid bodies are not set together stay `egret` The center of the map , The default is in the upper left corner of the coordinate But in `p2` In the physics engine , The default shape anchor is in the center of the rigid body So when using two merges, you need to set the anchor center of the map to be the same as the center of the rigid body The code is as follows :
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 }Small balls and squares overlap , And the impact center feels just at the center of the ball , It's not the edge of the ball
Problem phenomenon :
Check the reason :
It turned out to be a small ball map `egret.shape` The size of the rigid body is different from that of the small ball physics engine `p2.body` The rigid structure of the ball is actually a small area inside the mapThe code is as follows :
// After modification 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 Is the radius of the rigid body , You need to double the size to generate the ball map , because egret drawCirle Is the diameter ballShape = new p2.Circle({ radius:size }) ballBody = new p2.Body({ position:[locationX,locationY], mass:50 }) ball.width = (<p2.Circle>ballShape).radius*2 // The width of the ball is also the diameter ball.height = (<p2.Circle>ballShape).radius*2 // The height of the ball is the diameter ball.anchorOffsetX = ball.width/2 // Refer to the next question ball.anchorOffsetY = ball.height/2 ballBody.addShape(ballShape) ballBody.displays = [ball] this.world.addBody(ballBody) }The rotation value of the map and the rotation value of the rigid body are obviously the same , But the rotation angle and collision reaction feeling angle are not correct
Question why :
`egret` Which means rotating `rotate` The attribute is radian and `p2` Which means rotating `angle` The attribute is angular , That is to say `p2` The number of degrees written in is the number of degrees of rotation , But in `egret` You need to convert the angle into radians in the map of The conversion formula is as follows
Mathematically, we use radians instead of angles , because 360 Easy division is not important to mathematics , And it's easier to use radians in math . The relationship between angle and radian is :2π radian =360°. thus 1°≈0.0174533 radian ,1 radian ≈57.29578°.
- Angle to radian formula : radian = angle ÷180×π
2) Radian to angle formula : angle = radian ×180÷π
** The code is as follows :**
```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
}
}
边栏推荐
- ROS system problem: rosdep init
- SOC project AHB_ SD_ Host controller design
- No module named 'pyqt5 QtMultimedia‘
- 写一个C程序判断系统是大端字节序还是小端字节序
- Google Earth Engine(GEE)——墨累全球潮汐湿地变化 v1 (1999-2019) 数据集
- 安装setup对应的组件
- Graphic octet, really top
- ROS service communication programming
- SOC项目AHB_SD_HOST控制器设计
- The solution of memcpy memory overlap
猜你喜欢

Go语言指针介绍

SOC_AHB_SD_IF

SOC project AHB_ SD_ Host controller design

【转】存储器结构、cache、DMA架构分析

How does the CPU recognize the code?

程序猿入门攻略(十一)——结构体
![[datawhale team learning] task02: mathematical operation, string and text, list](/img/3e/c9c984d7576a2e410da7f81a8c0aa6.jpg)
[datawhale team learning] task02: mathematical operation, string and text, list

原理:WebMvcConfigurer 与 WebMvcConfigurationSupport避坑指南

【Mask-RCNN】基于Mask-RCNN的目标检测和识别

六,购物⻋与订单
随机推荐
1285_把AUTOSAR函数以及变量等定义的宏用脚本展开以提高可读性
Which securities company is good for opening a mobile account? Also, is it safe to open an account online?
[Hot100]10. Regular Expression Matching
RT thread Kernel Implementation (III): implementation of idle threads and blocking delay
Goland常用快捷键设置
Go常用命令
ROS-URDF
Performance comparison of random network, scale-free network, small world network and NS small world matlab simulation
leetcode:98. Validate binary search tree
Redis cache
Keil - the "trace HW not present" appears during download debugging
[hot100] palindrome substring and longest palindrome substring
Records of problems solved (continuously updated)
编写并运行第一个Go语言程序
InnoDB engine in MySQL
明天!“移动云杯”大赛空宣会开播!
【申博攻略】五.专家推荐信模板
【我的OpenGL学习进阶之旅】关于OpenGL的着色器的向量和矩阵分类的访问方式: xyzw/rgba/stpq以及数组下标
Problems and solutions of creating topic messages in ROS
First experience of Galaxy Kirin