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

Revision 484, 14.3 KB checked in by b0rland_parpg, 10 years ago (diff)

Updated to accomodate for new FIFE release -- remove references to view.

  • 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 time
19import fife
20from fife.extensions import pychan
21from sounds import SoundEngine
22from datetime import date
23from scripts.common.eventlistenerbase import EventListenerBase
24from local_loaders.loaders import loadMapFile
25from sounds import SoundEngine
26from settings import Setting
27from scripts.gui import hud
28from scripts.gui.popups import *
29from fife.extensions.pychan.tools import callbackWithArguments as cbwa
30from map import Map
31
32TDS = Setting()
33
34# this file should be the meta-file for all FIFE-related code
35# engine.py handles is our data model, whilst this is our view
36# in order to not replicate data, some of our data model will naturally
37# reside on this side of the fence (PC xpos and ypos, for example).
38# we should aim to never replicate any data as this leads to maintenance
39# issues (and just looks plain bad).
40# however, any logic needed to resolve this should sit in engine.py
41
42class World(EventListenerBase):
43    """World holds the data needed by fife to render the engine
44       The engine keeps a copy of this class"""
45    def __init__(self, engine):
46        """Constructor for engine
47           @type engine: fife.Engine
48           @param engine: A fife.Engine instance
49           @return: None"""
50        super(World, self).__init__(engine, reg_mouse=True, reg_keys=True)
51        # self.engine is a fife.Engine object, not an Engine object
52        self.engine = engine
53        self.event_manager = engine.getEventManager()
54        self.quitFunction = None
55
56        # self.data is an engine.Engine object, but is set in run.py
57        self.data = None
58        self.mouseCallback = None
59
60        # self.map is a Map object, set to none here
61        self.active_map = None
62        self.maps = {}
63
64        self.action_number = 1
65
66        # init the sound
67        self.sounds = SoundEngine(engine)
68
69        # don't force restart if skipping to new section
70        if TDS.readSetting("PlaySounds") == "1":
71            if not self.sounds.music_init:
72                self.sounds.playMusic("/music/preciouswasteland.ogg")
73
74        # The current highlighted object
75        self.highlight_obj = None
76       
77        # Last saved mouse coords
78        self.last_mousecoords = None
79
80        # faded objects in top layer
81        self.faded_objects = set()
82
83    def initHud(self):
84        """Initialize the hud member
85        @return: None"""
86        hud_callbacks = {
87            'saveGame': self.saveGame,
88            'loadGame': self.loadGame,
89            'quitGame': self.quitGame,
90        }
91        self.hud = hud.Hud(self.engine, TDS, self.data, hud_callbacks)
92   
93    def quitGame(self):
94        """Quits the game
95           @return: None"""
96        self.quitFunction()
97
98    def saveGame(self, *args, **kwargs):
99        """Saves the game state, delegates call to engine.Engine
100           @return: None"""
101        self.data.save(*args, **kwargs)
102
103    def loadGame(self, *args, **kwargs):
104        """Loads the game state, delegates call to engine.Engine
105           @return: None"""
106        self.data.load(*args, **kwargs)
107
108    def loadMap(self, map_name, filename):
109        """Loads a map and stores it under the given name in the maps list.
110           @type map_name: String
111           @param map_name: The name of the map to load
112           @type filename: String
113           @param filename: File which contains the map to be loaded
114           @return: None"""
115        if not map_name in self.maps:
116            map = Map(self.engine, self.data)
117            self.maps[map_name] = map
118            map.load(filename)
119        else:
120            self.setActiveMap(map_name)
121
122    def setActiveMap(self, map_name):
123        """Sets the active map that is to be rendered.
124           @type map_name: String
125           @param map_name: The name of the map to load
126           @return: None"""
127        # Turn off the camera on the old map before we turn on the camera
128        # on the new map.
129        self.active_map.cameras[self.active_map.my_cam_id].setEnabled(False)
130        # Make the new map active.
131        self.active_map = self.maps[map_name]
132        self.active_map.makeActive()
133
134    def displayObjectText(self, obj, text):
135        """Display on screen the text of the object over the object.
136           @type obj: fife.instance
137           @param obj: object to draw over
138           @type text: String
139           @param text: text to display over object
140           @return: None"""
141        obj.say(str(text), 1000)
142
143    def keyPressed(self, evt):
144        """Whenever a key is pressed, fife calls this routine.
145           @type evt: fife.event
146           @param evt: The event that fife caught
147           @return: None"""
148        key = evt.getKey()
149        key_val = key.getValue()
150
151        if(key_val == key.Q):
152            # we need to quit the game
153            self.hud.quitGame()
154        if(key_val == key.T):
155            self.active_map.toggleRenderer('GridRenderer')
156        if(key_val == key.F1):
157            # display the help screen and pause the game
158            self.hud.displayHelp()
159        if(key_val == key.F5):
160            self.active_map.toggleRenderer('CoordinateRenderer')
161        if(key_val == key.F7):
162            # F7 saves a screenshot to fife/clients/parpg/screenshots
163            t = "screenshots/screen-%s-%s.png" % \
164                    (date.today().strftime('%Y-%m-%d'),\
165                    time.strftime('%H-%M-%S'))
166            print "PARPG: Saved:",t
167            self.engine.getRenderBackend().captureScreen(t)
168        if(key_val == key.F10):
169            # F10 shows/hides the console
170            self.engine.getGuiManager().getConsole().toggleShowHide()
171        if(key_val == key.I):
172            # I opens and closes the inventory
173            self.hud.toggleInventory()
174        if(key_val == key.A):
175            # A adds a test action to the action box
176            # The test actions will follow this format: Action 1,
177            # Action 2, etc.
178            self.hud.addAction("Action " + str(self.action_number))
179            self.action_number += 1
180        if(key_val == key.ESCAPE):
181            # Escape brings up the main menu
182            self.hud.displayMenu()
183            # Hide the quit menu
184            self.hud.quit_window.hide()
185        if(key_val == key.M):
186            self.sounds.toggleMusic()
187        if(key_val == key.PAUSE):
188            # Pause pause/unpause the game
189            self.togglePause()
190
191    def mouseReleased(self, evt):
192        """If a mouse button is released, fife calls this routine.
193           We want to wait until the button is released, because otherwise
194           pychan captures the release if a menu is opened.
195           @type evt: fife.event
196           @param evt: The event that fife caught
197           @return: None"""
198        self.hud.hideContextMenu()
199        scr_point = fife.ScreenPoint(evt.getX(), evt.getY())
200        if(evt.getButton() == fife.MouseEvent.LEFT):
201            self.data.handleMouseClick(self.getCoords(scr_point))
202        elif(evt.getButton() == fife.MouseEvent.RIGHT):
203            # is there an object here?
204            instances = self.active_map.cameras[self.active_map.my_cam_id].\
205                            getMatchingInstances(scr_point, \
206                                                 self.active_map.agent_layer)
207            info = None
208            for inst in instances:
209                # check to see if this is an active item
210                if(self.data.objectActive(inst.getId())):
211                    # yes, get the data
212                    info = self.data.getItemActions(inst.getId())
213                    break
214
215            # take the menu items returned by the engine or show a
216            # default menu if no items
217            data = info or \
218                [["Walk", "Walk here", self.onWalk, self.getCoords(scr_point)]]
219            # show the menu
220            self.hud.showContextMenu(data, (scr_point.x, scr_point.y))
221
222    def onWalk(self, click):
223        """Callback sample for the context menu."""
224        self.hud.hideContainer()
225        self.data.game_state.PC.run(click)
226
227    def refreshTopLayerInstanceTransparencies(self):
228        """Fade or unfade TopLayer instances if the PC is under them."""
229        # get the PC's screen coordinates
230        camera = self.active_map.cameras[self.active_map.my_cam_id]
231        point = self.data.game_state.PC.behaviour.agent.getLocation()
232        scr_coords = camera.toScreenCoordinates(point.getMapCoordinates())
233
234        # find all instances on TopLayer that fall on those coordinates
235        instances = camera.getMatchingInstances(scr_coords,
236                        self.active_map.top_layer)
237        instance_ids = [ instance.getId() for instance in instances ]
238        faded_objects = self.faded_objects
239
240        # fade instances
241        for instance_id in instance_ids:
242            if instance_id not in faded_objects:
243                faded_objects.add(instance_id)
244                instance.get2dGfxVisual().setTransparency(128)
245
246        # unfade previously faded instances
247        for instance_id in faded_objects.copy():
248            if instance_id not in instance_ids:
249                faded_objects.remove(instance_id)
250                self.active_map.top_layer.getInstance(instance_id).\
251                        get2dGfxVisual().setTransparency(0)
252
253    def teleport(self, position):
254        """Called when a door is used that moves a player to a new
255           location on the same map. the setting of position may want
256           to be created as its own method down the road.
257           @type position: String Tuple
258           @param position: X,Y coordinates passed from engine.changeMap
259           @return: fife.Location"""
260        print position
261        coord = fife.DoublePoint3D(float(position[0]), float(position[1]), 0)
262        location = fife.Location(self.active_map.agent_layer)
263        location.setMapCoordinates(coord)
264        self.data.game_state.PC.teleport(location)
265
266    def mouseMoved(self, evt):
267        """Called when the mouse is moved
268           @type evt: fife.event
269           @param evt: The event that fife caught
270           @return: None"""
271        self.last_mousecoords = fife.ScreenPoint(evt.getX(), evt.getY())
272        self.highlightFrontObject()
273
274    def highlightFrontObject(self):
275        """Highlights the object that is at the current mouse coordinates"""
276        if self.last_mousecoords:
277            front_obj = self.getObjectAtCoords(self.last_mousecoords)
278            if front_obj != None:
279                if self.highlight_obj == None or front_obj.getId() != self.highlight_obj.getId():
280                    if self.highlight_obj:
281                        self.displayObjectText(self.highlight_obj,"")
282                    self.active_map.outline_render.removeAllOutlines()
283                    self.highlight_obj = front_obj
284                    self.active_map.outline_render.addOutlined(self.highlight_obj, 0, \
285                                                               137, 255, 2)
286                    # get the text
287                    item = self.data.objectActive(self.highlight_obj.getId())
288                    if item is not None:
289                        self.displayObjectText(self.highlight_obj, item.name)
290            else:
291                if self.highlight_obj:
292                    self.displayObjectText(self.highlight_obj,"")
293                self.active_map.outline_render.removeAllOutlines()
294                self.highlight_obj = None
295               
296    def getObjectAtCoords(self, coords):
297        """Get the object which is at the given coords
298            @type coords: fife.Screenpoint
299            @param coords: Coordinates where to check for an object
300            @rtype: fife.Object
301            @return: An object or None"""
302        i=self.active_map.cameras[self.active_map.my_cam_id].\
303            getMatchingInstances(coords, self.active_map.agent_layer)
304        # no object returns an empty tuple
305        if(i != ()):
306            front_y = 0
307           
308
309            for obj in i:
310                # check to see if this in our list at all
311                if(self.data.objectActive(obj.getId())):
312                    # check if the object is on the foreground
313                    obj_map_coords = \
314                                      obj.getLocation().getMapCoordinates()
315                    obj_screen_coords = self.active_map.\
316                        cameras[self.active_map.my_cam_id]\
317                        .toScreenCoordinates(obj_map_coords)
318
319                    if obj_screen_coords.y > front_y:
320                        #Object on the foreground
321                        front_y = obj_screen_coords.y
322                        return obj
323                    else:
324                        return None
325        else:
326            return None
327
328    def getCoords(self, click):
329        """Get the map location x, y coordinates from the screen coordinates
330           @type click: fife.ScreenPoint
331           @param click: Screen coordinates
332           @rtype: fife.Location
333           @return: The map coordinates"""
334        coord = self.active_map.cameras[self.active_map.my_cam_id].\
335                    toMapCoordinates(click, False)
336        coord.z = 0
337        location = fife.Location(self.active_map.agent_layer)
338        location.setMapCoordinates(coord)
339        return location
340
341    def togglePause(self):
342        """ Pause/Unpause the game.
343            @return: nothing"""
344        self.active_map.togglePause()
345   
346    def deleteMaps(self):
347        """Clear all currently loaded maps from FIFE as well as clear our
348            local map cache
349            @return: nothing"""
350        self.engine.getModel().deleteMaps()
351        self.engine.getModel().deleteObjects()
352        self.maps = {}
353
354    def pump(self):
355        """Routine called during each frame. Our main loop is in ./run.py"""
356        # uncomment to instrument
357        # t0 = time.time()
358        self.highlightFrontObject()
359        self.refreshTopLayerInstanceTransparencies()
360        # print "%05f" % (time.time()-t0,)
Note: See TracBrowser for help on using the repository browser.