예제 #1
0
class Bullet(pygame.sprite.Sprite, Drawable, EventHandler):
    height = 5
    width = 5

    def __init__(self, x, y, direction: Directon = Directon.UP, velocity=5):
        super().__init__()
        self.velocity = velocity
        self.direction = direction
        self.rect = Rect(int(x - self.width / 2), y - self.height, self.width,
                         self.height)
        self.image = Surface((self.width, self.height))
        self.image.fill(WHITE)

    def handle(self, event: pygame.event.Event):
        pass

    def draw(self, surface: pygame.Surface):
        pygame.draw.rect(surface, WHITE, self.rect)

    def update(self, *args, **kwargs):
        # noinspection PyTypeChecker
        self.rect.move_ip(0, self.velocity * self.direction.value)

        if self.rect.y < 0 or self.rect.y > SCREEN_HEIGHT:
            self.kill()
예제 #2
0
class Select(Sprite):
    def __init__(self):
        Sprite.__init__(self)
        self.image = pygame.image.load('images/selector.png').convert()
        self.image.set_colorkey(PUCE, RLEACCEL)
        self.rect = Rect(10, 10, 30, 30)
        self.index = 0

    def setX(self, x):
        newpos = (self.rect.topleft[0] + x)
        if (newpos > 0) and (newpos < COLUMNS * 40 + 10):
            self.rect.move_ip(x, 0)
            if x > 0:
                self.index += 1
            else:
                self.index -= 1

    def setY(self, y):
        newpos = (self.rect.topleft[1] + y)
        if (newpos > 0) and (newpos < ROWS * 40 + 10):
            self.rect.move_ip(0, y)
            if y > 0:
                self.index += COLUMNS
            else:
                self.index -= COLUMNS
예제 #3
0
class Star(pygame.sprite.Sprite, Drawable):
    height = 1
    width = 1
    move_step = 2

    def __init__(self, direction: Directon = Directon.DOWN):
        super().__init__()
        self.direction = direction
        self.rect = Rect(random.randint(0, SCREEN_WITH),
                         random.randint(0, SCREEN_HEIGHT), self.width,
                         self.height)
        self.image = Surface((self.width, self.height))
        self.image.fill(WHITE)

    def handle(self, event: pygame.event.Event):
        pass

    def draw(self, surface: pygame.Surface):
        pygame.draw.rect(surface, WHITE, self.rect)

    def update(self, *args, **kwargs):
        self.rect.move_ip(0, self.move_step)

        if self.rect.y < 0 or self.rect.y > SCREEN_HEIGHT:
            self.rect.y = 0
            self.rect.x = random.randint(0, SCREEN_WITH)
예제 #4
0
 def nearest_edge(self, x, y):
     """ The nearest lot boundary on which a fence might be erected """
     lot = self.nearest_lot(x, y)
     if not lot:
         return None
     proximities = [(y - lot.top,"north"),
                    (lot.bottom-y,"south"),
                    (lot.right-x,"east"),
                    (x-lot.left,"west")]
     proximities.sort()
     closest = proximities[0]
     dist,side = closest
     if dist > EDGE_TOLERANCE:
         return None
     horizontal = (side=="north" or side=="south")
     vertical = (side=="east" or side=="west")
     if horizontal:
         rect = Rect(lot.left, lot.top - FENCE_MARGIN_NORTH, lot.width, 2*FENCE_MARGIN_NORTH)
         if side == "south":
             rect.move_ip(0, LOT_DEPTH)
         if not WATER_RECT.colliderect(rect):
             return rect
     elif vertical:
         rect = Rect(lot.left - FENCE_MARGIN_WEST, lot.top, 2*FENCE_MARGIN_WEST, lot.height)
         if side == "east":
             rect.move_ip(LOT_WIDTH, 0)
         if not WATER_RECT.colliderect(rect):
             return rect
예제 #5
0
class Select(Sprite):
    def __init__(self):
        Sprite.__init__(self)
        self.image = pygame.image.load('images/selector.png').convert()
        self.image.set_colorkey(PUCE, RLEACCEL)
        self.rect=Rect(10, 10, 30, 30)
        self.index = 0

    def setX(self, x):
        newpos = (self.rect.topleft[0] + x)
        if (newpos > 0) and (newpos < COLUMNS * 40 + 10):
            self.rect.move_ip(x,0)
            if x > 0:
                self.index += 1
            else:
                self.index -= 1

    def setY(self, y):
        newpos = (self.rect.topleft[1] + y)
        if (newpos > 0) and (newpos < ROWS * 40 + 10):
            self.rect.move_ip(0, y)
            if y > 0:
                self.index += COLUMNS
            else:
                self.index -= COLUMNS
예제 #6
0
 def drawMap(self, surface_blit, tiles):
     for spr in tiles:
         rect = Rect(spr.rect.x - self.screenRect.x, spr.rect.y - self.screenRect.y, 0, 0)
         self.spritedict[spr] = surface_blit(spr.image, rect)
         surface_blit(self.fontRendererSmall.render(str(spr.f), False, (0, 0, 0)), rect)
         for action in spr.userActions:
             rect.move_ip(0, 10)
             surface_blit(self.fontRendererSmall.render(str(action), False, (0, 0, 0)), rect)
예제 #7
0
파일: player.py 프로젝트: XrXr/RapidPygame
class Player(Animated):
    """
    An instance is compatible with the level manager. Note that if
    :func:`rapidpg.levelmgr.collision.Level.update` is not used, a player
    instance doesn't have to be passed to the level manager
    """
    def __init__(self, surfs, interval):
        """
        :param surfs: A list of surfaces for animation
        :param interval: The interval between animation updates
        """
        super(Player, self).__init__({"right": Animation(surfs, interval)},
                                     lambda: "right", "right")
        self.jump_frames_left = 0
        self.jumping = False
        self.in_air = False
        self.up_speed = 20
        self.down_speed = 0
        self.dir = 'right'
        self.surfs = surfs
        self.rect = Rect(0, 0, 0, 0)
        if surfs:
            self.rect = surfs[0].get_rect()
        self.animation_interval = interval
        self.speed = 7

    def move(self, x, y):
        """
        Alias for ``plr.rect.move_ip``
        """
        self.rect.move_ip(x, y)

    def start_jump(self):
        """
        This method is used by the level manager to start the jump
        """
        if not self.jumping:
            self.jumping = True
            self.in_air = True
예제 #8
0
class Gun(Sprite):
    def __init__(self, width, height, move_amount):
        super().__init__()

        self.width = width
        self.height = height
        self.move_amount = move_amount

        self.image = pygame.image.load(os.path.join(ASSETS_PATH, "sprites", "crosshair.png")).convert_alpha()
        self.image = pygame.transform.scale(self.image, (35, 35))
        rect = self.image.get_rect()
        self.rect = Rect(rect.left + 5, rect.top + 5, rect.width - 10, rect.height - 10).move(width // 2, height // 2)

    def blit(self, surface):
        surface.blit(self.image, self.rect)

    def shoot(self, ducks):
        hit_ducks = pygame.sprite.spritecollide(self, ducks, dokill=False)

        return sum([duck.got_shot() for duck in hit_ducks if duck.alive])

    def go_north(self):
        self.rect.move_ip(0, -self.move_amount)

    def go_northeast(self):
        self.rect.move_ip(self.move_amount, -self.move_amount)

    def go_east(self):
        self.rect.move_ip(self.move_amount, 0)

    def go_southeast(self):
        self.rect.move_ip(self.move_amount, self.move_amount)

    def go_south(self):
        self.rect.move_ip(0, self.move_amount)

    def go_southwest(self):
        self.rect.move_ip(-self.move_amount, self.move_amount)

    def go_west(self):
        self.rect.move_ip(-self.move_amount, 0)

    def go_northwest(self):
        self.rect.move_ip(-self.move_amount, -self.move_amount)

    def update(self):
        if self.rect.x >= self.width:
            self.rect.move_ip(-(self.rect.x - self.width + 1), 0)

        if self.rect.x < 0:
            self.rect.move_ip(-self.rect.x + 1, 0)

        if self.rect.y >= self.height:
            self.rect.move_ip(0, -(self.rect.y - self.height + 1))

        if self.rect.y < 0:
            self.rect.move_ip(0, (-self.rect.y + 1))
예제 #9
0
파일: hero.py 프로젝트: Kranek/PacMan
class Hero(EventObserver):

    def __init__(self, x, y, rect_martix, container, evenent_handler):
        super().__init__(container, evenent_handler)
        self.rect_matrix = rect_martix
        self.map_point = (y, x) #cooridnates on map.txt
        self.x = x * 20 - 3 # coordinates used to paint object
        self.y = y * 20 - 3
        self.speed = 2
        self.active = True
        self.area_rect = Rect(self.x + 3, self.y + 3, 20, 20)
        self.direction = K_RIGHT
        self.new_direction = K_RIGHT
        self.movements = {K_UP: (0, -self.speed), K_RIGHT: (self.speed, 0),
                          K_DOWN: (0, self.speed), K_LEFT: (-self.speed, 0),
                          K_w: (0, -self.speed), K_d: (self.speed, 0),
                          K_s: (0, self.speed), K_a: (-self.speed, 0),
                          K_DELETE: (0, 0)}

    def move_hero(self, arguments):
        pass

    def move(self):
        self.x += self.movements[self.direction][0]
        self.y += self.movements[self.direction][1]
        self.area_rect.move_ip(self.movements[self.direction][0], self.movements[self.direction][1])

    def go_back(self):
        self.x -= self.movements[self.direction][0]
        self.y -= self.movements[self.direction][1]
        self.area_rect.move_ip(-self.movements[self.direction][0], -self.movements[self.direction][1])

    def get_proper_random_direction(self):
        directions = []
        if self.direction in PLAYER_ONE_KEYS:
            for direction in PLAYER_ONE_KEYS :
                if not self.is_this_the_wall(direction):
                    directions.append(direction)
            return directions[randint(0, len(directions) - 1)]
        else:
            for direction in PLAYER_TWO_KEYS:
                if not self.is_this_the_wall(direction):
                    directions.append(direction)
            return directions[randint(0, len(directions) - 1)]

    def in_place_to_change_direction(self):
        return self.rect_matrix.is_at_direction_change_place(self.area_rect)

    #checks if next point with givien direction to current hero map_point have wall on it
    def is_this_the_wall(self, direction):
         return self.rect_matrix.is_this_the_wall(self.area_rect, (int(self.movements[direction][0]/self.speed),
                                                             int(self.movements[direction][1]/self.speed)))

    def reload_movements(self):
        self.movements = {K_UP: (0, -self.speed), K_RIGHT: (self.speed, 0),
                          K_DOWN: (0, self.speed), K_LEFT: (-self.speed, 0),
                          K_DELETE: (0, 0)}

    def teleport(self, map_point):
        self.map_point = map_point #cooridnates on map.txt
        self.x = map_point[1] * 20 - 3 # coordinates used to paint object
        self.y = map_point[0] * 20 - 3
        self.area_rect = Rect(self.x + 3, self.y + 3, 20, 20)
예제 #10
0
파일: camera.py 프로젝트: XrXr/RapidPygame
class Camera:
    """
    Class for keeping track of the camera position. In early stage of development
    """
    def __init__(self, screen_res, level_rect, x_speed=15, y_speed=15,
                 left_threshold=10, right_threshold=75, up_threshold=10,
                 down_threshold=75):
        """

        :param screen_res: A tuple of int. (w, h)
        :param level_rect: A rectangle that covers all of the level
        :param x_speed: The horizontal speed of the camera
        :param y_speed: The vertical speed of the camera
        :param left_threshold:
            The percentage of screen to reach in order for the camera to scroll
            left
        :param right_threshold:
            The percentage of screen to reach in order for the camera to scroll
            right
        :param up_threshold:
            The percentage of screen to reach in order for the camera to scroll
            up
        :param down_threshold:
            The percentage of screen to reach in order for the camera to scroll
            down
        """
        self.level_rect = level_rect
        self.horizontal_speed = x_speed
        self.vertical_speed = y_speed
        self.screen_res = screen_res
        self.rect = Rect((0, 0), screen_res)

        self.x_bound = self.level_rect.width - self.rect.width
        self.y_bound = self.level_rect.height - self.rect.height

        self.right_threshold = self.rect.width * right_threshold / 100
        self.left_threshold = self.rect.width * left_threshold / 100
        self.up_threshold = self.rect.height * up_threshold / 100
        self.down_threshold = self.rect.height * down_threshold / 100

    def pan_left(self, h_speed):
        if self.rect.x == 0:
            return
        if self.rect.move(-h_speed, 0).x < 0:
            self.rect.move_ip(-self.rect.x, 0)
        else:
            self.rect.move_ip(-h_speed, 0)

    def pan_right(self, h_speed):
        if self.rect.x == self.x_bound:
            return
        if self.rect.x + h_speed + self.rect.width > self.level_rect.width:
            self.rect.move_ip((self.level_rect.width - (self.rect.x + self.rect.width)), 0)
        else:
            self.rect.move_ip(h_speed, 0)

    def pan_down(self, v_speed):
        if self.rect.y == self.y_bound:
            return
        if self.rect.y + v_speed + self.rect.height > self.level_rect.height:
            self.rect.move_ip(0, (self.level_rect.height - self.rect.y - self.rect.height))
        else:
            self.rect.move_ip(0, v_speed)

    def pan_up(self, v_speed):
        if self.rect.y == 0:
            return
        if self.rect.move(0, -v_speed).y < 0:
            self.rect.move_ip(0, -self.rect.y)
        else:
            self.rect.move_ip(0, -v_speed)

    def snap_to(self, player_rect):
        propose = self.rect.move(0, 0)
        propose.x = min(max(0, player_rect.x - self.screen_res[0] / 2), self.x_bound)
        propose.y = min(max(0, player_rect.y - self.screen_res[1] / 2), self.y_bound)
        self.rect = propose

    def update(self, player_rect, custom_speed=None):
        h_speed, v_speed = self.horizontal_speed, self.vertical_speed
        if custom_speed:
            h_speed, v_speed = custom_speed
        if player_rect.x - self.rect.x > self.right_threshold:
            self.pan_right(h_speed)
        elif player_rect.x - self.rect.x < self.left_threshold:
            self.pan_left(h_speed)
        if player_rect.y - self.rect.y > self.down_threshold:
            self.pan_down(v_speed)
        elif player_rect.y - self.rect.y < self.up_threshold:
            self.pan_up(v_speed)
예제 #11
0
class Block(Rect):
    def __init__(self):
        self.shape = []     # list to hold blocks which makes up the shape
        self.type = ""
        self.color = random.choice([BLUE, GREEN, RED, ORANGE])
        draw = random.randint(1, 2)
        if draw == 1:
            self.type = "I"
            self.state = 1
            self.block1 = Rect(0, 0, block_size, block_size)   # left, top, width, height
            self.block2 = Rect(block_size, 0, block_size, block_size)
            self.block3 = Rect(block_size * 2, 0, block_size, block_size)
            self.block4 = Rect(block_size * 3, 0, block_size, block_size)
        elif draw == 2:
            self.type = "square"
            self.block1 = Rect(0, 0, block_size, block_size)
            self.block2 = Rect(block_size, 0, block_size, block_size)
            self.block3 = Rect(0, block_size, block_size, block_size)
            self.block4 = Rect(block_size, block_size, block_size, block_size)

        self.shape.append(self.block1)
        self.shape.append(self.block2)
        self.shape.append(self.block3)
        self.shape.append(self.block4)

        # elif draw == 3:
        #     self.type = "T"
        #     self.state = 1
        #     self.block1 = Rect(block_size, block_size, block_size, block_size)
        #     self.block2 = Rect(block_size * 2, block_size, block_size, block_size)
        #     self.block3 = Rect(block_size * 3, block_size, block_size, block_size)
        #     self.block4 = Rect(block_size * 2, 0, block_size, block_size)

    def rotate(self):
        # prohibit rotation if finished positions already occupied !!!
        if self.type == "I":
            if self.state == 1:
                self.block1.move_ip(block_size, -block_size * 2)
                self.block2.move_ip(0, -block_size)
                self.block3.move_ip(-block_size, 0)
                self.block4.move_ip(-block_size * 2, block_size)
                self.state = 2
            else:
                self.block1.move_ip(-block_size, block_size*2)
                self.block2.move_ip(0, block_size)
                self.block3.move_ip(block_size, 0)
                self.block4.move_ip(block_size*2, -block_size)
                self.state = 1
        elif self.type == "square":
            pass

        # elif self.type == "T":
        #     if self.state == 1:

    def collide_down(self, d):
        for item in self.shape:
            if item.bottomleft in d:
                return True
        return False

    def move_left(self, d):
        clear_to_move = True
        for item in self.shape:
            if (item.topleft[0] - block_size, item.topleft[1]) in d or item.left == 0:
                clear_to_move = False
        if clear_to_move:
            for item in self.shape:
                item.move_ip(-block_size, 0)

    def move_right(self, d):
        clear_to_move = True
        for item in self.shape:
            if (item.topleft[0] + block_size, item.topleft[1]) in d or item.right == block_size * col:
                clear_to_move = False
        if clear_to_move:
            for item in self.shape:
                item.move_ip(block_size, 0)

    def move_down(self):
        for item in self.shape:
            item.move_ip(0, block_size)

    def key_press(self, d):
        key = pygame.key.get_pressed()

        if key[pygame.K_LEFT]:
            self.move_left(d)

        if key[pygame.K_RIGHT]:
            self.move_right(d)

        if key[pygame.K_UP]:
            self.rotate()

    def draw(self, surface):
        for item in self.shape:
            pygame.draw.rect(surface, self.color, item)

    def get_bottom(self):
        return self.block4.bottom
예제 #12
0
class Graphic(Component):
    """A 2D image that can draw itself onto a Surface or another
    Graphic.

    It maintains a position relative to the associated Entity's
    on-screen position and will be drawn there accordingly.
    (For example, if the Entity's position is (30, 30) and this
    Graphic's position is (2, 3), it will be drawn to (32, 33)
    on-screen.)

    Several effects can also be applied to it, such as flipping the
    image and adding or reducing transparency.

    Attributes:
        _image (Surface): Contains the Graphic's actual pixel data.
        _rect (Rect): Contains the Graphic's x and y-offsets relative
            to its associated Entity, as well as its width and height.
    """
    def __init__(self, source, x=0, y=0):
        """Declare and initialize instance variables.

        Args:
            source (Surface): Contains the 2D image associated with this
                Graphic.
            x (int): The x-offset of the Graphic's top-left corner
                relative to its associated Entity.
                The default value is 0.
            y (int): The y-offset of the Graphic's top-left corner
                relative to its associated Entity.
                The default value is 0.
        """
        super(Graphic, self).__init__()
        self._image = convert_to_colorkey_alpha(source)
        self._rect = Rect(x, y, source.get_width(), source.get_height())

    def offset(self, dx=0, dy=0):
        """Move the Graphic away from its original position relative to
        the associated Entity by a set horizontal and/or vertical
        distance.

        It is safe to pass floats as arguments to this method; they will
        automatically be rounded to the nearest whole number.

        Args:
            dx (int): The horizontal distance to travel. A positive
                value will move the Graphic to the right, while a
                negative value will move it to the left.
                Defaults to 0.
            dy (int): The vertical distance to travel. A positive value
                will move the Graphic down, while a negative value will
                move it up.
                Defaults to 0.
        """
        self._rect.move_ip(int(round(dx)), int(round(dy)))

    def set_position(self, new_x=None, new_y=None):
        """Re-position the Graphic onto an exact location relative to
        its associated Entity.

        It is safe to pass floats as arguments to this method; they will
        automatically be rounded to the nearest whole number.

        Args:
            new_x (int): The x-coordinate of the top-left corner for the
                Graphic's new position.
                This parameter is optional; you can omit it from the
                function call if you want to retain the Graphic's
                x-position.
            new_y (int): The y-coordinate of the top-left corner for the
                Graphic's new position.
                This parameter is optional; you can omit it from the
                function call if you want to retain the Graphic's
                y-position.
        """
        if new_x is not None:
            self._rect.x = int(round(new_x))
        if new_y is not None:
            self._rect.y = int(round(new_y))

    def get_width(self):
        return self._rect.width

    def get_height(self):
        return self._rect.height

    def center(self, axis, container_rect):
        """Move the associated Entity so that this Graphic is centered
        horizontally and/or vertically within an area of the screen.

        Args:
            axis (Axis): A literal from the Axis enum for specifying
                whether the image should be centered on the horizontal
                or vertical plane.
                To center the image on both planes, you can combine both
                values using the | (bitwise or) operator.
            container_rect (Rect): A Rect containing the position and
                dimensions of the area that this Graphic will be
                centered relative to.
        """
        if (axis & Axis.horizontal) == Axis.horizontal:
            centered_x = (container_rect.width - self.get_width()) / 2
            centered_x += container_rect.x
            self.entity.set_position(new_x=centered_x - self._rect.x)

        if (axis & Axis.vertical) == Axis.vertical:
            centered_y = (container_rect.height - self.get_height()) / 2
            centered_y += container_rect.y
            self.entity.set_position(new_y=centered_y - self._rect.y)

    def is_contained(self, container_rect):
        """Return a Boolean indicating whether this Graphic is
        completely contained within an area of the screen.
        (i.e. No pixels exceed the area's boundaries.)

        Args:
            container_rect (Rect): Contains the position and dimensions
                of the area this Graphic will be compared to.
        """
        if container_rect.contains(self.draw_rect()):
            return True
        else:
            return False

    def is_outside(self, container_rect):
        """Return a Boolean indicating whether this Graphic is
        completely outside of an area of the screen.
        (i.e. All pixels exceed the area's boundaries.)

        Args:
            container_rect (Rect): Contains the position and dimensions
                of the area this Graphic will be compared to.
        """
        if not container_rect.colliderect(self.draw_rect()):
            return True
        else:
            return False

    def draw_rect(self):
        """Return a Rect containing the actual position the Graphic
        will be drawn to, with the Entity's position taken into account.
        """
        return self._rect.move(self.entity.x, self.entity.y)

    def flip(self, axis):
        """Flip the image horizontally and/or vertically.

        Args:
            axis (Axis): A literal from the Axis enum for specifying
                whether to apply a horizontal or vertical flip.
                To flip the image both ways, you can combine both values
                using the | (bitwise or) operator.
        """
        if (axis & Axis.horizontal) == Axis.horizontal:
            self._image = pygame.transform.flip(self._image, True, False)
        if (axis & Axis.vertical) == Axis.vertical:
            self._image = pygame.transform.flip(self._image, False, True)

    def magnify(self, zoom):
        """Enlarge or shrink the image using an equal scale for the
        width and height.

        Args:
            zoom (float): The amount used to multiply the image's
                dimensions. For example, passing a value of 2 when the
                image's dimensions are 24x24 will enlarge the image to
                48x48. Passing 0.5 will shrink it to 12x12.
        """
        magnified_image = pygame.transform.scale(
            self._image, (int(round(self.get_width() * zoom)),
                          int(round(self.get_height() * zoom))))
        self._image = magnified_image
        self._update_rect_dimensions()

    def resize(self, new_width, new_height):
        """Stretch and/or shrink the image to fit new dimensions.

        Args:
            new_width (int): The width that the image will shrink or
                stretch to fit.
            new_height (int): The height that the image will shrink or
                stretch to fit.
        """
        resized_image = pygame.transform.scale(
            self._image, (int(round(new_width)), int(round(new_height))))
        self._image = resized_image
        self._update_rect_dimensions()

    def _update_rect_dimensions(self):
        """Update the width and height of _rect with the current
        dimensions of _image.
        """
        self._rect.width = self._image.get_width()
        self._rect.height = self._image.get_height()

    def opacify(self, amount):
        """Increase or decrease the image's transparency.

        Note that Graphic images always start with an opacity of 255,
        which is fully opaque.

        Args:
            amount (int): How much to add to the image's opacity value.
                Positive values will make the image more opaque, while
                negative values will make it more transparent.
                To make the image fully opaque, pass 255 or more. To
                make the image fully transparent, pass -255 or less.
        """
        self._image.set_alpha(self._image.get_alpha() + amount)

    def is_opaque(self):
        """Return a Boolean indicating whether the image is fully
        opaque.
        """
        if self._image.get_alpha() >= 255:
            return True
        else:
            return False

    def is_transparent(self):
        """Return a Boolean indicating whether the image is fully
        transparent.
        """
        if self._image.get_alpha() <= 0:
            return True
        else:
            return False

    def blit(self, source, position, rect=None, special_flags=0):
        """Draw a Surface on top of this Graphic.

        Args:
            source (Surface): The image that will be drawn onto this
                Graphic.
            position (tuple of int, int): Contains the x and y-positions
                of the source image relative to this Graphic.
            area (Rect): An optional parameter specifying the region of
                the source image that will be used.
                Leave this parameter blank to draw the entire source
                image.
            special_flags (int): A combination of various PyGame flags
                for blitting effects. See the PyGame documentation on
                Surface.blit() for more information.
                This is an optional parameter; leave it blank to use no
                flags when blitting.

        Returns:
            A Rect containing the region of this Graphic that was drawn
            onto.
        """
        x = position[0]
        y = position[1]
        return self._image.blit(source, (x, y), rect, special_flags)

    def draw(self, destination):
        """Draw this Graphic's image onto a destination Surface.

        Args:
            destination (Surface): Will have this Graphic drawn on it.

        Returns:
            A Rect containing the region of the destination that was
            drawn onto.
        """
        return destination.blit(self._image, self.draw_rect())
예제 #13
0
class PointerSprite(Sprite):
    _layer = 999
    image = pygame.image.load(resources.get_image_asset("pointer.png"))
    SPEED = 100  # pixels per second
    MAX_SPEED = 500
    ACCELERATION = .1
    MOVE = {  # pixels per second X, pixels per second Y
        pygame.K_LEFT: (-SPEED, 0),
        pygame.K_RIGHT: (SPEED, 0),
        pygame.K_UP: (0, -SPEED),
        pygame.K_DOWN: (0, SPEED)
    }

    def __init__(self, vertex_group, scroll_group, *groups):
        super(PointerSprite, self).__init__(*groups)
        self.rect = Rect((0, 0), self.image.get_rect().size)
        self.movement = (0.0, 0.0)
        self.selected_vertex_id = None
        self.vertex_group = vertex_group

        self.image = self.image.convert()
        self.image.set_colorkey(COLOR_KEY)

        # The scroll_group is needed because the pointer exists in screen space, not world space. We have to translate
        # the screen location of the hotspot to its relative position in world space.
        self.scroll_group = scroll_group

    def update(self, delta, events):
        self.process_events(events)
        self.rect.move_ip(*self.calculate_movement(delta))
        self.clamp_topleft()

    def clamp_topleft(self):
        w, h = pygame.display.get_surface().get_rect().size
        x, y = self.rect.topleft
        x = min(max(0, x), w)
        y = min(max(0, y), h)
        self.rect.topleft = (x, y)

    def process_events(self, events):
        for event in events:
            if pygame.MOUSEMOTION == event.type:
                self.movement = (0.0, 0.0)
                self.rect.topleft = event.pos
            elif pygame.MOUSEBUTTONUP == event.type:
                self.check_vertex_collision()
            elif pygame.KEYDOWN == event.type:
                if pygame.K_SPACE == event.key:
                    self.check_vertex_collision()
                else:
                    x, y = self.movement
                    dx, dy = self.MOVE.get(event.key, (0.0, 0.0))
                    self.movement = (x + dx, y + dy)
            elif pygame.KEYUP == event.type:
                if pygame.K_LEFT == event.key or pygame.K_RIGHT == event.key:
                    self.movement = (0.0, self.movement[1])
                elif pygame.K_UP == event.key or pygame.K_DOWN == event.key:
                    self.movement = (self.movement[0], 0.0)

    def check_vertex_collision(self):
        vertices = spritecollide(self, self.vertex_group, False,
                                 self.collide_hotspot)
        if vertices:
            self.selected_vertex_id = vertices[0].vertex.vertex_id
            logger.debug("Selected vertex %s" % self.selected_vertex_id)

    @staticmethod
    def collide_hotspot(pointer, vertex_sprite):
        view_x, view_y = pointer.scroll_group.view.topleft
        pointer_x, pointer_y = pointer.rect.topleft
        hotspot = (view_x + pointer_x, view_y + pointer_y)
        return vertex_sprite.rect.collidepoint(hotspot)

    def calculate_movement(self, delta):
        amount = delta / 1000.0
        dx, dy = self.movement

        if dx != 0 or dy != 0:
            dx += dx * self.ACCELERATION
            dy += dy * self.ACCELERATION
            if abs(dx) > self.MAX_SPEED:
                dx = -self.MAX_SPEED if dx < 0 else self.MAX_SPEED
            if abs(dy) > self.MAX_SPEED:
                dy = -self.MAX_SPEED if dy < 0 else self.MAX_SPEED
            self.movement = (dx, dy)

        return amount * dx, amount * dy
예제 #14
0
파일: ai.py 프로젝트: jiajian-wu/tetris_ai
class Block(Rect):

    def __init__(self, matrix):
        self.shape = []  # list to hold blocks which makes up the shape
        self.type = ""
        self.state = None
        self.color = random.choice([BLUE, GREEN, RED, ORANGE])
        self.curr_steps = 0
        self.steps = None
        self.starting_column = 4
        starting_left_pos = 4 * block_size
        draw = random.randint(1, 7)  # generate a shape
        if draw == 1:
            self.type = "I"
            # score() --> decides 1.state with best score 2.steps needed to the right
            self.score(matrix)
            if self.state == 0:
                self.block1 = Rect(starting_left_pos, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + block_size, 0, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size * 2, 0, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size * 3, 0, block_size, block_size)

            elif self.state == 1:
                self.block1 = Rect(starting_left_pos, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos, block_size * 2, block_size, block_size)
                self.block4 = Rect(starting_left_pos, block_size * 3, block_size, block_size)

        elif draw == 2:
            self.type = "square"
            # score() --> decides 1.state with best score 2.steps needed to the right
            self.score(matrix)
            if self.state == 0:
                self.block1 = Rect(starting_left_pos, 0, block_size, block_size)
                self.block2 = Rect(starting_left_pos + block_size, 0, block_size, block_size)
                self.block3 = Rect(starting_left_pos, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)

        elif draw == 3:
            self.type = "z"
            # score() --> decides 1.state with best score 2.steps needed to the right
            self.score(matrix)
            if self.state == 0:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + block_size, 0, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size * 2, block_size, block_size, block_size)

            elif self.state == 1:
                self.block1 = Rect(starting_left_pos + block_size, 0, block_size,
                                   block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + 0, block_size * 2, block_size, block_size)

        elif draw == 4:
            self.type = "z_2"
            # score() --> decides 1.state with best score 2.steps needed to the right
            self.score(matrix)
            if self.state == 0:
                self.block1 = Rect(starting_left_pos + block_size, 0, block_size,
                                   block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + block_size * 2, 0, block_size, block_size)
                self.block3 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)

            elif self.state == 1:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size, block_size * 2, block_size, block_size)

        elif draw == 5:
            self.type = "T"
            self.score(matrix)
            if self.state == 0:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + block_size, 0, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size * 2, 0, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)

            elif self.state == 1:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + 0, block_size * 2, block_size, block_size)

            elif self.state == 2:
                self.block1 = Rect(starting_left_pos + block_size, 0, block_size,
                                   block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size * 2, block_size, block_size, block_size)

            elif self.state == 3:
                self.block1 = Rect(starting_left_pos + block_size, 0, block_size,
                                   block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size, block_size * 2, block_size, block_size)

        elif draw == 6:
            self.type = "L"
            self.score(matrix)
            if self.state == 0:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + block_size, 0, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size, block_size * 2, block_size, block_size)

            elif self.state == 1:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + block_size, 0, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size * 2, 0, block_size, block_size)
                self.block4 = Rect(starting_left_pos + 0, block_size, block_size, block_size)

            elif self.state == 2:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos + 0, block_size * 2, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size, block_size * 2, block_size, block_size)

            elif self.state == 3:
                self.block1 = Rect(starting_left_pos + block_size * 2, 0, block_size,
                                   block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size * 2, block_size, block_size, block_size)

        elif draw == 7:
            self.type = "L_2"
            self.score(matrix)
            if self.state == 0:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + block_size, 0, block_size, block_size)
                self.block3 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + 0, block_size * 2, block_size, block_size)

            elif self.state == 1:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + 0, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size * 2, block_size, block_size, block_size)

            elif self.state == 2:
                self.block1 = Rect(starting_left_pos + block_size, 0, block_size,
                                   block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + block_size, block_size, block_size, block_size)
                self.block3 = Rect(starting_left_pos + 0, block_size * 2, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size, block_size * 2, block_size, block_size)

            elif self.state == 3:
                self.block1 = Rect(starting_left_pos + 0, 0, block_size, block_size)  # left, top, width, height
                self.block2 = Rect(starting_left_pos + block_size, 0, block_size, block_size)
                self.block3 = Rect(starting_left_pos + block_size * 2, 0, block_size, block_size)
                self.block4 = Rect(starting_left_pos + block_size * 2, block_size, block_size, block_size)

        self.shape.append(self.block1)
        self.shape.append(self.block2)
        self.shape.append(self.block3)
        self.shape.append(self.block4)

    def score(self, matrix):  # matrix: pos_matrix in Block class

        matrix_copy = copy.deepcopy(matrix)

        apex_list = []  # position i stores the row number of the highest block at column i.
        for j in range(col):
            try:
                idx = [matrix[i][j] for i in range(len(matrix))].index(1)
                apex_list.append(idx)
            except ValueError:
                apex_list.append(row)

        # for each type, evaluate all possible positions of each rotation.
        # The number of moves are (rotations * right).

        # first position stores max_score, second position stores state,
        # third position stores # of steps to take
        optimal_move = [None] * 3
        max_score = float("-inf")
        shape_variants = Shape(self.type)
        # print("Type is ", self.type)
        for state in range(len(shape_variants.all_combos)):
            # print("State is ", state)
            rightmost = shape_variants.rightmost[state] + self.starting_column
            for step_number in range(0, col - rightmost):  # steps to move RIGHT
                min_distance = math.inf
                for coord in shape_variants.pos[state]:
                    # find the minimum distance to move
                    # row number: coord[0], col number: coord[1]+step_number
                    distance = apex_list[coord[1] + step_number + self.starting_column] - coord[0]
                    if distance < min_distance:
                        min_distance = distance

                # move them
                for coord in shape_variants.pos[state]:
                    matrix_copy[coord[0] + min_distance - 1][coord[1] + step_number + self.starting_column] = 1

                score = self.score_matrix(matrix_copy, min_distance)

                # print("\nMatrix after one possible movement is: ")
                # for idx, r in enumerate(matrix_copy):
                #     print(f'{idx: > 5}', r)
                # print("\n")

                matrix_copy = copy.deepcopy(matrix)

                if score > max_score:
                    max_score = score
                    optimal_move[0] = max_score
                    optimal_move[1] = state
                    optimal_move[2] = step_number

            for step_number in range(-1, -(self.starting_column + 1), -1):  # steps to move LEFT
                min_distance = math.inf
                for coord in shape_variants.pos[state]:
                    # find the minimum distance to move
                    # row number: coord[0], col number: coord[1] + step_number + starting_column
                    distance = apex_list[coord[1] + step_number + self.starting_column] - coord[0]
                    if distance < min_distance:
                        min_distance = distance

                # move them
                for coord in shape_variants.pos[state]:
                    matrix_copy[coord[0] + min_distance - 1][coord[1] + step_number + self.starting_column] = 1

                score = self.score_matrix(matrix_copy, min_distance)

                # print("\nMatrix after one possible movement is: ")
                # for idx, r in enumerate(matrix_copy):
                #     print(f'{idx: > 5}', r)
                # print("\n")

                matrix_copy = copy.deepcopy(matrix)

                if score > max_score:
                    max_score = score
                    optimal_move[0] = max_score
                    optimal_move[1] = state
                    optimal_move[2] = step_number

        self.state = optimal_move[1]
        self.steps = optimal_move[2]

    def score_matrix(self, matrix, move_distance):
        score = 0
        row_cleared = 0
        for r in matrix:
            if set(r) == {1}:
                row_cleared += 1
        score += row_cleared * row_cleared

        landing_height = row - move_distance
        score -= landing_height

        holes = 0
        for i in range(row - 1):
            for j in range(col):
                if matrix[i][j] == 1:
                    try:
                        for k in range(i + 1, row):
                            if matrix[k][j] == 1:
                                break
                            if matrix[k][j] == 0:
                                holes += 1
                    except:
                        pass
        # print("# of holes: ", holes)
        score -= 4 * holes

        # cumulative well (a well with depth N will have 1+2+3+...+N score)
        well_sum = 0

        depth = 0
        for i in range(row):
            if matrix[i][0] == 0 and matrix[i][1] == 1:
                depth += 1
                well_sum += depth
            if matrix[i][0] == 1:
                depth = 0

        depth = 0
        for i in range(row):
            if matrix[i][col - 1] == 0 and matrix[i][col - 2] == 1:
                depth += 1
                well_sum += depth
            if matrix[i][col - 1] == 1:
                depth = 0

        for c in range(1, col - 1):
            depth = 0
            for r in range(row):
                if matrix[r][c] == 0 and matrix[r][c - 1] == 1 and matrix[r][c + 1] == 1:
                    depth += 1
                    well_sum += depth
                else:
                    depth = 0
        score -= well_sum
        # if well_sum > 10:
        #     print("Well sum: ", well_sum, "\nMatrix: ")
        #     for r in matrix:
        #         print(r)
        #     print("\n")

        #########################################################
        # Row Transition #
        row_transition = 0
        for r in range(row):
            if 1 in matrix[r]:
                state = 1
                for c in range(col):
                    if matrix[r][c] == 0:
                        curr_state = 0
                        if curr_state != state:
                            state = curr_state
                            row_transition += 1
                        if c == col - 1:
                            row_transition += 1
                    elif matrix[r][c] == 1:
                        curr_state = 1
                        if curr_state != state:
                            state = curr_state
                            row_transition += 1
                # print(r, "cumulative transition: ", row_transition)
        score -= row_transition
        # print("row_transition is ", row_transition, "\nMatrix: ")
        # for row_idx, r in enumerate(matrix):
        #     print(f'{row_idx:>5}', ": ", r)
        # print("\n")
        #####################################################

        #####################################################
        # Column Transition #
        col_transition = 0
        for c in range(col):
            state = 0
            for r in range(row):
                if matrix[r][c] == 1:
                    curr_state = 1
                    if curr_state != state:
                        state = curr_state
                        col_transition += 1
                elif matrix[r][c] == 0:
                    curr_state = 0
                    if curr_state != state:
                        state = curr_state
                        col_transition += 1
                    if r == row - 1:
                        col_transition += 1
        score -= col_transition
        #####################################################
        # print("cumulative col_transition is ", col_transition, "\nMatrix: ")
        # for row_idx, r in enumerate(matrix):
        #     print(f'{row_idx:>5}', ": ", r)
        # print("\n")

        score -= col_transition

        return score

    def move_down(self):
        # move left or right to desirable position calculated by score function
        if self.steps < 0:  # moving left
            if self.curr_steps > self.steps:
                for item in self.shape:
                    item.move_ip(-block_size, 0)
                self.curr_steps -= 1
        elif self.steps > 0:  # moving right
            if self.curr_steps < self.steps:
                for item in self.shape:
                    item.move_ip(block_size, 0)
                self.curr_steps += 1

        # move down
        for item in self.shape:
            item.move_ip(0, block_size)

    # controlled by key_press
    def rotate(self):
        # prohibit rotation if finished positions already occupied !!!
        if self.type == "I":
            if self.state == 1:
                self.block1.move_ip(block_size, -block_size * 2)
                self.block2.move_ip(0, -block_size)
                self.block3.move_ip(-block_size, 0)
                self.block4.move_ip(-block_size * 2, block_size)
                self.state = 2
            else:
                self.block1.move_ip(-block_size, block_size * 2)
                self.block2.move_ip(0, block_size)
                self.block3.move_ip(block_size, 0)
                self.block4.move_ip(block_size * 2, -block_size)
                self.state = 1
        elif self.type == "square":
            pass

        # elif self.type == "T":
        #     if self.state == 1:

    def collide_down(self, d):
        for item in self.shape:
            if item.bottomleft in d:
                return True
        return False

    def move_left(self, d):
        clear_to_move = True
        for item in self.shape:
            if (item.topleft[0] - block_size, item.topleft[1]) in d or item.left == 0:
                clear_to_move = False
        if clear_to_move:
            for item in self.shape:
                item.move_ip(-block_size, 0)

    def move_right(self, d):
        clear_to_move = True
        for item in self.shape:
            if (item.topleft[0] + block_size, item.topleft[1]) in d or item.right == block_size * col:
                clear_to_move = False
        if clear_to_move:
            for item in self.shape:
                item.move_ip(block_size, 0)

    def key_press(self, d):
        key = pygame.key.get_pressed()

        if key[pygame.K_LEFT]:
            self.move_left(d)

        if key[pygame.K_RIGHT]:
            self.move_right(d)

        if key[pygame.K_UP]:
            self.rotate()

    def draw(self, surface):
        for item in self.shape:
            pygame.draw.rect(surface, self.color, item)

    def get_bottom(self):
        return self.block4.bottom
예제 #15
0
class Widget(Sprite):
    """Use Widget class for better movement tracking

       Widget class inherits from Sprite class.
       Test cases for class Widget

       >>> from widget import *
       >>> import pygame
       >>> s = pygame.surface.Surface((30,30))
       >>> w = Widget(s, (0,0,30,30), (0,0))
       >>> w.rect
       <rect(0, 0, 30, 30)>
       >>> w.update()
       >>> w.rect
       <rect(0, 0, 30, 30)>
       >>> w.getMovement()
       [0, 0]

       >>> w.setX(1)
       >>> w.getX()
       1

       >>> w.setY(4)
       >>> w.getY()
       4

       >>> w.setMovement((3,5))
       >>> w.getMovement()
       (3, 5)

       >>> w.getName()
       (0, 0)

       >>> w.setPosition((5,7))
       >>> w.getPosition()
       (5, 7)
    """
    def __init__(self, image, rect, name=''):
        """Instantiate a widget with a given surface,
           rectangle, and (x,y) movement pair.
        """
        Sprite.__init__(self)
        self.movement = [0, 0]
        self.rect = Rect(rect)
        self.lastRect = self.rect
        self.image = image
        self.name = name
        self.frames = []
        self.frameIndex = 0
        self.frameRate = 1
        self.timeDelay = WIDGETFRAMES
        self.lastUpdate = 0
        self.world = None
        self.undone = False
        self.id = self.rect.top + self.rect.left +\
                  self.rect.width + self.rect.height

    def attachToWorld(self, world):
        self.world = world
        self.id = self.world.curWidgetID
        self.world.curWidgetID += 1

    def startAnimation(self, frames, startIndex, frameRate):
        self.frames = frames
        self.frameIndex = startIndex
        self.frameRate = frameRate
        self.image = self.frames[startIndex]
        self.lastUpdate = self.timeDelay

    def __str__(self):
        return str(self.rect.left) + str(self.rect.top) + str(self.id)

    def setMovement(self, vector):
        """Set movement with a pair"""
        if (self.movement != [0, 0] and vector == [0, 0]):
            self.world.dirtyGroup.add(self)
        self.movement = vector

    def getMovement(self):
        """Return movement as a pair"""
        return self.movement

    def setStop(self):
        """Set movement to 0"""
        self.setMovement([0, 0])

    def setY(self, y):
        """Set y-component of movement"""
        self.movement[1] = y

    def setX(self, x):
        """Set x-component of movement"""
        self.movement[0] = x

    def getX(self):
        """Get x-component of movement"""
        return self.movement[0]

    def getY(self):
        """Set y-component of movement"""
        return self.movement[1]

    def setPosition(self, pair):
        """Set x and y coords of Widget"""
        self.rect.topleft = pair

    def getPosition(self):
        """Get x and y coords of Widget"""
        return self.rect.topleft

    def update(self):
        """Move sprite according to its movement vector"""
        # Widget needs to be animated
        if (len(self.frames) > 0):
            if self.lastUpdate <= 0:
                self.frameIndex = (self.frameIndex + 1) % (len(self.frames))
                self.image = self.frames[self.frameIndex]
                self.lastUpdate = self.timeDelay
                self.world.dirtyGroup.add(self)
            else:
                self.lastUpdate -= 1

        elif (self.getMovement != [0, 0]):
            self.lastRect = Rect(self.rect)
            self.rect.move_ip(self.movement)
            self.world.dirtyGroup.add(self)

    def undoUpdate(self):
        """Widget returns to state prior to last update()"""
        self.rect = self.lastRect

    def getShadow(self):
        shadow = Sprite()
        shadow.rect = self.lastRect.move(0, 0)
        return shadow

    def getName(self):
        """Get name of Widget"""
        return self.name
예제 #16
0
파일: widget.py 프로젝트: bry/pybomber2
class Widget(Sprite):
    """Use Widget class for better movement tracking

       Widget class inherits from Sprite class.
       Test cases for class Widget

       >>> from widget import *
       >>> import pygame
       >>> s = pygame.surface.Surface((30,30))
       >>> w = Widget(s, (0,0,30,30), (0,0))
       >>> w.rect
       <rect(0, 0, 30, 30)>
       >>> w.update()
       >>> w.rect
       <rect(0, 0, 30, 30)>
       >>> w.getMovement()
       [0, 0]

       >>> w.setX(1)
       >>> w.getX()
       1

       >>> w.setY(4)
       >>> w.getY()
       4

       >>> w.setMovement((3,5))
       >>> w.getMovement()
       (3, 5)

       >>> w.getName()
       (0, 0)

       >>> w.setPosition((5,7))
       >>> w.getPosition()
       (5, 7)
    """

    def __init__(self, image, rect, name=''):
        """Instantiate a widget with a given surface,
           rectangle, and (x,y) movement pair.
        """
        Sprite.__init__(self)
        self.movement = [0, 0]
        self.rect = Rect(rect)
        self.lastRect = self.rect
        self.image = image
        self.name = name
        self.frames = []
        self.frameIndex = 0
        self.frameRate = 1
        self.timeDelay = WIDGETFRAMES
        self.lastUpdate = 0
        self.world = None
        self.undone = False
        self.id = self.rect.top + self.rect.left +\
                  self.rect.width + self.rect.height

    def attachToWorld(self, world):
        self.world = world
        self.id = self.world.curWidgetID
        self.world.curWidgetID += 1

    def startAnimation(self, frames, startIndex, frameRate):
        self.frames = frames
        self.frameIndex = startIndex
        self.frameRate = frameRate
        self.image = self.frames[startIndex]
        self.lastUpdate = self.timeDelay

    def __str__(self):
        return str(self.rect.left) + str(self.rect.top) + str(self.id)

    def setMovement(self, vector):
        """Set movement with a pair"""
        if(self.movement != [0,0]
           and vector == [0,0]):
            self.world.dirtyGroup.add(self)
        self.movement = vector

    def getMovement(self):
        """Return movement as a pair"""
        return self.movement

    def setStop(self):
        """Set movement to 0"""
        self.setMovement([0,0])

    def setY(self, y):
        """Set y-component of movement"""
        self.movement[1] = y

    def setX(self, x):
        """Set x-component of movement"""
        self.movement[0] = x

    def getX(self):
        """Get x-component of movement"""
        return self.movement[0]
    def getY(self):
        """Set y-component of movement"""
        return self.movement[1]

    def setPosition(self, pair):
        """Set x and y coords of Widget"""
        self.rect.topleft = pair

    def getPosition(self):
        """Get x and y coords of Widget"""
        return self.rect.topleft

    def update(self):
        """Move sprite according to its movement vector"""
        # Widget needs to be animated
        if (len(self.frames) > 0):
            if self.lastUpdate <= 0:
                self.frameIndex = (self.frameIndex+1)%(len(self.frames))
                self.image = self.frames[self.frameIndex]
                self.lastUpdate = self.timeDelay
                self.world.dirtyGroup.add(self)
            else:
                self.lastUpdate -= 1

        elif(self.getMovement != [0,0]):
            self.lastRect = Rect(self.rect)
            self.rect.move_ip(self.movement)
            self.world.dirtyGroup.add(self)

    def undoUpdate(self):
        """Widget returns to state prior to last update()"""
        self.rect = self.lastRect

    def getShadow(self):
        shadow = Sprite()
        shadow.rect = self.lastRect.move(0,0)
        return shadow

    def getName(self):
        """Get name of Widget"""
        return self.name