Mercurial > fife-parpg
changeset 543:cb7ec12214a9
Items can now be serialized/deserialized to/from disk. I haven't finished actors yet. This allows for persistent states when you enter/leave maps.
author | prock@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Wed, 02 Jun 2010 21:43:03 +0000 |
parents | 67f6f3538e88 |
children | c9bdf145069f |
files | demos/rpg/maps/level1.xml demos/rpg/maps/town.xml demos/rpg/scripts/actors/baseactor.py demos/rpg/scripts/actors/player.py demos/rpg/scripts/actors/questgiver.py demos/rpg/scripts/gamecontroller.py demos/rpg/scripts/objects/baseobject.py demos/rpg/scripts/objects/items.py demos/rpg/scripts/rpg.py demos/rpg/scripts/scene.py engine/python/fife/extensions/fife_settings.py |
diffstat | 11 files changed, 204 insertions(+), 67 deletions(-) [+] |
line wrap: on
line diff
--- a/demos/rpg/maps/level1.xml Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/maps/level1.xml Wed Jun 02 21:43:03 2010 +0000 @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="ascii"?> <map id="level1" format="1.0"> <import file="../objects/ground/grass/01/object.xml"></import> - <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_only" grid_type="square" id="ground_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> + <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_and_diagonals" grid_type="square" id="ground_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> <instances> <i o="grass:01" ns="http://www.fifengine.de/xml/rpg" x="-2.0" r="0" y="0.0" z="0.0"></i> <i r="0" x="-2.0" o="grass:01" z="0.0" y="1.0"></i> @@ -149,11 +149,11 @@ <i r="0" x="4.0" o="grass:01" z="0.0" y="8.0"></i> </instances> </layer> - <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_only" grid_type="square" id="item_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> + <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_and_diagonals" grid_type="square" id="item_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> <instances> </instances> </layer> - <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_only" grid_type="square" id="actor_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> + <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_and_diagonals" grid_type="square" id="actor_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> <instances> </instances> </layer>
--- a/demos/rpg/maps/town.xml Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/maps/town.xml Wed Jun 02 21:43:03 2010 +0000 @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="ascii"?> <map id="maintown" format="1.0"> <import file="../objects/ground/grass/01/object.xml"></import> - <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_only" grid_type="square" id="ground_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> + <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_and_diagonals" grid_type="square" id="ground_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> <instances> <i o="grass:01" ns="http://www.fifengine.de/xml/rpg" x="-2.0" r="0" y="0.0" z="0.0"></i> <i r="0" x="-2.0" o="grass:01" z="0.0" y="1.0"></i> @@ -149,11 +149,11 @@ <i r="0" x="4.0" o="grass:01" z="0.0" y="8.0"></i> </instances> </layer> - <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_only" grid_type="square" id="item_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> + <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_and_diagonals" grid_type="square" id="item_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> <instances> </instances> </layer> - <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_only" grid_type="square" id="actor_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> + <layer y_scale="1.0" y_offset="0.0" pathing="cell_edges_and_diagonals" grid_type="square" id="actor_layer" rotation="0.0" x_scale="1.0" x_offset="0.0" transparency="0"> <instances> </instances> </layer>
--- a/demos/rpg/scripts/actors/baseactor.py Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/scripts/actors/baseactor.py Wed Jun 02 21:43:03 2010 +0000 @@ -30,6 +30,7 @@ from fife.extensions.loaders import loadMapFile from scripts.objects.baseobject import ObjectActionListener, BaseGameObject, GameObjectTypes +from scripts.objects.items import GoldStack Actions = {'NONE':0, 'PICKUP':1, @@ -95,8 +96,10 @@ self._object.performNextAction() class Actor(BaseGameObject): - def __init__(self, gamecontroller, actortype, instancename, instanceid=None, createInstance=False): - super(Actor, self).__init__(gamecontroller, actortype, instancename, instanceid, createInstance) + def __init__(self, gamecontroller, layer, typename, instancename, instanceid=None, createInstance=False): + super(Actor, self).__init__(gamecontroller, layer, typename, instancename, instanceid, createInstance) + + self._type = GameObjectTypes["DEFAULT"] self._walkspeed = self._gamecontroller.settings.get("RPG", "DefaultActorWalkSpeed", 4.0) @@ -128,12 +131,12 @@ if len(self._inventory) >= self._maxinventoryitems: return else: - if item.modelname == "goldstack": + if type(item) == GoldStack: self._gold += item.value else: self._inventory.append(item) - item.onLeftClick() + item.onPickUp() def enterPortal(self, portal): if self._id == "player":
--- a/demos/rpg/scripts/actors/player.py Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/scripts/actors/player.py Wed Jun 02 21:43:03 2010 +0000 @@ -40,8 +40,10 @@ pass class Player(Actor): - def __init__(self, gamecontroller, playermodelname): - super(Player, self).__init__(gamecontroller, GameObjectTypes["PLAYER"], playermodelname, "player", True) + def __init__(self, gamecontroller, layer, playermodelname): + super(Player, self).__init__(gamecontroller, layer, "Player", playermodelname, "player", True) + self._type = GameObjectTypes["PLAYER"] + self._playermodelname = playermodelname self._actionlistener = PlayerActionListener(self._gamecontroller, self)
--- a/demos/rpg/scripts/actors/questgiver.py Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/scripts/actors/questgiver.py Wed Jun 02 21:43:03 2010 +0000 @@ -32,8 +32,9 @@ from scripts.actors.baseactor import Actor class QuestGiver(Actor): - def __init__(self, gamecontroller, instancename, instanceid=None, createInstance=False): - super(QuestGiver, self).__init__(gamecontroller, GameObjectTypes["QUESTGIVER"], instancename, instanceid, createInstance) + def __init__(self, gamecontroller, layer, typename, instancename, instanceid=None, createInstance=False): + super(QuestGiver, self).__init__(gamecontroller, layer, typename, instancename, instanceid, createInstance) + self._type = GameObjectTypes["QUESTGIVER"] self._quests = []
--- a/demos/rpg/scripts/gamecontroller.py Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/scripts/gamecontroller.py Wed Jun 02 21:43:03 2010 +0000 @@ -24,7 +24,7 @@ # #################################################################### # This is the rio de hola client for FIFE. -import sys, os, re, math, random, shutil +import sys, os, re, math, random, shutil, glob from fife import fife @@ -258,6 +258,9 @@ def newGame(self): self._guicontroller.hideMainMenu() + for filename in glob.glob("saves\*.xml"): + os.remove(filename) + mapname = self._settings.get("RPG", "TownMapFile", "town") self.loadMap(mapname) @@ -273,7 +276,8 @@ self._scene = None self._scene = Scene(self) - self._scene.createScene("maps/" + mapname + ".xml") + + self._scene.createScene(mapname) self._instancerenderer = fife.InstanceRenderer.getInstance(self._scene.cameras[self._settings.get("RPG", "DefaultCameraName", "camera1")]) self._floatingtextrenderer = fife.FloatingTextRenderer.getInstance(self._scene.cameras[self._settings.get("RPG", "DefaultCameraName", "camera1")]) @@ -285,9 +289,13 @@ def switchMap(self, newmapname): self._switchmaprequested = True self._newmap = newmapname + + self._scene.serialize() def endGame(self): if self._scene: + self._scene.serialize() + self._listener.detach() self._scene.destroyScene() self._scene = None
--- a/demos/rpg/scripts/objects/baseobject.py Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/scripts/objects/baseobject.py Wed Jun 02 21:43:03 2010 +0000 @@ -39,6 +39,16 @@ "GOLD":6, "PORTAL":7 } + +def getModuleByType(objtype): + if objtype == GameObjectTypes["ITEM"] or objtype == GameObjectTypes["GOLD"] or objtype == GameObjectTypes["PORTAL"]: + module = "items" + elif objtype == GameObjectTypes["QUESTGIVER"] or objtype == GameObjectTypes["ENEMY"]: + module = "npcs" + else: + module = "unknown" + + return module class ObjectActionListener(fife.InstanceActionListener): def __init__(self, gamecontroller, obj): @@ -57,7 +67,7 @@ class BaseGameObject(object): - def __init__(self, gamecontroller, objtype, instancename, instanceid=None, createInstance=False): + def __init__(self, gamecontroller, layer, typename, instancename, instanceid=None, createInstance=False): """ @param gamecontroller: A reference to the master game controller @param instancename: The name of the object to load. The object's XML file must @@ -70,6 +80,8 @@ """ self._gamecontroller = gamecontroller self._fifeobject = None + + self._typename = typename self._name = instancename if instanceid: self._id = instanceid @@ -81,18 +93,14 @@ self._actionlistener = None - self._type = objtype + self._type = GameObjectTypes["DEFAULT"] + + self._layer = layer if createInstance: - if self._type == GameObjectTypes["ITEM"] or self._type == GameObjectTypes["PORTAL"]: - self._layer = self._gamecontroller.scene.itemlayer - else: - self._layer = self._gamecontroller.scene.actorlayer - self._createFIFEInstance(self._layer) else: - self._instance = self._layer.getInstance(self._id) - self._instance.thisown = 0 + self._instance = None self._activated = True @@ -119,6 +127,26 @@ curloc.setExactLayerCoordinates(self._position) self.location = curloc + + def serialize(self, settings): + lvars = {} + lvars['posx'] = self._position.x + lvars['posy'] = self._position.y + lvars['typename'] = self._typename + + module = getModuleByType(self._type) + + settings.set(module, self._id, lvars) + + def deserialize(self, settings): + module = getModuleByType(self._type) + + lvars = settings.get(module, self._id, {}) + + x = float(lvars['posx']) + y = float(lvars['posy']) + + self.setMapPosition(x,y) def _createFIFEInstance(self, layer): """ @@ -134,6 +162,14 @@ self.setMapPosition(self._position.x,self._position.y) + def _findFIFEInstance(self, layer): + """ + @todo: throw InstanceNotFoundError + """ + self._instance = self._layer.getInstance(self._id) + if self._instance: + self._instance.thisown = 0 + def _getLocation(self): return self._instance.getLocation()
--- a/demos/rpg/scripts/objects/items.py Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/scripts/objects/items.py Wed Jun 02 21:43:03 2010 +0000 @@ -28,23 +28,12 @@ from fife import fife -from scripts.objects.baseobject import BaseGameObject, GameObjectTypes +from scripts.objects.baseobject import BaseGameObject, GameObjectTypes, getModuleByType class BaseItem(BaseGameObject): - def __init__(self, gamecontroller, objtype, itemtype, itemname): - super(BaseItem, self).__init__(gamecontroller, objtype, itemtype, itemname, True) - - def onLeftClick(self): - #remove item from the scene - self._gamecontroller.scene.removeObjectFromScene(self) - - def onDrop(self, dropx, dropy): - #recreate object - self._createFIFEInstance(self, self._gamecontroller.scene.itemlayer) - self.setMapPosition(dropx, dropy) - - self._gamecontroller.scene.addObjectToScene(self) + def __init__(self, gamecontroller, layer, typename, itemtype, itemname): + super(BaseItem, self).__init__(gamecontroller, layer, typename, itemtype, itemname, True) def _getItemType(self): return self._name @@ -54,13 +43,48 @@ itemtype = property(_getItemType) itemname = property(_getItemName) + +class PickableItem(BaseItem): + def __init__(self, gamecontroller, layer, typename, itemtype, itemname): + super(PickableItem, self).__init__(gamecontroller, layer, typename, itemtype, itemname) + self._type = GameObjectTypes["ITEM"] + + def onPickUp(self): + #remove item from the scene + self._gamecontroller.scene.removeObjectFromScene(self) -class GoldStack(BaseItem): - def __init__(self, gamecontroller, itemtype, itemname): - super(GoldStack, self).__init__(gamecontroller, GameObjectTypes["ITEM"], itemtype, itemname) + def onDrop(self, dropx, dropy): + #recreate object + self._createFIFEInstance(self, self._gamecontroller.scene.itemlayer) + self.setMapPosition(dropx, dropy) + + self._gamecontroller.scene.addObjectToScene(self) + +class GoldStack(PickableItem): + def __init__(self, gamecontroller, layer, typename, itemtype, itemname): + super(GoldStack, self).__init__(gamecontroller, layer, typename, itemtype, itemname) self._value = 0 + def serialize(self, settings): + super(GoldStack, self).serialize(settings) + + module = getModuleByType(self._type) + + lvars = settings.get(module, self._id, {}) + lvars['value'] = self._value + + settings.set(module, self._id, lvars) + + def deserialize(self, settings): + super(GoldStack, self).deserialize(settings) + + module = getModuleByType(self._type) + + lvars = settings.get(module, self._id, {}) + + self._value = int(lvars['value']) + def _getValue(self): return self._value @@ -70,14 +94,31 @@ value = property(_getValue, _setValue) class Portal(BaseItem): - def __init__(self, gamecontroller, itemtype, itemname): - super(Portal, self).__init__(gamecontroller, GameObjectTypes["PORTAL"], itemtype, itemname) + def __init__(self, gamecontroller, layer, typename, itemtype, itemname): + super(Portal, self).__init__(gamecontroller, layer, typename, itemtype, itemname) + self._type = GameObjectTypes["PORTAL"] self._dest = None + + def serialize(self, settings): + super(Portal, self).serialize(settings) - def onLeftClick(self): - pass + module = getModuleByType(self._type) + + lvars = settings.get(module, self._id, {}) + lvars['dest'] = self._dest + settings.set(module, self._id, lvars) + + def deserialize(self, settings): + super(Portal, self).deserialize(settings) + + module = getModuleByType(self._type) + + lvars = settings.get(module, self._id, {}) + + self._dest = lvars['dest'] + def _getDest(self): return self._dest
--- a/demos/rpg/scripts/rpg.py Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/scripts/rpg.py Wed Jun 02 21:43:03 2010 +0000 @@ -89,6 +89,7 @@ self.quit = (command.getCommandType() == fife.CMD_QUIT_GAME) if self.quit: command.consume() + self._gamecontroller.endGame() def onConsoleCommand(self, command): result = "" @@ -149,7 +150,6 @@ def _pump(self): if self._listener.quit: self.breakRequested = True - self._gamecontroller.endGame() else: self._gamecontroller.pump()
--- a/demos/rpg/scripts/scene.py Tue Jun 01 21:38:14 2010 +0000 +++ b/demos/rpg/scripts/scene.py Wed Jun 02 21:43:03 2010 +0000 @@ -35,7 +35,7 @@ from scripts.actors.questgiver import QuestGiver from scripts.quests.basequest import Quest, ReturnItemQuest, QuestTypes from scripts.actors.player import Player -from scripts.objects.baseobject import GameObjectTypes +from scripts.objects.baseobject import GameObjectTypes, getModuleByType from scripts.objects.items import BaseItem, GoldStack, Portal from scripts.misc.exceptions import ObjectNotFoundError, ObjectAlreadyInSceneError @@ -60,20 +60,20 @@ try: itemdict = self._objectsettings.get("items", itemid, {}) modeldict = self._modelsettings.get("models", itemdict["typename"], {}) - + print itemdict + print modeldict loadImportFile(modeldict["file"], self._gamecontroller.engine) if modeldict["type"] == "GOLD": - newitem = GoldStack(self._gamecontroller, modeldict["model"], itemid) + newitem = GoldStack(self._gamecontroller, self.itemlayer, itemdict["typename"], modeldict["model"], itemid) newitem.value = itemdict["value"] elif modeldict["type"] == "PORTAL": - print "portal" - newitem = Portal(self._gamecontroller, modeldict["model"], itemid) + newitem = Portal(self._gamecontroller, self.itemlayer, itemdict["typename"], modeldict["model"], itemid) newitem.dest = itemdict["dest"] else: - newitem = BaseItem(self._gamecontroller, modeldict["model"], itemid) + newitem = BaseItem(self._gamecontroller, self.itemlayer, itemdict["typename"], modeldict["model"], itemid) - newitem.setMapPosition(float(itemdict["posx"]), float(itemdict["posy"])) + newitem.deserialize(self._objectsettings) except KeyError, e: raise ObjectNotFoundError @@ -88,7 +88,7 @@ loadImportFile(modeldict["file"], self._gamecontroller.engine) if modeldict["type"] == "QUESTGIVER": - actor = QuestGiver(self._gamecontroller, modeldict["model"], actorid, True) + actor = QuestGiver(self._gamecontroller, self.actorlayer, objdict["typename"], modeldict["model"], actorid, True) questcount = self._modelsettings.get(actorid, "questcount", 0) for x in range(1,questcount+1): quest = "quest" + str(x) @@ -107,7 +107,7 @@ actor.addQuest(quest) elif modeldict["type"] == "NPC": - actor = Actor(self._gamecontroller, modeldict["model"], npc, True) + actor = Actor(self._gamecontroller, self.actorlayer, objdict["typename"], modeldict["model"], npc, True) actor.setMapPosition(float(objdict["posx"]), float(objdict["posy"])) @@ -129,6 +129,7 @@ self.addObjectToScene(newitem) except ObjectAlreadyInSceneError, e: self._gamecontroller.logger.log_error("Item already part of scene: " + newitem) + continue def loadActors(self, mapfilename): for npc in self._objectsettings.get("npcs", "npclist", []): @@ -143,6 +144,7 @@ self.addObjectToScene(actor) except ObjectAlreadyInSceneError, e: self._gamecontroller.logger.log_error("Actor already part of scene:" + actor) + continue def createPlayerObject(self): """ @@ -151,18 +153,32 @@ modeldict = self._modelsettings.get("models", "Player", {}) loadImportFile(modeldict["file"], self._gamecontroller.engine) - self._player = Player(self._gamecontroller, "warrior") + self._player = Player(self._gamecontroller, self.actorlayer, "warrior") + + playerfilename = os.path.join("saves", "player_save.xml") + + if os.path.isfile(playerfilename): + player_settings = Setting(settings_file=playerfilename, copy_dist=False) + self._player.deserialize(player_settings) - def createScene(self, mapfilename): + def createScene(self, mapname): + mapfilename = os.path.join("maps", mapname + ".xml") + if self._map: self.destroyScene() self._map = loadMapFile(mapfilename, self._gamecontroller.engine) - self._mapname = os.path.splitext(os.path.basename(mapfilename))[0] - objectfile = "maps/" + self._mapname + "_objects.xml" + self._mapname = mapname + + if os.path.isfile(os.path.join("saves", mapname + "_save.xml")): + objectfile = os.path.join("saves", mapname + "_save.xml") + else: + objectfile = os.path.join("maps", mapname + "_objects.xml") + modelfile = self._gamecontroller.settings.get("RPG", "AllObjectFile", "maps/allobjects.xml") + print objectfile self._objectsettings = Setting(app_name="",settings_file=objectfile) self._modelsettings = Setting(app_name="", settings_file=modelfile) @@ -242,6 +258,34 @@ def removeObjectFromScene(self, obj): obj.destroy() del self._objectlist[obj.id] + + def serialize(self): + filename = os.path.join("saves", self._mapname + "_save.xml") + playerfilename = os.path.join("saves", "player_save.xml") + settings = Setting(settings_file=filename, copy_dist=False) + player_settings = Setting(settings_file=playerfilename, copy_dist=False) + + itemlist = [] + npclist = [] + + for obj in self._objectlist.values(): + obj.serialize(settings) + module = getModuleByType(obj.type) + if module == "items": + itemlist.append(obj.id) + elif module == "npcs": + npclist.append(obj.id) + + settings.set("items", "itemlist", itemlist) + settings.set("npcs", "npclist", npclist) + + self._player.serialize(player_settings) + + settings.saveSettings() + player_settings.saveSettings() + + def deserialize(self): + pass def updateScene(self): pass @@ -263,6 +307,9 @@ def _getMap(self): return self._map + + def _getMapName(self): + return self._mapname actorlayer = property(_getActorLayer) itemlayer = property(_getItemLayer) @@ -270,4 +317,5 @@ player = property(_getPlayer) objectlist = property(_getObjectList) map = property(_getMap) + mapname = property(_getMapName)
--- a/engine/python/fife/extensions/fife_settings.py Tue Jun 01 21:38:14 2010 +0000 +++ b/engine/python/fife/extensions/fife_settings.py Wed Jun 02 21:43:03 2010 +0000 @@ -81,9 +81,6 @@ EMPTY_SETTINGS="""\ <?xml version='1.0' encoding='UTF-8'?> <Settings> - <Module name="FIFE"> - - </Module> </Settings> """ @@ -101,7 +98,7 @@ screen_height = settings.get("FIFE", "ScreenHeight", 768) """ - def __init__(self, app_name="", settings_file="", settings_gui_xml="", changes_gui_xml=""): + def __init__(self, app_name="", settings_file="", settings_gui_xml="", changes_gui_xml="", copy_dist=True): """ Initializes the Setting object. @@ -115,8 +112,8 @@ @type settings_file: C{string} @param settings_gui_xml: If you specify this parameter you can customize the look of the settings dialog box. - @note: As of now you MUST have all the elements of the default settings dialog box. - At some point we may make it customizable. + @param copy_dist: Copies the settings-dist.xml file to the settings_file location. If + this is False it will create a new empty xml file. """ self._app_name = app_name @@ -140,7 +137,7 @@ if not os.path.exists(os.path.join(self._appdata, self._settings_file)): - if os.path.exists('settings-dist.xml'): + if os.path.exists('settings-dist.xml') and copy_dist: shutil.copyfile('settings-dist.xml', os.path.join(self._appdata, self._settings_file)) else: #no settings file found @@ -204,6 +201,7 @@ def loadSettings(self): self._tree = ET.parse(os.path.join(self._appdata, self._settings_file)) + self._root_element = self._tree.getroot() self.validateTree()