Mercurial > pyntnclick
comparison pyntnclick/state.py @ 603:3ce19d33b51f pyntnclick
Rename state to game to not cause confusion with the other state
author | Neil Muller <neil@dip.sun.ac.za> |
---|---|
date | Sat, 11 Feb 2012 20:09:47 +0200 |
parents | 59f1ee3f5632 |
children | a25cd1c6335a |
comparison
equal
deleted
inserted
replaced
602:1aac5a3b17e1 | 603:3ce19d33b51f |
---|---|
20 self.close_detail = close_detail | 20 self.close_detail = close_detail |
21 self.end_game = end_game | 21 self.end_game = end_game |
22 | 22 |
23 def play_sound(self, scene_widget): | 23 def play_sound(self, scene_widget): |
24 if self.soundfile: | 24 if self.soundfile: |
25 sound = scene_widget.state.gd.sound.get_sound(self.soundfile) | 25 sound = scene_widget.game.gd.sound.get_sound(self.soundfile) |
26 sound.play() | 26 sound.play() |
27 | 27 |
28 def process(self, scene_widget): | 28 def process(self, scene_widget): |
29 """Helper function to do the right thing with a result object""" | 29 """Helper function to do the right thing with a result object""" |
30 self.play_sound(scene_widget) | 30 self.play_sound(scene_widget) |
50 if res: | 50 if res: |
51 # List may contain None's | 51 # List may contain None's |
52 res.process(scene_widget) | 52 res.process(scene_widget) |
53 | 53 |
54 | 54 |
55 class GameState(object): | 55 class Game(object): |
56 """Complete game state. | 56 """Complete game state. |
57 | 57 |
58 Game state consists of: | 58 Game state consists of: |
59 | 59 |
60 * items | 60 * items |
71 self.items = {} | 71 self.items = {} |
72 # list of item objects in inventory | 72 # list of item objects in inventory |
73 self.inventory = [] | 73 self.inventory = [] |
74 # currently selected tool (item) | 74 # currently selected tool (item) |
75 self.tool = None | 75 self.tool = None |
76 # Global game data | |
77 self.data = {} | |
76 # current scene | 78 # current scene |
77 self.current_scene = None | 79 self.current_scene = None |
78 # current detail view | 80 # current detail view |
79 self.current_detail = None | 81 self.current_detail = None |
80 # scene we came from, for enter and leave processing | 82 # scene we came from, for enter and leave processing |
90 | 92 |
91 def set_debug_rects(self, value=True): | 93 def set_debug_rects(self, value=True): |
92 self.debug_rects = value | 94 self.debug_rects = value |
93 | 95 |
94 def add_scene(self, scene): | 96 def add_scene(self, scene): |
95 scene.set_state(self) | 97 scene.set_game(self) |
96 self.scenes[scene.name] = scene | 98 self.scenes[scene.name] = scene |
97 | 99 |
98 def add_detail_view(self, detail_view): | 100 def add_detail_view(self, detail_view): |
99 detail_view.set_state(self) | 101 detail_view.set_game(self) |
100 self.detail_views[detail_view.name] = detail_view | 102 self.detail_views[detail_view.name] = detail_view |
101 | 103 |
102 def add_item(self, item): | 104 def add_item(self, item): |
103 item.set_state(self) | 105 item.set_game(self) |
104 self.items[item.name] = item | 106 self.items[item.name] = item |
105 | 107 |
106 def load_scenes(self, modname): | 108 def load_scenes(self, modname): |
107 mod = __import__("gamelib.scenes.%s" % (modname,), fromlist=[modname]) | 109 mod = __import__("gamelib.scenes.%s" % (modname,), fromlist=[modname]) |
108 for scene_cls in mod.SCENES: | 110 for scene_cls in mod.SCENES: |
203 class GameDeveloperGizmo(object): | 205 class GameDeveloperGizmo(object): |
204 """Base class for objects game developers see.""" | 206 """Base class for objects game developers see.""" |
205 | 207 |
206 def __init__(self): | 208 def __init__(self): |
207 """Set """ | 209 """Set """ |
208 self.state = None | 210 self.game = None |
209 self.gd = None | 211 self.gd = None |
210 self.resource = None | 212 self.resource = None |
211 self.sound = None | 213 self.sound = None |
212 | 214 |
213 def set_state(self, state): | 215 def set_game(self, game): |
214 self.state = state | 216 self.game = game |
215 self.gd = state.gd | 217 self.gd = game.gd |
216 self.resource = self.gd.resource | 218 self.resource = self.gd.resource |
217 self.sound = self.gd.sound | 219 self.sound = self.gd.sound |
218 self.setup() | 220 self.setup() |
219 | 221 |
220 def setup(self): | 222 def setup(self): |
228 | 230 |
229 class StatefulGizmo(GameDeveloperGizmo): | 231 class StatefulGizmo(GameDeveloperGizmo): |
230 | 232 |
231 # initial data (optional, defaults to none) | 233 # initial data (optional, defaults to none) |
232 INITIAL_DATA = None | 234 INITIAL_DATA = None |
235 STATE_KEY = None | |
233 | 236 |
234 def __init__(self): | 237 def __init__(self): |
235 GameDeveloperGizmo.__init__(self) | 238 GameDeveloperGizmo.__init__(self) |
236 self.data = {} | 239 self.state_key = self.STATE_KEY |
237 if self.INITIAL_DATA: | 240 self.state = None # set this with set_state if required |
238 # deep copy of INITIAL_DATA allows lists, sets and | 241 |
239 # other mutable types to safely be used in INITIAL_DATA | 242 def set_state(self, state): |
240 self.data.update(copy.deepcopy(self.INITIAL_DATA)) | 243 """Set the state object and initialize if needed""" |
244 self.state = state | |
245 if self.state_key not in self.state: | |
246 self.state[self.state_key] = {} | |
247 if self.INITIAL_DATA: | |
248 # deep copy of INITIAL_DATA allows lists, sets and | |
249 # other mutable types to safely be used in INITIAL_DATA | |
250 self.state[self.state_key].update( | |
251 copy.deepcopy(self.INITIAL_DATA)) | |
241 | 252 |
242 def set_data(self, key, value): | 253 def set_data(self, key, value): |
243 self.data[key] = value | 254 if self.state: |
255 self.state[self.state_key][key] = value | |
244 | 256 |
245 def get_data(self, key): | 257 def get_data(self, key): |
246 return self.data.get(key, None) | 258 if self.state: |
259 return self.state[self.state_key].get(key, None) | |
247 | 260 |
248 | 261 |
249 class Scene(StatefulGizmo): | 262 class Scene(StatefulGizmo): |
250 """Base class for scenes.""" | 263 """Base class for scenes.""" |
251 | 264 |
263 | 276 |
264 def __init__(self, state): | 277 def __init__(self, state): |
265 StatefulGizmo.__init__(self) | 278 StatefulGizmo.__init__(self) |
266 # scene name | 279 # scene name |
267 self.name = self.NAME if self.NAME is not None else self.FOLDER | 280 self.name = self.NAME if self.NAME is not None else self.FOLDER |
281 self.state_key = self.name | |
268 # map of thing names -> Thing objects | 282 # map of thing names -> Thing objects |
269 self.things = {} | 283 self.things = {} |
270 self._background = None | 284 self._background = None |
271 | 285 |
286 def set_game(self, game): | |
287 super(Scene, self).set_game(game) | |
288 self.set_state(game.data) | |
289 | |
272 def add_item(self, item): | 290 def add_item(self, item): |
273 self.state.add_item(item) | 291 self.game.add_item(item) |
274 | 292 |
275 def add_thing(self, thing): | 293 def add_thing(self, thing): |
276 self.things[thing.name] = thing | 294 self.things[thing.name] = thing |
277 thing.set_state(self.state) | 295 thing.set_game(self.game) |
278 thing.set_scene(self) | 296 thing.set_scene(self) |
279 | 297 |
280 def remove_thing(self, thing): | 298 def remove_thing(self, thing): |
281 del self.things[thing.name] | 299 del self.things[thing.name] |
282 if thing is self.state.current_thing: | 300 if thing is self.game.current_thing: |
283 self.state.current_thing.leave() | 301 self.game.current_thing.leave() |
284 self.state.current_thing = None | 302 self.game.current_thing = None |
285 | 303 |
286 def _get_description(self): | 304 def _get_description(self): |
287 text = (self.state.current_thing and | 305 text = (self.game.current_thing and |
288 self.state.current_thing.get_description()) | 306 self.game.current_thing.get_description()) |
289 if text is None: | 307 if text is None: |
290 return None | 308 return None |
291 label = BoomLabel(text) | 309 label = BoomLabel(text) |
292 label.set_margin(5) | 310 label.set_margin(5) |
293 label.border_width = 1 | 311 label.border_width = 1 |
330 | 348 |
331 Item may be an item in the list of items or None for the hand. | 349 Item may be an item in the list of items or None for the hand. |
332 | 350 |
333 Returns a Result object to provide feedback to the player. | 351 Returns a Result object to provide feedback to the player. |
334 """ | 352 """ |
335 if self.state.current_thing is not None: | 353 if self.game.current_thing is not None: |
336 return self.state.current_thing.interact(item) | 354 return self.game.current_thing.interact(item) |
337 | 355 |
338 def animate(self): | 356 def animate(self): |
339 """Animate all the things in the scene. | 357 """Animate all the things in the scene. |
340 | 358 |
341 Return true if any of them need to queue a redraw""" | 359 Return true if any of them need to queue a redraw""" |
350 | 368 |
351 def leave(self): | 369 def leave(self): |
352 return None | 370 return None |
353 | 371 |
354 def update_current_thing(self, pos): | 372 def update_current_thing(self, pos): |
355 if self.state.current_thing is not None: | 373 if self.game.current_thing is not None: |
356 if not self.state.current_thing.contains(pos): | 374 if not self.game.current_thing.contains(pos): |
357 self.state.current_thing.leave() | 375 self.game.current_thing.leave() |
358 self.state.current_thing = None | 376 self.game.current_thing = None |
359 for thing in self.things.itervalues(): | 377 for thing in self.things.itervalues(): |
360 if thing.contains(pos): | 378 if thing.contains(pos): |
361 thing.enter(self.state.tool) | 379 thing.enter(self.game.tool) |
362 self.state.current_thing = thing | 380 self.game.current_thing = thing |
363 break | 381 break |
364 | 382 |
365 def mouse_move(self, pos): | 383 def mouse_move(self, pos): |
366 """Call to check whether the cursor has entered / exited a thing. | 384 """Call to check whether the cursor has entered / exited a thing. |
367 | 385 |
428 StatefulGizmo.__init__(self) | 446 StatefulGizmo.__init__(self) |
429 # name of the thing | 447 # name of the thing |
430 self.name = self.NAME | 448 self.name = self.NAME |
431 # folder for resource (None is overridden by scene folder) | 449 # folder for resource (None is overridden by scene folder) |
432 self.folder = self.FOLDER | 450 self.folder = self.FOLDER |
451 self.state_key = self.NAME | |
433 # interacts | 452 # interacts |
434 self.interacts = self.INTERACTS | 453 self.interacts = self.INTERACTS |
435 # these are set by set_scene | 454 # these are set by set_scene |
436 self.scene = None | 455 self.scene = None |
437 self.current_interact = None | 456 self.current_interact = None |
451 def set_scene(self, scene): | 470 def set_scene(self, scene): |
452 assert self.scene is None | 471 assert self.scene is None |
453 self.scene = scene | 472 self.scene = scene |
454 if self.folder is None: | 473 if self.folder is None: |
455 self.folder = scene.FOLDER | 474 self.folder = scene.FOLDER |
456 self.state = scene.state | 475 self.game = scene.game |
476 self.set_state(self.game.data) | |
457 for interact in self.interacts.itervalues(): | 477 for interact in self.interacts.itervalues(): |
458 interact.set_thing(self) | 478 interact.set_thing(self) |
459 self.set_interact(self.INITIAL) | 479 self.set_interact(self.INITIAL) |
460 | 480 |
461 def set_interact(self, name): | 481 def set_interact(self, name): |
493 old_rect = self.current_interact.rect | 513 old_rect = self.current_interact.rect |
494 if old_rect: | 514 if old_rect: |
495 self.current_interact.rect = old_rect.move(self.scene.OFFSET) | 515 self.current_interact.rect = old_rect.move(self.scene.OFFSET) |
496 self.current_interact.draw(surface) | 516 self.current_interact.draw(surface) |
497 self.current_interact.rect = old_rect | 517 self.current_interact.rect = old_rect |
498 if self.state.debug_rects and self._interact_hilight_color: | 518 if self.game.debug_rects and self._interact_hilight_color: |
499 if hasattr(self.rect, 'collidepoint'): | 519 if hasattr(self.rect, 'collidepoint'): |
500 frame_rect(surface, self._interact_hilight_color, | 520 frame_rect(surface, self._interact_hilight_color, |
501 self.rect.inflate(1, 1), 1) | 521 self.rect.inflate(1, 1), 1) |
502 else: | 522 else: |
503 for rect in self.rect: | 523 for rect in self.rect: |