Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Powder simulation

edited August 26 in Code Sharing Posts: 160

Tapping on the screen will create random particles. To change the powder, tap on the buttons on the sides.
Material properties:
Water - flows around and through things randomly and spread out quickly
Grass - mostly stays in place but falls apart without dirt below it
Dirt - solid
Random - one powder, can be water, grass, dirt, powder, or acid
Acid - digs holes in solids and destroys water. Eventually disappears

--# Main

--FallingSand Single Install
--Installer created by @Briarfox
--- This will pull the FallingSand project into Codea for you
-- Instructions:
-- * Create a new project in Codea named FallingSand If you chose another name please change the variable Below
--This is case sensitive
ProjectName = "FallingSand"
-- * Paste this into the Main (not from the raw view, as iSafari will escape special characters)
-- * Make sure there is a single tab in the project
-- * Run and wait for success!
-- If all went well, you should have a FallingSand project now

function setup()
    local jsonCode

function getJsonLib()
    local tabs = listProjectTabs()
    if #tabs == 1 then
        print("Attempting to load json...")
        local handleSuccess = function(data)
            --saveProjectTab("json", data)
            jsonCode = data
            --sound(SOUND_POWERUP, 42179)
            print("json code loaded...")
            if jsonCode then
                print("Attempting to pull project...")
                l = loadstring(jsonCode)
        http.request("", handleSuccess)

function GetProject()
    local projectCheck = listProjectTabs(ProjectName)
    if #projectCheck ~= 0 then
   local handleSuccess = function(data,i,j)
        local gist = json.decode(data)
        local projName = ProjectName
        if gist.files["1aTabOrder"] then
            print("***Tab Order Found***")
            local taborder = gist.files["1aTabOrder"].content
            local strStart =1
            local strEnd =0
            strStart = string.find(taborder,"#",strEnd)
            strEnd = string.find(taborder,"\n",strStart)
            while strStart do
                local tmp = string.sub(taborder,strStart+1,strEnd-1)
                local name = ProjectName..":"..tmp
                tmp = tmp..".lua"
                strStart = string.find(taborder,"#",strEnd)
                strEnd = string.find(taborder,"\n",strStart)

            for k,v in pairs(gist.files) do
                local name = ProjectName .. ":" .. string.gsub(k,".lua","")
                saveProjectTab(name, v.content)
        sound(SOUND_PICKUP, 11797)
    local handleFailure = function(data)
        sound(SOUND_EXPLODE, 32351)

    http.request("",handleSuccess, handleFailure)
            sound(SOUND_EXPLODE, 32351)
Project name incorrect! 
Please make sure the variable ProjectName = "your project" matches the project name.
This is case sensitive!]])

Suggestions on performance would be much appreciated. I want it to perform at least 40fps with grid size WIDTH,HEIGHT.


  • dave1707dave1707 Mod
    Posts: 6,230

    @em2 I get this error.

    Main:327: attempt to call a nil value (global 'hsl2rgb')
    stack traceback:
        Main:327: in function <Main:326>
  • em2em2
    Posts: 160

    Does it work now? The old link won't work anymore; use the installer.

  • Posts: 142

    It worked for me. That's a pretty neat simulator!
    Frame-rate tip: don't print stuff into the output every frame or the game will get increasingly laggy

  • Posts: 10

    Well, one quick observation on performance: you don't need to do two deep copies of the grid on every update. Once you've made your 'next' grid at the beginning of the frame, you can just assign it to 'grid' once you've finished updating it so it'll be ready for the next frame.

  • Posts: 10

    function Grid:touched(touch)
        -- Codea does not automatically call this method
        local cc, hcc = self.cellSize,self.cellSize/2
        if touch.state == ENDED then
        local x, y = math.floor(touch.x/cc), math.floor(touch.y/cc)
        self:set(x, y, true)

    That'll make a significant difference with lots of simultaneous touches; iterating the whole grid to find the coordinate is clearly not needed, but admittedly not a bottleneck most of the time.
  • Posts: 10

    Also current version doesn't seem to be using the different particles you mention.

  • Posts: 10

    Oh yeah I was computing those coordinates slightly wrong. Should really go to bed, but will be trivial to get right.

  • edited August 26 Posts: 142

    @xinaes Are you trying to find the x and y of the cell that's being touched? A while ago (like a year), I made a pixel art painting project. I still have the formula I used in there somewhere!

    Here it is! This should work. I haven't really looked at all of @em2's code, but if it works the way I think it does, I'm quite certain the below code will work.

    size = --Put the amount of cells in each dimenion here
    self:set(math.ceil(size/math.min(WIDTH,HEIGHT) * t.x),math.ceil(size/math.min(WIDTH,HEIGHT) * t.y),true)

    Edit: Nevermind, that way didn't work properly. So I tried it like this with the same formula and it seemed to work

    self.grid[math.ceil(20/math.min(WIDTH,HEIGHT) * touch.x)][math.ceil(20/math.min(WIDTH,HEIGHT) * touch.y)] = true
  • em2em2
    edited August 26 Posts: 160

    Thanks for your suggestions. I should have checked the code I uploaded. When I used AutoGist to back up my project name, I mistyped it (with an extra space). I updated the installer with the new version above.
    Hopefully it should work with all the special powder stuff.
    P.S. I actually did create my own Pixel Art app. I'll post the link below.

  • edited September 7 Posts: 522

    This is one of those cool projects people post here where it is really impressive on its own, and even more so because it is so few lines of code!

    Is the grass setting supposed to draw static pixels and also draw gravity-affected pixels at the same time? That's what it does currently. The dirt setting draws only static pixels, which is how I'd assumed grass would work, and it confused me.

    You didn't ask for design suggestions, but I have a couple, for what it's worth, which is of course not much:

    1. I know the reset button will work as a "clear screen" button, but it would still be nice to have a dedicated "clear screen" button.
    2. The initial setting drops apparently-randomly-colored pixels wherever you draw. I like this mode. It seems like it is impossible to get back to it after you select any of the other materials.
    3. The random button randomly chooses one of the other settings and stays on it, but looking at it I had assumed that it would randomly pick one of the other settings every time you started a new touch. In other words, I assumed its randomness was a persistent setting, not a one-time thing. I think it would be cool if you made it work that way!
    4. I like the small pixel size, but for me it is a little too small for me to feel able to accurately target any one cell with my finger. Personally I would like to see it at 1.5x or 2x the current size.

    Overall, great though.

  • em2em2
    Posts: 160

    The grass is really supposed to be "held in place" by the dirt, which is static. (grass needs to be planted in dirt). As for the pixel size, I made it small so that playing with it would feel more "powdery", and I am too lazy to add in zoom features (like in my pixel art project). All in all, however, those are all great suggestions! Thanks a lot, @UberGoober.

  • Posts: 522

    I just wanted to be sure it's working how you intended. It sounds like grass should only fall unless held up by dirt, which isn't exactly what happens. But also I understand it's just a fun little thing you did that you may not be interested enough to put more time into. That's great too.

Sign In or Register to comment.