nice class you got there, a lot is going on.
I don’t put the code for drawing to the screen inside my abstract classes my self and another thing is the code that store the inventory can be done simpler.
here is a complete example that stores a monster including it’s loot (inventory) to disk and restores it (scroll to the end for the important bits.)
import json
import shelve
import hashlib
import random
import time
def genkey(data=None):
if data:
data = str(data)
else:
data = str( time.time() ) + str( random.randrange(1,10000) )
generated_id = hashlib.md5(data.encode('utf-8'))
return generated_id.hexdigest()
#-------------------------------------------------
class Base:
"""
Base Class
"""
def __init__(self,**kw):
super().__init__()
def __getitem__(self, key):
return getattr(self, key)
def __setitem__(self, key, value):
setattr(self, key, value)
def __repr__(self):
return "{} {}".format(type(self),vars(self))
def update(self,**kw):
for arg in kw:
if arg in vars(self):
if type(self[arg]) == dict:
self[arg].update(kw[arg])
else:
self[arg] = kw[arg]
else:
print("Error: Attribute [ ",arg," ] does not exists!")
#-------------------------------------------------
class GameObject(Base):
def __init__(self,**kw):
self.Id=0
self.name = "GameObject"
self.worldPosition = None
self.worldOrientation = None
self.worldScale = [1.0,1.0,1.0]
super().__init__()
self.update(**kw)
def __getitem__(self, key):
return getattr(self, key)
def __setitem__(self, key, value):
setattr(self, key, value)
def __repr__(self):
return "{} {}".format(type(self),vars(self))
#-------------------------------------------------
class DynamicGameObject(GameObject):
def __init__(self,**kw):
super().__init__()
self.stacksize = 1
self.count = 1
self.objsize = 100
self.update(**kw)
if self.count < 1:
self.count = 1
if self.count > self.stacksize:
self.stacksize = self.count
def addItemToStack(self,amount = 1):
if self.count < self.stacksize:
self.count += amount
if self.count > self.stacksize:
tmp = self.count - self.stacksize
self.count = self.stacksize
return tmp
return 0
def removeItemFromStack(self,amount = 1):
if self.count > amount:
self.count -= amount
return False
else:
self.count = 0
return True
def getallattr(self):
return vars(self)
#return self.name, self.objsize, self.worldPosition, self.worldOrientation, self.count, self.stacksize
#-------------------------------------------------
class basicContainer(Base):
def __init__(self,**kw):
self.Id = 0 #deprecated don't use.
self.key = "defaultkey"
self.name = "container"
self.items = {}
super().__init__()
self.update(**kw)
def __len__(self):
return len(self.items)
def __iter__(self):
for n in self.items:
yield self.items[n]
return self
def __next__(self):
return self
def add(self,item):
if hasattr(item,"key"):
self.items[item["key"]] = item
else:
self.items[genkey()] = item
def remove(self,item):
if hasattr(item,"key"):
if item["key"] in self.items:
outobj = self.items[item["key"]]
del self.items[item["key"]]
return outobj
else:
for key in self.items.keys():
if item == self.items[key]:
outobj = self.items[key]
del self.items[key]
return outobj
if hasattr(item,"name"):
print("ERROR :",item.name,"Not in",self.name)
else:
print("ERROR : Item Not in",self.name)
return None
#-------------------------------------------------
class Container(basicContainer):
def __init__(self,**kw):
self.maxitems = 10
self.maxitemsize = 0
self.active = True
self.containertype = ""
self.freeslots = []
super().__init__()
self.update(**kw)
if "items" in kw:
self.items = {}
for itm in kw["items"]:
obj,slot = kw["items"][itm]
self.items[itm] = [DynamicGameObject(**obj),slot]
if not self.freeslots:
self.freeslots = [i for i in range(0,self.maxitems) ]
def getallattr(self):
self.dumps()
def dumps(self):
allitems = {}
for itm in self.items:
tmp = self.items[itm]
allitems[itm] = [ tmp[0].getallattr(),tmp[1] ]
return {"name":self.name, "maxitems":self.maxitems, "maxitemsize":self.maxitemsize, "freeslots":self.freeslots, "active":self.active, "containertype":self.containertype, "items":allitems}
def swap(self,slot_a,slot_b): # slot_a = from , slot_b = to
if slot_b in self.freeslots:
for key in self.items:
itma,slota = self.items[key]
if slota==slot_a:
self.items[key][1]=slot_b
self.freeslots.append(slota)
self.freeslots.remove(slot_b)
self.freeslots.sort()
else:
tmp1=None
tmp2=None
for key in self.items:
itma,slota = self.items[key]
if slota==slot_a:
tmp1=key
for key in self.items:
itmb,slotb = self.items[key]
if slotb==slot_b:
tmp2=key
tmp = self.items[tmp1][1]
self.items[tmp1][1] = self.items[tmp2][1]
self.items[tmp2][1] = tmp
def findObjectsByName(self,name=""):
tmp = None
for item in self.items:
itm,slot = self.items[item]
if name == itm.name:
if tmp:
tmp.append(itm)
else:
tmp = [itm]
return tmp
def add(self,item,slot=None):
if self.maxitemsize !=0: # maxitemsize = 0 = no limit
if hasattr(item,"objsize"):
if item["objsize"]>self.maxitemsize:
print("Error : can't add ",item.name,"to",self.name,": object to big")
return False
if len(self.freeslots)>0:
if item["Id"] in self.items:
print("Error : can't add ",item.name,"to",self.name,": can't add the same object twice")
return False
else:
if slot:
if slot in self.freeslots:
index = self.freeslots.index(slot)
self.items[item["Id"]] = [item,self.freeslots[index]]
del self.freeslots[index]
else:
self.items[item["Id"]] = [item,self.freeslots[0]]
del self.freeslots[0]
else:
self.items[item["Id"]] = [item,self.freeslots[0]]
del self.freeslots[0]
return True
else:
print("Error : cant add ",item.name,": Container",self.name,"is Full")
return False
def delObjectfromslot(self,fromslot):
for item in self.items:
itm,slot = self.items[item]
if slot == fromslot:
out = self.remove(itm)
return out
return None
def remove(self,item):
if item["Id"] in self.items:
itm ,slot = self.items[item["Id"]]
self.freeslots.append(slot)
self.freeslots.sort()
#outobj = copy.copy(self.items[item["Id"]])
outobj = self.items[item["Id"]]
del self.items[item["Id"]]
return outobj[0]
else:
print("ERROR :",item.name,"Not in",self.name)
return False
def getfreeslots(self):
return self.freeslots
#-------------------------------------------------
class Loot:
"""
there be loot.
"""
def __init__(self):
super().__init__()
self.loot = Container(maxitems = 20)
def addLoot(self,data):
self.loot.add(data)
#-------------------------------------------------
class Dummy:
"""
Dummy Class
"""
def __init__(self):
super().__init__()
#-------------------------------------------------
class AI(Dummy):
"""
artificial intelligence (more or less)
"""
def __init__(self):
super().__init__()
self.state = None
#-------------------------------------------------
class Monster(Base,AI,Loot):
"""
There be Monsters.
"""
def __init__(self,**kw):
super().__init__()
self.name = "snake"
self.key = "defaultkey" # override this with unique key.
self.stats = {"LVL":1,"HP":100,"Mana":10,"XP":20}
self.update(**kw)
if "loot" in kw:
self.loot = Container(**kw["loot"])
def dumps(self):
return {"name":self.name,"key":self.key,"stats":self.stats,"loot":self.loot.dumps(),"state":self.state}
#-------------------------------------------------
def save(filename="defaultshelve",key="defaultkey",data=""):
"""
Save to Disc
"""
try:
with shelve.open(filename) as s:
s[key] = data
except:
print('ERROR: {}'.format(key))
#-------------------------------------------------
def load(filename="defaultshelve",key="defaultkey"):
"""
Load from Disc
"""
try:
with shelve.open(filename) as s:
return s[key]
except:
print('ERROR: {}'.format(key))
return json.dumps({})
#------- testing goes here --------
stats = {"stats":{"LVL":10,"HP":300}}
giraffe = Monster(key="awesomekey",name="giraffe",**stats)
giraffe.update(**stats)
giraffe.addLoot(DynamicGameObject(**{"Id":genkey(),"name":"grass","count":10}))
giraffe.addLoot(DynamicGameObject(**{"Id":genkey(),"name":"water","count":5,"stacksize":20}))
save( data = json.dumps(giraffe.dumps()) )
tmp = json.loads(load())
cat = Monster(**tmp)
cat.update(**{"key":"123","state":"sleeping","name":"cat"})
print("\n--print object--------------------------------------\n")
print(giraffe)
print("---")
print(cat)
print("\n--print dump from object--------------------------------------\n")
print(giraffe.dumps())
print("---")
print(cat.dumps())