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

Revision 91, 10.2 KB checked in by maximinus_parpg, 11 years ago (diff)

Big update to gfxsplit.py
It almost works now.
Added small wall section to map for testing.

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        self.obj_hash={}
75
76        self.hud = hud.Hud(self.engine, TDS)
77        self.hud.events_to_map["inventoryButton"] = cbwa(self.displayInventory, True)
78        self.hud.hud.mapEvents(self.hud.events_to_map)
79
80        self.hud.menu_events["quitButton"] = self.quitGame
81        self.hud.main_menu.mapEvents(self.hud.menu_events)
82
83        self.action_number = 1
84
85    def reset(self):
86        """Reset the map to default settings"""
87        self.transitions = []
88        self.PC = None
89        self.npcs = []
90        self.map,self.agent_layer = None,None
91        self.cameras = {}
92        self.PC = None
93        self.npcs = []
94        self.cur_cam2_x,self.initial_cam2_x,self.cam2_scrolling_right = 0,0,True
95        self.target_rotation = 0
96
97    def load(self, filename):
98        """Load a map given the filename
99           TODO: a map should only contain static items and floor tiles
100           Everything else should be loaded from the engine, because it
101           is subject to change"""
102        self.reset()
103        self.map = loadMapFile(filename, self.engine)
104        self.maplistener = MapListener(self.map)
105
106        # there must be a PC object on the objects layer!
107        self.agent_layer = self.map.getLayer('ObjectLayer')
108        # it's possible there's no transition layer
109        size = len('TransitionLayer')
110        for layer in self.map.getLayers():
111            # could be many layers, but hopefully no more than 3
112            if(layer.getId()[:size] == 'TransitionLayer'):
113                self.transitions.append(self.map.getLayer(layer.getId()))
114
115        # init the camera
116        for cam in self.view.getCameras():
117            self.cameras[cam.getId()] = cam
118        self.view.resetRenderers()
119        self.target_rotation = self.cameras['main'].getRotation()
120        self.cord_render = self.cameras['main'].getRenderer('CoordinateRenderer')
121       
122        # set the rnder text
123        rend = fife.FloatingTextRenderer.getInstance(self.cameras['main'])
124        text = self.engine.getGuiManager().createFont('fonts/rpgfont.png',
125                                                          0, str(TDS.readSetting("FontGlyphs", strip=False)))
126        rend.changeDefaultFont(text)
127
128    def addPC(self, agent):
129        """Add the player character to the map"""
130        # actually this is real easy, we just have to
131        # attach the main camera to the PC
132        self.cameras['main'].attach(agent)
133   
134    def addObject(self, xpos, ypos, gfx, name):
135        """Add an object or an NPC to the map
136           It makes no difference to fife which is which"""
137        obj = self.agent_layer.createInstance(
138                self.model.getObject(str(gfx), "PARPG"),
139                fife.ExactModelCoordinate(xpos,ypos,0.0), str(gfx))
140        obj.setRotation(0)
141        fife.InstanceVisual.create(obj)
142        # save it for later use
143        self.obj_hash[name]=obj
144
145    def displayObjectText(self, obj, text):
146        """Display on screen the text of the object over the object"""
147        # make sure that the object exists first
148        if obj in self.obj_hash:
149            self.obj_hash[obj].say(str(text), 3500)
150
151    def closeInventoryAndToggle(self):
152        self.inventory.closeInventory()
153        self.hud.toggleInventory()
154        self.inventoryShown = False
155
156    def displayInventory(self, callFromHud):
157        """Pause the game and enter the inventory screen
158           or close the inventory screen and resume the game
159           callFromHud should be set to true if you call this
160           function from the hud script"""
161        # show the inventory
162        if(self.firstInventory == True):
163            self.inventory = inventory.Inventory(self.engine)
164            self.inventory.events_to_map['close_button'] = self.closeInventoryAndToggle
165            self.inventory.inventory.mapEvents(self.inventory.events_to_map)
166            self.firstInventory = False
167            self.inventoryShown = True
168            if (callFromHud == False):
169                self.hud.toggleInventory()
170        # logically firstInventory is false here
171        elif(self.inventoryShown == True):
172            self.inventory.closeInventory()
173            self.inventoryShown = False
174            if (callFromHud == False):
175                self.hud.toggleInventory()
176        # and here inventoryShown must be false
177        else:
178            self.inventory.showInventory()
179            self.inventoryShown = True
180            if (callFromHud == False):
181                self.hud.toggleInventory()
182
183    # all key / mouse event handling routines go here
184    def keyPressed(self, evt):
185        """When a key is pressed, fife calls this routine."""
186        key = evt.getKey()
187        keyval = key.getValue()
188
189        if(keyval == key.Q):
190            # we need to quit the game
191            self.quitGame()
192        if(keyval == key.T):
193            self.toggle_renderer('GridRenderer')
194        if(keyval == key.F1):
195            # display the help screen and pause the game
196            self.displayHelp()
197        if(keyval == key.F5):
198            # logic would say we use similar code to above and toggle
199            # logic here does not work, my friend :-(
200            self.cord_render.setEnabled(not self.cord_render.isEnabled())
201        if(keyval == key.F7):
202            # F7 saves a screenshot to fife/clients/parpg/screenshots
203            t = "screenshots/screen-%s-%s.png" % (date.today().strftime('%Y-%m-%d'),
204                                                  time.strftime('%H-%M-%S'))
205            print "PARPG: Saved:",t
206            self.engine.getRenderBackend().captureScreen(t)
207        if(keyval == key.I):
208            # I opens and closes the inventory
209            self.displayInventory(callFromHud=False)
210        if(keyval == key.A):
211            # A adds a test action to the action box
212            # The test actions will follow this format: Action 1, Action 2, etc.
213            self.hud.addAction("Action " + str(self.action_number))
214            self.action_number += 1
215        if(keyval == key.ESCAPE):
216            # Escape brings up the main menu
217            self.hud.displayMenu()
218
219    def getCoords(self, click):
220        """Get the map location x, y cords that have been clicked"""
221        coord = self.cameras["main"].toMapCoordinates(click, False)
222        coord.z = 0
223        location = fife.Location(self.agent_layer)
224        location.setMapCoordinates(coord)
225        return location
226
227    def mousePressed(self, evt):
228        """If a mouse button is pressed down, fife cals this routine
229           Currently we only check for a left click, and we assume this is on
230           the map"""
231        click = fife.ScreenPoint(evt.getX(), evt.getY())
232        if(evt.getButton() == fife.MouseEvent.LEFT):
233            self.data.handleMouseClick(self.getCoords(click))
234        elif(evt.getButton() == fife.MouseEvent.RIGHT):
235            # there's no need to query fife about what things are where,
236            # the engine code should know....
237            coords = self.getCoords(click).getLayerCoordinates()
238            obj, text = self.data.getObjectText(coords.x, coords.y)
239            if(obj != ""):
240                self.displayObjectText(obj, text)
241
242    def toggle_renderer (self, r_name):
243        """Enable or disable the renderer named `r_name`"""
244        renderer = self.cameras['main'].getRenderer('GridRenderer')
245        renderer.setEnabled(not renderer.isEnabled())
246
247    def displayHelp(self):
248        """Displays the pop-up info and help screen"""
249        print "Help not yet coded"
250
251    def quitGame(self):
252        """Called when user requests to quit game
253           Just calls the ApplicationListener to do the quit"""
254        if(self.quitFunction != None):
255            self.quitFunction()
256
257    def pump(self):
258        """Routine called during each frame. Our main loop is in ./run.py
259           We ignore this main loop (but FIFE complains if it is missing)"""
260        pass
261
Note: See TracBrowser for help on using the repository browser.