# HG changeset patch # User Jeremy Thurgood # Date 1283947331 -7200 # Node ID 821b322e903b370545fab56d207b4296b0a6176b # Parent a91cb4bffd5d614fde9d56a64c07ddc5e0944d7a Separate "scene widgets" from "game-specific widgets". diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/bridge.py --- a/gamelib/scenes/bridge.py Wed Sep 08 00:59:51 2010 +0200 +++ b/gamelib/scenes/bridge.py Wed Sep 08 14:02:11 2010 +0200 @@ -12,12 +12,12 @@ from gamelib.state import Scene, Item, Thing, Result from gamelib.sound import get_current_playlist from gamelib.constants import DEBUG +from gamelib.scenewidgets import (InteractText, InteractNoImage, + InteractRectUnion, InteractImage, + InteractAnimated, GenericDescThing) from gamelib.scenes.game_constants import PLAYER_ID -from gamelib.scenes.scene_widgets import (Door, InteractText, InteractNoImage, - InteractRectUnion, InteractImage, - InteractAnimated, GenericDescThing, - BaseCamera, make_jim_dialog) +from gamelib.scenes.game_widgets import Door, BaseCamera, make_jim_dialog class Bridge(Scene): diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/crew_quarters.py --- a/gamelib/scenes/crew_quarters.py Wed Sep 08 00:59:51 2010 +0200 +++ b/gamelib/scenes/crew_quarters.py Wed Sep 08 14:02:11 2010 +0200 @@ -2,12 +2,12 @@ from gamelib.cursor import CursorSprite from gamelib.state import Scene, Item, Thing, Result +from gamelib.scenewidgets import (InteractText, InteractNoImage, + InteractRectUnion, InteractImage, + InteractAnimated, GenericDescThing) from gamelib.scenes.game_constants import PLAYER_ID -from gamelib.scenes.scene_widgets import (Door, InteractText, InteractNoImage, - InteractRectUnion, InteractImage, - InteractAnimated, GenericDescThing, - BaseCamera, make_jim_dialog) +from gamelib.scenes.game_widgets import Door, BaseCamera, make_jim_dialog class CrewQuarters(Scene): diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/cryo.py --- a/gamelib/scenes/cryo.py Wed Sep 08 00:59:51 2010 +0200 +++ b/gamelib/scenes/cryo.py Wed Sep 08 14:02:11 2010 +0200 @@ -10,11 +10,12 @@ from gamelib.cursor import CursorSprite from gamelib.state import Scene, Item, CloneableItem, Thing, Result from gamelib.constants import DEBUG +from gamelib.scenewidgets import (InteractText, InteractNoImage, + InteractRectUnion, InteractImage, + InteractAnimated, GenericDescThing) + from gamelib.scenes.game_constants import PLAYER_ID -from gamelib.scenes.scene_widgets import (Door, InteractText, InteractNoImage, - InteractRectUnion, InteractImage, - InteractAnimated, GenericDescThing, - make_jim_dialog) +from gamelib.scenes.game_widgets import Door, make_jim_dialog class Cryo(Scene): diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/engine.py --- a/gamelib/scenes/engine.py Wed Sep 08 00:59:51 2010 +0200 +++ b/gamelib/scenes/engine.py Wed Sep 08 14:02:11 2010 +0200 @@ -3,11 +3,12 @@ from albow.resource import get_image from gamelib.cursor import CursorSprite from gamelib.state import Scene, Item, Thing, Result +from gamelib.scenewidgets import (InteractText, InteractNoImage, + InteractRectUnion, InteractImage, + InteractAnimated, GenericDescThing) + from gamelib.scenes.game_constants import PLAYER_ID -from gamelib.scenes.scene_widgets import (Door, InteractText, InteractNoImage, - InteractRectUnion, InteractImage, - InteractAnimated, GenericDescThing, - make_jim_dialog) +from gamelib.scenes.game_widgets import Door, make_jim_dialog class Engine(Scene): diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/game_widgets.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gamelib/scenes/game_widgets.py Wed Sep 08 14:02:11 2010 +0200 @@ -0,0 +1,72 @@ +"""Generic, game specific widgets""" + + +from gamelib.state import Thing, Result + + +class Door(Thing): + """A door somewhere""" + + DEST = "map" + SCENE = None + + def __init__(self): + self.NAME = self.SCENE + '.door' + Thing.__init__(self) + + def is_interactive(self, tool=None): + return True + + def interact_without(self): + """Go to map.""" + self.state.set_current_scene("map") + + def get_description(self): + return 'An open doorway leads to the rest of the ship.' + + def interact_default(self, item): + return self.interact_without() + + +def make_jim_dialog(mesg, state): + "Utility helper function" + if state.scenes['bridge'].get_data('ai status') == 'online': + return Result(mesg, style='JIM') + else: + return None + + +class BaseCamera(Thing): + "Base class for the camera puzzles" + + INITIAL = 'online' + INITIAL_DATA = { + 'state': 'online', + } + + def get_description(self): + status = self.state.scenes['bridge'].get_data('ai status') + if status == 'online': + return "A security camera watches over the room" + elif status == 'looping': + return "The security camera is currently offline but should be working soon" + else: + return "The security camera is powered down" + + def is_interactive(self, tool=None): + return self.state.scenes['bridge'].get_data('ai status') == 'online' + + def interact_with_escher_poster(self, item): + # Order matters here, because of helper function + if self.state.scenes['bridge'].get_data('ai status') == 'online': + ai_response = make_jim_dialog("3D scene reconstruction failed. Critical error. Entering emergency shutdown.", self.state) + self.state.scenes['bridge'].set_data('ai status', 'looping') + return ai_response + + def animate(self): + ai_status = self.state.scenes['bridge'].get_data('ai status') + if ai_status != self.get_data('status'): + self.set_data('status', ai_status) + self.set_interact(ai_status) + super(BaseCamera, self).animate() + diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/machine.py --- a/gamelib/scenes/machine.py Wed Sep 08 00:59:51 2010 +0200 +++ b/gamelib/scenes/machine.py Wed Sep 08 14:02:11 2010 +0200 @@ -2,9 +2,11 @@ from gamelib.state import Scene, Item, Thing, Result from gamelib.cursor import CursorSprite -from gamelib.scenes.scene_widgets import (Door, InteractText, InteractNoImage, - InteractRectUnion, InteractImage, - InteractAnimated, GenericDescThing) +from gamelib.scenewidgets import (InteractText, InteractNoImage, + InteractRectUnion, InteractImage, + InteractAnimated, GenericDescThing) + +from gamelib.scenes.game_widgets import Door class Machine(Scene): diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/manual.py --- a/gamelib/scenes/manual.py Wed Sep 08 00:59:51 2010 +0200 +++ b/gamelib/scenes/manual.py Wed Sep 08 14:02:11 2010 +0200 @@ -8,12 +8,9 @@ from gamelib.cursor import CursorSprite from gamelib.state import Scene, Item, Thing, Result from gamelib.sound import get_current_playlist +from gamelib.scenewidgets import InteractNoImage, InteractImage from gamelib.scenes.game_constants import PLAYER_ID -from gamelib.scenes.scene_widgets import (Door, InteractText, InteractNoImage, - InteractRectUnion, InteractImage, - InteractAnimated, GenericDescThing, - BaseCamera, make_jim_dialog) # classes related the computer detail diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/map.py --- a/gamelib/scenes/map.py Wed Sep 08 00:59:51 2010 +0200 +++ b/gamelib/scenes/map.py Wed Sep 08 14:02:11 2010 +0200 @@ -8,11 +8,10 @@ """ from gamelib.state import Scene, Item, Thing, Result +from gamelib.scenewidgets import InteractRectUnion + from gamelib.scenes.game_constants import PLAYER_ID -from gamelib.scenes.scene_widgets import (Door, InteractText, InteractNoImage, - InteractRectUnion, InteractImage, - InteractAnimated, GenericDescThing, - make_jim_dialog) +from gamelib.scenes.game_widgets import make_jim_dialog class Map(Scene): diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/mess.py --- a/gamelib/scenes/mess.py Wed Sep 08 00:59:51 2010 +0200 +++ b/gamelib/scenes/mess.py Wed Sep 08 14:02:11 2010 +0200 @@ -4,14 +4,15 @@ from gamelib.state import Scene, Item, CloneableItem, Thing, Result from gamelib.cursor import CursorSprite -from gamelib.scenes.scene_widgets import (Door, InteractText, InteractNoImage, - InteractRectUnion, InteractImage, - InteractImageRect, InteractAnimated, - GenericDescThing) - from gamelib.sound import get_sound from gamelib import constants +from gamelib.scenewidgets import (InteractText, InteractNoImage, + InteractRectUnion, InteractImage, + InteractImageRect, InteractAnimated, + GenericDescThing) + from gamelib.scenes.game_constants import PLAYER_ID +from gamelib.scenes.game_widgets import Door class Mess(Scene): diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenes/scene_widgets.py --- a/gamelib/scenes/scene_widgets.py Wed Sep 08 00:59:51 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,218 +0,0 @@ -"""Generic, game specific widgets""" - -import random - -from pygame import Rect -from pygame.color import Color -from pygame.colordict import THECOLORS -from pygame.surface import Surface -from albow.resource import get_image - -from gamelib.state import Thing, Result -from gamelib.constants import DEBUG -from gamelib.widgets import BoomLabel - - -class Interact(object): - - def __init__(self, image, rect, interact_rect): - self.image = image - self.rect = rect - self.interact_rect = interact_rect - - def set_thing(self, thing): - pass - - def draw(self, surface): - if self.image is not None: - surface.blit(self.image, self.rect, None) - - def animate(self): - return False - - -class InteractNoImage(Interact): - - def __init__(self, x, y, w, h): - super(InteractNoImage, self).__init__(None, None, Rect(x, y, w, h)) - - -class InteractText(Interact): - """Display box with text to interact with -- mostly for debugging.""" - - def __init__(self, x, y, text, bg_color=None): - if bg_color is None: - bg_color = (127, 127, 127) - label = BoomLabel(text) - label.set_margin(5) - label.border_width = 1 - label.border_color = (0, 0, 0) - label.bg_color = bg_color - label.fg_color = (0, 0, 0) - image = Surface(label.size) - rect = Rect((x, y), label.size) - label.draw_all(image) - super(InteractText, self).__init__(image, rect, rect) - - -class InteractRectUnion(Interact): - - def __init__(self, rect_list): - # pygame.rect.Rect.unionall should do this, but is broken - # in some pygame versions (including 1.8, it appears) - rect_list = [Rect(x) for x in rect_list] - union_rect = rect_list[0] - for rect in rect_list[1:]: - union_rect = union_rect.union(rect) - super(InteractRectUnion, self).__init__(None, None, union_rect) - self.interact_rect = rect_list - - -class InteractImage(Interact): - - def __init__(self, x, y, image_name): - super(InteractImage, self).__init__(None, None, None) - self._pos = (x, y) - self._image_name = image_name - - def set_thing(self, thing): - self.image = get_image(thing.folder, self._image_name) - self.rect = Rect(self._pos, self.image.get_size()) - self.interact_rect = self.rect - - -class InteractImageRect(InteractImage): - def __init__(self, x, y, image_name, r_x, r_y, r_w, r_h): - super(InteractImageRect, self).__init__(x, y, image_name) - self._r_pos = (r_x, r_y) - self._r_size = (r_w, r_h) - - def set_thing(self, thing): - super(InteractImageRect, self).set_thing(thing) - self.interact_rect = Rect(self._r_pos, self._r_size) - - -class InteractAnimated(Interact): - """Interactive with an animation rather than an image""" - - # FIXME: Assumes all images are the same size - # anim_seq - sequence of image names - # delay - number of frames to wait between changing images - - def __init__(self, x, y, anim_seq, delay): - self._pos = (x, y) - self._anim_pos = 0 - self._names = anim_seq - self._frame_count = 0 - self._anim_seq = None - self._delay = delay - - def set_thing(self, thing): - self._anim_seq = [get_image(thing.folder, x) for x in self._names] - self.image = self._anim_seq[0] - self.rect = Rect(self._pos, self.image.get_size()) - self.interact_rect = self.rect - - def animate(self): - if self._anim_seq: - self._frame_count += 1 - if self._frame_count > self._delay: - self._frame_count = 0 - self._anim_pos += 1 - if self._anim_pos >= len(self._anim_seq): - self._anim_pos = 0 - self.image = self._anim_seq[self._anim_pos] - # queue redraw - return True - return False - - -class GenericDescThing(Thing): - "Thing with an InteractiveUnionRect and a description" - - INITIAL = "description" - - def __init__(self, prefix, number, description, areas): - super(GenericDescThing, self).__init__() - self.description = description - self.name = '%s.%s' % (prefix, number) - self.interacts = { - 'description' : InteractRectUnion(areas) - } - if DEBUG: - # Individual colors to make debugging easier - self._interact_hilight_color = Color(THECOLORS.keys()[number]) - - def get_description(self): - return self.description - - def is_interactive(self, tool=None): - return False - - -class Door(Thing): - """A door somewhere""" - - DEST = "map" - SCENE = None - - def __init__(self): - self.NAME = self.SCENE + '.door' - Thing.__init__(self) - - def is_interactive(self, tool=None): - return True - - def interact_without(self): - """Go to map.""" - self.state.set_current_scene("map") - - def get_description(self): - return 'An open doorway leads to the rest of the ship.' - - def interact_default(self, item): - return self.interact_without() - - -def make_jim_dialog(mesg, state): - "Utility helper function" - if state.scenes['bridge'].get_data('ai status') == 'online': - return Result(mesg, style='JIM') - else: - return None - - -class BaseCamera(Thing): - "Base class for the camera puzzles" - - INITIAL = 'online' - INITIAL_DATA = { - 'state': 'online', - } - - def get_description(self): - status = self.state.scenes['bridge'].get_data('ai status') - if status == 'online': - return "A security camera watches over the room" - elif status == 'looping': - return "The security camera is currently offline but should be working soon" - else: - return "The security camera is powered down" - - def is_interactive(self, tool=None): - return self.state.scenes['bridge'].get_data('ai status') == 'online' - - def interact_with_escher_poster(self, item): - # Order matters here, because of helper function - if self.state.scenes['bridge'].get_data('ai status') == 'online': - ai_response = make_jim_dialog("3D scene reconstruction failed. Critical error. Entering emergency shutdown.", self.state) - self.state.scenes['bridge'].set_data('ai status', 'looping') - return ai_response - - def animate(self): - ai_status = self.state.scenes['bridge'].get_data('ai status') - if ai_status != self.get_data('status'): - self.set_data('status', ai_status) - self.set_interact(ai_status) - super(BaseCamera, self).animate() - diff -r a91cb4bffd5d -r 821b322e903b gamelib/scenewidgets.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gamelib/scenewidgets.py Wed Sep 08 14:02:11 2010 +0200 @@ -0,0 +1,150 @@ +"""Interactive elements within a Scene.""" + + +from pygame import Rect +from pygame.color import Color +from pygame.colordict import THECOLORS +from pygame.surface import Surface +from albow.resource import get_image + +from gamelib.state import Thing +from gamelib.constants import DEBUG +from gamelib.widgets import BoomLabel + + +class Interact(object): + + def __init__(self, image, rect, interact_rect): + self.image = image + self.rect = rect + self.interact_rect = interact_rect + + def set_thing(self, thing): + pass + + def draw(self, surface): + if self.image is not None: + surface.blit(self.image, self.rect, None) + + def animate(self): + return False + + +class InteractNoImage(Interact): + + def __init__(self, x, y, w, h): + super(InteractNoImage, self).__init__(None, None, Rect(x, y, w, h)) + + +class InteractText(Interact): + """Display box with text to interact with -- mostly for debugging.""" + + def __init__(self, x, y, text, bg_color=None): + if bg_color is None: + bg_color = (127, 127, 127) + label = BoomLabel(text) + label.set_margin(5) + label.border_width = 1 + label.border_color = (0, 0, 0) + label.bg_color = bg_color + label.fg_color = (0, 0, 0) + image = Surface(label.size) + rect = Rect((x, y), label.size) + label.draw_all(image) + super(InteractText, self).__init__(image, rect, rect) + + +class InteractRectUnion(Interact): + + def __init__(self, rect_list): + # pygame.rect.Rect.unionall should do this, but is broken + # in some pygame versions (including 1.8, it appears) + rect_list = [Rect(x) for x in rect_list] + union_rect = rect_list[0] + for rect in rect_list[1:]: + union_rect = union_rect.union(rect) + super(InteractRectUnion, self).__init__(None, None, union_rect) + self.interact_rect = rect_list + + +class InteractImage(Interact): + + def __init__(self, x, y, image_name): + super(InteractImage, self).__init__(None, None, None) + self._pos = (x, y) + self._image_name = image_name + + def set_thing(self, thing): + self.image = get_image(thing.folder, self._image_name) + self.rect = Rect(self._pos, self.image.get_size()) + self.interact_rect = self.rect + + +class InteractImageRect(InteractImage): + def __init__(self, x, y, image_name, r_x, r_y, r_w, r_h): + super(InteractImageRect, self).__init__(x, y, image_name) + self._r_pos = (r_x, r_y) + self._r_size = (r_w, r_h) + + def set_thing(self, thing): + super(InteractImageRect, self).set_thing(thing) + self.interact_rect = Rect(self._r_pos, self._r_size) + + +class InteractAnimated(Interact): + """Interactive with an animation rather than an image""" + + # FIXME: Assumes all images are the same size + # anim_seq - sequence of image names + # delay - number of frames to wait between changing images + + def __init__(self, x, y, anim_seq, delay): + self._pos = (x, y) + self._anim_pos = 0 + self._names = anim_seq + self._frame_count = 0 + self._anim_seq = None + self._delay = delay + + def set_thing(self, thing): + self._anim_seq = [get_image(thing.folder, x) for x in self._names] + self.image = self._anim_seq[0] + self.rect = Rect(self._pos, self.image.get_size()) + self.interact_rect = self.rect + + def animate(self): + if self._anim_seq: + self._frame_count += 1 + if self._frame_count > self._delay: + self._frame_count = 0 + self._anim_pos += 1 + if self._anim_pos >= len(self._anim_seq): + self._anim_pos = 0 + self.image = self._anim_seq[self._anim_pos] + # queue redraw + return True + return False + + +class GenericDescThing(Thing): + "Thing with an InteractiveUnionRect and a description" + + INITIAL = "description" + + def __init__(self, prefix, number, description, areas): + super(GenericDescThing, self).__init__() + self.description = description + self.name = '%s.%s' % (prefix, number) + self.interacts = { + 'description' : InteractRectUnion(areas) + } + if DEBUG: + # Individual colors to make debugging easier + self._interact_hilight_color = Color(THECOLORS.keys()[number]) + + def get_description(self): + return self.description + + def is_interactive(self, tool=None): + return False +