Saving physic.bodies in a table

Hi, for the life of me, I can’t figure out how to save a table, I know users like Zoyt have made some snippets of code to do this, but I can’t get my head around using it to save physics bodies or vec2s, could someone explain please walk me through what the code does, or give me some pointers of what to do? :slight_smile:

Zoyts code:

--# Main
-- String Table

-- Use this function to perform your initial setup
function setup()
    jo = {{1,2,3},{2,3,5}}
    saveProjectData("jo",tToS("jo",jo))
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)

    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
table = readProjectData("jo", "jo = {}")
assert(loadstring(table))()

if table == jo then
    print("It Worked")
end
end

function tToS(name, value, saved)
    local function basicSerialize (o)
        if type(o) == "number" then
            return tostring(o)
        else -- assume it is a string
            return string.format("%q", o)
        end
    end
    saved = saved or {}
    local returnStr = name.." = " 
    if type(value) == "number" or type(value) == "string" then
        returnStr = returnStr..basicSerialize(value).."\
"
    elseif type(value) == "table" then
        if saved[value] then
            returnStr = returnStr..saved[value].."\
"
        else
            saved[value] = name
            returnStr = returnStr.."{}\
"
            for k,v in pairs(value) do 
                local fieldname = string.format("%s[%s]", name, basicSerialize(k))
                returnStr = returnStr..tToS(fieldname, v, saved)
            end
        end
    else
        error("Cannot save a " .. type(value))
    end
    return returnStr
end

Thanks,

Prynok

@Prynok Here’s something I posted over a year ago. It saves physics.bodies in a table.

http://twolivesleft.com/Codea/Talk/discussion/1349/brownian-motion-kind-of/p1

@dave1707 Does it save them to be used later ex: close app and reopen it, or does it just put the physic.bodies into a table. Because I already know how to put them in a table, just need help saving the data for the player when they close the app.

Sorry if it wasn’t clear enough.

@Prynok It creates a new table each time the program is run. Saving a table with saveLocalData is a little more involved, but can be done. It just takes a little more thought in saving/reading the information.

@dave1707 but what about in a building game where you have to save the users work? Creating a new table wouldn’t solve anything

@Prynok After some checking, I’m not sure if you can save a physics.body. If you print the information of a physics.body, it says it’s a rigidbody and gives a memory address. That address is specific to that program and won’t mean anything in another program if you read the saved information. You could probably save a lot of the information about the physics.body and recreate it with that info, but saving the actual rigidbody probably won’t work. EDIT: what physics.body are you trying to save ( circle, polygon, etc.)

Polygon, in the shape of a square.

@Prynok You can save a lot of the information about the polygon in localData and then recreate the polygon when the program is started again. Look at the list of information under physics.body and decide what information you want to save, ie. x,y,points, etc. Then you can recreate a new polygon using that information when the program starts.

@Prynok Here’s a simple example. I create a circle that falls under the influence of gravity. When you tap the screen, I save the current information and destroy the physics.body. When you tap the screen again, I recreate the circle at the x,y position, and with the velocity it had when I destroyed it. You would do the same thing, saving the polygon information you need. You would save the information with saveLocalData and then read it back in to recreate it. I just used the table information so I wouldn’t have to add all the other code for save/read local data. Tap the screen before the circle reaches the bottom of the screen. Wait a little while and tap the screen to recreate the object. Taping the screen again will recreate the saved object again.


function setup()
    saved=false
    tab={}
    c1=physics.body(CIRCLE,10)
    c1.x=WIDTH/2
    c1.y=HEIGHT
end

function draw()
    background(40, 40, 50)
    if c1.x~=nil then
        ellipse(c1.x,c1.y,20)
    end
end

function saveData()
    tab.x=c1.x
    tab.y=c1.y
    tab.radius=c1.radius
    tab.lv=c1.linearVelocity
    print(tab.x)
    print(tab.y)
    print(tab.radius)
    print(tab.lv)
end

function create()
    c1=physics.body(CIRCLE,10)
    c1.x=tab.x
    c1.y=tab.y
    c1.radius=tab.radius
    c1.linearVelocity=tab.lv
end
    

function touched(t)
    if t.state==BEGAN then
        if saved then
            create()
        else
            saveData()
            saved=true
            c1:destroy()
        end
    end
end

Hmm, intesting, I thought readLocalData only did strings though. Doesn’t it?

@Prynok Here’s the above code using saveLocalData and readLocalData.


function setup()
    clearLocalData()
    saved=false
    c1=physics.body(CIRCLE,10)
    c1.x=WIDTH/2
    c1.y=HEIGHT
end

function draw()
    background(40, 40, 50)
    if c1.x~=nil then
        ellipse(c1.x,c1.y,20)
    end
end

function saveData()
    saveLocalData("c1x",c1.x)
    saveLocalData("c1y",c1.y)
    saveLocalData("c1radius",c1.radius)
    saveLocalData("c1lvx",c1.linearVelocity.x)
    saveLocalData("c1lvy",c1.linearVelocity.y)
end

function create()
    c1=physics.body(CIRCLE,10)
    c1.x=readLocalData("c1x")
    c1.y=readLocalData("c1y")
    c1.radius=readLocalData("c1radius")
    c1.linearVelocity=vec2(readLocalData("c1lvx"),readLocalData("c1lvy"))
end    

function touched(t)
    if t.state==BEGAN then
        if saved then
            create()
        else
            saveData()
            saved=true
            c1:destroy()
        end
    end
end

Sorry @dave1707, but that still doesn’t answer my question, how could I save data in a table? The example above just uses a few variables for it. How could I read over entire table, save save all the physic bodies in it?

Sorry if I’m being confusing

What I think Dave1707 is saying, is that you can’t save the actual physics body. What you can do is save all the information you need to create a new body that is exactly the same, as a string of information, like the x and y position, radius etc.

Your problem is that Codea never gives you the actual data in the physics object. When you write “b = physics.body(…)”, Codea only puts the memory address of the object in b, not all the data.

So you never get to see what the physics body data actually looks like, and you have no way of saving it. All you can do is build an identical copy.

@Prynok You would loop thru the table creating the keys for saveLocalData based on the table offsets. You would save the info using those keys so that when you readLocalData, you could recreate the physics.bodies based on the keys you read. Here’s an example showing a table of 2 physics.bodies. I read thru the table saving the info. I read the info and recreate the table. This will vary based on your info.


function setup()
    clearLocalData()
    
    -- create a table of 2 physics.bodies
    tab={}
    tab[1]=physics.body(CIRCLE,10)
    tab[1].x=100
    tab[1].y=200
    tab[1].radius=20
    
    tab[2]=physics.body(CIRCLE,10)
    tab[2].x=300
    tab[2].y=150
    tab[2].radius=15
    
    
    -- read the table and save the info
    for z=1,#tab do
        saveLocalData("tab"..z.."-x",tab[z].x)
        saveLocalData("tab"..z.."-y",tab[z].y)
        saveLocalData("tab"..z.."-radius",tab[z].radius)
    end
    
    -- read the info and recreate the table
    tab={}
    ld=listLocalData()
    for z=1,#ld/3 do  -- 3 entries for the 2 objects
        tab[z]=physics.body(CIRCLE,10)
        tab[z].x=readLocalData("tab"..z.."-x")
        tab[z].y=readLocalData("tab"..z.."-y")
        tab[z].radius=readLocalData("tab"..z.."-radius")
    end
    
    -- print the table info
    for z=1,#tab do
        print(tab[z].x)
        print(tab[z].y)
        print(tab[z].radius)
    end       
end