Corona学习指南之物理physics

本文详细介绍了如何在Corona应用中使用Box2D物理引擎,包括设置物理引擎、创建刚体及碰撞检测等内容。涵盖了刚体类型、属性设置及碰撞处理等关键信息。

一.物理引擎设置

我们来讨论一下如何在Corona应用中设置Box2D物理引擎。物理引擎通常用来开发那些需要模拟移动、碰撞以及在各种物理力作用下的交互的应用。

1.设置物理引擎

为了使用物理引擎,你必须导入这个库。

local physics = require( "physics" )

2.Start / Pause / Stop

  • physics.start():开启物理引擎
  • physics.pause():暂停物理引擎
  • physics.stop():”销毁”物理引擎

3.Sleeping Bodies(Sleeping 刚体)

默认地,如果刚体几秒钟后没有发生碰撞行为,就会”sleep”,这样的话,可能会减少性能开销。但是有些情况下,你不希望这样,你可以使用body.isSleepingAllowed = false来对特定的刚体改变这种行为,或者使用physics.start( true )来对处在物理环境中的所有物体进行设置。

4.物理引擎模拟参数

物理引擎提供了几个参数用来改变默认的引擎特点:

  • physics.setGravity():设置重力的X、Y轴的加速度,默认是( 0, 9.8 )模拟真实的物理世界。你可以任意设置:physics.setGravity( 0, 6 )
  • 请它参数请看Simulation Options

二.刚体

我们来讨论一下如何创建Box2D物理刚体,包括多边形和多元素刚体。

Corona将物理刚体看作是显示对象的扩展,

1.创建刚体

Corona中所有的刚体都是通过physics.addBody()这个函数来创建的。这允许你将任何显示的对象转化为刚体,包括设置刚体的属性,只需几行代码。

physics.addBody( object, { properties } )

2.刚体属性

所有的刚体都拥有三种核心的属性,每个都是以键值对的形式来定义的,当然,它们是可选的。

  • Density:密度,默认以水的密度1.0作为默认值
  • Friction:摩擦力,0代表没有摩擦力,1.0代表很大的摩擦力,默认值是0.3
  • Bounce:弹力,决定刚体发生碰撞后反弹的速度,值大于0.3是相对有弹性的,值为1.0会永远反弹回去,默认值是0.2
local crate = display.newImage( "crate.png", 100, 200 )
physics.addBody( crate, { density=1.0, friction=0.3, bounce=0.2 } )

local balloon = display.newImage( "balloon.png", 200, 200 )
physics.addBody( balloon, { density=0.1, friction=0.1, bounce=0.4 } )

3.刚体类型

刚体类型分为三种:dynamicstatickinematic

  • dynamic:动态刚体可以通过代码来手动移动,但一般是通过物理力来控制的,例如重力等。
  • static:静态刚体,在物理引擎下不会移动,可以通过用户来手动移动,不会接受速度的应用。静态物体只会与dynamic类型的刚体发生碰撞。
  • kinematic:运动刚体,只会在速度作用下发生移动,运动刚体不会对物理力发生作用,它们只能通过设置速度来发生移动,且只与dynamic类型的刚体发生碰撞。
physics.addBody( triangle, "static", { density=1.6, friction=0.5, bounce=0.2 } )
或者
physics.addBody( triangle, { density=1.6, friction=0.5, bounce=0.2 } )
triangle.bodyType = "static"

4.刚体的种类

  • Rectangular Bodies:矩形刚体,默认是该种类型的刚体
local platform = display.newImage( "platform.png", 600, 200 )
physics.addBody( platform, { density=1.0, friction=0.3, bounce=0.2 } )
  • Circular Bodies:圆形刚体,通过在属性表中添加radius参数来创建圆形刚体
local ball = display.newImage( "ball.png", 100, 100 )
physics.addBody( ball, { radius=50, density=1.0, friction=0.3, bounce=0.2 } )
  • Polygonal Bodies:多边形刚体,通过参数shape来创建,这是一个lua的表类型,包含(x,y)对,每一对定义了多边形的顶点,这些点是相对于显示对象的中心来定义的,显示对象的中心点坐标为(0,0)。
local triangle = display.newImage( "triangle.png" )
triangle.x = 200
triangle.y = 150

local triangleShape = { 0,-35, 37,30, -37,30 }

physics.addBody( triangle, { shape=triangleShape, density=1.6, friction=0.5, bounce=0.2 } )


local pentagon = display.newImage( "pentagon.png" )
pentagon.x = 200
pentagon.y = 50

local pentagonShape = { 0,-37, 37,-10, 23,34, -23,34, -37,-10 }

physics.addBody( pentagon, { shape=pentagonShape, density=3.0, friction=0.8, bounce=0.3 } )

注意,多边形刚体定义顶点必须是顺时针,是凸出来的,最多8个顶点。
- Multi-Element Bodies:多元素刚体,我们可以通过对多边形刚体的组合来构建多元素刚体,因为Box2D中多边形刚体必须要是凸变形,所以凹变形可以通过对凸变形进行组装来完成。多边形刚体的创建方法:

local car = display.newImage( "car.png" )
local roofShape = { -20,-10, 20,-10, 20,10, -20,10 }
local hoodShape = { 0,-35, 37,30, -37,30 }
local trunkShape = { 0,-37, 37,-10, 23,34, -23,34, -37,-10 }

physics.addBody( car, "dynamic",
    { density=3.0, friction=0.5, bounce=0.2, shape=roofShape },
    { density=6.0, friction=0.6, bounce=0.4, shape=hoodShape },
    { density=4.0, friction=0.5, bounce=0.4, shape=trunkShape }
)
  • Offset/Angled Rectangular Bodies
  • Edge Shape (Chain) Body
  • Outline Bodies

5.销毁刚体

刚体可以和显示对象一样可以被销毁:

object:removeSelf()
或者
display.remove( object )

同样地,你可以移除物体刚体作用,而显示对象依然保存在屏幕上:

physics.removeBody()

6.Sensors感应器

任何刚体,都可以作为感应器。感应器不会与其他刚体产生物理的作用,但其他刚体碰到感应器时会产生碰撞事件。当你检测刚体是否与特定区域发生碰撞,且不受到力作用时候,这个就非常有用。

physics.addBody( goal, "static", { isSensor=true } )
或者
physics.addBody( goal, "static" )
goal.isSensor = true

7.刚体拥有的属性

8.刚体拥有的方法

  • object:setLinearVelocity():设置刚体X、Y轴的线性速度。单位是像素/秒
  • object:getLinearVelocity():返回刚体X、Y轴的线性速度。单位是像素/秒
  • object:applyForce()
  • object:applyLinearImpulse()
  • object:applyTorque()
  • object:applyAngularImpulse()
  • object:resetMassData()

三.碰撞检测

我们来讨论一下物理刚体之间的碰撞,以及如何忽略(过滤)特定刚体间的碰撞。

1.刚体事件

类型:collisionpreCollisionpostCollision

2.碰撞处理

本地碰撞处理:适用于一对多

local crate1 = display.newImage( "crate.png" )
physics.addBody( crate1, { density=3.0, friction=0.5, bounce=0.3 } )
crate1.myName = "first crate"

local crate2 = display.newImage( "crate.png" )
physics.addBody( crate2, { density=3.0, friction=0.5, bounce=0.3 } )
crate2.myName = "second crate"

local function onLocalCollision( self, event )

    if ( event.phase == "began" ) then
        print( self.myName .. ": collision began with " .. event.other.myName )

    elseif ( event.phase == "ended" ) then
        print( self.myName .. ": collision ended with " .. event.other.myName )
    end
end

crate1.collision = onLocalCollision
crate1:addEventListener( "collision", crate1 )

crate2.collision = onLocalCollision
crate2:addEventListener( "collision", crate2 )

全局碰撞处理:适用于多对多

local crate1 = display.newImage( "crate.png", 100, 200 )
physics.addBody( crate1, { density = 1.0, friction = 0.3, bounce = 0.2 } )
crate1.myName = "first crate"

local crate2 = display.newImage( "crate.png", 100, 120 )
physics.addBody( crate2, { density = 1.0, friction = 0.3, bounce = 0.2 } )
crate2.myName = "second crate"

local function onGlobalCollision( event )

    if ( event.phase == "began" ) then
        print( "began: " .. event.object1.myName .. " and " .. event.object2.myName )

    elseif ( event.phase == "ended" ) then
        print( "ended: " .. event.object1.myName .. " and " .. event.object2.myName )
    end
end

Runtime:addEventListener( "collision", onGlobalCollision )

3.碰撞过滤

默认,任何刚体都会和其它刚体之间发生碰撞,你可以微调下这种行为。有两种方式可以完成我们的目的:

  • categoryBits/maskBits
    你可以给你的刚体对象分配categoryBitsmaskBits,通过一个"filter"参数,它是一个可选的表,在刚体创建的时候分配的。一个刚体和其它刚体发生碰撞的情况是:其它刚体的categoryBits处在(小于)该刚体的categoryBits中。通常,一个刚体只有一个categoryBit,可以有多个maskBit
local floor = display.newRect( 0, 0, 320, 80 )
physics.addBody( floor, "static", { bounce=0.8, filter=floorCollisionFilter } )

local redCollisionFilter = { categoryBits=2, maskBits=3 } 

local blueCollisionFilter = { categoryBits=4, maskBits=5 } 

local redSquare = display.newRect( 0, 80, 40, 40 )
redSquare:setFillColor( 1, 0, 0 )
physics.addBody( redSquare, { friction=0, filter=redCollisionFilter } )

local blueSquare = display.newRect( 80, 80, 40, 40 )
blueSquare:setFillColor( 0, 0, 1 )
physics.addBody( blueSquare, { friction=0, filter=blueCollisionFilter } )
  • groupIndex:另一种碰撞过滤的方法是给每个刚体分配一个groupIndex。这个值可以是正、负正数,拥有相同正groupIndex值的刚体总是彼此碰撞,拥有相同负groupIndex值的刚体总不会彼此碰撞。
local greenCollisionFilter = { groupIndex = -2 }

如果groupIndexcollisionBits/maskBits同时分配的话,优先考虑groupIndex

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值