Liquid Simulation (the real thing!) Working in Corona SDK.

@gtatarkin: If you wrote your own physics engine that was truly capable of implementing something like eaguirre’s liquid simulation, it would be the best selling 3rd Party Tool on this site. Better get started! [import]uid: 40137 topic_id: 17023 reply_id: 65056[/import]

I’m a novice and eleven years old.
It’s cool, but we need two things to get it right:

Speed (ESSENTIAL):
We need to get the frame rate to work better. The max speed for me has been about 31 fps. And that’s after things stop moving. At the start, the max speed for me has been about 16 fps. If we can get the max speed once things settle down to be about 60, that would be great.

Appearance (NOT SO CRUCIAL, BUT USEFUL):
Liquid in real life tries to balance out so that the surface is as flat as it can be. We need to get that to work somehow. Just a thought.

Also, when I tried a physics explosion on the “liquid” to toss it around, it seemed like gravity reversed! I’m not making it up! I even turned off tilt-based gravity and it still reversed! Try it out for yourself. Here’s the code for “explosions”:

[code]
local function onLocalCollision( self, event )
if ( event.phase == “began” and self.myName == “circle” ) then
local forcex = event.other.x-self.x
local forcey = event.other.y-self.y-20
if (forcex < 0) then
forcex = 0-(80+forcex)-12
else
forcex = 80-forcex+12
end
event.other:applyForce( forcex, forcey, self.x, self.y )
end
end
local circle = “”

local function setBomb ( event )
if(event.phase == “began”) then
circle = display.newCircle( event.x, event.y, 80 )
circle.myName = “circle”
circle:setFillColor( 0, 0, 0, 0 )
physics.addBody( circle, “static”, {isSensor = true} )
circle.collision = onLocalCollision
circle:addEventListener( “collision”, circle )
end
if(event.phase == “ended”) then
circle:removeSelf()
end
end

Runtime:addEventListener( “touch”, setBomb ) [import]uid: 82408 topic_id: 17023 reply_id: 66084[/import]

Hello Community,
We profiled this piece of code and identified some slow lines of code. However, optimizing it will be more difficult as we are unfamiliar with how this program works. A profiler result can be viewed at our blog here.
http://www.mydevelopersgames.com/site/category/corona-profiler-2/


-M.Y. Developers [import]uid: 55057 topic_id: 17023 reply_id: 75588[/import]

How to put this water into a Group??? [import]uid: 27760 topic_id: 17023 reply_id: 115164[/import]

I forgot that we can use the blendMode of an image, so I replace these lines of code:

 balls[#balls+1] = display.newImage("touch01.png")   
 balls[#balls]:setFillColor( 0,255,0 )   
 balls[#balls].blendMode = "add"  

and I removed a lot of the code.

The “touch01.png” for my test is a 48x48 radial fill circle (white in the middle and transparent on the outside). It’s white because with the setFillColor function I can change the color of the liquid.
The code is much faster than previous versions and I use only 100 circles to create the liquid. So it will run better on a device.

So here it is the new code:

[code]


– Copyright 2012 Emilio Aguirre, All Rights Reserved.
www.emilioaguirre.com

– Permission is hereby granted, free of charge, to any person obtaining a copy of
– this software and associated documentation files (the “Software”), to deal in the
– Software without restriction, including without limitation the rights to use, copy,
– modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
– and to permit persons to whom the Software is furnished to do so, subject to the
– following conditions:

– The above copyright notice and this permission notice shall be included in all copies
– or substantial portions of the Software.

– THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
– IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
– FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
– AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
– LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
– OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
– THE SOFTWARE.

– This is a demo of a liquid simulation.
– Touch the screen to see the gravity changes, the liquid will go
– in the opposite direction.


local physics = require(“physics”)

– Define variables
local imgBuffer = {} – Image buffer
local w1= math.floor(display.contentWidth)
local h1= math.floor(display.contentHeight)
local refreshImage – Flag to handle when to draw
local line={} – Lines table

– Start Physics
physics.start()

– Hide status bar
display.setStatusBar( display.HiddenStatusBar )

– Create background rect
local bg = display.newRect( 0, 0, 320, 480 )
bg:setFillColor( 0, 127, 255)

– Create the border to prevent the liquid to fall
borderCollisionFilter = { categoryBits = 1, maskBits = 6 } – collides with (4 & 2) only
borderBodyElement = { friction=0.1, bounce=0.1, filter=borderCollisionFilter }

local borderTop = display.newRect( 0, 0, 320, 1 )
borderTop:setFillColor( 0, 0, 0, 0)
physics.addBody( borderTop, “static”, borderBodyElement )

local borderBottom = display.newRect( 0, 479, 320, 1 )
borderBottom:setFillColor( 0, 0, 0, 0)
physics.addBody( borderBottom, “static”, borderBodyElement )

local borderLeft = display.newRect( 0, 1, 1, 480 )
borderLeft:setFillColor( 0, 0, 0, 0)
physics.addBody( borderLeft, “static”, borderBodyElement )

local borderRight = display.newRect( 319, 1, 1, 480 )
borderRight:setFillColor( 0, 0, 0, 0)
physics.addBody( borderRight, “static”, borderBodyElement )

– Add anoter wall in the middle
local wall = display.newRect( 60, 350, 140, 20 )
wall:setFillColor( 255, 255, 0)
wall.rotation=45
physics.addBody( wall, “static”, borderBodyElement )

wall = display.newRect( 140, 250, 140, 20 )
wall:setFillColor( 255, 255, 0)
wall.rotation=-45
physics.addBody( wall, “static”, borderBodyElement )

– Create 400 balls that will serve as the liquid elements

local balls = {}
local ballsCollisionFilter = { categoryBits = 2, maskBits = 3 } – collides with (2 & 1) only
local ballsBody = { density=1000, friction=0.0, bounce=0.1, radius=6, filter=ballsCollisionFilter }

local function spawn()
ballsBody.radius=math.random(3,6)
balls[#balls+1] = display.newImage(“touch01.png”)
balls[#balls]:setFillColor( 0,255,0 )
balls[#balls].blendMode = “add”
balls[#balls].x = 160
balls[#balls].y = 200
balls[#balls].isLiquid = true
physics.addBody( balls[#balls], ballsBody )
end
local tm = timer.performWithDelay(40, spawn,100)

– Callback to global accelerometer

local function onTilt( event )
physics.setGravity( 9.8 * event.xGravity, -9.8 * event.yGravity )
end


– Callback to frame

local onTouchCallback = function( event )
physics.setGravity( 9.8 * (event.x - 180)/100, 9.8 * (event.y-240)/100)
end

– Create event listeners

Runtime:addEventListener( “accelerometer”, onTilt )
Runtime:addEventListener( “touch”, onTouchCallback )
[/code] [import]uid: 9975 topic_id: 17023 reply_id: 115974[/import]

mmm not sure if you can add objects with physical attributes to a Group. Need to review the documentation. [import]uid: 9975 topic_id: 17023 reply_id: 115976[/import]