source: trunk/game/scripts/world.py @ 264

Revision 264, 10.6 KB checked in by Kaydeth_parpg, 10 years ago (diff)

Ticket #72: Patch by Kaydeth. The separate objects file was merged back into the main map file that FIFE parses to load each Map. The Map, Engine, and World classes were all updated to allow game object creation to happen as the map file is loaded. loaders.py and xmlmap.py were copied from the FIFE code base and made local so that we can now customize how we pass the parsed map and object information to FIFE.

  • Property svn:eol-style set to native
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
18import fife, time
19import pychan
20from sounds import SoundEngine
21from datetime import date
22from scripts.common.eventlistenerbase import EventListenerBase
23from local_loaders.loaders import loadMapFile
24from sounds import SoundEngine
25from settings import Setting
26from scripts import inventory, hud
27from scripts.popups import *
28from pychan.tools import callbackWithArguments as cbwa
29from map import Map
30
31TDS = Setting()
32
33# this file should be the meta-file for all FIFE-related code
34# engine.py handles is our data model, whilst this is our view
35# in order to not replicate data, some of our data model will naturally
36# reside on this side of the fence (PC xpos and ypos, for example).
37# we should aim to never replicate any data as this leads to maintainance
38# issues (and just looks plain bad).
39# however, any logic needed to resolve this should sit in engine.py
40
41class World(EventListenerBase):
42    """World holds the data needed by fife to render the engine
43       The engine keeps a copy of this class"""
44    def __init__(self, engine):
45        """Constructor for engine
46           @type engine: fife.Engine
47           @param engine: A fife.Engine instance
48           @return: None"""
49        super(World, self).__init__(engine, regMouse = True, regKeys = True)
50        # self.engine is a fife.Engine object, not an Engine object
51        self.engine = engine
52        self.eventmanager = engine.getEventManager()
53        self.quitFunction = None
54       
55        # self.data is an engine.Engine object, but is set in run.py
56        self.data = None
57        self.mouseCallback = None
58        self.obj_hash={}
59        # self.map is a Map object, set to none here
60        self.activeMap = None
61        self.maps = {}
62        self.hud = hud.Hud(self.engine, self, TDS)
63
64        self.action_number = 1
65        # setup the inventory
66        # make slot 'A1' and 'A3' container daggers
67        inv_data = {'A1':'dagger01', 'A3':'dagger01'}
68        self.inventory = inventory.Inventory(self.engine, inv_data, self.hud.refreshReadyImages, self.hud.toggleInventoryButton)
69        self.hud.refreshReadyImages()
70       
71        self.boxOpen = False
72        self.boxCreated = False
73       
74        # init the sound
75        self.sounds = SoundEngine(engine)
76       
77        # don't force restart if skipping to new section
78        if (TDS.readSetting("PlaySounds") == "1"):
79            if(self.sounds.music_init == False):
80                self.sounds.playMusic("/music/preciouswasteland.ogg")
81               
82    def saveFunction(self, *args, **kwargs):
83        """Callback for save game
84           @return: None"""
85        self.data.save(*args, **kwargs)
86
87    def loadFunction(self, *args, **kwargs):
88        """Callback for load game
89           @return: None"""
90        self.data.load(*args, **kwargs)
91
92    def loadMap(self, mapname, filename):
93        """Loads a map an stores it under the given name in the maps list.
94        """
95        map = Map(self.engine, self.data)
96       
97        """Need to set active map before we load it because the map
98        loader uses call backs that expect to find an active map.
99        This needs to be reworked.
100        """
101        self.maps[mapname] = map
102        self.setActiveMap(mapname)
103
104        map.load(filename)
105
106   
107    def setActiveMap(self, mapname):
108        """Sets the active map that is to be rendered.
109        """
110        self.activeMap = self.maps[mapname]
111        self.activeMap.makeActive()
112
113    def displayObjectText(self, obj, text):
114        """Display on screen the text of the object over the object.
115           @type obj: fife.instance
116           @param obj: object to draw over
117           @type text: text
118           @param text: text to display over object
119           @return: None"""
120        obj.say(str(text), 1000)
121
122    # all key / mouse event handling routines go here
123    def keyPressed(self, evt):
124        """Whenever a key is pressed, fife calls this routine.
125           @type evt: fife.event
126           @param evt: The event that fife caught
127           @return: None"""
128        key = evt.getKey()
129        keyval = key.getValue()
130
131        if(keyval == key.Q):
132            # we need to quit the game
133            self.hud.quitGame()
134        if(keyval == key.T):
135            self.activeMap.toggle_renderer('GridRenderer')
136        if(keyval == key.F1):
137            # display the help screen and pause the game
138            self.hud.displayHelp()
139        if(keyval == key.F5):
140            # logic would say we use similar code to above and toggle
141            # logic here does not work, my friend :-(
142            self.cord_render.setEnabled(not self.cord_render.isEnabled())
143        if(keyval == key.F7):
144            # F7 saves a screenshot to fife/clients/parpg/screenshots
145            t = "screenshots/screen-%s-%s.png" % (date.today().strftime('%Y-%m-%d'),
146                                                  time.strftime('%H-%M-%S'))
147            print "PARPG: Saved:",t
148            self.engine.getRenderBackend().captureScreen(t)
149        if(keyval == key.F10):
150            # F10 shows/hides the console
151            self.engine.getGuiManager().getConsole().toggleShowHide()
152        if(keyval == key.I):
153            # I opens and closes the inventory
154            self.hud.displayInventory(callFromHud=False)
155        if(keyval == key.A):
156            # A adds a test action to the action box
157            # The test actions will follow this format: Action 1, Action 2, etc.
158            self.hud.addAction("Action " + str(self.action_number))
159            self.action_number += 1
160        if(keyval == key.ESCAPE):
161            # Escape brings up the main menu
162            self.hud.displayMenu()
163        if(keyval == key.M):
164            self.sounds.toggleMusic()
165
166    def mouseReleased(self, evt):
167        """If a mouse button is released, fife calls this routine.
168           We want to wait until the button is released, because otherwise
169           pychan captures the release if a menu is opened.
170           @type evt: fife.event
171           @param evt: The event that fife caught
172           @return: None"""
173        self.hud.context_menu.hide() # hide the context menu in case it is displayed
174        scr_point = fife.ScreenPoint(evt.getX(), evt.getY())
175        if(evt.getButton() == fife.MouseEvent.LEFT):
176            self.data.handleMouseClick(self.getCoords(scr_point))     
177        elif(evt.getButton() == fife.MouseEvent.RIGHT):
178            # is there an object here?
179            instances = self.activeMap.cameras['main'].getMatchingInstances(scr_point, self.activeMap.agent_layer)
180            info = None
181            for inst in instances:
182                # check to see if this is an active item
183                if(self.data.objectActive(inst.getId())):           
184                    # yes, get the data
185                    info = self.data.getItemActions(inst.getId())
186                    break
187               
188            # take the menu items returned by the engine or show a default menu if no items   
189            data = info or [["Walk", "Walk here", self.onWalk, self.getCoords(scr_point)]]
190            # show the menu
191            self.hud.showContextMenu(data, (scr_point.x, scr_point.y))
192
193    def onWalk(self, click):
194        """Callback sample for the context menu.
195        """
196        self.hud.context_menu.hide()
197        self.data.gameState.PC.run(click)
198
199    def mouseMoved(self, evt):
200        """Called when the mouse is moved
201           @type evt: fife.event
202           @param evt: The event that fife caught
203           @return: None"""
204        click = fife.ScreenPoint(evt.getX(), evt.getY())
205        i=self.activeMap.cameras['main'].getMatchingInstances(click, self.activeMap.agent_layer)
206        # no object returns an empty tuple
207        if(i != ()):
208            for obj in i:
209                # check to see if this in our list at all
210                if(self.data.objectActive(obj.getId())):
211                    # yes, so outline
212                    self.activeMap.outline_render.addOutlined(obj, 0, 137, 255, 2)
213                    # get the text
214                    item = self.data.objectActive(obj.getId())
215                    if(item):
216                        self.displayObjectText(obj, item.name)
217        else:
218            # erase the outline
219            self.activeMap.outline_render.removeAllOutlines()
220
221    def getCoords(self, click):
222        """Get the map location x, y cords from the screen co-ords
223           @type click: fife.ScreenPoint
224           @param click: Screen co-ords
225           @rtype: fife.Location
226           @return: The map co-ords"""
227        coord = self.activeMap.cameras["main"].toMapCoordinates(click, False)
228        coord.z = 0
229        location = fife.Location(self.activeMap.agent_layer)
230        location.setMapCoordinates(coord)
231        return location
232
233    def createBoxGUI(self, title):
234        """
235        Creates a window to display the contents of a box
236
237        @type title: string
238        @param title: The title for the window
239        @return: None
240        """
241        if ((self.boxCreated == True) and (self.boxOpen == False)):
242            # if it has already been created, just show it
243            self.box_container.showContainer()
244            self.boxOpen = True
245        else:
246            # otherwise create it then show it
247            data = ["dagger01", "empty", "empty", "empty", "empty",
248                    "empty", "empty", "empty", "empty"]
249            self.box_container = ContainerGUI(self.engine, unicode(title), data)
250            def close_and_delete():
251                self.box_container.hideContainer()
252                self.boxOpen = False
253            events = {'takeAllButton':close_and_delete,
254                      'closeButton':close_and_delete}
255            self.box_container.container_gui.mapEvents(events)
256            self.box_container.showContainer()
257            self.boxOpen = True
258            self.boxCreated = True
259
260    def createExamineBox(self, title, desc):
261        self.examineBox = ExaminePopup(self.engine, title, desc)
262        self.examineBox.showPopUp()
263
264    def pump(self):
265        """Routine called during each frame. Our main loop is in ./run.py
266           We ignore this main loop (but FIFE complains if it is missing)."""
267        pass
Note: See TracBrowser for help on using the repository browser.