コード例 #1
6
ファイル: Gamescreen.py プロジェクト: daniehol/Roguelike
def make_stats_box(screen, player, dungeon_level, box_x_start, box_heigth, box_width):
    """Create the box displaying the stats
       @param screen: the screen to draw on
       @param player: the player object
       @param dungeon_level: the current dungeon level
       @param box_x_start: rectangle upper left corner x-coordinate 
       @param box_heigth: height of rectangle
       @param box_width: width of rectangle
    """

    #create the rectangle
    stats_box = Rect(box_x_start, 0, box_width, box_heigth)
    #set font type
    stats_font = font.SysFont('arial', 20)
    #render game info
    player_HP = stats_font.render("Hit Points: " + str(player.getHP()), True, Color('white'))
    player_AP = stats_font.render("Attack Power: " + str(player.getAttackPower()), True, Color('white'))
    player_Armor = stats_font.render("Armor: " + str(player.getArmor()), True, Color('white'))
    level = stats_font.render("Dungeon Level: " + str(dungeon_level), True, Color('white'))

    #For each line of text, draw it on the screen and move the rectangle for the next line
    screen.fill(Color('Black'), stats_box)
    screen.blit(player_HP, stats_box)
    screen.blit(player_AP, stats_box.move(0, player_HP.get_height()))
    screen.blit(player_Armor, stats_box.move(0, player_HP.get_height() + player_AP.get_height()))
    screen.blit(level, stats_box.move(0, player_HP.get_height() + player_AP.get_height() + player_Armor.get_height()))
コード例 #2
1
ファイル: obj.py プロジェクト: ikn/wvoas
class Star (object):
    def __init__ (self, level, pos, got):
        self.rect = Rect(pos, conf.STAR_SIZE)
        self.got = got
        self.bg = level.game.img('star-bg.png')
        self.fg = level.game.img('star-fg.png')
        self.sfc = pg.Surface(self.fg.get_size()).convert_alpha()
        self.glow = 0
        self.glow_dirn = 1

    def draw (self, screen, offset):
        r = self.rect.move(offset)
        screen.blit(self.bg, r)
        sfc = self.sfc
        g = self.glow
        # draw fg with opacity level from glow
        sfc.fill((255, 255, 255, ir(g * 255)))
        sfc.blit(self.fg, (0, 0), None, pg.BLEND_RGBA_MULT)
        screen.blit(sfc, r)
        # update glow
        d = self.glow_dirn
        g += d * conf.STAR_PULSE_SPEED
        gb = min(1, max(0, g))
        if g != gb:
            d *= -1
        self.glow = gb
        self.glow_dirn = d
コード例 #3
0
    def __draw_active_power_ups(self, text_rect: Rect) -> None:
        if bool(self.__active_power_up_jump):
            original_rect = self.__active_power_up_jump.sprite.rect
            self.__active_power_up_jump.draw(self.__surface, text_rect.move((original_rect.width + 5) * -2, -4))

        if bool(self.__active_power_up_shield):
            original_rect = self.__active_power_up_shield.sprite.rect
            self.__active_power_up_shield.draw(self.__surface, text_rect.move((original_rect.width + 5) * -1, -4))
コード例 #4
0
ファイル: maze.py プロジェクト: Valink16/MazeGen
    def show_unoptimized(
            self):  # Requires pygame, will crash if launched without it
        for i in range(len(self.walls) - self.hwStartIndex):
            if self.walls[i]:
                pos = Rect(i % (self.w + 1) * self.cw,
                           i // (self.w + 1) * self.ch, 0, 0)
                draw.line(self.window, (0, 0, 0), pos[:2],
                          pos.move(0, self.ch)[:2])

        for i in range(self.hwStartIndex, len(self.walls)):
            if self.walls[i]:
                a = (i - self.hwStartIndex)
                pos = Rect(a % self.w * self.cw, a // self.w * self.ch, 0, 0)
                draw.line(self.window, (0, 0, 0), pos[:2],
                          pos.move(self.cw, 0)[:2])
コード例 #5
0
def make_O(rect: Rect, bw: int) -> Sequence[Rect]:
    rects = []
    for i in range(2):
        for j in range(2):
            r = rect.move(i*bw, j*bw)
            rects.append(r)
    return rects
コード例 #6
0
ファイル: view.py プロジェクト: YoannQDQ/pyweek-dojo
    def _prepare_sprite(self, sprite):
        """Prepare a sprite before drawing.

        Return the corresponding rectangle.
        """
        # Aliases
        old_rect_dct = self.spritedict
        use_update = self._use_update
        # Test dirty rects
        try: sprite.dirty_rects
        except AttributeError: sprite.dirty_rects = None
        # Update dirtyness
        if not sprite.dirty and sprite.dirty_rects:
            sprite.dirty = 1
        # Get actual size
        try: size_rect = Rect((0,0), sprite.source_rect.size)
        except AttributeError: size_rect = Rect((0,0), sprite.rect.size)
        # Compare rect
        new_rect = size_rect.move(sprite.rect.topleft)
        has_moved = new_rect != old_rect_dct[sprite]
        # Whole rect is dirty
        if not use_update or has_moved or sprite.dirty_rects is None:
            sprite.dirty_rects = [size_rect]
            return new_rect
        # Clip the dirty rects
        for k, area in enumerate(sprite.dirty_rects):
            sprite.dirty_rects[k] = area.clip(size_rect)
        # Return
        return new_rect
コード例 #7
0
class Platform:
    def __init__(self, x, y):
        self.PLATFORM_HEIGHT = c.platform_height
        self.PLATFORM_WIDTH = c.platform_width
        self.PLATFORM_COLOR = c.platform_color
        #self.platform_image = image.load("data/blocks/platform.png")
        #self.platform_image.set_colorkey(Color(self.PLATFORM_COLOR))
        self.platform = Rect(x, y, self.PLATFORM_WIDTH, self.PLATFORM_HEIGHT)

    '''def left(self):
        return self.platform.left
    def right(self):
        return self.platform.right
    def top(self):
        return self.platform.top
    def bottom(self):
        return self.platform.bottom'''

    def draw(self, surface, pos):
        #surface.blit(self.platform_image, self.platform.move(pos))
        draw.rect(surface, self.PLATFORM_COLOR, self.platform.move(pos))

    def update(self):
        pass

    def move(self, dx, dy):
        self.platform.x += dx
        self.platform.y += dy
コード例 #8
0
ファイル: rect_test.py プロジェクト: annie60/Xilarius
 def test_move(self):
     r = Rect(1, 2, 3, 4)
     move_x = 10
     move_y = 20
     r2 = r.move(move_x, move_y)
     expected_r2 = Rect(r.left + move_x, r.top + move_y, r.width, r.height)
     self.assertEqual(expected_r2, r2)
コード例 #9
0
ファイル: camera.py プロジェクト: sergentserg/BlastZone
    def apply(self, rect: pg.Rect) -> pg.Rect:
        """Returns a rectangle offset by the camera's position.

        :param rect: pygame rectangle whose position we wish to offset.
        :return: A rectangle whose coordinates are the input's, offset by the camera's.
        """
        return rect.move(-self.rect.x, -self.rect.y)
コード例 #10
0
ファイル: view.py プロジェクト: vxgmichel/pyweek-dojo
    def _prepare_sprite(self, sprite):
        """Prepare a sprite before drawing.

        Return the corresponding rectangle.
        """
        # Aliases
        old_rect_dct = self.spritedict
        use_update = self._use_update
        # Test dirty rects
        try:
            sprite.dirty_rects
        except AttributeError:
            sprite.dirty_rects = None
        # Update dirtyness
        if not sprite.dirty and sprite.dirty_rects:
            sprite.dirty = 1
        # Get actual size
        try:
            size_rect = Rect((0, 0), sprite.source_rect.size)
        except AttributeError:
            size_rect = Rect((0, 0), sprite.rect.size)
        # Compare rect
        new_rect = size_rect.move(sprite.rect.topleft)
        has_moved = new_rect != old_rect_dct[sprite]
        # Whole rect is dirty
        if not use_update or has_moved or sprite.dirty_rects is None:
            sprite.dirty_rects = [size_rect]
            return new_rect
        # Clip the dirty rects
        for k, area in enumerate(sprite.dirty_rects):
            sprite.dirty_rects[k] = area.clip(size_rect)
        # Return
        return new_rect
コード例 #11
0
ファイル: rect_test.py プロジェクト: CTPUG/pygame_cffi
 def test_move( self ):
     r = Rect( 1, 2, 3, 4 )
     move_x = 10
     move_y = 20
     r2 = r.move( move_x, move_y )
     expected_r2 = Rect(r.left+move_x,r.top+move_y,r.width,r.height)
     self.assertEqual( expected_r2, r2 )
コード例 #12
0
def rectAnchor(posn, size, anchor=NW):
    "Returns a rectangle using a position relative to the specified anchor point"
    w, h = size
    r = Rect(posn + size)
    dx = 0 if anchor & WEST else w if anchor & EAST else w // 2
    dy = 0 if anchor & NORTH else h if anchor & SOUTH else h // 2
    return r.move(-dx, -dy)
コード例 #13
0
ファイル: item_screen.py プロジェクト: bpa/renegade
 def cache_inventory(self):
   '''Making the assumption that we won't really have that many items'''
   self.inventory_text = []
   add = self.inventory_text.append
   text = self.render_text
   loc = Rect(375,50,0,0)
   for i in self.inventory:
       add(text(i.get_name(),loc))
       loc.move_ip(0,25)
   if len(self.inventory_text) == 0:
       add(text("Your inventory is empty",loc.move(30,0)))
コード例 #14
0
class Body():
    def __init__(self):
        self.pos = Pt(0, 0)
        # self.radius = Position(15, -25)
        self.shape = Rect(0, 0, 30, 50)

        self.scheme = None
        self.name = None

    @property
    def cpos(self):
        # return self.pos - self.radius
        return self.pos

    @property
    def rect(self):
        return self.shape.move(self.pos.x, self.pos.y)

    def update(self, level, keys):
        pass

    def draw(self, surface, camera):
        tpos = camera.transform(self.cpos)
        # sprite = self.sprites[self.state.name]
        # surface.blit(sprite, tpos)

        pt = camera.transform(self.pos)
        br = Rect(pt, (0, self.shape.height)).inflate(
            self.shape.width / 2, 0).move(0, -self.shape.height)
        # pygame.draw.rect(surface, pygame.Color('azure'), camera.transform(self.rect))

        pygame.draw.rect(surface, pygame.Color('skyblue'), br)
        # helper.marker(pt, surface)

        # tp = camera.transform(self.pos)
        # pygame.draw.line(surface, (200, 0, 0), (tp[0], tp[1]-10), (tp[0], tp[1]+10))
        # pygame.draw.line(surface, (200, 0, 0), (tp[0]-10, tp[1]), (tp[0]+10, tp[1]))

    @staticmethod
    def from_xml(xml_node):
        def load_tuple(val):
            return make_tuple(xml_node.attrib[val])

        position = load_tuple('pos')
        size = load_tuple('size')
        scheme = xml_node.attrib['scheme']

        body = Body()
        body.pos = Pt(position)
        body.shape = Rect((0, 0), size)
        body.name = xml_node.attrib['id']
        # body.scheme = schemes.get(scheme)
        body.scheme = scheme
        return body
コード例 #15
0
class GameObject:
    def __init__(self, x, y, w, h, speed=(0, 0)):
        self.bounds = Rect(x, y, w, h)
        self.speed = speed

    @property
    def left(self):
        return self.bounds.left

    @property
    def right(self):
        return self.bounds.right

    @property
    def top(self):
        return self.bounds.top

    @property
    def bottom(self):
        return self.bounds.bottom

    @property
    def width(self):
        return self.bounds.width

    @property
    def height(self):
        return self.bounds.height

    @property
    def center(self):
        return self.bounds.center

    @property
    def centerx(self):
        return self.bounds.centerx

    @property
    def centery(self):
        return self.bounds.centery

    def draw(self, surface):
        pass

    def move(self, dx, dy):
        self.bounds = self.bounds.move(dx, dy)

    def update(self):
        """"""
        if self.speed == [0, 0]:
            return

        self.move(*self.speed)
コード例 #16
0
ファイル: Gamescreen.py プロジェクト: jordanforbes/Roguelike
def make_stats_box(screen, player, dungeon_level, box_x_start, box_heigth,
                   box_width):
    """Create the box displaying the stats
       @param screen: the screen to draw on
       @param player: the player object
       @param dungeon_level: the current dungeon level
       @param box_x_start: rectangle upper left corner x-coordinate 
       @param box_heigth: height of rectangle
       @param box_width: width of rectangle
    """

    #create the rectangle
    stats_box = Rect(box_x_start, 0, box_width, box_heigth)
    #set font type
    stats_font = font.SysFont('arial', 20)
    #render game info
    player_HP = stats_font.render("Hit Points: " + str(player.getHP()), True,
                                  Color('white'))
    player_AP = stats_font.render(
        "Attack Power: " + str(player.getAttackPower()), True, Color('white'))
    player_Armor = stats_font.render("Armor: " + str(player.getArmor()), True,
                                     Color('white'))
    level = stats_font.render("Dungeon Level: " + str(dungeon_level), True,
                              Color('white'))

    #For each line of text, draw it on the screen and move the rectangle for the next line
    screen.fill(Color('Black'), stats_box)
    screen.blit(player_HP, stats_box)
    screen.blit(player_AP, stats_box.move(0, player_HP.get_height()))
    screen.blit(
        player_Armor,
        stats_box.move(0,
                       player_HP.get_height() + player_AP.get_height()))
    screen.blit(
        level,
        stats_box.move(
            0,
            player_HP.get_height() + player_AP.get_height() +
            player_Armor.get_height()))
コード例 #17
0
ファイル: sprites.py プロジェクト: jcemelanda/pykapers
class Player(Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.xvel = 0
        self.yvel = 0
        self.onGround = True
        self.image = Surface((32, 32))
        self.image.fill(Color("#00FFFF"))
        self.image.convert()
        self.rect = Rect(x, y, 32, 32)

    def update(self):
        self.rect = self.rect.move(3, 0)
コード例 #18
0
ファイル: gm.py プロジェクト: Anstow/TeamAwesome
 def rect (self, rect):
     # need to set dirty in old and new rects (if changed)
     last = self.last_rect
     rect = Rect(rect)
     if rect != last:
         sz = rect.size
         if sz != last.size:
             self.resize(*sz)
         else:
             # handled in resize
             self._rect = rect
             self._postrot_rect = Rect(rect.move(self._rot_offset)[:2],
                                       self._postrot_rect[2:])
             self._mk_dirty()
コード例 #19
0
ファイル: gui.py プロジェクト: nbudin/solidfuel
 def _widgetRect(self, widget, rect=None):
     # simplistic.  doesn't account for scaling or translation.  If you want those, implement the
     # _widgetRect(rect) method on your widget class itself.
     if rect is None:
         rect = Rect(0, 0, widget.w, widget.h)
         
     if widget is self:
         return rect
     elif widget.parent is None:
         return None
     elif hasattr(widget, '_widgetRect'):
         return self._widgetRect(widget.parent, widget._widgetRect(rect))
     elif issubclass(widget.__class__, Translatable):
         return self._widgetRect(widget.parent, rect.move(widget.x, widget.y))
     else:
         return self._widgetRect(widget.parent, rect)
コード例 #20
0
ファイル: widget.py プロジェクト: Lekyn/tea-garden
class Widget(sprite.Sprite):
    #a widget has a position
    def __init__(self, x=None, y=None):
        sprite.Sprite.__init__(self)
        self.image, self.rect = self.load_image(self.display,
                                                Color('#FF00FF'))
        self.x = x
        self.y = y
        if self.x is not None:
            if self.y is not None:
                self.rect = Rect(x*50, y*50, 50, 50)

    # functions should be implemented in subclasses
    # if they are relevant to that widget type
    def eaten(self):
        return ("boredom", -1)

    def played(self):
        return ("boredom", -1)

    # if creature tries to walk into widget,
    def intersected(self):
        return ("boredom", -1)

    def mated(self, tako):
        return ("boredom", -1)

    def load_image(self, name, colorkey=None):
        fullname = os.path.join('img', name)
        img = image.load(fullname)
        img = img.convert()
        if colorkey is not None:
            if colorkey is -1:
                colorkey = img.get_at((0,0))
            img.set_colorkey(colorkey, RLEACCEL)
        return img, img.get_rect()

    def update_rect(self):
        self.rect = Rect(self.x*50, self.y*50, 50, 50)

    def move_rect(self, x, y):
        self.rect = self.rect.move(x*50, y*50)
コード例 #21
0
ファイル: camera.py プロジェクト: mick-warehime/swmp
 def shift_by_topleft(self, rect: pg.Rect) -> pg.Rect:
     return rect.move(self.rect.topleft)
コード例 #22
0
class PlayerCommand:
    """ Display pannel for player input/output
        Controls display area for player input/output """
    def __init__(self):
        self.msg1 = "text area 1"
        self.msg2 = "text area 2"
        self.msg3 = "text area 3"
        self.x = 50
        self.width = 20
        self.offset = 0
        self.back_color = "black"
        self.message_rect = Rect(600, 0, SCREEN_WIDTH, SCREEN_HEIGHT)
        self.message_size = (int(self.message_rect[2]) - self.message_rect[0],
                             int(self.message_rect[3]))
        self.unit_group_rect = Rect(630, 150, 15, 15)
        self.player_msg = "Player message here"
        self.tick_counter = "Ticks here"

    def msg_to_player(self, screen):
        """ tracks and handles messages to player """
        message1_sf = DEFAULT_GAME_FONT.render(self.player_msg, True,
                                               Color('white'))
        screen.blit(message1_sf, (20, 550, SCREEN_WIDTH, SCREEN_HEIGHT))
        """ tick counter """
        message2_sf = DEFAULT_GAME_FONT.render(self.tick_counter, True,
                                               Color('white'))
        screen.blit(message2_sf, (20, 20, SCREEN_WIDTH, SCREEN_HEIGHT))

    def draw_messageboard(self, screen):
        self.draw_rimmed_box(screen, self.message_rect,
                             (self.x, self.width, self.offset), 4,
                             Color(self.back_color))
        DEFAULT_GAME_FONT = pygame.font.SysFont('arial', 18)
        message1_sf = DEFAULT_GAME_FONT.render(self.msg1, True, Color('white'))
        message2_sf = DEFAULT_GAME_FONT.render(self.msg2, True, Color('white'))
        message3_sf = DEFAULT_GAME_FONT.render(self.msg3, True, Color('white'))
        message4 = "Heroes: " + str(HERO_WINS)
        message4_sf = DEFAULT_GAME_FONT.render(message4, True, Color('white'))
        message5 = "Enemies: " + str(ENEMY_WINS)
        message5_sf = DEFAULT_GAME_FONT.render(message5, True, Color('white'))
        screen.blit(message1_sf,
                    self.message_rect.move(0, message1_sf.get_height()))
        screen.blit(message2_sf,
                    self.message_rect.move(0,
                                           message2_sf.get_height() * 2))
        screen.blit(message3_sf,
                    self.message_rect.move(0,
                                           message2_sf.get_height() * 3))
        screen.blit(message4_sf,
                    self.message_rect.move(0,
                                           message4_sf.get_height() * 4))
        screen.blit(message5_sf,
                    self.message_rect.move(0,
                                           message5_sf.get_height() * 5))
        self.msg_to_player(screen)

    def draw_player_units(self, screen, unit_group):
        """ blits player unit text to output display window """
        self.draw_rimmed_box(screen, Rect(600, 150, SCREEN_WIDTH,
                                          SCREEN_HEIGHT),
                             (self.x, self.width, self.offset), 4,
                             Color(self.back_color))
        DEFAULT_GAME_FONT = pygame.font.SysFont('arial', 12)
        offset = 0
        for unit in unit_group:
            message1_sf = DEFAULT_GAME_FONT.render(unit.info_msg1, True,
                                                   Color('white'))
            message1_status = DEFAULT_GAME_FONT.render(unit.txt_status, True,
                                                       Color('white'))
            message2_sf = DEFAULT_GAME_FONT.render(unit.info_msg2, True,
                                                   Color('white'))
            screen.blit(
                message1_sf,
                self.unit_group_rect.move(
                    0,
                    message1_sf.get_height() * 1 + offset * 24))
            screen.blit(
                message1_status,
                self.unit_group_rect.move(
                    100,
                    message1_status.get_height() * 1 + offset * 24))
            screen.blit(
                message2_sf,
                self.unit_group_rect.move(
                    0,
                    message2_sf.get_height() * 2 + offset * 24))
            for button in unit.unit_btns:
                button.draw(screen)
            offset += 2

    def draw_rimmed_box(self,
                        screen,
                        box_rect,
                        box_color,
                        rim_width=0,
                        rim_color=Color('black')):
        """ Draw a rimmed box on the given surface. 
            The rim is drawn outside the box rect. 
        """
        if rim_width:
            rim_rect = Rect(box_rect.left - rim_width,
                            box_rect.top - rim_width,
                            box_rect.width + rim_width * 2,
                            box_rect.height + rim_width * 2)
            pygame.draw.rect(screen, rim_color, rim_rect)
        pygame.draw.rect(screen, box_color, box_rect)

    def in_field(self, pos):
        """ verify if clicked pos is in playable grid area  - returns True/False """
        loc = self.coord_to_grid(pos)
        if loc[0] < 0 or loc[0] >= self.x or loc[1] < 0 or \
           loc[1] >= GRID_SIZE[1]:
            #print("you missed the player_command grid")
            return (False)
        else:
            return (True)

    def grid_clicked(self, pos):
        """ tells what grid was clicked on and reports for testing purposes 
            pos: the passed mouse coordinates variable passed through 
        """
        if self.in_field(pos):
            #print("click is in player_command field")
            #print("pos clicked:", pos)
            dummy = False


################################################################################
## TEST
################################################################################
#
# if __name__ == "__main__":
#
#     screen = pygame.display.set_mode((params.SCREEN_WIDTH, params.SCREEN_HEIGHT), 0, 32) # create screen area for tiles
#
#     #pawn = SimpleUnit()
#     pawn_group = SimpleUnitGroup(screen)
#     for unit in pawn_group.group_list:
#         print("unit loc:", unit.loc)
#     #test loop to give coords to units
#     for unit in pawn_group.group_list:
#         unit.targ_tile = (25,25)
#         unit.active = True
#         print("status:") # test of status message update
#         print(unit.info_msg1) # test of status message update
#         print(unit.info_msg2) # test of status message update
#     #test loop to move units
#         unit.move_unit()
#     for unit in pawn_group.group_list: # check locations again to see if moved
#         print("unit loc:", unit.loc)
#
#     # test player groups - test works #
#     all_players = PlayerUnitGroup(screen) #                         - These lines are the lines to call/create the players & units for a game
#
#     all_players.print_all_player_units() # Test to print all player units to shell - works
#
#     all_players.update_players() # Test of update logic path
#
#     print()
#     print("-- TEST DONE --")
#     print()
#     pygame.quit()
#     sys.exit()
コード例 #23
0
 def movement_shoot_monster(self):
     self.rect_bullet = Rect.move(self.rect_bullet,0,self._shootSpeed)
     rect(self.surface, self.color_bullet_monster, self.rect_bullet)
コード例 #24
0
ファイル: dialog.py プロジェクト: bpa/renegade
class Dialog:

    def __init__(self, text, options=None):
        self.options = options
        if options is not None:
            self.selection = 0
        else:
            self.selection = None

        self.fg = pygame.color.Color('white')
        self.bg = pygame.color.Color('blue')
        self.tr = pygame.color.Color('black')

        half = core.screen.get_width() * 4 / 5
        self.rect = Rect(0,0,half,0)
        self.text = text
        self.font = pygame.font.Font(None, 20)
        self.split_text()
        self.render_text()

        self.window = core.wm.window(half,self.rect.height,'center','center')
        self.window.update = self.update
        self.window.handle_event = self.handle_event
        self.screen = self.window.image
        self.screen.set_colorkey(self.tr, RLEACCEL)

        self.rect = Rect(self.window.rect)
        self.rect.center = self.screen.get_rect().center

        r = self.rect.inflate(-6,-6)
        self.bgwin = core.wm.window(r.width,r.height,'center','center',z=3)
        self.bgwin.image.fill(self.bg)
        self.bgwin.image.set_alpha(128)

        self.borderwin = core.wm.window(self.rect.width,self.rect.height, \
            'center','center', z=2)
        self.borderwin.image.fill(self.tr)
        dialog.draw_round_border(self.borderwin.image,color=self.fg)
        self.borderwin.image.set_colorkey(self.tr, RLEACCEL)

    def hide(self):
        self.window.hide()
        self.bgwin.hide()
        self.borderwin.hide()

    def nop(self): pass
    def update(self):
        self.window.update = self.nop
        self.screen.fill(self.tr)
        draw_round_border(self.screen,color=self.fg)
        current_y = 10
        for line in self.rendered:
            self.screen.blit(line, self.rect.move(10,current_y))
            current_y = current_y + self.font.get_linesize()
        current_y = current_y + self.font.get_linesize()
        first_option_y = current_y
        for option in self.rendered_opts:
            self.screen.blit(option, self.rect.move(20,current_y))
            current_y = current_y + self.font.get_linesize()
        if self.selection is not None:
            y_pos = first_option_y + self.selection * self.font.get_linesize()
            y_pos = y_pos + self.font.get_linesize() / 2 # Center it in line
            rect = self.rect.move(10, y_pos)
            center = (rect.left, rect.top)
            draw.circle(self.screen, self.fg, center, 5)

    def render_one_line(self, line):
        return self.font.render(line, True, self.fg).convert_alpha()

    def render_text(self):
        self.rendered = map(self.render_one_line, self.lines)
        if self.options is not None:
            self.rendered_opts = map(self.render_one_line, self.options)
            line_count = len(self.rendered) + len(self.rendered_opts) + 1
        else:
            self.rendered_opts = []
            line_count = len(self.rendered)
        self.rect.height = self.font.get_linesize() * line_count + 20

    def split_text(self):
        self.lines = []
        current = ''
        for chunk in re.split(' ', self.text):
            width, height = self.font.size(current + chunk + ' ')
            if width < self.rect.width - 10:
                current = current + chunk + ' '
            else:
                self.lines.append(current)
                current = chunk + ' '
        if len(current) > 1:
            self.lines.append(current)

    def selection_up(self):
        if self.selection is not None:
            if self.selection == 0:
              self.selection = len(self.options)-1
            else:
              self.selection = self.selection - 1
        self.window.update = self.update

    def selection_down(self):
        if self.selection is not None:
            if self.selection < len(self.options)-1:
                self.selection = self.selection + 1
            else:
              self.selection = 0
        self.window.update = self.update

    def run(self):
        self.window.show()
        self.window.focus()
        core.wm.run()
        core.wm.running = True
        self.dispose()
        core.game.save_data.map.focus()
        if self.selection is not None:
            return self.selection
        else: return None

    def handle_event(self, event):
        if event.type == PUSH_ARROW_EVENT or \
             event.type == REPEAT_ARROW_EVENT:
            if core.event_bag.is_up():
                self.selection_up()
            elif core.event_bag.is_down():
                self.selection_down()
        elif event.type == PUSH_ACTION_EVENT:
            core.wm.running = False

    def dispose(self):
        self.rendered = None
        self.window.destroy()
        self.bgwin.destroy()
        self.borderwin.destroy()
        self.window.update = None
コード例 #25
0
ファイル: level.py プロジェクト: ikn/wvoas
class Level (object):
    def __init__ (self, game, event_handler = None, ID = 0, cp = -1):
        self.game = game
        # input
        if event_handler is not None:
            event_handler.add_event_handlers({
                pg.KEYDOWN: self.skip,
                pg.MOUSEBUTTONDOWN: self.skip
            })
            event_handler.add_key_handlers([
                (conf.KEYS_BACK, self.pause, eh.MODE_ONDOWN),
                (conf.KEYS_RESET, self.reset, eh.MODE_ONDOWN),
                (conf.KEYS_JUMP, self.jump, eh.MODE_ONDOWN_REPEAT, 1, 1)
            ] + [
                (ks, [(self.move, (i,))], eh.MODE_HELD)
                for i, ks in enumerate((conf.KEYS_LEFT, conf.KEYS_RIGHT))
            ])
        w, h = conf.RES
        self.centre = (w / 2, h / 2)
        ww, wh = conf.WINDOW_SIZE
        border = (2 * (ww + 5), 2 * (wh + 5))
        self.window_bds = pg.Rect(0, 0, w, h).inflate(border)
        self.clouds = []
        self.load_graphics()
        if event_handler is not None:
            self.move_channel = game.move_channel
            self.star_channel = game.star_channel
        else:
            self.move_channel = None
            self.star_channel = None
        # load first level
        self.ID = None
        self.init(ID, cp)

    def init (self, ID = None, cp = None):
        self.paused = False
        self.dying = False
        self.first_dying = False
        self.winning = False
        self.fading = False
        self.particles = []
        self.particle_rects = []
        self.void_jitter = [conf.VOID_JITTER_X, conf.VOID_JITTER_Y, conf.VOID_JITTER_T]
        self.first = True
        # get level/current checkpoint
        if ID is None:
            # same level
            ID = self.ID
        if ID != self.ID:
            # new level
            self.ID = ID
            self.current_cp = cp if cp is not None else -1
            # clouds: randomise initial positions and velocities
            self.clouds = cs = []
            w, h = conf.RES
            imgs = self.imgs
            vx0 = conf.CLOUD_SPEED
            vy0 = vx0 * conf.CLOUD_VERT_SPEED_RATIO
            self.cloud_vel = [vx0 * random0(), vy0 * random0()]
            vx = conf.CLOUD_MOD_SPEED_RATIO
            vy = vx * conf.CLOUD_VERT_SPEED_RATIO
            for c in conf.CLOUDS:
                c_w, c_h = imgs[c].get_size()
                s = (c_w, c_h)
                c_w /= 2
                c_h /= 2
                pos = [randint(-c_w, w - c_w), randint(-c_h, h - c_h)]
                vel = [vx * random0(), vy * random0()]
                cs.append((pos, vel, s))
        elif cp is not None:
            self.current_cp = cp
        data = conf.LEVELS[ID]
        # background
        self.bgs = data.get('bgs', conf.DEFAULT_BGS)
        # player
        if self.current_cp >= 0:
            p = list(data['checkpoints'][self.current_cp][:2])
            s_p, s_c = conf.PLAYER_SIZE, conf.CHECKPOINT_SIZE
            for i in (0, 1):
                p[i] += float(s_c[i] - s_p[i]) / 2
        else:
            p = data['player_pos']
        self.player = Player(self, p)
        # window
        x, y = Rect(self.to_screen(self.player.rect)).center
        w, h = conf.HALF_WINDOW_SIZE
        self.window = Rect(x - w, y - h, 2 * w, 2 * h)
        self.old_window = self.window.copy()
        # checkpoints
        s = conf.CHECKPOINT_SIZE
        self.checkpoints = [Rect(p + s) for p in data.get('checkpoints', [])]
        # goal
        self.goal = Rect(data['goal'] + conf.GOAL_SIZE)
        self.goal_img = self.goal.move(conf.GOAL_OFFSET)
        self.goal_img.size = self.imgs['goal'].get_size()
        # stars
        self.stars = [Star(self, p, [ID, i] in conf.STARS)
                      for i, p in enumerate(data.get('stars', []))]
        if self.star_channel is not None and not all(s.got for s in self.stars):
            self.star_channel.unpause()
        # rects
        self.all_rects = [Rect(r) for r in data.get('rects', [])]
        self.all_vrects = [Rect(r) for r in data.get('vrects', [])]
        self.arects = [Rect(r) for r in data.get('arects', [])]
        self.update_rects()

    def skip (self, evt):
        if self.dying and self.dying_counter < conf.DIE_SKIP_THRESHOLD and \
           not (evt.type == pg.KEYDOWN and evt.key in conf.KEYS_BACK) and \
           not self.winning:
            self.init()
        elif conf.DEBUG and evt.type == pg.MOUSEBUTTONDOWN:
            r = self.player.rect
            c = self.window.center
            print 'moving to', c
            for i in (0, 1):
                r[i] = c[i] - (r[i + 2] / 2)
            self.player.old_rect = r

    def pause (self, *args):
        if self.move_channel is not None:
            self.move_channel.pause()
        if self.star_channel is not None:
            self.star_channel.pause()
        self.game.start_backend(ui.Paused, self)
        self.paused = True

    def reset (self, *args):
        if not self.winning:
            self.init()

    def jump (self, key, mode, mods):
        self.player.jump(mode == 0)

    def move (self, key, mode, mods, i):
        self.player.move(i)

    def update_window (self):
        w = self.window
        wp0 = w.topleft
        wp1 = w.bottomright
        s = conf.RES
        self.inverse_win = rs = []
        for px in (0, 1, 2):
            for py in (0, 1, 2):
                if px == py == 1:
                    continue
                r = [0, 0, 0, 0]
                for i, p in enumerate((px, py)):
                    if p == 0:
                        r[i + 2] = wp0[i]
                    if p == 1:
                        r[i] = wp0[i]
                        r[i + 2] = wp1[i] - wp0[i]
                    elif p == 2:
                        r[i] = wp1[i]
                        r[i + 2] = s[i] - wp1[i]
                if r[2] > 0 and r[3] > 0:
                    rs.append(Rect(r))

    def get_clip (self, r1, r2, err = 0):
        x01, y01, w, h = r1
        x11, y11 = x01 + w, y01 + h
        x02, y02, w, h = r2
        x12, y12 = x02 + w, y02 + h
        x0, y0 = max(x01, x02), max(y01, y02)
        x1, y1 = min(x11, x12), min(y11, y12)
        w, h = x1 - x0, y1 - y0
        if w > err and h > err:
            return (x0, y0, w, h)

    def update_rects (self):
        self.update_window()
        # rects
        self.rects = rects = []
        self.draw_rects = draw = []
        w = self.window
        for r in self.all_rects:
            c = w.clip(r)
            if c:
                rects.append(c)
                draw.append(r)
        # vrects
        self.vrects = rects = []
        ws = self.inverse_win
        for r in self.all_vrects:
            for w in ws:
                c = w.clip(r)
                if c:
                    rects.append(c)

    def handle_collisions (self):
        get_clip = self.get_clip
        p = self.player.rect
        p0 = list(p)
        for r in self.rects + self.vrects + self.arects:
            if get_clip(r, p):
                r_x0, r_y0, w, h = r
                r_x1, r_y1 = r_x0 + w, r_y0 + h
                p_x0, p_y0, w, h = p
                p_x1, p_y1 = p_x0 + w, p_y0 + h
                x, dirn = min((p_x1 - r_x0, 0), (p_y1 - r_y0, 1),
                              (r_x1 - p_x0, 2), (r_y1 - p_y0, 3))
                axis = dirn % 2
                p[axis] += (1 if dirn >= 2 else -1) * x
                self.player.impact(axis, 0)
                if axis == 1:
                    self.vert_dirn = dirn
        # screen left/right
        if p[0] < 0:
            p[0] = 0
            self.player.impact(0, 0)
        elif p[0] + p[2] > conf.RES[0]:
            p[0] = conf.RES[0] - p[2]
            self.player.impact(0, 0)
        # die if still colliding
        axes = set()
        e = conf.ERR
        colliding = [r for r in self.rects + self.vrects + self.arects \
                     if get_clip(r, p, e)]
        if colliding:
            for r in colliding:
                r_x0, r_y0, w, h = r
                r_x1, r_y1 = r_x0 + w, r_y0 + h
                p_x0, p_y0, w, h = p
                p_x1, p_y1 = p_x0 + w, p_y0 + h
                x, dirn = min((p_x1 - r_x0, 0), (p_y1 - r_y0, 1),
                              (r_x1 - p_x0, 2), (r_y1 - p_y0, 3))
                axes.add(dirn % 2)
            if len(axes) == 2:
                dirn = .5
            else:
                dirn = .95 if axes.pop() == 0 else .1
            self.die(dirn)

    def die (self, dirn = .5):
        self.first_dying = True
        self.dying = True
        self.dying_counter = conf.DIE_TIME
        # particles
        pos = list(Rect(self.to_screen(self.player.rect)).center)
        self.add_ptcls('die', pos, dirn)
        # sound
        if self.move_channel is not None:
            self.move_channel.pause()
        self.game.play_snd('die')

    def next_level (self, save = True, progress = True):
        if progress:
            if self.move_channel is not None:
                self.move_channel.pause()
            if self.star_channel is not None:
                self.star_channel.pause()
        i = self.ID
        if not conf.COMPLETED and i + 1 in conf.EXISTS:
            # there's a next level
            if save:
                conf.CURRENT_LEVEL = i + 1
            if progress:
                self.init(i + 1)
        else:
            if save:
                conf.COMPLETED = True
            if progress:
                self.game.switch_backend(ui.LevelSelect)

    def win (self):
        if self.winning:
            return
        self.winning = True
        self.next_level(progress = False)
        if self.ID not in conf.COMPLETED_LEVELS:
            conf.COMPLETED_LEVELS.append(self.ID)
        conf.dump()
        self.start_fading(lambda: self.next_level(False))

    def update (self):
        # fade counter
        if self.fading:
            self.fade_counter -= 1
            if self.fade_counter == 0:
                self.fading = False
                del self.fade_sfc
                self.fade_cb()
        # move player
        if not self.dying:
            pl = self.player
            pl.update()
        # get amount to move window by
        w = self.window
        self.old_window = w.copy()
        x0, y0 = self.centre
        if self.paused or self.first:
            dx = dy = 0
            self.first = False
        else:
            x, y = pg.mouse.get_pos()
            dx, dy = x - x0, y - y0
            # don't move too far outside the screen
            w_moved = w.move(dx, dy).clamp(self.window_bds)
            dx, dy = w_moved[0] - w[0], w_moved[1] - w[1]
        pg.mouse.set_pos(x0, y0)
        wx0, wy0, ww, wh = self.total_window = w.union(w.move(dx, dy))
        # move window
        if self.dying:
            # just move window
            w.move_ip(dx, dy)
            self.update_rects()
        else:
            self.vert_dirn = 3
            if dx == dy == 0:
                # just handle collisions
                self.handle_collisions()
            else:
                # check if player and window intersect
                wx1, wy1 = wx0 + ww, wy0 + wh
                r = pl.rect
                o_r = pl.old_rect
                px0, py0 = min(r[0], o_r[0]), min(r[1], o_r[1])
                px1 = max(r[0] + r[2], o_r[0] + o_r[2])
                py1 = max(r[1] + r[3], o_r[1] + o_r[3])
                if px1 > wx0 and py1 > wy0 and px0 < wx1 and py0 < wy1:
                    # if so, move window a few pixels at a time
                    c = conf.WINDOW_MOVE_AMOUNT
                    for axis, d in ((0, dx), (1, dy)):
                        dirn = 1 if d > 0 else -1
                        while d * dirn > 0:
                            d -= dirn * c
                            rel = [0, 0]
                            rel[axis] += c * dirn + (0 if d * dirn > 0 else d)
                            w.move_ip(rel)
                            self.update_rects()
                            if not self.dying:
                                self.handle_collisions()
                else:
                    # else move it the whole way
                    w.move_ip(dx, dy)
                    self.update_rects()
                    self.handle_collisions()
            if self.vert_dirn == 1:
                pl.on_ground = conf.ON_GROUND_TIME
        # clouds
        if self.clouds:
            # jitter
            jx = conf.CLOUD_JITTER
            jy = jx * conf.CLOUD_VERT_SPEED_RATIO
            v0 = self.cloud_vel
            v0[0] += jx * random0()
            v0[1] += jy * random0()
            r = conf.RES
            for p, v, s in self.clouds:
                for i, (i_w, r_w) in enumerate(zip(s, r)):
                    # move
                    x = p[i]
                    x += v0[i] + v[i]
                    # wrap
                    if x + i_w < 0:
                        x = r_w
                    elif x > r_w:
                        x = -i_w
                    p[i] = x
        # particles
        ptcls = []
        rects = []
        for k, j, group in self.particles:
            g = []
            x0, y0 = conf.RES
            x1 = y1 = 0
            for c, p, v, size, t in group:
                x, y = p
                # update boundary
                if x < x0:
                    x0 = x
                if y < y0:
                    y0 = y
                if x + size > x1:
                    x1 = x + size
                if y + size > y1:
                    y1 = y + size
                t -= 1
                if t != 0:
                    # move
                    vx, vy = v
                    x += vx
                    y += vy
                    # update boundary
                    if x < x0:
                        x0 = x
                    if y < y0:
                        y0 = y
                    if x + size > x1:
                        x1 = x + size
                    if y + size > y1:
                        y1 = y + size
                    # damp/jitter
                    vx *= k
                    vy *= k
                    vx += j * random0()
                    vy += j * random0()
                    g.append((c, (x, y), (vx, vy), size, t))
            if g:
                ptcls.append((k, j, g))
            if x1 > x0 and y1 > y0:
                rects.append((int(x0), int(y0), ceil(x1 - x0), ceil(y1 - y0)))
        self.particles = ptcls
        self.particle_rects = rects
        # death counter
        if self.dying:
            self.dying_counter -= 1
            if self.dying_counter == 0:
                self.init()
            return
        # player velocity
        pl.update_vel()
        # die if OoB
        if pl.rect[1] > conf.RES[1]:
            self.die()
        # win if at goal
        p = pl.rect
        c = w.clip(self.goal)
        if c and self.get_clip(p, c):
            self.win()
        # check if at checkpoints
        for c in self.checkpoints[self.current_cp + 1:]:
            if w.clip(c) and self.get_clip(p, c):
                self.current_cp += 1
        # check if at stars
        for i, s in enumerate(self.stars):
            if not s.got and w.clip(s.rect) and self.get_clip(p, s.rect):
                #self.game.play_snd('collectstar')
                if self.star_channel is not None and all(s.got for s in self.stars):
                    self.star_channel.pause()
                s.got = True
                conf.STARS.append([self.ID, i])
                conf.dump()

    def load_graphics (self):
        self.imgs = imgs = {}
        for img in ('void', 'window', 'rect', 'vrect', 'arect',
                    'checkpoint-current', 'checkpoint', 'goal') + \
                   conf.BGS + conf.CLOUDS:
            imgs[img] = self.game.img(img + '.png')
        self.window_sfc = pg.Surface(conf.WINDOW_SIZE).convert_alpha()

    def to_screen (self, rect):
        return [ir(x) for x in rect]

    def add_ptcls (self, key, pos, dirn = .5):
        particles = []
        data = conf.PARTICLES[key]
        max_speed = data['speed']
        max_size = data['size']
        k = data['damping']
        j = data['jitter']
        max_life = data['life']
        dirn *= pi / 2
        for c, amount in data['colours']:
            a, b = divmod(amount, 1)
            amount = int(a) + (1 if random() < b else 0)
            while amount > 0:
                size = randint(1, max_size)
                amount -= size
                angle = random() * 2 * pi
                speed = max_speed * expovariate(5)
                v = (speed * cos(dirn) * cos(angle), speed * sin(dirn) * sin(angle))
                life = int(random() * max_life)
                if life > 0:
                    particles.append((c, tuple(pos), v, size, life))
        self.particles.append((k, j, particles))

    def start_fading (self, cb):
        if not self.fading:
            self.fading = True
            self.fade_counter = conf.FADE_TIME
            self.fade_sfc = pg.Surface(conf.RES).convert_alpha()
            self.fade_cb = cb

    def update_jitter (self, jitter):
        if len(jitter) == 3:
            jx, jy, t0 = jitter
            t = t0
            ox, oy = randint(0, jx), randint(0, jy)
            jitter += [ox, oy, t]
        else:
            jx, jy, t0, ox, oy, t = jitter
            if t == 0:
                ox, oy = randint(0, jx), randint(0, jy)
                jitter[3] = ox
                jitter[4] = oy
                jitter[5] = t0
        jitter[5] -= 1

    def draw (self, screen):
        # don't draw on last frame
        #if not self.game.running:
            #return False
        imgs = self.imgs
        w = self.window
        pl = self.player
        pl.pre_draw()
        # background
        jitter = self.void_jitter
        self.update_jitter(jitter)
        ox, oy = jitter[3], jitter[4]
        img = imgs['void']
        draw_all = jitter[5] == conf.VOID_JITTER_T - 1 or self.fading or self.paused
        if self.paused:
            self.paused = False
        if draw_all:
            tile(screen, img, (0, 0) + screen.get_size(), ox, oy)
        else:
            draw_rects = self.particle_rects + [self.total_window, self.goal_img]
            if self.first_dying or not self.dying:
                draw_rects.append(pl.rect_img.union(pl.old_rect_img))
            for r in draw_rects:
                tile(screen, img, r, ox, oy, (0, 0))
        # vrects
        img = imgs['vrect']
        for r in self.all_vrects:
            tile(screen, img, r)
        # window
        offset = (-w[0], -w[1])
        w_sfc = self.window_sfc
        # window background: static images
        for img in self.bgs:
            if isinstance(img, str):
                pos = (0, 0)
            else:
                img, pos = img
            w_sfc.blit(imgs[img], Rect(pos + (0, 0)).move(offset))
        # clouds
        for c, (p, v, s) in zip(conf.CLOUDS, self.clouds):
            w_sfc.blit(imgs[c], Rect(self.to_screen(p + [0, 0])).move(offset))
        # rects in window
        img = imgs['rect']
        for r, r_full in zip(self.rects, self.draw_rects):
            tile(w_sfc, img, r.move(offset), full = r_full.move(offset))
        # checkpoints
        for i, r in enumerate(self.checkpoints):
            img = imgs['checkpoint' + ('-current' if i == self.current_cp else '')]
            w_sfc.blit(img, r.move(offset))
        # window border
        w_sfc.blit(imgs['window'], (0, 0), None, pg.BLEND_RGBA_MULT)
        # copy window area to screen
        screen.blit(w_sfc, w)
        # arects
        img = imgs['arect']
        for r in self.arects:
            tile(screen, img, r)
        # goal
        screen.blit(imgs['goal'], self.goal_img)
        # stars
        for s in self.stars:
            if not s.got:
                s.draw(screen, (0, 0))
        # player
        if not self.dying:
            pl.draw(screen)
        # particles
        for k, j, g in self.particles:
            for c, p, v, size, t in g:
                screen.fill(c, p + (size, size))
        # fadeout
        if self.fading:
            t = conf.FADE_TIME - self.fade_counter
            alpha = conf.FADE_RATE * float(t) / conf.FADE_TIME
            alpha = min(255, ir(alpha))
            self.fade_sfc.fill((0, 0, 0, alpha))
            screen.blit(self.fade_sfc, (0, 0))
            draw_all = True
        if self.first_dying:
            self.first_dying = False
        if draw_all:
            return True
        else:
            return draw_rects + self.arects
コード例 #26
0
ファイル: unit.py プロジェクト: timbodude/project_alpha
class PlayerCommand:
    """ Display pannel for player input/output
        Controls display area for player input/output """

    def __init__(self):
        self.msg1 = "text area 1"
        self.msg2 = "text area 2"
        self.msg3 = "text area 3"
        self.x = 50
        self.width = 20
        self.offset = 0
        self.back_color = "black"
        self.message_rect = Rect(600, 0, SCREEN_WIDTH, SCREEN_HEIGHT)
        self.message_size = (int(self.message_rect[2]) - self.message_rect[0], int(self.message_rect[3]))
        self.unit_group_rect = Rect(630, 150, 15, 15)
        self.player_msg = "Player message here"
        self.tick_counter = "Ticks here"

    def msg_to_player(self, screen):
        """ tracks and handles messages to player """
        message1_sf = DEFAULT_GAME_FONT.render(self.player_msg, True, Color("white"))
        screen.blit(message1_sf, (20, 550, SCREEN_WIDTH, SCREEN_HEIGHT))
        """ tick counter """
        message2_sf = DEFAULT_GAME_FONT.render(self.tick_counter, True, Color("white"))
        screen.blit(message2_sf, (20, 20, SCREEN_WIDTH, SCREEN_HEIGHT))

    def draw_messageboard(self, screen):
        self.draw_rimmed_box(screen, self.message_rect, (self.x, self.width, self.offset), 4, Color(self.back_color))
        DEFAULT_GAME_FONT = pygame.font.SysFont("arial", 18)
        message1_sf = DEFAULT_GAME_FONT.render(self.msg1, True, Color("white"))
        message2_sf = DEFAULT_GAME_FONT.render(self.msg2, True, Color("white"))
        message3_sf = DEFAULT_GAME_FONT.render(self.msg3, True, Color("white"))
        message4 = "Heroes: " + str(HERO_WINS)
        message4_sf = DEFAULT_GAME_FONT.render(message4, True, Color("white"))
        message5 = "Enemies: " + str(ENEMY_WINS)
        message5_sf = DEFAULT_GAME_FONT.render(message5, True, Color("white"))
        screen.blit(message1_sf, self.message_rect.move(0, message1_sf.get_height()))
        screen.blit(message2_sf, self.message_rect.move(0, message2_sf.get_height() * 2))
        screen.blit(message3_sf, self.message_rect.move(0, message2_sf.get_height() * 3))
        screen.blit(message4_sf, self.message_rect.move(0, message4_sf.get_height() * 4))
        screen.blit(message5_sf, self.message_rect.move(0, message5_sf.get_height() * 5))
        self.msg_to_player(screen)

    def draw_player_units(self, screen, unit_group):
        """ blits player unit text to output display window """
        self.draw_rimmed_box(
            screen,
            Rect(600, 150, SCREEN_WIDTH, SCREEN_HEIGHT),
            (self.x, self.width, self.offset),
            4,
            Color(self.back_color),
        )
        DEFAULT_GAME_FONT = pygame.font.SysFont("arial", 12)
        offset = 0
        for unit in unit_group:
            message1_sf = DEFAULT_GAME_FONT.render(unit.info_msg1, True, Color("white"))
            message1_status = DEFAULT_GAME_FONT.render(unit.txt_status, True, Color("white"))
            message2_sf = DEFAULT_GAME_FONT.render(unit.info_msg2, True, Color("white"))
            screen.blit(message1_sf, self.unit_group_rect.move(0, message1_sf.get_height() * 1 + offset * 24))
            screen.blit(message1_status, self.unit_group_rect.move(100, message1_status.get_height() * 1 + offset * 24))
            screen.blit(message2_sf, self.unit_group_rect.move(0, message2_sf.get_height() * 2 + offset * 24))
            for button in unit.unit_btns:
                button.draw(screen)
            offset += 2

    def draw_rimmed_box(self, screen, box_rect, box_color, rim_width=0, rim_color=Color("black")):
        """ Draw a rimmed box on the given surface. 
            The rim is drawn outside the box rect. 
        """
        if rim_width:
            rim_rect = Rect(
                box_rect.left - rim_width,
                box_rect.top - rim_width,
                box_rect.width + rim_width * 2,
                box_rect.height + rim_width * 2,
            )
            pygame.draw.rect(screen, rim_color, rim_rect)
        pygame.draw.rect(screen, box_color, box_rect)

    def in_field(self, pos):
        """ verify if clicked pos is in playable grid area  - returns True/False """
        loc = self.coord_to_grid(pos)
        if loc[0] < 0 or loc[0] >= self.x or loc[1] < 0 or loc[1] >= GRID_SIZE[1]:
            # print("you missed the player_command grid")
            return False
        else:
            return True

    def grid_clicked(self, pos):
        """ tells what grid was clicked on and reports for testing purposes 
            pos: the passed mouse coordinates variable passed through 
        """
        if self.in_field(pos):
            # print("click is in player_command field")
            # print("pos clicked:", pos)
            dummy = False
コード例 #27
0
ファイル: _windowbase.py プロジェクト: Clarabel/PyIsoX3
class Window(pygame.sprite.Sprite):

    def __init__(self, x, y, width, height):
        pygame.sprite.Sprite.__init__(self)
        self.image = Surface((width, height)).convert(32, pygame.RLEACCEL)
        self._windowskin = None
        self.rect = Rect(x, y, width, height)
        self.selected_rect = None
        self.widgets = []
        
    @property
    def offset(self):
        return 16

    @property
    def screen_pos(self):
        pos = self.rect.topleft
        return (pos[0] + self.offset, pos[1] + self.offset)
    
    @property
    def font(self):
        if not hasattr(self, '_font'):
            self._font = pygame.font.Font(None, 24)
        return self._font
    @font.setter
    def font(self, value):
        self._font = value
        
    def create_contents(self):
        w, h = self.rect.inflate(-2*self.offset, -2*self.offset).size
        self.contents = Surface((w, h)).convert_alpha()
        self.font_color = (255,255,255)

    def draw_text(self, x, y, text):
        bmp = self.font.render(text, 1, self.font_color)
        self.contents.blit(bmp, (x,y))

    def draw_selected(self, destsurf):
        if self.selected_rect:
            rect = self.selected_rect.move(self.rect.topleft)
            selected_surf = destsurf.subsurface(rect)
            pygame.transform.scale(self._select_src, self.selected_rect.size,
                                   selected_surf)
            
    @property
    def windowskin(self):
        return self._windowskin

    @windowskin.setter
    def windowskin(self, value):
        self._windowskin = value
        self._background = self._windowskin.subsurface(0,0,64,64)
        self._cadre = self._windowskin.subsurface(64,0,64,64)
        self._select_src = self._windowskin.subsurface(64,64,32,32)
        w, h = self.rect.size
        pygame.transform.scale(self._background, (w, h), self.image)
        #draw the four corners on the window
        for src, dest in [[(0, 0), (0,0)],
                     [(48, 0), (w-16, 0)],
                     [(0, 48), (0, h-16)],
                     [(48, 48), (w-16, h-16)]]:
            src_rect = Rect(src, (16, 16))
            dest_rect = Rect(dest, (16, 16))
            self.image.blit(self._cadre.subsurface(src_rect), dest)

    def draw(self, destsurf):
        destsurf.blit(self.image, self.rect)
        self.draw_selected(destsurf)
        destsurf.blit(self.contents, self.rect.move(self.offset, self.offset),
                                      self.contents_src)
        
    def add_widget(self, widget):
        self.widgets.append(widget)
        widget.parent = self
        widget.parent_offset = self.offset

    @property
    def contents_size(self):
        width, height = self.rect.inflate(-2*self.offset, -2*self.offset).size
        return width, height
    @property
    def contents_rect(self):
        "return the visible rect of contents"
        return self.rect.inflate(-2*self.offset, -2*self.offset)
    @property
    def contents_src(self):
        return self.contents.get_rect()
コード例 #28
0
ファイル: camera.py プロジェクト: MykleCode/pygame-doodlejump
    def apply_rect(self, rect: Rect) -> Rect:
        """ Transforms given rect relative to camera position.
		:param rect pygame.Rect: the rect to transform
		"""
        return rect.move((0, -self.state.topleft[1]))
コード例 #29
0
def make_I(rect: Rect, bw: int) -> Sequence[Rect]:
    return [rect.move(i*bw, 0) for i in range(4)]
コード例 #30
0
class Widget(object):
    #  rect            Rect       bounds in parent's coordinates
    #  parent          Widget     containing widget
    #  subwidgets      [Widget]   contained widgets
    #  focus_switch    Widget     subwidget to receive key events
    #  fg_color        color      or None to inherit from parent
    #  bg_color        color      to fill background, or None
    #  visible         boolean
    #  border_width    int        width of border to draw around widget, or None
    #  border_color    color      or None to use widget foreground color
    #  tab_stop        boolean    stop on this widget when tabbing
    #  anchor          string     of 'ltrb'

    font = FontProperty('font')
    fg_color = ThemeProperty('fg_color')
    bg_color = ThemeProperty('bg_color')
    bg_image = ThemeProperty('bg_image')
    scale_bg = ThemeProperty('scale_bg')
    border_width = ThemeProperty('border_width')
    border_color = ThemeProperty('border_color')
    sel_color = ThemeProperty('sel_color')
    margin = ThemeProperty('margin')
    menu_bar = overridable_property('menu_bar')
    is_gl_container = overridable_property('is_gl_container')

    tab_stop = False
    enter_response = None
    cancel_response = None
    anchor = 'ltwh'
    debug_resize = False
    _menubar = None
    _visible = True
    _is_gl_container = False
    redraw_every_event = True

    tooltip = None
    tooltipText = None
    doNotTranslate = False

    # 'name' is used to track widgets without parent
    name = 'Widget'

    # 'focusable' is used to know if a widget can have the focus.
    # Used to tell container widgets like Columns or Dialogs tofind the next focusable widget
    # in their children.
    focusable = True

    def __init__(self, rect=None, **kwds):
        if rect and not isinstance(rect, Rect):
            raise TypeError("Widget rect not a pygame.Rect")
        self._rect = Rect(rect or (0, 0, 100, 100))
        # -# Translation live update preparation
        self.__lang = albow.translate.getLang()
        self.__update_translation = False
        self.shrink_wrapped = False
        # -#
        self.parent = None
        self.subwidgets = []
        self.focus_switch = None
        self.is_modal = False
        self.set(**kwds)
        self.root = self.get_root()
        self.setup_spacings()

    def __repr__(self):
        return "{0} {1}, child of {2}".format(super(Widget, self).__repr__(), getattr(self, "text", "\b").encode('ascii', errors='backslashreplace'), self.parent)

    # -# Translation live update preparation
    @property
    def get_update_translation(self):
        return self.__update_translation

    def set_update_ui(self, v):
        if v:
            self.font = self.predict_font({})
            for widget in self.subwidgets:
                widget.set_update_ui(v)
            if self.shrink_wrapped:
                self.shrink_wrap()
            if hasattr(self, 'calc_size'):
                self.calc_size()
            self.invalidate()
        self.__update_translation = v

    # -#

    def setup_spacings(self):
        def new_size(size):
            size = float(size * 1000) / float(100)
            size = int(size * resource.font_proportion / 1000)
            return size

        self.margin = new_size(self.margin)
        if hasattr(self, 'spacing'):
            self.spacing = new_size(self.spacing)

    def set(self, **kwds):
        for name, value in kwds.items():
            if not hasattr(self, name):
                raise TypeError("Unexpected keyword argument '%s'" % name)
            setattr(self, name, value)

    def get_rect(self):
        return self._rect

    def set_rect(self, x):
        old_size = self._rect.size
        self._rect = Rect(x)
        self._resized(old_size)

    resizing_axes = {'h': 'lr', 'v': 'tb'}
    resizing_values = {'': [0], 'm': [1], 's': [0, 1]}

    def set_resizing(self, axis, value):
        chars = self.resizing_axes[axis]
        anchor = self.anchor
        for c in chars:
            anchor = anchor.replace(c, '')
        for i in self.resizing_values[value]:
            anchor += chars[i]
        self.anchor = anchor + value

    def _resized(self, xxx_todo_changeme):
        (old_width, old_height) = xxx_todo_changeme
        new_width, new_height = self._rect.size
        dw = new_width - old_width
        dh = new_height - old_height
        if dw or dh:
            self.resized(dw, dh)

    def resized(self, dw, dh):
        if self.debug_resize:
            print("Widget.resized:", self, "by", (dw, dh), "to", self.size)
        for widget in self.subwidgets:
            widget.parent_resized(dw, dh)

    def parent_resized(self, dw, dh):
        debug_resize = self.debug_resize or getattr(self.parent, 'debug_resize', False)
        if debug_resize:
            print("Widget.parent_resized:", self, "by", (dw, dh))
        left, top, width, height = self._rect
        move = False
        resize = False
        anchor = self.anchor
        if dw:
            factors = [1, 1, 1]  # left, width, right
            if 'r' in anchor:
                factors[2] = 0
            if 'w' in anchor:
                factors[1] = 0
            if 'l' in anchor:
                factors[0] = 0
            if any(factors):
                resize = factors[1]
                move = factors[0] or factors[2]
                # print "lwr", factors
                left += factors[0] * dw / sum(factors)
                width += factors[1] * dw / sum(factors)
                # left = (left + width) + factors[2] * dw / sum(factors) - width

        if dh:
            factors = [1, 1, 1]  # bottom, height, top
            if 't' in anchor:
                factors[2] = 0
            if 'h' in anchor:
                factors[1] = 0
            if 'b' in anchor:
                factors[0] = 0
            if any(factors):
                resize = factors[1]
                move = factors[0] or factors[2]
                # print "bht", factors
                top += factors[2] * dh / sum(factors)
                height += factors[1] * dh / sum(factors)
                # top = (top + height) + factors[0] * dh / sum(factors) - height

        if resize:
            if debug_resize:
                print("Widget.parent_resized: changing rect to", (left, top, width, height))
            self.rect = Rect((left, top, width, height))
        elif move:
            if debug_resize:
                print("Widget.parent_resized: moving to", (left, top))
            self._rect.topleft = (left, top)

    rect = property(get_rect, set_rect)

    left = rect_property('left')
    right = rect_property('right')
    top = rect_property('top')
    bottom = rect_property('bottom')
    width = rect_property('width')
    height = rect_property('height')
    size = rect_property('size')
    topleft = rect_property('topleft')
    topright = rect_property('topright')
    bottomleft = rect_property('bottomleft')
    bottomright = rect_property('bottomright')
    midleft = rect_property('midleft')
    midright = rect_property('midright')
    midtop = rect_property('midtop')
    midbottom = rect_property('midbottom')
    center = rect_property('center')
    centerx = rect_property('centerx')
    centery = rect_property('centery')

    def get_visible(self):
        return self._visible

    def set_visible(self, x):
        self._visible = x

    visible = overridable_property('visible')

    def add(self, arg, index=None):
        if arg:
            if isinstance(arg, Widget):
                if index is not None:
                    arg.set_parent(self, index)
                else:
                    arg.set_parent(self)
            else:
                for item in arg:
                    self.add(item)

    def add_centered(self, widget):
        w, h = self.size
        widget.center = w // 2, h // 2
        self.add(widget)

    def remove(self, widget):
        if widget in self.subwidgets:
            widget.set_parent(None)

    def set_parent(self, parent, index=None):
        if parent is not self.parent:
            if self.parent:
                self.parent._remove(self)
            self.parent = parent
            if parent:
                parent._add(self, index)

    def all_parents(self):
        widget = self
        parents = []
        while widget.parent:
            parents.append(widget.parent)
            widget = widget.parent
        return parents

    def _add(self, widget, index=None):
        if index is not None:
            self.subwidgets.insert(index, widget)
        else:
            self.subwidgets.append(widget)
        if hasattr(widget, "idleevent"):
            # print "Adding idle handler for ", widget
            self.root.add_idle_handler(widget)

    def _remove(self, widget):
        if hasattr(widget, "idleevent"):
            # print "Removing idle handler for ", widget
            self.root.remove_idle_handler(widget)
        self.subwidgets.remove(widget)

        if self.focus_switch is widget:
            self.focus_switch = None

    def draw_all(self, surface):
        if self.visible:
            surf_rect = surface.get_rect()
            bg_image = self.bg_image
            if bg_image:
                assert isinstance(bg_image, Surface)
                if self.scale_bg:
                    bg_width, bg_height = bg_image.get_size()
                    width, height = self.size
                    if width > bg_width or height > bg_height:
                        hscale = width / bg_width
                        vscale = height / bg_height
                        bg_image = rotozoom(bg_image, 0.0, max(hscale, vscale))
                r = bg_image.get_rect()
                r.center = surf_rect.center
                surface.blit(bg_image, r)
            else:
                bg = self.bg_color
                if bg:
                    surface.fill(bg)
            self.draw(surface)
            bw = self.border_width
            if bw:
                if self.has_focus() and hasattr(self, "highlight_color"):
                    bc = self.highlight_color
                else:
                    bc = self.border_color or self.fg_color
                frame_rect(surface, bc, surf_rect, bw)
            for widget in self.subwidgets:
                sub_rect = widget.rect
                if debug_rect:
                    print("Widget: Drawing subwidget %s of %s with rect %s" % (
                        widget, self, sub_rect))
                sub_rect = surf_rect.clip(sub_rect)
                if sub_rect.width > 0 and sub_rect.height > 0:
                    try:
                        sub = surface.subsurface(sub_rect)
                    except ValueError as e:
                        if str(e) == "subsurface rectangle outside surface area":
                            self.diagnose_subsurface_problem(surface, widget)
                        else:
                            raise
                    else:
                        widget.draw_all(sub)
            self.draw_over(surface)

    def diagnose_subsurface_problem(self, surface, widget):
        mess = "Widget %s %s outside parent surface %s %s" % (
            widget, widget.rect, self, surface.get_rect())
        sys.stderr.write("%s\n" % mess)
        surface.fill((255, 0, 0), widget.rect)

    def draw(self, surface):
        pass

    def draw_over(self, surface):
        pass

    def find_widget(self, pos):
        for widget in self.subwidgets[::-1]:
            if widget.visible:
                r = widget.rect
                if r.collidepoint(pos):
                    return widget.find_widget(subtract(pos, r.topleft))
        return self

    def handle_mouse(self, name, event):
        self.augment_mouse_event(event)
        self.call_handler(name, event)
        self.setup_cursor(event)

    def mouse_down(self, event):
        self.call_parent_handler("mouse_down", event)

    def mouse_up(self, event):
        self.call_parent_handler("mouse_up", event)

    def augment_mouse_event(self, event):
        event.dict['local'] = self.global_to_local(event.pos)

    def setup_cursor(self, event):
        global current_cursor
        cursor = self.get_cursor(event) or arrow_cursor
        if cursor is not current_cursor:
            set_cursor(*cursor)
            current_cursor = cursor

    def dispatch_key(self, name, event):
        if self.visible:

            if event.type == KEYDOWN:
                menubar = self._menubar
                if menubar and menubar.handle_command_key(event):
                    return
            widget = self.focus_switch
            if widget:
                widget.dispatch_key(name, event)
            else:
                self.call_handler(name, event)
        else:
            self.call_parent_handler(name, event)

    def get_focus(self):
        widget = self
        while 1:
            focus = widget.focus_switch
            if not focus:
                break
            widget = focus
        return widget

    def notify_attention_loss(self):
        widget = self
        while 1:
            if widget.is_modal:
                break
            parent = widget.parent
            if not parent:
                break
            focus = parent.focus_switch
            if focus and focus is not widget:
                self.root.notMove = False
                focus.dispatch_attention_loss()
            widget = parent

    def dispatch_attention_loss(self):
        widget = self
        if hasattr(self, "_highlighted"):
            self._highlighted = False
        while widget:
            widget.attention_lost()
            widget = widget.focus_switch

    def attention_lost(self):
        pass

    def handle_command(self, name, *args):
        method = getattr(self, name, None)
        if method:
            return method(*args)
        else:
            parent = self.next_handler()
            if parent:
                return parent.handle_command(name, *args)

    def next_handler(self):
        if not self.is_modal:
            return self.parent

    def call_handler(self, name, *args):
        method = getattr(self, name, None)
        if method:
            return method(*args)
        else:
            return 'pass'

    def call_parent_handler(self, name, *args):
        parent = self.next_handler()
        if parent:
            parent.call_handler(name, *args)

    def global_to_local(self, p):
        return subtract(p, self.local_to_global_offset())

    def local_to_global(self, p):
        return add(p, self.local_to_global_offset())

    def local_to_global_offset(self):
        d = self.topleft
        parent = self.parent
        if parent:
            d = add(d, parent.local_to_global_offset())
        return d

    def key_down(self, event):
        k = event.key
        # print "Widget.key_down:", k ###
        if k == K_RETURN or k == K_KP_ENTER:
            if self.enter_response is not None:
                self.dismiss(self.enter_response)
                return
        elif k == K_ESCAPE:
            self.root.fix_sticky_ctrl()
            if self.cancel_response is not None:
                self.dismiss(self.cancel_response)
                return
        elif k == K_TAB:
            self.tab_to_next()
            return
        self.call_parent_handler('key_down', event)

    def key_up(self, event):
        self.call_parent_handler('key_up', event)

    def is_inside(self, container):
        widget = self
        while widget:
            if widget is container:
                return True
            widget = widget.parent
        return False

    @property
    def is_hover(self):
        return self.root.hover_widget is self

    def present(self, centered=True):
        # print "Widget: presenting with rect", self.rect
        if self.root is None:
            self.root = self.get_root()
        if "ControlPanel" not in str(self):
            self.root.notMove = True
        if centered:
            self.center = self.root.center
        self.root.add(self)
        try:
            self.root.run_modal(self)
            self.dispatch_attention_loss()
        finally:
            self.root.remove(self)
        # print "Widget.present: returning", self.modal_result
        if "ControlPanel" not in str(self):
            self.root.notMove = False
        return self.modal_result

    def dismiss(self, value=True):
        self.root.notMove = False
        self.modal_result = value

    def get_root(self):
        return root_widget

    def get_top_widget(self):
        top = self
        while top.parent and not top.is_modal:
            top = top.parent
        return top

    def focus(self):
        parent = self.next_handler()
        if parent:
            parent.focus_on(self)
            if hasattr(self, "_highlighted"):
                self._highlighted = True

    def focus_on(self, subwidget):
        old_focus = self.focus_switch
        if old_focus is not subwidget:
            if old_focus:
                old_focus.dispatch_attention_loss()
            self.focus_switch = subwidget
        self.focus()

    def has_focus(self):
        return self.is_modal or (self.parent and self.parent.focused_on(self))

    def focused_on(self, widget):
        return self.focus_switch is widget and self.has_focus()

    def focus_chain(self):
        result = []
        widget = self
        while widget:
            result.append(widget)
            widget = widget.focus_switch
        return result

    def shrink_wrap(self):
        contents = self.subwidgets
        if contents:
            rects = [widget.rect for widget in contents]
            # rmax = Rect.unionall(rects) # broken in PyGame 1.7.1
            rmax = rects.pop()
            for r in rects:
                rmax = rmax.union(r)
            self._rect.size = add(rmax.topleft, rmax.bottomright)
        # -# Translation live update preparation
        self.shrink_wrapped = True
        # -#

    def invalidate(self):
        if self.root:
            self.root.bonus_draw_time = False

    @staticmethod
    def get_cursor(event):
        return arrow_cursor

    def predict(self, kwds, name):
        try:
            return kwds[name]
        except KeyError:
            return theme.root.get(self.__class__, name)

    def predict_attr(self, kwds, name):
        try:
            return kwds[name]
        except KeyError:
            return getattr(self, name)

    def init_attr(self, kwds, name):
        try:
            return kwds.pop(name)
        except KeyError:
            return getattr(self, name)

    def predict_font(self, kwds, name='font'):
        return kwds.get(name) or theme.root.get_font(self.__class__, name)

    def get_margin_rect(self):
        r = Rect((0, 0), self.size)
        d = -2 * self.margin
        r.inflate_ip(d, d)
        return r

    def set_size_for_text(self, width, nlines=1):
        if width is not None:
            font = self.font
            d = 2 * self.margin
            if isinstance(width, str):
                width, height = font.size(width)
                width += d + 2
            else:
                height = font.size("X")[1]
            self.size = (width, height * nlines + d)

    def tab_to_first(self):
        chain = self.get_tab_order()
        if chain:
            chain[0].focus()

    def _is_next_in_tab(self, top, delta=1):
        """Helper function to find if the current widget is ne 'next' on when 'tabbing'.
        :param top: Widget: The 'top' widget to find 'self' in tab order.
        :param delta: int: The index modifier. Shall be 1 or -1. Defaults to 1.
        Returns a tuple: (<'self' index in 'top.get_tab_order()' result>, <'top.subwidgets>)
        If 'self' is not found, the first tuple element is 0, and the second one a tuple of widgets.
        If self is found, the first elemnt is the index it was found, the second one one a tuple of widgets."""
        idx = 0
        chain = top.get_tab_order()
        if self in chain:
            idx = chain.index(self) + delta
        return idx, chain

    def tab_to_next(self):
        """Give focus to the next focusable widget."""
        top = self.get_top_widget()
        # If SHIFT key is hold down, set the index modifier to -1 to iterate to the previuos widget
        # instead of the next one.
        delta = 1
        if self.root.get_modifiers()["shift"]:
            delta = -1
        idx, subwidgets = self._is_next_in_tab(top, delta)
        chain = top.get_tab_order() + subwidgets
        target = chain[idx % len(chain)]
        while not target.focusable:
            _, subwidgets = target._is_next_in_tab(target, delta)
            chain = chain + subwidgets
            idx = chain.index(target) + delta
            target = chain[idx % len(chain)]

        self.get_focus().dispatch_attention_loss()
        target.focus()

    def get_tab_order(self):
        result = []
        self.collect_tab_order(result)
        return result

    def collect_tab_order(self, result):
        if self.visible:
            if self.tab_stop:
                result.append(self)
            for child in self.subwidgets:
                child.collect_tab_order(result)

            #    def tab_to_first(self, start = None):
            #        if debug_tab:
            #            print "Enter Widget.tab_to_first:", self ###
            #            print "...start =", start ###
            #        if not self.visible:
            #            if debug_tab: print "...invisible" ###
            #            self.tab_to_next_in_parent(start)
            #        elif self.tab_stop:
            #            if debug_tab: print "...stopping here" ###
            #            self.focus()
            #        else:
            #            if debug_tab: print "...tabbing to next" ###
            #            self.tab_to_next(start or self)
            #        if debug_tab: print "Exit Widget.tab_to_first:", self ###
            #
            #    def tab_to_next(self, start = None):
            #        if debug_tab:
            #            print "Enter Widget.tab_to_next:", self ###
            #            print "...start =", start ###
            #        sub = self.subwidgets
            #        if sub:
            #            if debug_tab: print "...tabbing to first subwidget" ###
            #            sub[0].tab_to_first(start or self)
            #        else:
            #            if debug_tab: print "...tabbing to next in parent" ###
            #            self.tab_to_next_in_parent(start)
            #        if debug_tab: print "Exit Widget.tab_to_next:", self ###
            #
            #    def tab_to_next_in_parent(self, start):
            #        if debug_tab:
            #            print "Enter Widget.tab_to_next_in_parent:", self ###
            #            print "...start =", start ###
            #        parent = self.parent
            #        if parent and not self.is_modal:
            #            if debug_tab: print "...telling parent to tab to next" ###
            #            parent.tab_to_next_after(self, start)
            #        else:
            #            if self is not start:
            #                if debug_tab: print "...wrapping back to first" ###
            #                self.tab_to_first(start)
            #        if debug_tab: print "Exit Widget.tab_to_next_in_parent:", self ###
            #
            #    def tab_to_next_after(self, last, start):
            #        if debug_tab:
            #            print "Enter Widget.tab_to_next_after:", self, last ###
            #            print "...start =", start ###
            #        sub = self.subwidgets
            #        i = sub.index(last) + 1
            #        if debug_tab: print "...next index =", i, "of", len(sub) ###
            #        if i < len(sub):
            #            if debug_tab: print "...tabbing there" ###
            #            sub[i].tab_to_first(start)
            #        else:
            #            if debug_tab: print "...tabbing to next in parent" ###
            #            self.tab_to_next_in_parent(start)
            #        if debug_tab: print "Exit Widget.tab_to_next_after:", self, last ###

    def inherited(self, attribute):
        value = getattr(self, attribute)
        if value is not None:
            return value
        else:
            parent = self.next_handler()
            if parent:
                return parent.inherited(attribute)

    def __contains__(self, event):
        r = Rect(self._rect)
        r.left = 0
        r.top = 0
        p = self.global_to_local(event.pos)
        return r.collidepoint(p)

    def get_mouse(self):
        return self.root.get_mouse_for(self)

    def get_menu_bar(self):
        return self._menubar

    def set_menu_bar(self, menubar):
        if menubar is not self._menubar:
            if self._menubar:
                self.remove(self._menubar)
            self._menubar = menubar
            if menubar:
                if menubar.width == 0:
                    menubar.width = self.width
                    menubar.anchor = 'lr'
                self.add(menubar)

    def get_is_gl_container(self):
        return self._is_gl_container

    def set_is_gl_container(self, x):
        self._is_gl_container = x

    def gl_draw_all(self, root, offset):
        if not self.visible:
            return
        # from OpenGL import GL, GLU

        rect = self.rect.move(offset)
        if self.is_gl_container:
            self.gl_draw_self(root, offset)
            suboffset = rect.topleft
            for subwidget in self.subwidgets:
                subwidget.gl_draw_all(root, suboffset)
        else:
            try:
                surface = Surface(self.size, SRCALPHA)
            except:
                # size error?
                return
            self.draw_all(surface)
            data = image.tostring(surface, 'RGBA', 1)
            w, h = root.size
            GL.glViewport(0, 0, w, h)
            GL.glMatrixMode(GL.GL_PROJECTION)
            GL.glLoadIdentity()
            GLU.gluOrtho2D(0, w, 0, h)
            GL.glMatrixMode(GL.GL_MODELVIEW)
            GL.glLoadIdentity()
            GL.glRasterPos2i(max(rect.left, 0), max(h - rect.bottom, 0))
            GL.glPushAttrib(GL.GL_COLOR_BUFFER_BIT)
            GL.glEnable(GL.GL_BLEND)
            GL.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA)
            GL.glDrawPixels(self.width, self.height,
                            GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, fromstring(data, dtype='uint8'))
            GL.glPopAttrib()
            GL.glFlush()

    def gl_draw_self(self, root, offset):
        pass
コード例 #31
0
ファイル: player.py プロジェクト: ehouse/Bunbunmaru
class Player( Entity ):
	def __init__( self, lives, score, bulletMan, maxSpeed, sprite, viewBox, bulletSprite, bulletBox ):
		# position vars
		self.SPAWN_X = 300
		self.SPAWN_Y = 600
		self.xpos = self.SPAWN_X
		self.ypos = self.SPAWN_Y
		Entity.__init__( self, 400 , 300, sprite, Rect( self.xpos - 10,
							self.ypos - 10, self.xpos + 54, self.ypos + 54 ) )

		# movement vars
		self._maxSpeed = maxSpeed
		self._focusedSpeed = maxSpeed /  2.0
		self._xSpeed = 0
		self._ySpeed = 0

		# Game vars
		self.lives = lives
		self.score = score
		self.invincible = False
		self._invincibilityTime = 5000
		self._bulletMan = bulletMan
		self._FIRE_COOL_MAX = 10
		self._fireCoolDown = 0

		# sprite vars
		self._itemBox = Rect( self.xpos, self.ypos, self.xpos + 64,
									self.ypos + 64 )
		self._viewBox = viewBox
		self._bulletSprite = bulletSprite
		self._bulletBox = bulletBox

	def act( self ):
		"""
		Handles movement and other actions for the player
		"""

		#TODO possibly think of a more elegant way to handle this
		focused = False
		up = False
		down = False
		left = False
		right = False
		focus = False
		fire = False
		bomb = False

		if pygame.key.get_focused():
			keys = pygame.key.get_pressed()
			up = keys[K_UP]
			down = keys[K_DOWN]
			right = keys[K_RIGHT]
			left = keys[K_LEFT]
			focus = keys[K_LSHIFT]
			fire = keys[K_z]
			bomb = keys[K_x]
		# Get if focused here
		if focused == True:
			if up == True:
				self._ySpeed = -1 * self._focusedSpeed
			elif down == True:
				self._ySpeed = self._focusedSpeed
			else:
				self._ySpeed = 0

			if left == True:
				self._xSpeed = -1 * self._focusedSpeed
			elif right == True:
				self._xSpeed = self._focusedSpeed
			else:
				self._xSpeed = 0
		else:
			if up == True:
				self._ySpeed = -1 * self._maxSpeed
			elif down == True:
				self._ySpeed = self._maxSpeed
			else:
				self._ySpeed = 0

			if left == True:
				self._xSpeed = -1 * self._maxSpeed
			elif right == True:
				self._xSpeed = self._maxSpeed
			else:
				self._xSpeed = 0

		if self._viewBox.x < 0 and self._xSpeed < 0:
			self._xSpeed = 0
		elif self._viewBox.x >= 800 - 64 and self._xSpeed > 0:
			self._xSpeed = 0

		if self._viewBox.y < 0 and self._ySpeed < 0:
			self._ySpeed = 0
		elif self._viewBox.y >= 600 - 64 and self._ySpeed > 0:
			self._ySpeed = 0

		if fire and self._fireCoolDown <= 0:
			self._fire()
			self._fireCoolDown = self._FIRE_COOL_MAX
		elif self._fireCoolDown > 0:
			self._fireCoolDown -= 1

		self._move()

		#TODO invincibility timer

	def _fire( self ):
		bullet = Bullet( self.xpos, self.ypos, -5, 1, self._bulletSprite,
						self._bulletSprite.get_rect())
		bullet2 = Bullet( self.xpos, self.ypos, -5, 1, self._bulletSprite,
						self._bulletSprite.get_rect())
		xpos = self._viewBox.x + 16
		ypos = self._viewBox.y + 22
		bullet._hitbox.move_ip(xpos, ypos)
		xpos = self._viewBox.x + 30
		ypos = self._viewBox.y + 22
		bullet2._hitbox.move_ip(xpos, ypos)
		self._bulletMan.addPlayerBullet( bullet )
		self._bulletMan.addPlayerBullet( bullet2 )
	def draw( self, screen ):
		screen.blit(self._sprite,(self._viewBox))

	def destroy( self ):
		"""
		Moves the player off screen temporally, then respawns them at the starting position
		"""
		#TODO Draw explosion
		self.xpos = -99
		self.ypos = -99

		self.hitbox = self.hitbox.move( self._xSpeed, self._ySpeed )
		self._itemBox = self._itemBox.move( self._xSpeed, self._ySpeed )

	def collidesWith( self ):
		pass

	def spawn( self ):
		self.xpos = self.SPAWN_X
		self.ypos = self.SPAWN_Y
		self.invincible = True

	def _move( self ):
		"""
		Moves the player based off of the xSpeed and YSpeed
		"""
		self.xpos = self.xpos + self._xSpeed
		self.ypos = self.ypos + self._ySpeed

		self._viewBox = self._viewBox.move( self._xSpeed, self._ySpeed)

		self._hitbox = self._hitbox.move( self._xSpeed, self._ySpeed )
		self._itemBox = self._itemBox.move( self._xSpeed, self._ySpeed )
コード例 #32
0
ファイル: character.py プロジェクト: donhilion/JumpAndRun
class Character(object):
	""" The character class.

	An object of this class represents the playable character.

	Attributes:
		_state: The current state of the character. This might be STANDING, WALKING or JUMPING.
		_lives: The current number of lives left.
		_points: The current points of this character
		_is_falling: Determines if the character is falling at the moment.
		_dy: Vertical speed of the character.
		_direction: The direction the character is looking. This can be LEFT, RIGHT or NONE.
		_invincible: Determines if the character is invincible at the moment.
		_walk_animation: Contains the walking animation.
		_stand_animation: Contains the standing animation
		_jump_animation: Contains the jumping animation for the NONE direction.
		_jump_right_animation: Contains the jumping animation for the directions LEFT and RIGHT.
		_death_animation: Contains the death animation of the character.
		_collision_rect: The rectangle for collision detection.
		_top_rect: The rectangle for on the top of the character.
		_bottom_rect: The rectangle for on the bottom of the character.
		_left_rect: The rectangle for on the left of the character.
		_right_rect: The rectangle for on the right of the character.
		_collect_sound: The sound for collecting coins.
	"""

	# Values for the _state attribute.
	STANDING, WALKING, JUMPING = range(3)
	# Values for the _direction attribute.
	LEFT, RIGHT, NONE = range(3)
	# Horizontal speed.
	SPEED = 1
	# If true more information is displayed.
	DEBUG = False
	# Maximal falling speed.
	MAX_FALLING = 2
	# Vertical acceleration.
	V_FALLING = 0.1
	# Width of the character.
	WIDTH = 27
	# Height of the character.
	HEIGHT = 48

	def __init__(self, pos=[0, 0], state=STANDING, lives=3, points=0, walk_animation=None, stand_animation=None,
				 jump_animation=None, jump_right_animation=None, death_animation=None):
		""" Generates a new instance of this class.

		Generates a new instance of the character class and sets the field information.
		If the animation arguments are left empty, the standard animations will be used.

		Args:
			pos: The starting position of the character.
			state: The starting state of the character.
			lives: The starting number of lives of the character.
			points: The starting point count of the character.
			walk_animation: The walking animation of the character.
			stand_animation: The standing animation of the character.
			jump_animation: The jumping animation of the character for the direction NONE.
			jump_right_animation: The jumping animation of the character for the directions LEFT and RIGHT.
			death_animation: The death animation of the character.
		"""
		self._state = state
		self._lives = lives
		self._points = points
		self._is_falling = False
		self._dy = 0
		self._direction = Character.NONE
		self._invincible = 0
		if walk_animation is None or stand_animation is None or jump_animation is None or jump_right_animation is None:
			animation_manager = AnimationManager.MANAGER
			animation = animation_manager.get_animation("animations")
			if walk_animation is None:
				walk_animation = Animated(PictureManager.MANAGER, animation[0], animation[1]["HeroWalk"], True)
			if stand_animation is None:
				stand_animation = Animated(PictureManager.MANAGER, animation[0], animation[1]["HeroStand"])
			if jump_animation is None:
				jump_animation = Animated(PictureManager.MANAGER, animation[0], animation[1]["HeroJump"])
			if jump_right_animation is None:
				jump_right_animation = Animated(PictureManager.MANAGER, animation[0], animation[1]["HeroJumpRight"],
												True)
			if death_animation is None:
				death_animation = (PictureManager.MANAGER, animation[0], animation[1]["HeroDie"])
		self._walk_animation = walk_animation
		self._stand_animation = stand_animation
		self._jump_animation = jump_animation
		self._jump_right_animation = jump_right_animation
		self._death_animation = death_animation

		self._pos = pos[:]

		self._collision_rect = Rect(pos[0], pos[1], Character.WIDTH, Character.HEIGHT)

		self._top_rect = Rect(pos[0], pos[1], Character.WIDTH, 1)
		self._bottom_rect = Rect(pos[0], pos[1] + Character.HEIGHT - 1, Character.WIDTH, 1)
		self._left_rect = Rect(pos[0], pos[1], 1, Character.HEIGHT - 1)
		self._right_rect = Rect(pos[0] + Character.WIDTH - 1, pos[1], 1, Character.HEIGHT - 1)

		self._collect_sound = SoundManager.MANAGER.get_sound("coin.wav")

	def draw(self, surface, tick, camera, size):
		""" The drawing method.

		This method draws the character on the given surface.

		Args:
			surface: The surface the character will be drawn on.
			tick: The current tick of the game.
			camera: The position of the camera.
			size: The size of the window. This argument is not used at the moment.
		"""
		if self._state == Character.STANDING:
			self._stand_animation.draw(surface, self._collision_rect.x - camera[0], self._collision_rect.y - camera[1],
									   tick)
		elif self._state == Character.WALKING:
			self._walk_animation.draw(surface, self._collision_rect.x - camera[0], self._collision_rect.y - camera[1],
									  tick, self._direction == Character.LEFT)
		elif self._state == Character.JUMPING:
			if self._direction == Character.NONE:
				self._jump_animation.draw(surface, self._collision_rect.x - camera[0],
										  self._collision_rect.y - camera[1], tick)
			else:
				self._jump_right_animation.draw(surface, self._collision_rect.x - camera[0],
												self._collision_rect.y - camera[1], tick,
												self._direction == Character.LEFT)
		if Character.DEBUG:
			move = camera[:]
			move[0] *= -1
			move[1] *= -1
			pygame.draw.rect(surface, (255, 255, 255), self._collision_rect.move(move), 2)
			pygame.draw.rect(surface, (255, 0, 0), self._top_rect.move(move), 1)
			pygame.draw.rect(surface, (255, 0, 0), self._bottom_rect.move(move), 1)
			pygame.draw.rect(surface, (0, 0, 255), self._left_rect.move(move), 1)
			pygame.draw.rect(surface, (0, 0, 255), self._right_rect.move(move), 1)

	def tick(self, platforms, collectables):
		""" Method for handling game ticks.

		This method should be called every tick to calculate the character changes.

		Args:
			platforms: The platforms of the level.
			collectables: The collectables, like coins, of the level.
		"""
		self._direction = Character.NONE
		if self._invincible > 0:
			self._invincible -= 1
		self._state = Character.STANDING
		if self._is_falling:
			if self._dy < Character.MAX_FALLING:
				self._dy += Character.V_FALLING
			self._state = Character.JUMPING
		else:
			self._dy = 0
		self._pos[1] += self._dy
		self._adjust_rects()

		movedX = 0
		movedY = 0
		for platform in platforms:
			while platform.collides(self._collision_rect):
				dx = 0
				dy = 0
				if platform.collides(self._top_rect):
					dy += 1
				if platform.collides(self._bottom_rect):
					dy -= 1
				if platform.collides(self._left_rect):
					dx += 1
				if platform.collides(self._right_rect):
					dx -= 1
				if dx == 0 and dy == 0: # completely in platform
					print("a")
					return # TODO: dead
				if (dx != 0 and dx == -movedX) or (dy != 0 and dy == -movedY): # crushed
					return # TODO: dead
				self._pos[0] += dx
				self._pos[1] += dy
				self._adjust_rects()
				movedX = dx
				movedY = dy

		for collectable in collectables:
			if collectable.collides(self._collision_rect):
				self._points += collectable.get_value()
				collectables.remove(collectable)
				self._collect_sound.play()


	def move(self, dx, platforms):
		""" This method moves the character.

		This method moves the character depending of the direction and the platforms of the level.

		Args:
			dx: The direction of the movement.
			platforms: The platforms of the level.
		"""
		if dx < 0:
			self._direction = Character.LEFT
		elif dx > 0:
			self._direction = Character.RIGHT

		self._pos[0] += dx * Character.SPEED
		self._adjust_rects()
		if self._state is not Character.JUMPING:
			self._state = Character.WALKING

	def jump(self):
		""" This method lets the character jump.

		Calling this method, the vertical speed of the character is set to 5 in the up direction. This results in a jump.
		"""
		self._is_falling = True
		self._dy = -5

	def get_points(self):
		""" Method to get the current points.

		This method returns the current point count of the character.

		Returns:
			The current point count of the character.
		"""
		return self._points

	def is_colliding(self, rect):
		""" Method for checking for collision.

		This method checks if the character collides with the given rectangle.

		Args:
			rect: The rectangle to check with.

		Returns:
			True if the character collides with the given rectangle. Else otherwise.
		"""
		return rect.colliderect(self._collision_rect)

	def get_x(self):
		""" Returns the x coordinate.

		This method returns the x coordinate of the character.

		Returns:
			The x coordinate.
		"""
		return self._collision_rect.x + 14

	def get_y(self):
		""" Returns the y coordinate.

		This method returns the y coordinate of the character.

		Returns:
			The y coordinate.
		"""
		return self._collision_rect.y + 25

	def get_lives(self):
		"""	Returns the lives.

		This method returns the current live count of the character.

		Returns:
			The current lives.
		"""
		return self._lives

	def change_lives(self, dl):
		""" Changes the current lives.

		This method changes the current live count by the given amount.

		Args:
			dl: The delta to changes the live count by.
		"""
		self._lives += dl
		if dl < 0:
			self._invincible = 100
			self.jump()

	def change_points(self, dp):
		""" Changes the current points.

		This method changes the current point count by the given amount.

		Args:
			dp: The delta to change the point count by.
		"""
		self._points += dp

	def is_invincible(self):
		""" Returns the invincible flag.

		This method returns if the character is invincible at the moment.

		Returns:
			True if the character is invincible at the moment. Else otherwise.
		"""
		return self._invincible

	def get_walking_line(self):
		""" Returns the walking line.

		This method returns the character's current walking line.

		Returns:
			The character's current walking line.
		"""
		return self._bottom_rect.move(0,1)

	def get_death_animation(self):
		""" Returns the death animation.

		This method returns the death animation on the current location of the character.

		Returns:
			The death animation of the character.
		"""
		return Animation(self._death_animation[0], self._death_animation[1], self._death_animation[2],
						 (self._collision_rect.x - 11, self._collision_rect.y))

	def _adjust_rects(self):
		self._collision_rect.x = self._pos[0]
		self._collision_rect.y = self._pos[1]
		self._top_rect.x = self._collision_rect.x
		self._top_rect.y = self._collision_rect.y
		self._bottom_rect.x = self._collision_rect.x
		self._bottom_rect.y = self._collision_rect.y + Character.HEIGHT - 1
		self._left_rect.x = self._collision_rect.x
		self._left_rect.y = self._collision_rect.y
		self._right_rect.x = self._collision_rect.x + Character.WIDTH - 1
		self._right_rect.y = self._collision_rect.y
コード例 #33
0
class Person(sprite.Sprite):
    image_list_right = [image.load(script_dir + im) for im in []]
    image_list_left = [image.load(script_dir + im) for im in []]

    def __init__(self, x, y, speed=5, hp=None, name='', group=None):
        self.anim_count = 0
        self.how_much_animations = len(self.image_list_right)
        self.image = self.image_list_right[0]

        self.rect = self.image_list_right[0].get_rect()
        width, height = self.rect.bottomright
        self.rect = Rect((x - width, y), (width, height))

        self.is_dead = False
        self.is_go_right = True
        self.is_go_left = False
        self.is_fall = True
        self.is_jump = False
        self.can_jump = False

        self.name = name

        self.speed = speed

        self.hp = hp
        self.damage = 0
        self.person_rect_list = []
        self.time = 0
        self.object_list = []

        self.cook_count = 0
        self.get_damage = False
        super().__init__(group)

    def __str__(self):
        return f'Персонаж - {self.name}. Координаты: {self.rect.x, self.rect.y}.' \
               f' Здоровье {self.hp}. Урон {self.damage}.'

    def set_time(self):
        '''Запоминает время получения урона'''
        self.time = time.time()

    def check_time(self):
        '''Проверяет, прошло ли время неуязвимости после получения урона или нет.'''
        return time.time() - self.time > 0.4

    def move(self, x=0, y=0):
        '''Общая функция перемещения персонажей.
         Возвращает True, если персонаж при перемещении вошел в какой-либо блок.'''
        self.change_animation()
        self.rect = self.rect.move(x, y)
        return self.in_other_rect(x, y)

    def give_object_list(self, object_list):
        '''Получает список объектов. ОБъекты всё, с чем на уровне взоимодействует персонаж.'''
        self.object_list = object_list

    def go_left(self):
        self.is_go_left = True
        self.is_go_right = False
        self.move(x=-self.speed)

    def go_right(self):
        self.is_go_left = False
        self.is_go_right = True
        self.move(x=self.speed)

    def enemy_move(self):
        '''Правила перемещения врагов, у всех разный метод.'''

    def change_hp(self, how_much):
        '''Меняет здоровье на значение. Значение не приводится к отрицательному или положительному числу.'''

        self.get_damage = True
        if how_much < 0:  # Временная неуязвимость при уроне
            if self.check_time():
                self.hp += how_much
                self.dead()
                self.set_time()
        else:
            self.hp += how_much

    def dead(self):
        if self.hp <= 0:
            self.is_dead = True

    def fall(self):
        '''Падение персонажа. ПЕрсонаж падает всегда когда не прыгает
        (если на блоке, то его возвращает на местin_other_rect'''
        if not self.is_jump or not self.can_jump:
            if not self.move(y=self.speed * 3):
                self.can_jump = False
            else:
                self.can_jump = True
                self.is_fall = False
        else:
            self.is_fall = False

    def change_animation(self):
        '''Меняет анимации при перемещении.'''
        self.anim_count += 1
        if self.anim_count >= self.how_much_animations:
            self.anim_count = 0
        if self.is_go_right:
            self.image = self.image_list_right[self.anim_count]
        elif self.is_go_left:
            self.image = self.image_list_left[self.anim_count]

    def in_other_rect(self, x=0, y=0):
        '''Если прерсонаж пападет в блок, выталкивает его, причем не всегда в первоначальное положение.
         Сторона выталкивания зависит от стороны движения персонажа. НЕ ВЫТАЛКИВАЕТ ПЕРСОНАЖА,
         ЕСЛИ в методе взоимодействия объекта с персонажам указано не выталкивать персоенажа.'''
        answer = []
        for object in self.object_list:
            if object:  # если не мертв(для персонажей), или активен (для блоков) возвращает True.
                if self.rect.colliderect(
                        object.rect) and self.rect != object.rect:
                    if not object.unique_properties(
                            self
                    ):  # мы должны получит True если блок сам уникально меняет координаты персонажа
                        if y < 0:
                            _, rect_y = object.rect.bottomright
                            self.rect = Rect(
                                (self.rect.x, rect_y),
                                (self.rect.width, self.rect.height))
                            answer.append('u')
                        elif y > 0:
                            self.can_jump = True
                            _, rect_y = object.rect.topright
                            self.rect = Rect(
                                (self.rect.x, rect_y - self.rect.height),
                                (self.rect.width, self.rect.height))
                            answer.append('d')
                        elif x < 0 and object.type != 'enemy':
                            rect_x, _ = object.rect.bottomright
                            self.rect = Rect(
                                (object.rect.x + self.rect.width, self.rect.y),
                                (self.rect.width, self.rect.height))
                            answer.append('l')
                        elif x > 0 and object.type != 'enemy':
                            rect_x, _ = object.rect.topleft
                            self.rect = Rect(
                                (object.rect.x - self.rect.width, self.rect.y),
                                (self.rect.width, self.rect.height))
                            answer.append('r')
        return answer

    def change_cook_count(self, how_much=1):
        self.cook_count += how_much

    def unique_properties(self, hero):
        '''Уникальное взоимодействие с персонажами. Некий абстрактный метод,
         который может быть реализован или не реализован в дочерних классах'''
        return True
コード例 #34
0
class Monster(sprite.Sprite):
    def __init__(self, move_time, nodes):
        sprite.Sprite.__init__(self)
        self.nodes = nodes
        self.orig_nodes = nodes
        self.move_time = move_time
        self.spawn_time = time.time()
        self.image = Surface((40, 40)).convert()
        self.image_inside = Surface((38, 38)).convert()
        self.image_inside.fill((0, 255, 0))
        self.image.blit(self.image_inside, (1, 1))
        self.pos = (80, 40)
        self.real_pos = (80, 40)
        self.rect = Rect(self.pos, self.image.get_size())
        self.speed = 2
        self.speed_mod = 1
        self.diag_speed = 2
        self.target_pos = (880, 560)
        self.value = 1
        self.cost = 0
        self.health = 100
        self.damage_mod = 1
        self.counter = 0
        self.cur_node = self.nodes[0]
        self.the_dir = (0, 0)
        self.can_move = False

        self.name = "Monster"
        self.description = "A basic monster with slow movement speed and moderate health."

    def update(self, window):

        if time.time() - self.spawn_time >= self.move_time:
            self.can_move = True
            # If it's hit the last block
            if len(self.nodes) < 1:
                self.kill()
                return self.value
            else:

                # Figuring direction
                if self.nodes[0].rect.x > self.cur_node.rect.x:
                    self.the_dir = (1, 0)
                elif self.nodes[0].rect.x < self.cur_node.rect.x:
                    self.the_dir = (-1, 0)
                elif self.nodes[0].rect.y > self.cur_node.rect.y:
                    self.the_dir = (0, 1)
                elif self.nodes[0].rect.y < self.cur_node.rect.y:
                    self.the_dir = (0, -1)

                # Check to see the most the monster can move
                for speed in range(0, self.speed + 1):
                    t_dir = tuple(
                        [x * speed * self.speed_mod for x in self.the_dir])

                    # Monster can only move this much
                    if self.rect.move(t_dir) == self.nodes[0].rect:
                        self.rect.move_ip(t_dir)
                        self.real_pos = tuple(
                            map(sum, zip(self.real_pos, t_dir)))
                        self.cur_node = self.nodes.pop(0)
                        break
                else:
                    # The monster can move by self.speed
                    a = tuple([
                        x * self.speed * self.speed_mod for x in self.the_dir
                    ])
                    self.real_pos = tuple(map(sum, zip(self.real_pos, a)))
                    self.pos = tuple(map(round, self.real_pos))
                    self.rect.x, self.rect.y = self.pos

                # Conditions for the monster to die
                die_conditions = [
                    self.rect.top >= window.get_height(),
                    self.rect.left >= window.get_width(), self.rect.bottom <= 0
                ]
                if any(die_conditions):
                    self.kill()
                    return self.value

                # Resetting the modifiers, they'll be changed if the monster is under an effect
                self.speed_mod = 1
                self.damage_mod = 1
        return 0

    # Does damage to the monster and checks if it dies
    def damage(self, damage):
        self.health -= damage * self.damage_mod

        # Returns the amount of money to grant the player if the monster dies and also how much damage was done
        if self.health <= 0:
            self.kill()
            return self.value, damage * self.damage_mod
        else:
            return None, damage * self.damage_mod
コード例 #35
0
def make_Lr(rect: Rect, bw: int) -> Sequence[Rect]:
    rects = [rect]
    rects.extend([rect.move(i*bw, bw) for i in range(3)])
    return rects
コード例 #36
0
ファイル: box.py プロジェクト: keltoff/Demiurge
class Body:
    def __init__(self):
        self.pos = Pt(0, 0)
        self.shape = Rect(0, 0, 30, 50)

        self.scheme = None
        self.name = None

        self.speed = 10

        self.on_line = None

    @property
    def cpos(self):
        return self.pos

    def update(self, level, keys, is_player):
        if is_player:
            shift = Pt(0, 0)
            for key, change in {
                    'UP': (0, 10),
                    'DN': (0, -10),
                    'LT': (-10, 0),
                    'RT': (10, 0)
            }.iteritems():
                if key in keys:
                    shift += change
            self.pos = self.on_line.try_move(self.pos + shift)

            switch, dist = None, float('inf')
            if isinstance(self.on_line, HLine):
                if 'UP' in keys:
                    switch, dist = self.on_line.up_closest(self.pos)
                if 'DN' in keys:
                    switch, dist = self.on_line.down_closest(self.pos)
            if isinstance(self.on_line, VLine):
                if 'LT' in keys:
                    switch, dist = self.on_line.left_closest(self.pos)
                if 'RT' in keys:
                    switch, dist = self.on_line.right_closest(self.pos)

            if switch and dist <= self.speed:
                self.on_line = switch
                self.pos = switch.try_move(self.pos)
        else:
            # AI
            pass

    def draw(self, surface, camera, is_player):
        tpos = camera.transform(self.cpos)
        rect = self.shape.move(tpos.x, tpos.y)

        if is_player:
            color = pygame.Color('blue')
        else:
            color = pygame.Color('gray')
        pygame.draw.rect(surface, color, rect)

        if self.on_line:
            helper.marker(tpos, surface, 'o')
        else:
            helper.marker(tpos, surface, 'x')
コード例 #37
0
def make_Z(rect: Rect, bw: int) -> Sequence[Rect]:
    return [rect, rect.move(bw, 0),
            rect.move(bw, bw), rect.move(2*bw, bw)]
コード例 #38
0
def make_T(rect: Rect, bw: int) -> Sequence[Rect]:
    return [rect.move(-bw, 0), rect, rect.move(bw, 0), rect.move(0, bw)]
コード例 #39
0
ファイル: model.py プロジェクト: YoannQDQ/pyweek-dojo
class PlayerModel(BaseModel):
    """Player model. Most of the game physics is implemented here."""

    # Physics
    air_friction = 0.5, 0.5   # s-1
    gravity = 0, 981          # pixel/s-2
    load_speed = 600          # pixel/s-2
    init_speed = 250          # pixel/s
    max_loading_speed = 1000  # pixel/s

    # Animation
    period = 2.0           # s
    pre_jump = 0.25        # s
    load_factor_min = 5    # period-1
    load_factor_max = 10   # period-1
    blinking_period = 0.2  # s

    # Hitbox
    hitbox_ratio = 0.33

    # Direction to Rect attributes for wall collision
    collide_dct = {Dir.DOWN: "bottom",
                   Dir.LEFT: "left",
                   Dir.RIGHT: "right",
                   Dir.UP: "top"}

    # Resource to get the player size
    ref = "player_1"

    def init(self, pid):
        """Initialize the player."""
        # Attributes
        self.id = pid
        self.border = self.parent.border
        self.resource = self.control.resource
        # Player rectangle
        self.size = self.resource.image.get(self.ref)[0].get_size()
        self.rect = Rect((0, 0), self.size)
        if pid == 1:
            self.rect.bottomleft = self.border.rect.bottomleft
        else:
            self.rect.bottomright = self.border.rect.bottomright
        # Player state
        self.speed = self.remainder = xytuple(0.0, 0.0)
        self.control_dir = Dir.NONE
        self.save_dir = Dir.NONE
        self.pos = Dir.DOWN
        self.fixed = True
        self.ko = False
        self.steps = [self.rect]
        # Animation timer
        self.timer = Timer(self,
                           stop=self.period,
                           periodic=True).start()
        # Loading timer
        self.loading_timer = Timer(self,
                                   start=self.init_speed,
                                   stop=self.max_loading_speed)
        # Delay timer
        self.delay_timer = Timer(self,
                                 stop=self.pre_jump,
                                 callback=self.delay_callback)
        # Dying timer
        self.blinking_timer = Timer(self.parent.parent,
                                    stop=self.blinking_period,
                                    periodic=True)
        # Debug
        if self.control.settings.debug_mode:
            RectModel(self, "head", Color("red"))
            RectModel(self, "body", Color("green"))
            RectModel(self, "legs", Color("blue"))

    def register_dir(self, direction):
        """Register a new direction from the controller."""
        if any(direction):
            self.save_dir = direction
        self.control_dir = direction

    @property
    def delta_tuple(self):
        """Delta time as an xytuple."""
        return xytuple(self.delta, self.delta)

    @property
    def colliding(self):
        """True when colliding with the other player, False otherwise."""
        return self.parent.colliding

    @property
    def loading(self):
        """True when the player is loading a jump, False otherwise."""
        return self.loading_timer.is_set or not self.loading_timer.is_paused

    @property
    def prepared(self):
        """True when the player is prepared a jump, False otherwise."""
        return self.loading or not self.delay_timer.is_paused

    @property
    def loading_speed(self):
        """The current loading speed value."""
        return self.loading_timer.get()

    def set_ko(self):
        """Knock the player out."""
        self.ko = True
        self.fixed = False

    def load(self):
        """Register a load action."""
        if self.colliding:
            return
        self.delay_timer.reset().start()
        self.timer.set(self.period*0.9)

    def delay_callback(self, timer):
        """Start loading the jump."""
        self.loading_timer.reset().start(self.load_speed)
        self.timer.reset().start()

    def jump(self):
        """Make the player jump."""
        if self.colliding:
            return
        # Check conditions
        if self.fixed and not self.ko:
            dir_coef = self.current_dir
            if any(dir_coef):
                dir_coef /= (abs(dir_coef),)*2
                # Update speed
                self.speed += dir_coef * ((self.loading_speed,)*2)
            # Update status
            if self.pos != Dir.DOWN or any(dir_coef):
                self.save_dir = Dir.NONE
                self.pos = Dir.NONE
                self.fixed = False
        # Reset loading
        self.delay_timer.reset()
        self.loading_timer.reset()
        # Reset animation
        self.timer.reset().start()

    def update_collision(self):
        """Handle wall collisions."""
        collide_dct = dict(self.collide_dct.items())
        # Loop over changes
        while not self.border.rect.contains(self.rect):
            self.fixed = True
            self.save_dir = self.control_dir
            dct = {}
            # Test against the 4 directions.
            for direc, attr in collide_dct.items():
                rect = self.rect.copy()
                value = getattr(self.border.rect, attr)
                setattr(rect, attr, value)
                distance = abs(xytuple(*rect.topleft) - self.rect.topleft)
                dct[distance] = rect, direc, attr
            # Aply the smallest change
            self.rect, self.pos, _ = dct[min(dct)]
            del collide_dct[self.pos]
        # Do not grab the wall when KO
        if self.ko and self.pos != Dir.DOWN:
            self.fixed = False

    @property
    def loading_ratio(self):
        """Loading ratio between 0 and 1."""
        res = float(self.loading_speed - self.init_speed)
        return res / (self.max_loading_speed - self.init_speed)

    @property
    def current_dir(self):
        """Current direction with x and y in (-1, 0, 1)."""
        # Static case
        if self.fixed:
            if not any(self.save_dir) or \
               sum(self.save_dir*self.pos) > 0:
                return xytuple(0, 0)
            current_dir = self.save_dir - self.pos
            sign = lambda arg: cmp(arg, 0)
            return current_dir.map(sign)
        # Dynamic case
        return Dir.closest_dir(self.speed)

    def get_rect_from_dir(self, direction):
        """Compute a hitbox inside the player in a given direction."""
        size = xytuple(*self.size) * ((self.hitbox_ratio,)*2)
        attr = Dir.DIR_TO_ATTR[direction]
        rect = Rect((0, 0), size)
        value = getattr(self.rect, attr)
        setattr(rect, attr, value)
        return rect

    @property
    def head(self):
        """Head hitbox. Currently not used."""
        if self.ko:
            return Rect(0, 0, 0, 0)
        if self.fixed:
            return self.get_rect_from_dir(self.pos * (-1, -1))
        return self.get_rect_from_dir(self.current_dir * (-1, -1))

    @property
    def body(self):
        """Body hitbox. Currently not used."""
        if self.ko:
            return Rect(0, 0, 0, 0)
        return self.get_rect_from_dir(Dir.NONE)

    @property
    def legs(self):
        """Legs hitbox."""
        if self.ko or self.fixed:
            return Rect(0, 0, 0, 0)
        return self.get_rect_from_dir(self.current_dir)

    def update(self):
        """Update the player state."""
        # Get acc
        acc = -self.speed * self.air_friction
        acc += self.gravity
        # Update speed
        self.speed += self.delta_tuple * acc
        if self.fixed:
            self.speed *= 0, 0
        # Get step
        step = self.delta_tuple * self.speed
        step += self.remainder
        intstep = step.map(round)
        self.remainder = step - intstep
        # Register steps
        args = Rect(self.rect), self.rect.move(intstep)
        self.steps = list(Dir.generate_rects(*args))
        # Update timer
        if self.loading:
            delta = self.load_factor_max - self.load_factor_min
            ratio = self.load_factor_min + self.loading_ratio * delta
            self.timer.start(ratio)
コード例 #40
0
class Monster(sprite.Sprite):
    def __init__(self, move_time, nodes):
        sprite.Sprite.__init__(self)
        self.nodes = nodes
        self.orig_nodes = nodes
        self.move_time = move_time
        self.spawn_time = time.time()
        self.image = Surface((40, 40)).convert()
        self.image_inside = Surface((38, 38)).convert()
        self.image_inside.fill((0, 255, 0))
        self.image.blit(self.image_inside, (1, 1))
        self.pos = (80, 40)
        self.real_pos = (80, 40)
        self.rect = Rect(self.pos, self.image.get_size())
        self.speed = 2
        self.speed_mod = 1
        self.diag_speed = 2
        self.target_pos = (880, 560)
        self.value = 1
        self.cost = 0
        self.health = 100
        self.damage_mod = 1
        self.counter = 0
        self.cur_node = self.nodes[0]
        self.the_dir = (0, 0)
        self.can_move = False

        self.name = "Monster"
        self.description = "A basic monster with slow movement speed and moderate health."

    def update(self, window):

        if time.time() - self.spawn_time >= self.move_time:
            self.can_move = True
            # If it's hit the last block
            if len(self.nodes) < 1:
                self.kill()
                return self.value
            else:

                # Figuring direction
                if self.nodes[0].rect.x > self.cur_node.rect.x:
                    self.the_dir = (1, 0)
                elif self.nodes[0].rect.x < self.cur_node.rect.x:
                    self.the_dir = (-1, 0)
                elif self.nodes[0].rect.y > self.cur_node.rect.y:
                    self.the_dir = (0, 1)
                elif self.nodes[0].rect.y < self.cur_node.rect.y:
                    self.the_dir = (0, -1)

                # Check to see the most the monster can move
                for speed in range(0, self.speed+1):
                    t_dir = tuple([x * speed * self.speed_mod for x in self.the_dir])

                    # Monster can only move this much
                    if self.rect.move(t_dir) == self.nodes[0].rect:
                        self.rect.move_ip(t_dir)
                        self.real_pos = tuple(map(sum, zip(self.real_pos, t_dir)))
                        self.cur_node = self.nodes.pop(0)
                        break
                else:
                    # The monster can move by self.speed
                    a = tuple([x * self.speed * self.speed_mod for x in self.the_dir])
                    self.real_pos = tuple(map(sum, zip(self.real_pos, a)))
                    self.pos = tuple(map(round, self.real_pos))
                    self.rect.x, self.rect.y = self.pos

                # Conditions for the monster to die
                die_conditions = [self.rect.top >= window.get_height(),
                                  self.rect.left >= window.get_width(),
                                  self.rect.bottom <= 0]
                if any(die_conditions):
                    self.kill()
                    return self.value

                # Resetting the modifiers, they'll be changed if the monster is under an effect
                self.speed_mod = 1
                self.damage_mod = 1
        return 0

    # Does damage to the monster and checks if it dies
    def damage(self, damage):
        self.health -= damage*self.damage_mod

        # Returns the amount of money to grant the player if the monster dies and also how much damage was done
        if self.health <= 0:
            self.kill()
            return self.value, damage*self.damage_mod
        else:
            return None, damage*self.damage_mod
コード例 #41
0
ファイル: Animation.py プロジェクト: hanssonr/pxlgrvty
class Animation(Sprite):
    
    __mElapsedTime = None
    __mLooping = None
    __mRunning = None
    __mIsDone = None
    
    __mCurrentFrame = None
    __mCurrentRow = None
    __mDrawRect = None
    
    def __init__(self, sprite, framesX, framesY, animationtime, size, looping = True, running = True):
        super(Animation, self).__init__(sprite)
        
        self.__mElapsedTime = 0.0
        self.__mLooping = looping
        self.__mRunning = running
        self.__mIsDone = False
        self.__mCurrentFrame = 0
        self.__mCurrentRow = 0
        self.__mDrawRect = None
        
        Sprite.setSize(self, size)
        self.__mFramesX = framesX
        self.__mFramesY = framesY
        self.__mFrameHeight = Sprite.getHeight(self) / framesY
        self.__mFrameWidth = Sprite.getWidth(self) / framesX
        self.__mMaxTime = animationtime / self.__mFramesX
        self.__mDrawRect = Rect(self.__mCurrentFrame * self.__mFrameWidth, self.__mCurrentRow * self.__mFrameHeight, self.__mFrameWidth, self.__mFrameHeight)
    
    def draw(self, delta, position):
        if self.__mRunning:
            self.__mElapsedTime += delta
        
            if self.__mElapsedTime > self.__mMaxTime:
                
                self.__mCurrentFrame += 1
                
                if self.__mCurrentFrame >= self.__mFramesX:
                    self.__mCurrentFrame = 0
                    
                    if not self.__mLooping:
                        self.__mIsDone = True
                        self.__mRunning = False
            
                self.__mElapsedTime = 0.0
        
        Sprite.draw(self, position, self.__mDrawRect.move(self.__mCurrentFrame * self.__mFrameWidth, self.__mCurrentRow * self.__mFrameHeight))
    
    def freeze(self, frameX, frameY = 0):
        self.__mRunning = False
        self.__mCurrentFrame = frameX
        self.__mCurrentRow = frameY
    
    def continueAnimation(self):
        self.__mRunning = True
    
    def setLooping(self, looping):
        self.__mLooping = looping
        
    def gotoRow(self, row):
        if row <= self.__mFramesY:
            self.__mCurrentRow = row
            
    def getRect(self):
        return Rect(self.__mCurrentFrame * self.__mFrameWidth, self.__mCurrentRow * self.__mFrameHeight, self.__mFrameWidth, self.__mFrameHeight)
            
    def getFrame(self):
        return self.__mCurrentFrame
    
    def getRow(self):
        return self.__mCurrentRow
    
    def isAnimationDone(self):
        return self.__mIsDone
    
    def reset(self):
        self.__mIsDone = False
        self.__mCurrentFrame = 0
        self.__mCurrentRow = 0
        self.__mRunning = True
        
    def isLooping(self):
        return self.__mLooping
コード例 #42
0
 def move_paddle(self, paddle: pygame.Rect, control):
     if control[0] == 1:
         paddle = paddle.move(0, -PADDLE_SPEED)
     elif control[1] == 1:
         paddle = paddle.move(0, PADDLE_SPEED)
     return paddle
コード例 #43
0
class PlayerModel(BaseModel):
    """Player model. Most of the game physics is implemented here."""

    # Physics
    air_friction = 0.5, 0.5  # s-1
    gravity = 0, 981  # pixel/s-2
    load_speed = 600  # pixel/s-2
    init_speed = 250  # pixel/s
    max_loading_speed = 1000  # pixel/s

    # Animation
    period = 2.0  # s
    pre_jump = 0.25  # s
    load_factor_min = 5  # period-1
    load_factor_max = 10  # period-1
    blinking_period = 0.2  # s

    # Hitbox
    hitbox_ratio = 0.33

    # Direction to Rect attributes for wall collision
    collide_dct = {
        Dir.DOWN: "bottom",
        Dir.LEFT: "left",
        Dir.RIGHT: "right",
        Dir.UP: "top",
    }

    # Resource to get the player size
    ref = "player_1"

    def init(self, pid):
        """Initialize the player."""
        # Attributes
        self.id = pid
        self.border = self.parent.border
        self.resource = self.control.resource
        # Player rectangle
        self.size = self.resource.image.get(self.ref)[0].get_size()
        self.rect = Rect((0, 0), self.size)
        if pid == 1:
            self.rect.bottomleft = self.border.rect.bottomleft
        else:
            self.rect.bottomright = self.border.rect.bottomright
        # Player state
        self.speed = self.remainder = xytuple(0.0, 0.0)
        self.control_dir = Dir.NONE
        self.save_dir = Dir.NONE
        self.pos = Dir.DOWN
        self.fixed = True
        self.ko = False
        self.steps = [self.rect]
        # Animation timer
        self.timer = Timer(self, stop=self.period, periodic=True).start()
        # Loading timer
        self.loading_timer = Timer(
            self, start=self.init_speed, stop=self.max_loading_speed
        )
        # Delay timer
        self.delay_timer = Timer(self, stop=self.pre_jump, callback=self.delay_callback)
        # Dying timer
        self.blinking_timer = Timer(
            self.parent.parent, stop=self.blinking_period, periodic=True
        )
        # Debug
        if self.control.settings.debug_mode:
            RectModel(self, "head", Color("red"))
            RectModel(self, "body", Color("green"))
            RectModel(self, "legs", Color("blue"))

    def register_dir(self, direction):
        """Register a new direction from the controller."""
        if any(direction):
            self.save_dir = direction
        self.control_dir = direction

    @property
    def delta_tuple(self):
        """Delta time as an xytuple."""
        return xytuple(self.delta, self.delta)

    @property
    def colliding(self):
        """True when colliding with the other player, False otherwise."""
        return self.parent.colliding

    @property
    def loading(self):
        """True when the player is loading a jump, False otherwise."""
        return self.loading_timer.is_set or not self.loading_timer.is_paused

    @property
    def prepared(self):
        """True when the player is prepared a jump, False otherwise."""
        return self.loading or not self.delay_timer.is_paused

    @property
    def loading_speed(self):
        """The current loading speed value."""
        return self.loading_timer.get()

    def set_ko(self):
        """Knock the player out."""
        self.ko = True
        self.fixed = False

    def load(self):
        """Register a load action."""
        if self.colliding:
            return
        self.delay_timer.reset().start()
        self.timer.set(self.period * 0.9)

    def delay_callback(self, timer):
        """Start loading the jump."""
        self.loading_timer.reset().start(self.load_speed)
        self.timer.reset().start()

    def jump(self):
        """Make the player jump."""
        if self.colliding:
            return
        # Check conditions
        if self.fixed and not self.ko:
            dir_coef = self.current_dir
            if any(dir_coef):
                dir_coef /= (abs(dir_coef),) * 2
                # Update speed
                self.speed += dir_coef * ((self.loading_speed,) * 2)
            # Update status
            if self.pos != Dir.DOWN or any(dir_coef):
                self.save_dir = Dir.NONE
                self.pos = Dir.NONE
                self.fixed = False
        # Reset loading
        self.delay_timer.reset()
        self.loading_timer.reset()
        # Reset animation
        self.timer.reset().start()

    def update_collision(self):
        """Handle wall collisions."""
        collide_dct = dict(list(self.collide_dct.items()))
        # Loop over changes
        while not self.border.rect.contains(self.rect):
            self.fixed = True
            self.save_dir = self.control_dir
            dct = {}
            # Test against the 4 directions.
            for direc, attr in list(collide_dct.items()):
                rect = self.rect.copy()
                value = getattr(self.border.rect, attr)
                setattr(rect, attr, value)
                distance = abs(xytuple(*rect.topleft) - self.rect.topleft)
                dct[distance] = rect, direc, attr
            # Aply the smallest change
            self.rect, self.pos, _ = dct[min(dct)]
            del collide_dct[self.pos]
        # Do not grab the wall when KO
        if self.ko and self.pos != Dir.DOWN:
            self.fixed = False

    @property
    def loading_ratio(self):
        """Loading ratio between 0 and 1."""
        res = float(self.loading_speed - self.init_speed)
        return res / (self.max_loading_speed - self.init_speed)

    @property
    def current_dir(self):
        """Current direction with x and y in (-1, 0, 1)."""
        # Static case
        if self.fixed:
            if not any(self.save_dir) or sum(self.save_dir * self.pos) > 0:
                return xytuple(0, 0)
            current_dir = self.save_dir - self.pos
            sign = lambda arg: (arg > 0) - (arg < 0)
            return current_dir.map(sign)
        # Dynamic case
        return Dir.closest_dir(self.speed)

    def get_rect_from_dir(self, direction):
        """Compute a hitbox inside the player in a given direction."""
        size = xytuple(*self.size) * ((self.hitbox_ratio,) * 2)
        attr = Dir.DIR_TO_ATTR[direction]
        rect = Rect((0, 0), size)
        value = getattr(self.rect, attr)
        setattr(rect, attr, value)
        return rect

    @property
    def head(self):
        """Head hitbox. Currently not used."""
        if self.ko:
            return Rect(0, 0, 0, 0)
        if self.fixed:
            return self.get_rect_from_dir(self.pos * (-1, -1))
        return self.get_rect_from_dir(self.current_dir * (-1, -1))

    @property
    def body(self):
        """Body hitbox. Currently not used."""
        if self.ko:
            return Rect(0, 0, 0, 0)
        return self.get_rect_from_dir(Dir.NONE)

    @property
    def legs(self):
        """Legs hitbox."""
        if self.ko or self.fixed:
            return Rect(0, 0, 0, 0)
        return self.get_rect_from_dir(self.current_dir)

    def update(self):
        """Update the player state."""
        # Get acc
        acc = -self.speed * self.air_friction
        acc += self.gravity
        # Update speed
        self.speed += self.delta_tuple * acc
        if self.fixed:
            self.speed *= 0, 0
        # Get step
        step = self.delta_tuple * self.speed
        step += self.remainder
        intstep = step.map(round)
        self.remainder = step - intstep
        # Register steps
        args = Rect(self.rect), self.rect.move(intstep)
        self.steps = list(Dir.generate_rects(*args))
        # Update timer
        if self.loading:
            delta = self.load_factor_max - self.load_factor_min
            ratio = self.load_factor_min + self.loading_ratio * delta
            self.timer.start(ratio)