Esempio n. 1
0
class Application(BaseApplication.BaseApplication):
    """The application class represents a group of browser windows."""
    def __init__(self, prefs=None, display=None):
        self.root = Tk(className='Grail', screenName=display)
        self.root.withdraw()
        resources = os.path.join(script_dir, "data", "Grail.ad")
        if os.path.isfile(resources):
            self.root.option_readfile(resources, "startupFile")
        BaseApplication.BaseApplication.__init__(self, prefs)
        # The stylesheet must be initted before any Viewers, so it
        # registers its' prefs callbacks first, hence reloads before the
        # viewers reconfigure w.r.t. the new styles.
        self.stylesheet = Stylesheet.Stylesheet(self.prefs)
        self.load_images = 1  # Overridden by cmd line or pref.

        # socket management
        sockets = self.prefs.GetInt('sockets', 'number')
        self.sq = SocketQueue(sockets)
        self.prefs.AddGroupCallback('sockets',
                                    lambda self=self: \
                                    self.sq.change_max(
                                        self.prefs.GetInt('sockets',
                                                          'number')))

        # initialize on_exit_methods before global_history
        self.on_exit_methods = []
        self.global_history = GlobalHistory.GlobalHistory(self)
        self.login_cache = {}
        self.rexec_cache = {}
        self.url_cache = CacheManager(self)
        self.image_cache = ImageCache(self.url_cache)
        self.auth = AuthenticationManager(self)
        self.root.report_callback_exception = self.report_callback_exception
        if sys.stdin.isatty():
            # only useful if stdin might generate KeyboardInterrupt
            self.keep_alive()
        self.browsers = []
        self.iostatuspanel = None
        self.in_exception_dialog = None
        from ancillary import Greek
        for k, v in Greek.entitydefs.items():
            Application.dingbatimages[k] = (v, '_sym')
        self.root.bind_class("Text", "<Alt-Left>", self.dummy_event)
        self.root.bind_class("Text", "<Alt-Right>", self.dummy_event)

    def dummy_event(self, event):
        pass

    def register_on_exit(self, method):
        self.on_exit_methods.append(method)

    def unregister_on_exit(self, method):
        try:
            self.on_exit_methods.remove(method)
        except ValueError:
            pass

    def exit_notification(self):
        for m in self.on_exit_methods[:]:
            try:
                m()
            except:
                pass

    def add_browser(self, browser):
        self.browsers.append(browser)

    def del_browser(self, browser):
        try:
            self.browsers.remove(browser)
        except ValueError:
            pass

    def quit(self):
        self.root.quit()

    def open_io_status_panel(self):
        if not self.iostatuspanel:
            from ancillary import IOStatusPanel
            self.iostatuspanel = IOStatusPanel.IOStatusPanel(self)
        else:
            self.iostatuspanel.reopen()

    def maybe_quit(self):
        if not (self.embedded or self.browsers):
            self.quit()

    def go(self):
        try:
            try:
                if ilu_tk:
                    ilu_tk.RunMainLoop()
                else:
                    self.root.mainloop()
            except KeyboardInterrupt:
                pass
        finally:
            self.exit_notification()

    def keep_alive(self):
        # Exercise the Python interpreter regularly so keyboard
        # interrupts get through
        self.root.tk.createtimerhandler(KEEPALIVE_TIMER, self.keep_alive)

    def get_cached_image(self, url):
        return self.image_cache.get_image(url)

    def set_cached_image(self, url, image, owner=None):
        self.image_cache.set_image(url, image, owner)

    def open_url(self, url, method, params, reload=0, data=None):
        api = self.url_cache.open(url, method, params, reload, data=data)
        api._url_ = url
        return api

    def open_url_simple(self, url):
        api = self.open_url(url, 'GET', {})
        errcode, errmsg, meta = api.getmeta()
        if errcode != 200:
            raise IOError(('url open error', errcode, errmsg, meta))
        return URLReadWrapper(api, meta)

    def get_cache_keys(self):
        """For applets."""
        return self.url_cache.items.keys()

    def decode_pipeline(self, fp, content_encoding, error=1):
        if self.decode_prog.has_key(content_encoding):
            prog = self.decode_prog[content_encoding]
            if not prog: return fp
            tfn = tempfile.mktemp()
            ok = 0
            try:
                temp = open(tfn, 'w')
                BUFSIZE = 8192
                while 1:
                    buf = fp.read(BUFSIZE)
                    if not buf: break
                    temp.write(buf)
                temp.close()
                ok = 1
            finally:
                if not ok:
                    try:
                        os.unlink(tfn)
                    except os.error:
                        pass
            pipeline = '%s <%s; rm -f %s' % (prog, tfn, tfn)
            # XXX What if prog fails?
            return os.popen(pipeline, 'r')
        if error:
            self.error_dialog(
                IOError,
                "Can't decode content-encoding: %s" % content_encoding)
        return None

    decode_prog = {
        'gzip': 'gzip -d',
        'x-gzip': 'gzip -d',
        'compress': 'compress -d',
        'x-compress': 'compress -d',
    }

    def exception_dialog(self, message="", root=None):
        exc, val, tb = sys.exc_type, sys.exc_value, sys.exc_traceback
        self.exc_dialog(message, exc, val, tb, root)

    def report_callback_exception(self, exc, val, tb, root=None):
        self.exc_dialog("in a callback function", exc, val, tb, root)

    def exc_dialog(self, message, exc, val, tb, root=None):
        if self.in_exception_dialog:
            print()
            print("*** Recursive exception", message)
            import traceback
            traceback.print_exception(exc, val, tb)
            return
        self.in_exception_dialog = 1

        def f(s=self, m=message, e=exc, v=val, t=tb, root=root):
            s._exc_dialog(m, e, v, t, root)

        if TkVersion >= 4.1:
            self.root.after_idle(f)
        else:
            self.root.after(0, f)

    def _exc_dialog(self, message, exc, val, tb, root=None):
        # XXX This needn't be a modal dialog --
        # XXX should SafeDialog be changed to support callbacks?
        from utils import SafeDialog
        msg = "An exception occurred " + str(message) + " :\n"
        msg = msg + str(exc) + " : " + str(val)
        dlg = SafeDialog.Dialog(
            root or self.root,
            text=msg,
            title="Python Exception: " + str(exc),
            bitmap='error',
            default=0,
            strings=("OK", "Show traceback"),
        )
        self.in_exception_dialog = 0
        if dlg.num == 1:
            self.traceback_dialog(exc, val, tb)

    def traceback_dialog(self, exc, val, tb):
        # XXX This could actually just create a new Browser window...
        from utils import TbDialog
        TbDialog.TracebackDialog(self.root, exc, val, tb)

    def error_dialog(self, exc, msg, root=None):
        # Display an error dialog.
        # Return when the user clicks OK
        # XXX This needn't be a modal dialog
        from utils import SafeDialog
        if type(msg) in (List, Tuple):
            s = ''
            for item in msg:
                s = s + ':\n' + str(item)
            msg = s[2:]
        else:
            msg = str(msg)
        SafeDialog.Dialog(
            root or self.root,
            text=msg,
            title="Error: " + str(exc),
            bitmap='error',
            default=0,
            strings=('OK', ),
        )

    dingbatimages = {
        'ldots': ('...', None),  # math stuff
        'sp': (' ', None),
        'hairsp': ('\240', None),
        'thinsp': ('\240', None),
        'emdash': ('--', None),
        'endash': ('-', None),
        'mdash': ('--', None),
        'ndash': ('-', None),
        'ensp': (' ', None)
    }

    def clear_dingbat(self, entname):
        if self.dingbatimages.has_key(entname):
            del self.dingbatimages[entname]

    def set_dingbat(self, entname, entity):
        self.dingbatimages[entname] = entity

    def load_dingbat(self, entname):
        if self.dingbatimages.has_key(entname):
            return self.dingbatimages[entname]
        gifname = grailutil.which(entname + '.gif', self.iconpath)
        if gifname:
            img = PhotoImage(file=gifname, master=self.root)
            self.dingbatimages[entname] = img
            return img
        self.dingbatimages[entname] = None
        return None
Esempio n. 2
0
class Game:
    tile_dir = "data/images/tiles/"
    ui_dir = "data/images/ui/"

    def __init__(self):

        # Define window properties
        self.window_size = self.window_width, self.window_height = 640, 640
        self.tile_size = 32
        self.depth = 0
        self.flags = 0
        self.fps = 60

        # Initialize pygame
        pygame.init()

        # Define basic pygame properties
        self.screen = pygame.display.set_mode(self.window_size, self.flags, self.depth)
        self.clock = pygame.time.Clock()

        # Load the image cache
        self.tile_cache = ImageCache(Game.tile_dir)
        self.ui_cache = ImageCache(Game.ui_dir)

        # Define the key entities and default to None until we start the main game loop
        self.player = None

    def main_menu_loop(self):
        start_game = False

        # Create buttons with the static callback functions
        new_game_img = self.ui_cache.get_image("new_game_but")
        new_game_img_hov = self.ui_cache.get_image("new_game_but_hover")
        new_game_button = Button(self.get_half_width(), self.get_half_height() - 50,
                                 new_game_img, new_game_img_hov, 200, 50, start_game_cb)

        quit_img = self.ui_cache.get_image("quit_but")
        quit_img_hover = self.ui_cache.get_image("quit_but_hover")
        quit_button = Button(self.get_half_width(), self.get_half_height() + 10,
                             quit_img, quit_img_hover, 200, 50, quit_game)

        # Define sprite group for buttons to easily draw
        button_entities = pygame.sprite.Group()
        button_entities.add((new_game_button, quit_button))

        # Retrieve other UI images from cache
        bg_img = self.ui_cache.get_image("menu_bg")
        credits_img = self.ui_cache.get_image("credits")

        # Only draw background and other static images once to screen
        self.screen.blit(bg_img, (0, 0))
        self.screen.blit(credits_img, (20, self.window_height - 50))

        # Set the screen title
        pygame.display.set_caption("The Forming")

        while not start_game:
            self.clock.tick(self.fps)
            mouse_clicked = False

            # Loop through all events
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                if event.type == pygame.MOUSEBUTTONDOWN:
                    mouse_clicked = True
                if event.type == pygame.KEYDOWN:
                    pass

            # Update the buttons. Start game will return True if clicked, exiting the menu loop
            start_game = new_game_button.update(pygame.mouse.get_pos(), mouse_clicked)
            quit_button.update(pygame.mouse.get_pos(), mouse_clicked)

            button_entities.draw(self.screen)

            pygame.display.flip()

        self.main_game_loop()

    def main_game_loop(self):

        # Define the entity groups
        character_entities = pygame.sprite.Group()  # All character entities (including Player.py)
        built_entities = pygame.sprite.Group()  # Anything the player has built

        # Build the level
        level = Level()
        level.generate(self.tile_cache)

        # Create the player
        player_sprites = "data/images/player/"
        camera = Camera(main_camera, level.width * self.tile_size, level.height * self.tile_size,
                        self.window_width, self.window_height)
        self.player = Player(32, 32, player_sprites, self.tile_size, self.tile_size, 2, camera)
        character_entities.add(self.player)

        # Create cursor entity for better collisions
        cursor = Cursor()

        game_running = True

        up, down, left, right = 0, 0, 0, 0

        while game_running:

            # Reset game variables
            mouse_clicked = False

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    quit_game()

                # Key down events
                if event.type == pygame.KEYDOWN:

                    if event.key in (pygame.K_UP, pygame.K_w):
                        up = 1
                    if event.key in (pygame.K_DOWN, pygame.K_s):
                        down = 1
                    if event.key in (pygame.K_LEFT, pygame.K_a):
                        left = 1
                    if event.key in (pygame.K_RIGHT, pygame.K_d):
                        right = 1

                # Key up events
                if event.type == pygame.KEYUP:

                    if event.key in (pygame.K_UP, pygame.K_w):
                        up = 0
                    if event.key in (pygame.K_DOWN, pygame.K_s):
                        down = 0
                    if event.key in (pygame.K_LEFT, pygame.K_a):
                        left = 0
                    if event.key in (pygame.K_RIGHT, pygame.K_d):
                        right = 0

            cursor.update()

            for tile in level.terrain:
                self.screen.blit(tile.image, self.player.camera.apply(tile))

            for tile in level.obstacles:
                self.screen.blit(tile.image, self.player.camera.apply(tile))

            for character in character_entities:
                self.screen.blit(character.image, self.player.camera.apply(character))

            self.player.update(up, down, left, right, level.obstacles)

            pygame.display.flip()

        self.main_menu_loop()

    def get_half_width(self):
        return self.window_width / 2

    def get_half_height(self):
        return self.window_height / 2
Esempio n. 3
0
class Application(BaseApplication.BaseApplication):

    """The application class represents a group of browser windows."""

    def __init__(self, prefs=None, display=None):
        self.root = Tk(className='Grail', screenName=display)
        self.root.withdraw()
        resources = os.path.join(script_dir, "data", "Grail.ad")
        if os.path.isfile(resources):
            self.root.option_readfile(resources, "startupFile")
        BaseApplication.BaseApplication.__init__(self, prefs)
        # The stylesheet must be initted before any Viewers, so it
        # registers its' prefs callbacks first, hence reloads before the
        # viewers reconfigure w.r.t. the new styles.
        self.stylesheet = Stylesheet.Stylesheet(self.prefs)
        self.load_images = 1            # Overridden by cmd line or pref.

        # socket management
        sockets = self.prefs.GetInt('sockets', 'number')
        self.sq = SocketQueue(sockets)
        self.prefs.AddGroupCallback('sockets',
                                    lambda self=self: \
                                    self.sq.change_max(
                                        self.prefs.GetInt('sockets',
                                                          'number')))

        # initialize on_exit_methods before global_history
        self.on_exit_methods = []
        self.global_history = GlobalHistory.GlobalHistory(self)
        self.login_cache = {}
        self.rexec_cache = {}
        self.url_cache = CacheManager(self)
        self.image_cache = ImageCache(self.url_cache)
        self.auth = AuthenticationManager(self)
        self.root.report_callback_exception = self.report_callback_exception
        if sys.stdin.isatty():
            # only useful if stdin might generate KeyboardInterrupt
            self.keep_alive()
        self.browsers = []
        self.iostatuspanel = None
        self.in_exception_dialog = None
        import Greek
        for k, v in Greek.entitydefs.items():
            Application.dingbatimages[k] = (v, '_sym')
        self.root.bind_class("Text", "<Alt-Left>", self.dummy_event)
        self.root.bind_class("Text", "<Alt-Right>", self.dummy_event)

    def dummy_event(self, event):
        pass

    def register_on_exit(self, method):
        self.on_exit_methods.append(method)
    def unregister_on_exit(self, method):
        try: self.on_exit_methods.remove(method)
        except ValueError: pass
    def exit_notification(self):
        for m in self.on_exit_methods[:]:
            try: m()
            except: pass

    def add_browser(self, browser):
        self.browsers.append(browser)

    def del_browser(self, browser):
        try: self.browsers.remove(browser)
        except ValueError: pass

    def quit(self):
        self.root.quit()

    def open_io_status_panel(self):
        if not self.iostatuspanel:
            import IOStatusPanel
            self.iostatuspanel = IOStatusPanel.IOStatusPanel(self)
        else:
            self.iostatuspanel.reopen()

    def maybe_quit(self):
        if not (self.embedded or self.browsers):
            self.quit()

    def go(self):
        try:
            try:
                if ilu_tk:
                    ilu_tk.RunMainLoop()
                else:
                    self.root.mainloop()
            except KeyboardInterrupt:
                pass
        finally:
            self.exit_notification()

    def keep_alive(self):
        # Exercise the Python interpreter regularly so keyboard
        # interrupts get through
        self.root.tk.createtimerhandler(KEEPALIVE_TIMER, self.keep_alive)

    def get_cached_image(self, url):
        return self.image_cache.get_image(url)

    def set_cached_image(self, url, image, owner=None):
        self.image_cache.set_image(url, image, owner)

    def open_url(self, url, method, params, reload=0, data=None):
        api = self.url_cache.open(url, method, params, reload, data=data)
        api._url_ = url
        return api

    def open_url_simple(self, url):
        api = self.open_url(url, 'GET', {})
        errcode, errmsg, meta = api.getmeta()
        if errcode != 200:
            raise IOError, ('url open error', errcode, errmsg, meta)
        return URLReadWrapper(api, meta)

    def get_cache_keys(self):
        """For applets."""
        return self.url_cache.items.keys()

    def decode_pipeline(self, fp, content_encoding, error=1):
        if self.decode_prog.has_key(content_encoding):
            prog = self.decode_prog[content_encoding]
            if not prog: return fp
            tfn = tempfile.mktemp()
            ok = 0
            try:
                temp = open(tfn, 'w')
                BUFSIZE = 8192
                while 1:
                        buf = fp.read(BUFSIZE)
                        if not buf: break
                        temp.write(buf)
                temp.close()
                ok = 1
            finally:
                if not ok:
                    try:
                        os.unlink(tfn)
                    except os.error:
                        pass
            pipeline = '%s <%s; rm -f %s' % (prog, tfn, tfn)
            # XXX What if prog fails?
            return os.popen(pipeline, 'r')
        if error:
            self.error_dialog(IOError,
                "Can't decode content-encoding: %s" % content_encoding)
        return None

    decode_prog = {
        'gzip': 'gzip -d',
        'x-gzip': 'gzip -d',
        'compress': 'compress -d',
        'x-compress': 'compress -d',
        }

    def exception_dialog(self, message="", root=None):
        exc, val, tb = sys.exc_type, sys.exc_value, sys.exc_traceback
        self.exc_dialog(message, exc, val, tb, root)

    def report_callback_exception(self, exc, val, tb, root=None):
        self.exc_dialog("in a callback function", exc, val, tb, root)

    def exc_dialog(self, message, exc, val, tb, root=None):
        if self.in_exception_dialog:
            print
            print "*** Recursive exception", message
            import traceback
            traceback.print_exception(exc, val, tb)
            return
        self.in_exception_dialog = 1
        def f(s=self, m=message, e=exc, v=val, t=tb, root=root):
            s._exc_dialog(m, e, v, t, root)
        if TkVersion >= 4.1:
            self.root.after_idle(f)
        else:
            self.root.after(0, f)

    def _exc_dialog(self, message, exc, val, tb, root=None):
        # XXX This needn't be a modal dialog --
        # XXX should SafeDialog be changed to support callbacks?
        import SafeDialog
        msg = "An exception occurred " + str(message) + " :\n"
        msg = msg + str(exc) + " : " + str(val)
        dlg = SafeDialog.Dialog(root or self.root,
                                text=msg,
                                title="Python Exception: " + str(exc),
                                bitmap='error',
                                default=0,
                                strings=("OK", "Show traceback"),
                                )
        self.in_exception_dialog = 0
        if dlg.num == 1:
            self.traceback_dialog(exc, val, tb)

    def traceback_dialog(self, exc, val, tb):
        # XXX This could actually just create a new Browser window...
        import TbDialog
        TbDialog.TracebackDialog(self.root, exc, val, tb)

    def error_dialog(self, exc, msg, root=None):
        # Display an error dialog.
        # Return when the user clicks OK
        # XXX This needn't be a modal dialog
        import SafeDialog
        if type(msg) in (ListType, TupleType):
            s = ''
            for item in msg:
                s = s + ':\n' + str(item)
            msg = s[2:]
        else:
            msg = str(msg)
        SafeDialog.Dialog(root or self.root,
                      text=msg,
                      title="Error: " + str(exc),
                      bitmap='error',
                      default=0,
                      strings=('OK',),
                      )

    dingbatimages = {'ldots': ('...', None),    # math stuff
                     'sp': (' ', None),
                     'hairsp': ('\240', None),
                     'thinsp': ('\240', None),
                     'emdash': ('--', None),
                     'endash': ('-', None),
                     'mdash': ('--', None),
                     'ndash': ('-', None),
                     'ensp': (' ', None)
                     }

    def clear_dingbat(self, entname):
        if self.dingbatimages.has_key(entname):
            del self.dingbatimages[entname]

    def set_dingbat(self, entname, entity):
        self.dingbatimages[entname] = entity

    def load_dingbat(self, entname):
        if self.dingbatimages.has_key(entname):
            return self.dingbatimages[entname]
        gifname = grailutil.which(entname + '.gif', self.iconpath)
        if gifname:
            img = PhotoImage(file=gifname, master=self.root)
            self.dingbatimages[entname] = img
            return img
        self.dingbatimages[entname] = None
        return None
Esempio n. 4
0
class Character(Entity):
    def __init__(self,
                 start_x,
                 start_y,
                 sprite_dir,
                 width,
                 height,
                 frames,
                 cache=None):
        Entity.__init__(self)

        # Directory where all the sprites will be held
        # This must include up, down, left, right in both idle and walking positions
        # TODO: Implement other movement types
        self.sprite_dir = sprite_dir

        # We can preload the cache in for duplicated characters or just create a new one
        if cache is None:
            self.cache = ImageCache(sprite_dir)
        else:
            self.cache = cache

        # Default the sprite to face down
        self.image = self.cache.get_image("down_1")

        # Where to spawn the character
        self.x_speed = 0
        self.y_speed = 0
        self.width = width
        self.height = height

        # Define movement properties
        self.speed = 8
        self.sneak_mult = 0.4
        self.sprint_mult = 1.5

        # Animation properties
        self.anim_frames = frames  # How many animation frames
        self.current_anim_frame = 0
        self.frame_wait = 4  # How long to wait between frames
        self.current_frame_wait = 0

        self.rect = Rect(start_x, start_y, self.width, self.height)

    def update(self, up, down, left, right, obstacles):
        x_dir = -left + right
        y_dir = -up + down

        self.x_speed = x_dir * self.speed
        self.y_speed = y_dir * self.speed

        # Update the characters rect to apply movement
        self.rect.left += self.x_speed
        self.rect.top += self.y_speed

        self.animate()

    def animate(self):

        # Just determine which frame of which direction to use as current image
        if self.x_speed < 0:
            self.image = self.cache.get_image("left_" +
                                              str(self.current_anim_frame))
        elif self.x_speed > 0:
            self.image = self.cache.get_image("right_" +
                                              str(self.current_anim_frame))
        elif self.y_speed < 0:
            self.image = self.cache.get_image("up_" +
                                              str(self.current_anim_frame))
        elif self.y_speed > 0:
            self.image = self.cache.get_image("down_" +
                                              str(self.current_anim_frame))

        # Because there is such a low frame rate in the animations, it is handy to have a system inplace
        # to create a pause between frames
        self.current_frame_wait += 1
        if self.current_frame_wait >= self.frame_wait:
            # Frame switch
            self.current_anim_frame += 1
            if self.current_anim_frame >= self.anim_frames:
                self.current_anim_frame = 0
            self.current_frame_wait = 0

    def get_pos(self):
        return self.rect.left, self.rect.top