source: trunk/PARPG/scripts/world.py @ 76

Revision 76, 9.2 KB checked in by bretzel_parpg, 11 years ago (diff)

Added a functional options menu to the game. Right now it has options for fullscreen and sounds.

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
19import time
20from datetime import date
21from scripts.common.eventlistenerbase import EventListenerBase
22from loaders import loadMapFile
23from agents.hero import Hero
24from agents.npc import NPC
25from settings import Setting
26from scripts import inventory
27from scripts import hud
28from pychan.tools import callbackWithArguments as cbwa
29
30TDS = Setting()
31
32# this file should be the meta-file for all FIFE-related code
33# engine.py handles is our data model, whilst this is our view
34# in order to not replicate data, some of our data model will naturally
35# reside on this side of the fence (PC xpos and ypos, for example).
36# we should aim to never replicate any data as this leads to maintainance
37# issues (and just looks plain bad).
38# however, any logic needed to resolve this should sit in engine.py
39
40class MapListener(fife.MapChangeListener):
41    """This class listens to changes happening on the map.
42       Since in theory we initiate these ourselves, do we need this class?"""
43    def __init__(self, map):
44        fife.MapChangeListener.__init__(self)
45
46    def onMapChanged(self, map, changedLayers):
47        pass
48
49    def onLayerCreate(self, map, layer):
50        pass
51
52    def onLayerDelete(self, map, layer):
53        pass
54
55class Map:
56    def __init__(self, fife_map):
57        self.listener = MapListener
58        self.map = fife_map
59
60class World(EventListenerBase):
61    """World holds the data needed by fife to render the engine
62       The engine keeps a copy of this class"""
63    def __init__(self, engine):
64        super(World, self).__init__(engine, regMouse = True, regKeys = True)
65        self.engine = engine
66        self.eventmanager = engine.getEventManager()
67        self.model = engine.getModel()
68        self.view = self.engine.getView()
69        self.quitFunction = None
70        self.inventoryShown = False
71        self.firstInventory = True
72        self.data = None
73        self.mouseCallback = None
74
75        self.hud = hud.Hud(self.engine, TDS)
76        self.hud.events_to_map["inventoryButton"] = cbwa(self.displayInventory, True)
77        self.hud.hud.mapEvents(self.hud.events_to_map)
78
79        self.hud.menu_events["quitButton"] = self.quitGame
80        self.hud.main_menu.mapEvents(self.hud.menu_events)
81
82        self.action_number = 1
83
84    def reset(self):
85        """Rest the map to default settings"""
86        self.transitions = []
87        self.PC = None
88        self.npcs = []
89        self.map,self.agent_layer = None,None
90        self.cameras = {}
91        self.PC = None
92        self.npcs = []
93        self.cur_cam2_x,self.initial_cam2_x,self.cam2_scrolling_right = 0,0,True
94        self.target_rotation = 0
95
96    def load(self, filename):
97        """Load a map given the filename
98           TODO: a map should only contain static items and floor tiles
99           Everything else should be loaded from the engine, because it
100           is subject to change"""
101        self.reset()
102        self.map = loadMapFile(filename, self.engine)
103        self.maplistener = MapListener(self.map)
104
105        # there must be a PC object on the objects layer!
106        self.agent_layer = self.map.getLayer('ObjectLayer')
107        # it's possible there's no transition layer
108        size = len('TransitionLayer')
109        for layer in self.map.getLayers():
110            # could be many layers, but hopefully no more than 3
111            if(layer.getId()[:size] == 'TransitionLayer'):
112                self.transitions.append(self.map.getLayer(layer.getId()))
113
114        # init the camera
115        for cam in self.view.getCameras():
116            self.cameras[cam.getId()] = cam
117        self.view.resetRenderers()
118        self.target_rotation = self.cameras['main'].getRotation()
119        self.cord_render = self.cameras['main'].getRenderer('CoordinateRenderer')
120
121    def addPC(self, agent):
122        """Add the player character to the map"""
123        # actually this is real easy, we just have to
124        # attach the main camera to the PC
125        self.cameras['main'].attach(agent)
126   
127    def addObject(self, xpos, ypos, name):
128        """Add an object or an NPC to the map
129           It makes no difference to fife which is which"""
130        obj = self.agent_layer.createInstance(
131                self.model.getObject(str(name), "PARPG"),
132                fife.ExactModelCoordinate(xpos,ypos,0.0), str(name))
133        obj.setRotation(0)
134        fife.InstanceVisual.create(obj)
135
136    def displayInventory(self, callFromHud):
137        """Pause the game and enter the inventory screen
138           or close the inventory screen and resume the game
139           callFromHud should be set to true if you call this
140           function from the hud script"""
141        # show the inventory
142        if(self.firstInventory == True):
143            self.inventory = inventory.Inventory(self.engine)
144            self.firstInventory = False
145            self.inventoryShown = True
146            if (callFromHud == False):
147                self.hud.toggleInventory()
148        # logically firstInventory is false here
149        elif(self.inventoryShown == True):
150            self.inventory.closeInventory()
151            self.inventoryShown = False
152            if (callFromHud == False):
153                self.hud.toggleInventory()
154        # and here inventoryShown must be false
155        else:
156            self.inventory.showInventory()
157            self.inventoryShown = True
158            if (callFromHud == False):
159                self.hud.toggleInventory()
160
161    # all key / mouse event handling routines go here
162    def keyPressed(self, evt):
163        """When a key is pressed, fife calls this routine."""
164        key = evt.getKey()
165        keyval = key.getValue()
166
167        if(keyval == key.Q):
168            # we need to quit the game
169            self.quitGame()
170        if(keyval == key.T):
171            self.toggle_renderer('GridRenderer')
172        if(keyval == key.F1):
173            # display the help screen and pause the game
174            self.displayHelp()
175        if(keyval == key.F5):
176            # logic would say we use similar code to above and toggle
177            # logic here does not work, my friend :-(
178            self.cord_render.setEnabled(not self.cord_render.isEnabled())
179        if(keyval == key.F7):
180            # F7 saves a screenshot to fife/clients/parpg/screenshots
181            t = "screenshots/screen-%s-%s.png" % (date.today().strftime('%Y-%m-%d'),
182                                                  time.strftime('%H:%M:%S'))
183            self.engine.getRenderBackend().captureScreen(t)
184        if(keyval == key.I):
185            # I opens and closes the inventory
186            self.displayInventory(callFromHud=False)
187        if(keyval == key.A):
188            # A adds a test action to the action box
189            # The test actions will follow this format: Action 1, Action 2, etc.
190            self.hud.addAction("Action " + str(self.action_number))
191            self.action_number += 1
192        if(keyval == key.ESCAPE):
193            # Escape brings up the main menu
194            self.hud.displayMenu()
195
196    def getCoords(self, click):
197        """Get the map location x, y cords that have been clicked"""
198        coord = self.cameras["main"].toMapCoordinates(click, False)
199        coord.z = 0
200        location = fife.Location(self.agent_layer)
201        location.setMapCoordinates(coord)
202        return location
203
204    def mousePressed(self, evt):
205        """If a mouse button is pressed down, fife cals this routine
206           Currently we only check for a left click, and we assume this is on
207           the map"""
208        click = fife.ScreenPoint(evt.getX(), evt.getY())
209        if(evt.getButton() == fife.MouseEvent.LEFT):
210            self.data.handleMouseClick(self.getCoords(click))
211        elif(evt.getButton() == fife.MouseEvent.RIGHT):
212            # there's no need to query fife about what things are where,
213            # the engine code should know....
214            coords = self.getCoords(click).getLayerCoordinates()
215            obj = self.data.getObjectString(coords.x, coords.y)
216            if(obj != ""):
217                print obj
218
219    def toggle_renderer (self, r_name):
220        """Enable or disable the renderer named `r_name`"""
221        renderer = self.cameras['main'].getRenderer('GridRenderer')
222        renderer.setEnabled(not renderer.isEnabled())
223
224    def displayHelp(self):
225        """Displays the pop-up info and help screen"""
226        print "Help not yet coded"
227
228    def quitGame(self):
229        """Called when user requests to quit game
230           Just calls the ApplicationListener to do the quit"""
231        if(self.quitFunction != None):
232            self.quitFunction()
233
234    def pump(self):
235        """Routine called during each frame. Our main loop is in ./run.py
236           We ignore this main loop (but FIFE complains if it is missing)"""
237        pass
238
Note: See TracBrowser for help on using the repository browser.