Mercurial > fife-parpg
comparison clients/rio_de_hola/scripts/world.py @ 246:8156de05a544
Documentation for the World
class in rio de hola.
author | phoku@33b003aa-7bff-0310-803a-e67f0ece8222 |
---|---|
date | Wed, 25 Mar 2009 15:42:14 +0000 |
parents | ed1565a5a2a0 |
children | 040387b7167f |
comparison
equal
deleted
inserted
replaced
245:ed1565a5a2a0 | 246:8156de05a544 |
---|---|
33 def onLayerDelete(self, map, layer): | 33 def onLayerDelete(self, map, layer): |
34 pass | 34 pass |
35 | 35 |
36 | 36 |
37 class World(EventListenerBase): | 37 class World(EventListenerBase): |
38 """ | |
39 The world! | |
40 | |
41 This class handles: | |
42 setup of map view (cameras ...) | |
43 loading the map | |
44 GUI for right clicks | |
45 handles mouse/key events which aren't handled by the GUI. | |
46 ( by inheriting from EventlistenerBase ) | |
47 | |
48 That's obviously too much, and should get factored out. | |
49 """ | |
38 def __init__(self, engine): | 50 def __init__(self, engine): |
39 super(World, self).__init__(engine, regMouse=True, regKeys=True) | 51 super(World, self).__init__(engine, regMouse=True, regKeys=True) |
40 self.engine = engine | 52 self.engine = engine |
41 self.eventmanager = engine.getEventManager() | 53 self.eventmanager = engine.getEventManager() |
42 self.model = engine.getModel() | 54 self.model = engine.getModel() |
47 self.instancemenu = None | 59 self.instancemenu = None |
48 self.instance_to_agent = {} | 60 self.instance_to_agent = {} |
49 self.dynamic_widgets = {} | 61 self.dynamic_widgets = {} |
50 | 62 |
51 def show_instancemenu(self, clickpoint, instance): | 63 def show_instancemenu(self, clickpoint, instance): |
64 """ | |
65 Build and show a popupmenu for an instance that the player | |
66 clicked on. The available actions are dynamically added to | |
67 the menu (and mapped to the onXYZ functions). | |
68 """ | |
52 if instance.getFifeId() == self.hero.agent.getFifeId(): | 69 if instance.getFifeId() == self.hero.agent.getFifeId(): |
53 return | 70 return |
54 | 71 |
55 dynamicbuttons = ('moveButton', 'talkButton', 'kickButton', 'inspectButton') | 72 # Create the popup. |
56 if not self.instancemenu: | 73 self.build_instancemenu() |
57 self.instancemenu = pychan.loadXML('gui/instancemenu.xml') | |
58 self.instancemenu.mapEvents({ | |
59 'moveButton' : self.onMoveButtonPress, | |
60 'talkButton' : self.onTalkButtonPress, | |
61 'kickButton' : self.onKickButtonPress, | |
62 'inspectButton' : self.onInspectButtonPress, | |
63 }) | |
64 for btn in dynamicbuttons: | |
65 self.dynamic_widgets[btn] = self.instancemenu.findChild(name=btn) | |
66 for btn in dynamicbuttons: | |
67 try: | |
68 self.instancemenu.removeChild(self.dynamic_widgets[btn]) | |
69 except pychan.exceptions.RuntimeError: | |
70 pass | |
71 | |
72 self.instancemenu.clickpoint = clickpoint | 74 self.instancemenu.clickpoint = clickpoint |
73 self.instancemenu.instance = instance | 75 self.instancemenu.instance = instance |
74 | 76 |
77 # Add the buttons according to circumstances. | |
75 self.instancemenu.addChild(self.dynamic_widgets['inspectButton']) | 78 self.instancemenu.addChild(self.dynamic_widgets['inspectButton']) |
76 target_distance = self.hero.agent.getLocationRef().getLayerDistanceTo(instance.getLocationRef()) | 79 target_distance = self.hero.agent.getLocationRef().getLayerDistanceTo(instance.getLocationRef()) |
77 if target_distance > 3.0: | 80 if target_distance > 3.0: |
78 self.instancemenu.addChild(self.dynamic_widgets['moveButton']) | 81 self.instancemenu.addChild(self.dynamic_widgets['moveButton']) |
79 else: | 82 else: |
80 if self.instance_to_agent.has_key(instance.getFifeId()): | 83 if self.instance_to_agent.has_key(instance.getFifeId()): |
81 self.instancemenu.addChild(self.dynamic_widgets['talkButton']) | 84 self.instancemenu.addChild(self.dynamic_widgets['talkButton']) |
82 self.instancemenu.addChild(self.dynamic_widgets['kickButton']) | 85 self.instancemenu.addChild(self.dynamic_widgets['kickButton']) |
86 # And show it :) | |
83 self.instancemenu.position = (clickpoint.x, clickpoint.y) | 87 self.instancemenu.position = (clickpoint.x, clickpoint.y) |
84 self.instancemenu.show() | 88 self.instancemenu.show() |
89 | |
90 def build_instancemenu(self): | |
91 """ | |
92 Just loads the menu from an XML file | |
93 and hooks the events up. | |
94 The buttons are removed and later re-added if appropiate. | |
95 """ | |
96 dynamicbuttons = ('moveButton', 'talkButton', 'kickButton', 'inspectButton') | |
97 self.instancemenu = pychan.loadXML('gui/instancemenu.xml') | |
98 self.instancemenu.mapEvents({ | |
99 'moveButton' : self.onMoveButtonPress, | |
100 'talkButton' : self.onTalkButtonPress, | |
101 'kickButton' : self.onKickButtonPress, | |
102 'inspectButton' : self.onInspectButtonPress, | |
103 }) | |
104 for btn in dynamicbuttons: | |
105 self.dynamic_widgets[btn] = self.instancemenu.findChild(name=btn) | |
106 self.instancemenu.removeAllChildren() | |
85 | 107 |
86 def hide_instancemenu(self): | 108 def hide_instancemenu(self): |
87 if self.instancemenu: | 109 if self.instancemenu: |
88 self.instancemenu.hide() | 110 self.instancemenu.hide() |
89 | 111 |
90 def reset(self): | 112 def reset(self): |
113 """ | |
114 Clear the agent information and reset the moving secondary camera state. | |
115 """ | |
91 self.map, self.agentlayer = None, None | 116 self.map, self.agentlayer = None, None |
92 self.cameras = {} | 117 self.cameras = {} |
93 self.hero, self.girl, self.clouds, self.beekeepers = None, None, [], [] | 118 self.hero, self.girl, self.clouds, self.beekeepers = None, None, [], [] |
94 self.cur_cam2_x, self.initial_cam2_x, self.cam2_scrolling_right = 0, 0, True | 119 self.cur_cam2_x, self.initial_cam2_x, self.cam2_scrolling_right = 0, 0, True |
95 self.target_rotation = 0 | 120 self.target_rotation = 0 |
96 self.instance_to_agent = {} | 121 self.instance_to_agent = {} |
97 | 122 |
98 def load(self, filename): | 123 def load(self, filename): |
124 """ | |
125 Load a xml map and setup agents and cameras. | |
126 """ | |
99 self.filename = filename | 127 self.filename = filename |
100 self.reset() | 128 self.reset() |
101 self.map = loadMapFile(filename, self.engine) | 129 self.map = loadMapFile(filename, self.engine) |
102 self.maplistener = MapListener(self.map) | 130 self.maplistener = MapListener(self.map) |
103 | 131 |
132 self.initAgents() | |
133 self.initCameras() | |
134 | |
135 def initAgents(self): | |
136 """ | |
137 Setup agents. | |
138 | |
139 For this techdemo we have a very simple 'active things on the map' model, | |
140 which is called agents. All rio maps will have a separate layer for them. | |
141 | |
142 Note that we keep a mapping from map instances (C++ model of stuff on the map) | |
143 to the python agents for later reference. | |
144 """ | |
104 self.agentlayer = self.map.getLayer('TechdemoMapGroundObjectLayer') | 145 self.agentlayer = self.map.getLayer('TechdemoMapGroundObjectLayer') |
105 self.hero = Hero(self.model, 'PC', self.agentlayer) | 146 self.hero = Hero(self.model, 'PC', self.agentlayer) |
106 self.instance_to_agent[self.hero.agent.getFifeId()] = self.hero | 147 self.instance_to_agent[self.hero.agent.getFifeId()] = self.hero |
107 self.hero.start() | 148 self.hero.start() |
108 | 149 |
113 self.beekeepers = create_anonymous_agents(self.model, 'beekeeper', self.agentlayer, Beekeeper) | 154 self.beekeepers = create_anonymous_agents(self.model, 'beekeeper', self.agentlayer, Beekeeper) |
114 for beekeeper in self.beekeepers: | 155 for beekeeper in self.beekeepers: |
115 self.instance_to_agent[beekeeper.agent.getFifeId()] = beekeeper | 156 self.instance_to_agent[beekeeper.agent.getFifeId()] = beekeeper |
116 beekeeper.start() | 157 beekeeper.start() |
117 | 158 |
159 # Clouds are currently defunct. | |
118 cloudlayer = self.map.getLayer('TechdemoMapTileLayer') | 160 cloudlayer = self.map.getLayer('TechdemoMapTileLayer') |
119 self.clouds = create_anonymous_agents(self.model, 'Cloud', cloudlayer, Cloud) | 161 self.clouds = create_anonymous_agents(self.model, 'Cloud', cloudlayer, Cloud) |
120 for cloud in self.clouds: | 162 for cloud in self.clouds: |
121 cloud.start(0.1, 0.05) | 163 cloud.start(0.1, 0.05) |
122 | 164 |
165 | |
166 def initCameras(self): | |
167 """ | |
168 Before we can actually see something on screen we have to specify the render setup. | |
169 This is done through Camera objects which offer a viewport on the map. | |
170 | |
171 For this techdemo two cameras are used. One follows the hero(!) via 'attach' | |
172 the other one scrolls around a bit (see the pump function). | |
173 """ | |
123 for cam in self.view.getCameras(): | 174 for cam in self.view.getCameras(): |
124 self.cameras[cam.getId()] = cam | 175 self.cameras[cam.getId()] = cam |
125 self.cameras['main'].attach(self.hero.agent) | 176 self.cameras['main'].attach(self.hero.agent) |
126 | 177 |
127 self.view.resetRenderers() | 178 self.view.resetRenderers() |
179 # Floating text renderers currntly only support one font. | |
180 # ... so we set that up. | |
181 # You'll se that for our demo we use a image font, so we have to specify the font glyphs | |
182 # for that one. | |
128 renderer = fife.FloatingTextRenderer.getInstance(self.cameras['main']) | 183 renderer = fife.FloatingTextRenderer.getInstance(self.cameras['main']) |
129 textfont = self.engine.getGuiManager().createFont('fonts/rpgfont.png', 0, str(TDS.readSetting("FontGlyphs", strip=False))); | 184 textfont = self.engine.getGuiManager().createFont('fonts/rpgfont.png', 0, str(TDS.readSetting("FontGlyphs", strip=False))); |
130 renderer.changeDefaultFont(textfont) | 185 renderer.changeDefaultFont(textfont) |
131 | 186 |
187 # The small camera shouldn't be cluttered by the 'humm di dums' of our hero. | |
188 # So we disable the renderer simply by setting its font to None. | |
132 renderer = fife.FloatingTextRenderer.getInstance(self.cameras['small']) | 189 renderer = fife.FloatingTextRenderer.getInstance(self.cameras['small']) |
133 renderer.changeDefaultFont(None) | 190 renderer.changeDefaultFont(None) |
134 | 191 |
192 # The following renderers are used for debugging. | |
193 # Note that by default ( that is after calling View.resetRenderers or Camera.resetRenderers ) | |
194 # renderers will be handed all layers. That's handled here. | |
135 renderer = self.cameras['main'].getRenderer('CoordinateRenderer') | 195 renderer = self.cameras['main'].getRenderer('CoordinateRenderer') |
136 renderer.clearActiveLayers() | 196 renderer.clearActiveLayers() |
137 renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("CoordinateLayerName")))) | 197 renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("CoordinateLayerName")))) |
138 | 198 |
139 renderer = self.cameras['main'].getRenderer('QuadTreeRenderer') | 199 renderer = self.cameras['main'].getRenderer('QuadTreeRenderer') |
140 renderer.setEnabled(True) | 200 renderer.setEnabled(True) |
141 renderer.clearActiveLayers() | 201 renderer.clearActiveLayers() |
142 if str(TDS.readSetting("QuadTreeLayerName")): | 202 if str(TDS.readSetting("QuadTreeLayerName")): |
143 renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("QuadTreeLayerName")))) | 203 renderer.addActiveLayer(self.map.getLayer(str(TDS.readSetting("QuadTreeLayerName")))) |
144 | 204 |
145 self.cameras['small'].getLocationRef().setExactLayerCoordinates( fife.ExactModelCoordinate( 40.0, 40.0, 0.0 )) | 205 # Set up the second camera |
206 # NOTE: We need to explicitly call setLocation, there's a bit of a messup in the Camera code. | |
207 self.cameras['small'].setLocation(self.hero.agent.getLocation()) | |
208 #self.cameras['small'].getLocationRef().setExactLayerCoordinates( fife.ExactModelCoordinate( 40.0, 40.0, 0.0 )) | |
146 self.initial_cam2_x = self.cameras['small'].getLocation().getExactLayerCoordinates().x | 209 self.initial_cam2_x = self.cameras['small'].getLocation().getExactLayerCoordinates().x |
147 self.cur_cam2_x = self.initial_cam2_x | 210 self.cur_cam2_x = self.initial_cam2_x |
148 self.cam2_scrolling_right = True | 211 self.cam2_scrolling_right = True |
149 # We need to set the second cameras location | |
150 self.cameras['small'].setLocation(self.hero.agent.getLocation()) | |
151 self.target_rotation = self.cameras['main'].getRotation() | 212 self.target_rotation = self.cameras['main'].getRotation() |
152 | 213 |
153 def save(self, filename): | 214 def save(self, filename): |
154 saveMapFile(filename, self.engine, self.map) | 215 saveMapFile(filename, self.engine, self.map) |
155 | 216 |
164 r.setEnabled(not r.isEnabled()) | 225 r.setEnabled(not r.isEnabled()) |
165 elif keystr == 's': | 226 elif keystr == 's': |
166 c = self.cameras['small'] | 227 c = self.cameras['small'] |
167 c.setEnabled(not c.isEnabled()) | 228 c.setEnabled(not c.isEnabled()) |
168 elif keystr == 'r': | 229 elif keystr == 'r': |
169 pass | 230 self.model.deleteMaps() |
170 # self.model.deleteMaps() | 231 self.view.clearCameras() |
171 # self.metamodel.deleteDatasets() | 232 self.load(self.filename) |
172 # self.view.clearCameras() | |
173 # self.load(self.filename) | |
174 elif keystr == 'o': | 233 elif keystr == 'o': |
175 self.target_rotation = (self.target_rotation + 90) % 360 | 234 self.target_rotation = (self.target_rotation + 90) % 360 |
176 elif keyval in (fife.Key.LEFT_CONTROL, fife.Key.RIGHT_CONTROL): | 235 elif keyval in (fife.Key.LEFT_CONTROL, fife.Key.RIGHT_CONTROL): |
177 self.ctrldown = True | 236 self.ctrldown = True |
178 | 237 |
225 | 284 |
226 def onConsoleCommand(self, command): | 285 def onConsoleCommand(self, command): |
227 result = '' | 286 result = '' |
228 try: | 287 try: |
229 result = str(eval(command)) | 288 result = str(eval(command)) |
230 except: | 289 except Exception, e: |
231 pass | 290 result = str(e) |
232 return result | 291 return result |
233 | 292 |
293 # Callbacks from the popupmenu | |
234 def onMoveButtonPress(self): | 294 def onMoveButtonPress(self): |
235 self.hide_instancemenu() | 295 self.hide_instancemenu() |
236 self.hero.run(self.instancemenu.instance.getLocationRef()) | 296 self.hero.run(self.instancemenu.instance.getLocationRef()) |
237 | 297 |
238 def onTalkButtonPress(self): | 298 def onTalkButtonPress(self): |