Building mode & saving

Hello, I have just some question about panda3D :slight_smile:

How to do a system like SIMS 2 (build or buy mode) ?

I want Something like this video, in “00:25”.
How to make a system where the player can add, for exemple, wood fence in the map (one by one) ?
fr.youtube.com/watch?v=7Q0hZbRWNR4

And how to save the map after this ?

and I have this questions, not very important, but well :

  • how to have a polygone counter in the screen ?

Thanks in advance :slight_smile:

first thats part of your game.

some thing like

if your_money> fence_cost:
 your_money -= fence_cost
 fence = load.loadMode('fence.egg')
 fence.setPos(buildfloater.getPos())

saving level has been discussed to death search the forums.

thank you very much :slight_smile:

I will try it later :smiley:

So, i’ve tried to make somethink like Sims 2 , and it’s work :slight_smile:

But right now, i have some problems with the saving system :s

In fact, i’ve seen the treeform code, but it’s not work.

here is a test code :

# -*- coding:Latin-1 -*- 
import direct.directbase.DirectStart 
from pandac.PandaModules import *
from direct.showbase.DirectObject import DirectObject  
from direct.actor import Actor   
from direct.task import Task
from direct.gui.DirectGui import * 
import cPickle, random, os, math, sys, colorsys 

class World (DirectObject) : 
    def __init__ (self)  : 
     self.Player ()
     self.GUI () 
    
     self.keyMap = {"left":0, "right":0, "forward" :0, "backward" :0, "rotateL" :0, "rotateR":0 }     # variable permettant au joueur de bouger
     self.CameraKeyMap = {"left":0, "right":0, "forward":0, "backward":0, "up":0, "down":0, "rotateR":0, "rotateL":0 }
     self.prevtime = 0 

    # commandes du joueur 
     self.accept ('arrow_left', self.setKey, ["rotateL",1])  
     self.accept ('arrow_left-up', self.setKey, ["rotateL",0]) 
     self.accept ('arrow_right', self.setKey, ["rotateR",1]) 
     self.accept ('arrow_right-up', self.setKey, ["rotateR",0]) 
     self.accept ('arrow_up', self.setKey, ['forward',1] )
     self.accept ('arrow_up-up', self.setKey, ['forward',0] )
     self.accept ('arrow_down', self.setKey, ['backward',1] )
     self.accept ('arrow_down-up', self.setKey, ['backward',0] )
     self.accept ('lcontrol', self.setKey, ['run', 1] )
     self.accept ('lcontrol-up', self.setKey, ['run',0] )
     self.accept ('a', self.setKey, ['ActionButton',1])
     self.accept ('a-up', self.setKey, ['ActionButton',0])    
    # commande de la caméra
     self.accept ('8', self.CamerasetKey, ['forward', 1] )
     self.accept ('8-up', self.CamerasetKey, ['forward', 0] ) 
     self.accept ('7', self.CamerasetKey, ['rotateR', 1] )
     self.accept ('7-up', self.CamerasetKey, ['rotateR', 0] ) 
     self.accept ('9', self.CamerasetKey, ['rotateL', 1] )
     self.accept ('9-up', self.CamerasetKey, ['rotateL', 0] ) 
     self.accept ('5', self.CamerasetKey, ['backward', 1] )
     self.accept ('5-up', self.CamerasetKey, ['backward', 0] ) 
     self.accept ('6', self.CamerasetKey, ['right', 1] )
     self.accept ('6-up', self.CamerasetKey, ['right', 0] ) 
     self.accept ('4', self.CamerasetKey, ['left', 1] )
     self.accept ('4-up', self.CamerasetKey, ['left', 0] ) 
     self.accept ('+', self.CamerasetKey, ['up', 1] )
     self.accept ('+-up', self.CamerasetKey, ['up', 0] ) 
     self.accept ('-', self.CamerasetKey, ['down', 1] )
     self.accept ('--up', self.CamerasetKey, ['down', 0] ) 

     self.accept ('m', self.saving)    # saving 

     taskMgr.add(self.move,"moveTask")
     base.disableMouse( )
     base.camera.setPos (0,0,3)    

    ##  les fonctions   ##
    def Player (self) :
     self.Player1 = Actor.Actor ("models/panda-model")
     self.Player1.reparentTo (render) 
     self.Player1.setScale (0.01,0.01,0.01) 
    def setKey(self, key, value):  self.keyMap[key] = value 
    def CamerasetKey (self, key, value) : self.CameraKeyMap[key] = value 
    def move (self, task) :
        elapsed = task.time - self.prevtime
        if (self.keyMap["forward"]!=0)  :
            backward = self.Player1.getNetTransform().getMat().getRow3(1)
            backward.setZ(0)
            backward.normalize()
            self.Player1.setPos(self.Player1.getPos() - backward*(elapsed*10))
        if (self.keyMap["backward"]!=0) :
            backward = self.Player1.getNetTransform().getMat().getRow3(1)
            backward.setZ(0)
            backward.normalize()
            self.Player1.setPos(self.Player1.getPos() + backward*(elapsed*10))
        if (self.keyMap ["rotateL"]!=0 )  : 
            self.Player1.setH(self.Player1.getH() - elapsed*100)
        if (self.keyMap ["rotateR"] !=0 ) :
            self.Player1.setH(self.Player1.getH() + elapsed*100)   
        # move for camera
        if (self.CameraKeyMap["forward"]!=0) :
            backward = base.camera.getNetTransform().getMat().getRow3(1)
            base.camera.setPos(base.camera.getPos() + backward*(elapsed*50))
        if (self.CameraKeyMap["backward"]!=0) :
            backward = base.camera.getNetTransform().getMat().getRow3(1)
            base.camera.setPos(base.camera.getPos() - backward*(elapsed*50))
        if (self.CameraKeyMap["right"]!=0) :    
            base.camera.setH(base.camera.getH() - elapsed*70)
        if (self.CameraKeyMap["left"]!=0) :    
            base.camera.setH(base.camera.getH() + elapsed*70)
        if (self.CameraKeyMap["up"]!=0) :   
            base.camera.setZ(base.camera.getZ() + elapsed*20)
        if (self.CameraKeyMap["down"]!=0) :   
            base.camera.setZ(base.camera.getZ() - elapsed*20)
        if (self.CameraKeyMap["rotateR"]!=0) :    
            base.camera.setP(base.camera.getP() - elapsed*20)
        if (self.CameraKeyMap["rotateL"]!=0) :    
            base.camera.setP(base.camera.getP() + elapsed*20)
        self.prevtime = task.time
        return Task.cont 

    ## Graphic user Interface ##
    def GUI (self) :
     self.ButtonBuild = DirectButton(text = ("Smiley", "click!",),scale=.06,command = self.SmileyModel )
     self.ButtonBuild.setPos (1, 0.8, -0.9) 

    def loading(self,file):
        data = cPickle.load(open(file,"Saving"))
        self.users,self.zones = data
    def saving(self):
        data = self.smile
        #data = self.pack.pack(data)
        open(file,'Saving').write(data)
    def SmileyModel (self) :
        self.smile = loader.loadModel ("models/smiley")
        self.smile.reparentTo (render)
        self.smile.setPos(self.Player1.getPos()) 

w = World () 
run ()

and here is the problem in the compilation :

open(file,'Saving').write(data)
TypeError : coercing to Unicode : need string or buffer, type found

What can I do to resolve this problem ?
Thanks in advance :smiley:

open(file,“rb”) for read binary data
open(file,“rw”) for write binary data

you have to pickle in order to save some thing
you can NOT pickle PANDA3D classes
so create your own pure python data structure and pickle it and save

        data = list and dicts and any thing.
        open(file,'wb').write(cPickle.dumps(data))

there is millions of alternatives to pickle you can just write all the values as a text file. You can also use the struct module to write it in binary.

sorry but i don’t know how to do :blush:

if you have a little exemple :slight_smile:

I’ve tried this →

But not work

thanks in advance :smiley:

what is self.pack.pack ? I don’t get it. I also have it in my code which is even more odd! Have you been spying on me and copying my bugz?

In my code i called my “packer” pack and it has a function to pack … its sort of like pickle but its my creation and i dont suggest it for new users because it has no documintaion and etc … where did you get it?

now i feel bad for confusing you with all the pickle-packer stuff
here is some code

# this might help
# http://docs.python.org/lib/module-pickle.html
import cPickle

# read the value from a file if it does not exist just set the value to one
try:
    value = cPickle.load(open('datafile.pickle','rb'))
except:
    # could not load set it to one
    value = 1

print "value is",value
value += 1 # add one to it

# save the value
cPickle.dump(value,open('datafile.pickle','wb'))

when you run it multiple times it remembers the value

$ python test-pickle.py
value is 1
$ python test-pickle.py
value is 2
$ python test-pickle.py
value is 3
$ python test-pickle.py
value is 4
$ python test-pickle.py
value is 5
$ python test-pickle.py
value is 6
$ python test-pickle.py
value is 7
$ python test-pickle.py
value is 8
$ python test-pickle.py

→ yes, it was in this topic : panda3d.etc.cmu.edu/phpbb2/viewt … ht=cpickle

So, right now, cPickle is more clear for me :slight_smile:
Thank you very much :smiley:

But I still have a problem. :blush:
Now I understand with value ( money of the player for exemple) :slight_smile:

But how to do the same thing for objects in the world ?
are there an easy way to save all objets created in the world ?
(because i want to do something like building mode in sims 2)

Thanks in advance.

If each of your object is a pickleable python class (ie not a Panda3D class) then one simple way is to keep a list or a dictionnary of every object you create and then pickle the dictionnary

wow…wow…wow…

I think not only me who confuse bout this pickle stuff

I suggest you try with NxPanda for saving method
just download the zip and find the samples there
I forget just try in the forum.
( note its only work if u use NxPanda for ur Physic ) or so I think :laughing:

who knows it may work for you cost it still didn’t work for me yet
but I still working on it

so for now I use this pickle stuff, its work ( in a simple game : coordinate where the box last :laughing: ) just need more reassembles for my game code so it really work

import cPickle
from random import *
import direct.directbase.DirectStart
from pandac.PandaModules import *

# set the all objects list to empty
allobjects = []

def createJunk():
    for i in range(10):
        teapot = loader.loadModel('teapot')
        teapot.setPos(random()*100-50,random()*100-50,0)  # use random to create random positons
        teapot.setHpr(random()*360,0,0) # use random to create random rotations
        teapot.reparentTo(render)
        allobjects.append(teapot) # dont forget to add this to the all objects list for saving 

def loadPickle():
    data = cPickle.load(open('nodepaths.pickle','rb'))
    print "we read this data",data
    for nodepath in data:
        teapot = loader.loadModel('teapot')
        pos,hpr = nodepath # extract pos,hrp form tuple pos,hpr = ( pos , hpr )
        teapot.setPos(*pos) # * is used to unwrap a list   fun(*pos) -> fun(pos[0],pos[1],pos[2])
        teapot.setHpr(*hpr)
        teapot.reparentTo(render)
        allobjects.append(teapot)  # dont forget to add this to the all objects list for saving 

def savePickel():
    data = []            
    for nodepath in allobjects:
        pos = nodepath.getPos()[0],nodepath.getPos()[1],nodepath.getPos()[2]  # pos = a,b,c -> pos = (a,b,c) ; another tupple
        hpr = nodepath.getHpr()[0],nodepath.getHpr()[1],nodepath.getHpr()[2]
        data.append((pos,hpr))
    print "this is our data:",data
    cPickle.dump(data,open('nodepaths.pickle','wb'))

def simulation(task):
    for nodepath in allobjects:
        # just do some thing simple like move them all forward
        nodepath.setPos(nodepath,Vec3(0,.01,0))
    return task.cont


try:
    # read the value from a file
    loadPickle()
except:
    # could not load node paths just create some randoms ones
    createJunk()
taskMgr.add(simulation, 'simulation') # add as simulation task which will just move junk forward
try:
    run()
except:
    pass
# we are done lets save and quit
savePickel()

thank you very much !
I will try later !

hello :smiley:

So I 've tried this right now and it’s work very well.
thanks everyone :slight_smile:

But right now, there are another problem… :blush:

I can save, but i can’t remove something.

I’ve tried “removeNode” and “loader.unloadModel”, but it’s not work :confused:

How can i do to remove something ?

thanks in advance

if your are using my script above you should try to figure out how it works. The object should not be in “allobjects” then it will not be saved.

yes, i know this.

but, if i save something, and i want (later) to remove it, how can i do ?

thanks in advance.

Then you can remove it on load? Or when you do remove it node.removeNode() also do allobjects.remove(node).

very good, that works :slight_smile:

I forgot to remove it from “allobject” :stuck_out_tongue:

thanks treeform :smiley:

you could also if you know how your models are named just

allbojects = render.findAllMatches('**/yourmodelname').asList()

some thing to think about.

hello :slight_smile:

I have another problem with cPickle :blush:

right now, when i save one objects, cPickle load two objects o_O .

for exemple, if i just save a taepot, and i load it, i have a teapot and a panda in the same place.

here is the code :

import direct.directbase.DirectStart 
import cPickle, sys
from pandac.PandaModules import * 
from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import PandaNode,NodePath,Camera,TextNode
from pandac.PandaModules import Filename
from direct.gui.DirectGui import * 

class World (DirectObject) :
    def __init__ (self)  : 
     self.allobjects = []    
     self.GUI () 
    def GUI (self) :
     self.ButtonFile = DirectOptionMenu(text="File", scale=0.05,items=["File", "Save", "Load"],
     initialitem=0,highlightColor=(0.65,0.65,0.65,1),command=self.File )
     self.ButtonFile.setPos (-1.33, 0, 0.963)

     self.ButtonPanda = DirectButton(text = ("Teapot", "click!"),scale=.05,command = self.Panda )
     self.ButtonPanda.setPos (1, 0, -0.9) 

     self.ButtonRalph = DirectButton(text = ("Ralph", "click!"),scale=.05,command = self.Teapot )
     self.ButtonRalph.setPos (1, 0, -0.4)    
    def File (self, arg) :# pour changer de temps (ensoleillé,neige, etc.)
     if (arg == "Save") : self.savePickle ()
     if (arg == "Load") : self.loadPickle ()

    def Panda (self) :
        self.panda = loader.loadModel ("models/panda-model.egg.pz")
        self.panda.reparentTo (render)
        self.panda.setPos(0,0,0) 
        self.panda.setScale (0.1,0.1,0.1)
        self.allobjects.append(self.panda)      
    def Teapot (self) :
        self.teapot = loader.loadModel ("models/teapot.egg.pz")
        self.teapot.reparentTo (render)
        self.teapot.setPos(35,0,0) 
        self.allobjects.append(self.teapot) 

    def loadPickle(self):
     data = cPickle.load(open('nodepaths.pickle','rb'))
     for nodepath in data:
        self.teapot = loader.loadModel ("models/teapot.egg.pz")
        self.teapot.reparentTo (render)
        pos = nodepath        
        self.teapot.setPos(*pos)    

        self.panda = loader.loadModel ("models/panda-model.egg.pz")
        pos = nodepath       
        self.panda.setPos (*pos) 
        self.panda.setScale (0.1,0.1,0.1)
        self.panda.reparentTo (render)
    def savePickle (self):
     data = []           
     for nodepath in self.allobjects:
        pos = nodepath.getPos()[0],nodepath.getPos()[1],nodepath.getPos()[2]  # pos = a,b,c -> pos = (a,b,c) ; another tupple
        data.append((pos))
     cPickle.dump(data,open('nodepaths.pickle','wb'))

w = World () 
run () 

how can i do to resolve this problem ?

thanks in advance