LiquidFun 要点

LiquidFun 物理引擎允许您模拟水龙头、水池、波浪、溪流和其他令人惊叹的基于物理的效果,类似于Corona游戏(如 Freeze! 2 – Brothers)或其他物理世界并非完全由刚体组成的游戏中所呈现的效果。除了基本的液体效果外,您还可以实现半液体弹性/凝胶状物体,创建在接触时混合并融合颜色的液体,检测和操纵液体的“区域”等等。

粒子系统

在 LiquidFun 中,所有液体都由粒子系统表示,这意味着溪流或水池是由许多相互作用以模拟所需效果的“粒子”组成的。每个粒子都是圆形的,它们是粒子系统中最小的物质单位。默认情况下,粒子表现为液体,但您可以更改单个粒子或粒子组的行为。您还可以设置粒子属性,例如位置、速度和颜色。

重要

LiquidFun 框架定义的粒子与基于发射器的display.newEmitter() 生成的粒子无关。换句话说,这两种粒子类型是来自不同库的不同对象,它们不会发生物理交互 — 事实上,基于发射器的粒子根本不支持物理碰撞。

在 Corona 中,您可以通过 physics.newParticleSystem() 函数创建一个 ParticleSystem 对象

physics.newParticleSystem( params )

在此 API 中,params 是一个参数表,只有一个必需元素:要为每个粒子实例渲染的粒子图像的文件名 (filename)

local physics = require( "physics" )
physics.start()
 
local testParticleSystem = physics.newParticleSystem(
{
    filename = "particle.png"
})

但是,为了使您的粒子系统表现更好,您应该指定一些其他属性。至少,您应该定义粒子 radius 来控制构成液体效果的粒子的大小。另一个有用的参数是 imageRadius,如果定义了该参数,它将指示 Corona 以与 radius 定义的物理实体不同的尺寸渲染粒子图像。本质上,如果 imageRadius 略大于 radius,则粒子会有些重叠,从而产生更具凝聚力的液体状外观。

local physics = require( "physics" )
physics.start()
 
local testParticleSystem = physics.newParticleSystem(
{
    filename = "particle.png",
    radius = 2,
    imageRadius = 4
})

其他参数及其用途的完整列表超出了本教程的范围,因此请参阅文档LiquidFun 程序员指南了解更多信息。

创建粒子

建立粒子系统后,可以使用 object:createParticle() 方法生成新的粒子。它接受一个可选参数表,用于控制每个生成粒子的行为,例如

testParticleSystem:createParticle(
{
    x = 0,
    y = 0,
    velocityX = 256,
    velocityY = 480,
    color = { 1, 0.2, 0.4, 1 },
    lifetime = 32.0,
    flags = { "water", "colorMixing" }
})

这些参数大多是不言自明的:

需要注意的是,object:createParticle() 只在整个系统中创建一个粒子,因此要创建有用的场景,您需要通过重复计时器或其他重复方法调用此函数来生成大量粒子。例如

local physics = require( "physics" )
physics.start()

local testParticleSystem = physics.newParticleSystem(
{
    filename = "particle.png",
    radius = 2,
    imageRadius = 4
})

local function onTimer( event )

    testParticleSystem:createParticle(
    {
        x = 0,
        y = 0,
        velocityX = 256,
        velocityY = 480,
        color = { 1, 0.2, 0.4, 1 },
        lifetime = 32.0,
        flags = { "water", "colorMixing" }
    })
end

timer.performWithDelay( 20, onTimer, 0 )

创建粒子组

除了在系统中创建单个粒子外,您还可以使用 object:createGroup() 函数创建相关的粒子。本质上,这会在一个命令中用多个粒子“填充”定义的区域,并且可以为该组分配各种行为和视觉属性。例如

local physics = require( "physics" )
physics.start()

local testParticleSystem = physics.newParticleSystem(
{
    filename = "particle.png",
    radius = 2,
    imageRadius = 4
})

testParticleSystem:createGroup(
{
    x = 0,
    y = 0,
    color = { 0, 0.3, 1, 1 },
    halfWidth = 64,
    halfHeight = 32,
    flags = { "water", "colorMixing" }
})

此代码生成一个矩形粒子组,但您也可以创建圆形组和任意形状组。请参阅文档了解有关创建不同组类型的信息。

施加力/冲量

可以通过 object:applyForce() API 将线性力应用于粒子系统中所有粒子的中心。此方法接受两个数值,分别表示在 **x** 和 **y** 方向上施加的力的大小。例如

testParticleSystem:applyForce( 0, -9.8 * testParticleSystem.particleMass )

或者,您可以使用 object:applyLinearImpulse() API 对所有粒子施加线性冲量。这与上述方法类似,不同之处在于冲量是瞬间的牛顿秒冲击力。例如

testParticleSystem:applyLinearImpulse( 0, -9.8 * testParticleSystem.particleMass )

区域查询

虽然生成单个粒子甚至粒子组可以提供一些惊人的效果,但在某些时候您可能需要检测和操纵定义区域内的粒子。这是通过 object:queryRegion() 函数使用以下语法完成的

ParticleSystem:queryRegion( upperLeftX, upperLeftY, lowerRightX, lowerRightY, hitProperties )

定义的区域必须是矩形的,它由前四个参数定义 — 只需指定左上角(upperLeftX/upperleftY)右下角(lowerRightX/lowerRightY)即可查询由这些坐标创建的矩形区域。

最后一个参数 hitProperties 是一个可选属性表,可以应用于该区域中的每个粒子。有效属性包括

因此,如果您想对某个区域中的所有粒子应用向上的 **y** 速度,代码可能如下所示

local hits = testParticleSystem:queryRegion( 10, 40, 100, 160, { velocityY=-40 } )
注意

hitProperties 表中可能应用的所有值都是将应用于每个粒子当前关联值的增量值。例如,如果您将 velocityY-40 应用于该区域中的粒子,它不会直接将 -40 设置为它们的实际 **y** 速度,而是将该速度以增量关系应用于粒子已有的任何现有速度。

粒子碰撞

检测 LiquidFun 粒子与其他物理对象之间的碰撞事件是一个深入的主题,超出了本教程的范围。有关此主题的更多详细信息,请参阅 LiquidFun 粒子碰撞 教程。

总结

本教程旨在简要介绍 Corona 中的 LiquidFun 物理引擎,但该框架的功能超出了此范围。请查阅文档LiquidFun 程序员指南了解更多信息。