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

Revision 340, 11.5 KB checked in by eliedebrauwer, 10 years ago (diff)

Ticket #66: Patch by Saritor, This patch implements Kaydeth's camera fix as well as a fix for letting us be able to remove the PC entry on individual map files. However the very first map a player starts the game on will need such an entry. fixes[s:trac, t:66]

  • 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
20import 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 import hud
28from scripts.popups import *
29from 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        # setup the inventory model
65        # make slot 'A1' and 'A3' container daggers
66        inv_model = {'A1':'dagger01', 'A3':'dagger01'}
67
68        hud_callbacks = {
69            'saveGame': self.saveGame,
70            'loadGame': self.loadGame,
71            'quitGame': self.quitGame,
72        }
73        self.hud = hud.Hud(self.engine, TDS, inv_model, hud_callbacks)
74        self.action_number = 1
75
76        # init the sound
77        self.sounds = SoundEngine(engine)
78       
79        # don't force restart if skipping to new section
80        if (TDS.readSetting("PlaySounds") == "1"):
81            if(self.sounds.music_init == False):
82                self.sounds.playMusic("/music/preciouswasteland.ogg")
83               
84    def quitGame(self):
85        """Quits the game
86        @return: None"""
87        self.quitFunction()
88
89    def saveGame(self, *args, **kwargs):
90        """Saves the game state, delegates call to engine.Engine
91           @return: None"""
92        self.data.save(*args, **kwargs)
93
94    def loadGame(self, *args, **kwargs):
95        """Loads the game state, delegates call to engine.Engine
96           @return: None"""
97        self.data.load(*args, **kwargs)
98       
99    def loadMap(self, map_name, filename):
100        """Loads a map and stores it under the given name in the maps list.
101           @type map_name: String
102           @param map_name: The name of the map to load
103           @type filename: String
104           @param filename: File which contains the map to be loaded
105           @return: None"""
106        if not map_name in self.maps:
107            map = Map(self.engine, self.data)
108            self.maps[map_name] = map       
109            map.load(filename)
110        else:
111            self.setActiveMap(map_name)
112   
113    def setActiveMap(self, map_name):
114        """Sets the active map that is to be rendered.
115           @type map_name: String
116           @param map_name: The name of the map to load
117           @return: None"""
118        # Turn off the camera on the old map before we turn on the camera
119        # on the new map.
120        self.active_map.cameras[self.active_map.my_cam_id].setEnabled(False)
121        # Make the new map active.
122        self.active_map = self.maps[map_name]
123        self.active_map.makeActive()
124
125    def displayObjectText(self, obj, text):
126        """Display on screen the text of the object over the object.
127           @type obj: fife.instance
128           @param obj: object to draw over
129           @type text: String
130           @param text: text to display over object
131           @return: None"""
132        obj.say(str(text), 1000)
133
134    def keyPressed(self, evt):
135        """Whenever a key is pressed, fife calls this routine.
136           @type evt: fife.event
137           @param evt: The event that fife caught
138           @return: None"""
139        key = evt.getKey()
140        key_val = key.getValue()
141
142        if(key_val == key.Q):
143            # we need to quit the game
144            self.hud.quitGame()
145        if(key_val == key.T):
146            self.active_map.toggle_renderer('GridRenderer')
147        if(key_val == key.F1):
148            # display the help screen and pause the game
149            self.hud.displayHelp()
150        if(key_val == key.F5):
151            # logic would say we use similar code to above and toggle
152            # logic here does not work, my friend :-(
153            self.cord_render.setEnabled(not self.cord_render.isEnabled())
154        if(key_val == key.F7):
155            # F7 saves a screenshot to fife/clients/parpg/screenshots
156            t = "screenshots/screen-%s-%s.png" % \
157                    (date.today().strftime('%Y-%m-%d'),\
158                    time.strftime('%H-%M-%S'))
159            print "PARPG: Saved:",t
160            self.engine.getRenderBackend().captureScreen(t)
161        if(key_val == key.F10):
162            # F10 shows/hides the console
163            self.engine.getGuiManager().getConsole().toggleShowHide()
164        if(key_val == key.I):
165            # I opens and closes the inventory
166            self.hud.toggleInventory()
167        if(key_val == key.A):
168            # A adds a test action to the action box
169            # The test actions will follow this format: Action 1,
170            # Action 2, etc.
171            self.hud.addAction("Action " + str(self.action_number))
172            self.action_number += 1
173        if(key_val == key.ESCAPE):
174            # Escape brings up the main menu
175            self.hud.displayMenu()
176            # Hide the quit menu
177            self.hud.quit_window.hide()
178        if(key_val == key.M):
179            self.sounds.toggleMusic()
180
181    def mouseReleased(self, evt):
182        """If a mouse button is released, fife calls this routine.
183           We want to wait until the button is released, because otherwise
184           pychan captures the release if a menu is opened.
185           @type evt: fife.event
186           @param evt: The event that fife caught
187           @return: None"""
188        self.hud.hideContextMenu()
189        scr_point = fife.ScreenPoint(evt.getX(), evt.getY())
190        if(evt.getButton() == fife.MouseEvent.LEFT):
191            self.data.handleMouseClick(self.getCoords(scr_point))     
192        elif(evt.getButton() == fife.MouseEvent.RIGHT):
193            # is there an object here?
194            instances = self.active_map.cameras[self.active_map.my_cam_id].\
195                            getMatchingInstances(scr_point, \
196                                                 self.active_map.agent_layer)
197            info = None
198            for inst in instances:
199                # check to see if this is an active item
200                if(self.data.objectActive(inst.getId())):           
201                    # yes, get the data
202                    info = self.data.getItemActions(inst.getId())
203                    break
204               
205            # take the menu items returned by the engine or show a
206            # default menu if no items   
207            data = info or \
208                [["Walk", "Walk here", self.onWalk, self.getCoords(scr_point)]]
209            # show the menu
210            self.hud.showContextMenu(data, (scr_point.x, scr_point.y))
211
212    def onWalk(self, click):
213        """Callback sample for the context menu."""
214        self.hud.hideContainer()
215        self.data.game_state.PC.run(click)
216
217    def teleport(self, position):
218        """Called when a door is used that moves a player to a new
219           location on the same map. the setting of position may want
220           to be created as its own method down the road.
221           @type position: String Tuple
222           @param position: X,Y coordinates passed from engine.changeMap
223           @return: fife.Location
224        """
225        print position
226        coord = fife.DoublePoint3D(float(position[0]), float(position[1]), 0)
227        location = fife.Location(self.active_map.agent_layer)
228        location.setMapCoordinates(coord)
229        self.data.game_state.PC.teleport(location)
230
231    def mouseMoved(self, evt):
232        """Called when the mouse is moved
233           @type evt: fife.event
234           @param evt: The event that fife caught
235           @return: None"""
236        click = fife.ScreenPoint(evt.getX(), evt.getY())
237        i=self.active_map.cameras[self.active_map.my_cam_id].getMatchingInstances(click, \
238                                                self.active_map.agent_layer)
239        # no object returns an empty tuple
240        if(i != ()):
241            front_y = 0
242            front_obj = None
243
244            for obj in i:
245                # check to see if this in our list at all
246                if(self.data.objectActive(obj.getId())):
247                    # check if the object is on the foreground
248                    obj_map_coords = \
249                                      obj.getLocation().getMapCoordinates()
250                    obj_screen_coords = self.active_map.cameras["main"]\
251                                    .toScreenCoordinates(obj_map_coords)
252                   
253                    if obj_screen_coords.y > front_y:
254                        #Object on the foreground
255                        front_y = obj_screen_coords.y
256                        front_obj = obj
257
258            if front_obj:                   
259                self.active_map.outline_render.removeAllOutlines() 
260                self.active_map.outline_render.addOutlined(front_obj, 0, \
261                                                               137, 255, 2)
262                # get the text
263                item = self.data.objectActive(front_obj.getId())
264                if(item is not None):
265                    self.displayObjectText(front_obj, item.name)
266        else:
267            # erase the outline
268            self.active_map.outline_render.removeAllOutlines()
269
270    def getCoords(self, click):
271        """Get the map location x, y coordinates from the screen coordinates
272           @type click: fife.ScreenPoint
273           @param click: Screen coordinates
274           @rtype: fife.Location
275           @return: The map coordinates"""
276        coord = self.active_map.cameras[self.active_map.my_cam_id].toMapCoordinates(click, False)
277        coord.z = 0
278        location = fife.Location(self.active_map.agent_layer)
279        location.setMapCoordinates(coord)
280        return location
281
282    def pump(self):
283        """Routine called during each frame. Our main loop is in ./run.py
284           We ignore this main loop (but FIFE complains if it is missing)."""
285        pass
Note: See TracBrowser for help on using the repository browser.