source: trunk/PARPG/scripts/engine.py @ 69

Revision 69, 7.0 KB checked in by maximinus_parpg, 11 years ago (diff)

Started incrementing object complexity.
Now you can map or non map objects.

Line 
1#!/usr/bin/python
2
3#   This file is part of PARPG.
4
5#   PARPG is free software: you can redistribute it and/or modify
6#   it under the terms of the GNU General Public License as published by
7#   the Free Software Foundation, either version 3 of the License, or
8#   (at your option) any later version.
9
10#   PARPG is distributed in the hope that it will be useful,
11#   but WITHOUT ANY WARRANTY; without even the implied warranty of
12#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13#   GNU General Public License for more details.
14
15#   You should have received a copy of the GNU General Public License
16#   along with PARPG.  If not, see <http://www.gnu.org/licenses/>.
17
18# there should be NO references to FIFE here!
19from xml.sax import make_parser
20from xml.sax.handler import ContentHandler
21from agents.hero import Hero
22from agents.npc import NPC
23from objects import GameObject
24
25# design note:
26# there is a map file that FIFE reads. We use that file for half the map
27# format because the map editor in FIFE uses it, and secondly because it
28# save us writing a bunch of new code.
29# However, the objects and characters on a map are liable to change
30# whilst the game is being run, so when we change the map, we need to
31# to grab the objects and npc data EITHER from the engine state, or grab
32# from another file if in their initial state
33# This other file has the name AAA_objects.xml where AAA.xml is the name
34# of the original mapfile.
35
36class LocalXMLParser(ContentHandler):
37    """Class inherits from ContantHandler, and is used to parse the
38       local objects data"""
39    def __init__(self):
40        self.search = "objects"
41        self.pc = None
42        self.objects = []
43        self.npcs = []
44   
45    def startElement(self, name, attrs):
46        """Called every time we meet a new element in the XML file"""
47        # we are only looking for the 'layer' elements, the rest we ignore
48        if(name == "PC"):
49            # already have a PC?
50            if(self.pc != None):
51                sys.stderr.write("Error: 2 PC characters defined")
52                sys.exit(False)
53            # grab the data and store that as well
54            try:
55                xpos = attrs.getValue("xpos")
56                ypos = attrs.getValue("ypos")
57            except(KeyError):
58                sys.stderr.write("Error: Data missing in PC definition")
59                sys.exit(False)
60            # store for later
61            self.pc=[xpos,ypos]
62        elif(name == "NPC"):
63            # let's parse and add the data
64            try:
65                xpos=attrs.getValue("xpos")
66                ypos = attrs.getValue("ypos")
67                gfx = attrs.getValue("gfx")
68                ident = attrs.getValue("id")
69                text = attrs.getValue("text")
70            except(KeyError):
71                sys.stderr.write("Error: Data missing in NPC definition\n")
72                sys.exit(False)
73            # now we have the data, save it for later
74            self.npcs.append([xpos, ypos, gfx, ident, text])
75        elif(name == "object"):
76            # same old same old
77            try:
78                display = attrs.getValue("display")
79                if(display == "True"):
80                    xpos = attrs.getValue("xpos")
81                    ypos = attrs.getValue("ypos")
82                    gfx = attrs.getValue("gfx")
83                else:
84                    owner = attrs.getValue("owner")
85                ident = attrs.getValue("id")
86                text = attrs.getValue("text")
87            except(KeyError):
88                sys.stderr.write("Error: Data missing in object definition\n")
89                sys.exit(False)
90            # now we have the data, save it for later
91            if(display == "True"):
92                self.objects.append([True, xpos, ypos, gfx, ident, text])
93            else:
94                self.objects.append([False, gfx, ident, text])
95
96class Engine:
97    """Engine holds the logic for the game
98       Since some data (object position and so forth) is held in the
99       fife, and would be pointless to replicate, we hold a instance of
100       the fife view here. This also prevents us from just having a
101       function heavy controller"""
102    def __init__(self, view):
103        self.view = view
104        self.PC = None
105        self.npcs = []
106        self.objects = []
107
108    def loadObjects(self, filename):
109        """Load objects from the XML file
110           Returns True if it worked, False otherwise"""
111        try:
112            objects_file = open(filename, 'rt')
113        except(IOError):
114            sys.stderr.write("Error: Can't find objects file\n")
115            return False
116        # now open and read the XML file
117        parser = make_parser()
118        cur_handler = LocalXMLParser()
119        parser.setContentHandler(cur_handler)
120        parser.parse(objects_file)
121        objects_file.close()
122        # must have at least 1 PC
123        if(cur_handler.pc == None):
124            sys.stderr.write("Error: No PC defined\n")
125            sys.exit(False)
126        # now add to the map and the engine
127        self.addPC(cur_handler.pc)
128        self.addNPCs(cur_handler.npcs)
129        self.addObjects(cur_handler.objects)
130        return True
131
132    def addPC(self,pc):
133        """Add the PC to the world"""
134        self.view.addObject(float(pc[0]), float(pc[1]),"PC")
135        self.PC = Hero("PC", self.view.agent_layer)
136        # ensure the PC starts on a default action
137        self.PC.start()
138        self.view.addPC(self.PC.agent)
139
140    def addObjects(self,objects):
141        """Add all of the objects we found into the fife map
142           and into our class
143           An NPC is just an object to FIFE"""
144        for i in objects:
145            if(i[0] == True):
146                self.view.addObject(float(i[1]), float(i[2]), i[3])
147                # now add it as an engine object
148                self.objects.append(GameObject(i)
149
150    def addNPCs(self,npcs):
151        """Add all of the NPCs we found into the fife map
152           and into this class"""
153        for i in npcs:
154            self.view.addObject(float(i[0]), float(i[1]), i[2])
155            # now add as engine data
156            self.npcs.append(NPC(int(float(i[0])), int(float(i[1])),
157                                 i[3], i[4]))
158
159    def getObjectString(self, xpos, ypos):
160        """Get the objects description of itself"""
161        # cycle through all of the objects; do we have something there?
162        for i in self.objects:
163            if((xpos == i.xpos)and(ypos == i.ypos)):
164                # yes, we have a match, so return the text
165                return i.text
166        for i in self.npcs:
167            if((xpos == i.xpos)and(ypos == i.ypos)):
168                # yes, we have a match, so return the text
169                return i.text
170        # nothing, but return the empty string in case we print it
171        return ""
172
173    def loadMap(self,map_file):
174        """Load a new map
175           TODO: needs some error checking"""
176        # first we let FIFE load the rest of the map
177        self.view.load(map_file)
178        # then we update FIFE with the PC, NPC and object details
179        self.loadObjects(map_file[:-4]+"_objects.xml")
180
181    def handleMouseClick(self,position):
182        self.PC.run(position)
183
Note: See TracBrowser for help on using the repository browser.