Example #1
0
class Background(Sprite, ABC):
    def __init__(self,
                 filename: str,
                 top: float,
                 speed: float,
                 x: Optional[float] = None,
                 mirror: bool = True):
        if x is None:
            x = 2

        self.x = x * Const.game_height
        self.speed = speed

        self.image = CachedImage(filename, mirror and random.getrandbits(1))

        self.height = self.image.get_height() * Const.pixel_size
        self.width = self.image.get_width() * Const.pixel_size
        self.y = top

    def update(self, context: Context, sprites: Sprites):
        self.x -= context.x_delta * self.speed

    def render(self, surface: pygame.Surface, size_factor: float):
        h = int(self.height * size_factor)
        w = int(self.width * size_factor)

        img = self.image.scale(w, h)

        l = int(self.x * size_factor)
        rect = pygame.Rect(0 if l >= 0 else abs(l), 0, w + min(0, l), h)

        surface.blit(img, (max(0, l), self.y * size_factor), rect)

    @property
    def box(self) -> GameRect:
        return GameRect(self.x, self.y, self.width, self.height)

    def can_delete(self) -> bool:
        return self.x <= -self.width
Example #2
0
class Tartan(Sprite):

    def __init__(self):
        self.__x = 0
        self.meters = Const.offset_meters
        self.image = CachedImage("res/img/noice.png")
        self.border = self.image.get_width() * Const.pixel_size
        self.random_line = [-1, 1]

        self.score = score.load_score()

    def update(self, context: Context, sprites: Sprites):
        self.__x -= context.x_delta
        self.meters = context.meters
        while self.__x < -self.border:
            self.__x += self.border

        self.random_line[0] -= context.x_delta
        if self.random_line[0] < 0 and random.random() < 0.05:
            self.random_line[0] = 3 * Const.game_height
            self.random_line[1] = random.randint(1, 2)

    def render(self, surface: pygame.Surface, size_factor: float):
        area = Const.tartan_area(surface)
        surface.fill((156, 67, 47), area)

        size = int(self.image.get_width() * Const.pixel_size * size_factor)
        img = self.image.scale(size, size)

        for i in range(0, surface.get_width() // size + 2):
            surface.blit(img, (i * size + self.__x * size_factor, area.top))

        t = int((Const.tartan_top + Const.pixel_size) * size_factor)
        h = int(Const.tartan_height * 0.38 * size_factor)
        lines = [
            t,
            t + h,
            t + 2 * h
        ]

        for y in lines:
            for x in range(0, 3 * Const.game_height):
                surface.fill((255, 200, 200),
                             pygame.Rect(
                                 int((x + self.__x) * size_factor),
                                 y,
                                 int(size_factor * 1),
                                 int(size_factor * Const.pixel_size)
                             ))

        m = 50
        next_meter_in = m - (self.meters - Const.player_position) % m
        next_meter_str = str(int(((self.meters - Const.player_position) // m + 1) * m))
        surface.fill((255, 200, 200),
                     pygame.Rect(
                         int(next_meter_in * size_factor),
                         lines[0],
                         int(size_factor * Const.pixel_size),
                         h
                     ))
        font = pygame.font.Font("res/arcade.ttf", h)
        img = font.render(next_meter_str, True, (255, 200, 200))
        surface.blit(img, (int((next_meter_in - 2 * Const.pixel_size) * size_factor) - img.get_width(),
                           int(lines[0] + h / 2 - img.get_height() * 0.45)))

        surface.fill((255, 200, 200),
                     pygame.Rect(
                         int(self.random_line[0] * size_factor),
                         lines[self.random_line[1]],
                         int(size_factor * Const.pixel_size),
                         h
                     ))

        PADDING = Const.pixel_size * 2
        for i, (name, s) in reversed(list(enumerate(self.score))):
            left = s - (self.meters - Const.player_position)
            if -Const.game_height < left < Const.game_height * 3:
                text = f"{i + 1}   {name}".rstrip()
                img = font.render(text, True, (255, 255, 255))

                pixel = int(Const.pixel_size * size_factor)
                surface.fill((133, 94, 66),
                             pygame.Rect(
                                 int(left * size_factor) - pixel,
                                 int(Const.tartan_top * size_factor - h),
                                 int(size_factor * Const.pixel_size) + 2 * pixel,
                                 h
                             ))

                l = int((left - PADDING) * size_factor - img.get_width() // 2)
                surface.fill((106, 75, 53),
                             pygame.Rect(
                                 max(0, l - pixel),
                                 int(Const.tartan_top * size_factor - h * 1.5) - pixel,
                                 img.get_width() + PADDING * 2 * size_factor + min(0, l) + 2 * pixel,
                                 img.get_height() + 2 * pixel
                             ))

                surface.fill((133, 94, 66),
                             pygame.Rect(
                                 max(0, l),
                                 int(Const.tartan_top * size_factor - h * 1.5),
                                 img.get_width() + PADDING * 2 * size_factor + min(0, l),
                                 img.get_height()
                             ))

                surface.blit(img, (
                    int(left * size_factor - img.get_width() // 2),
                    int(Const.tartan_top * size_factor - h * 1.5)
                ))

    def box(self) -> GameRect:
        return GameRect(0, 0, 1, 1)

    def type(self) -> Type:
        return Type.TARTAN
Example #3
0
class Ball(Sprite, ABC):

    def __init__(self, x=None):
        if x is None:
            self.x = 2 * Const.game_height
        else:
            self.x = x

        self.image = CachedImage(self.filename())
        self.diameter = self.image.get_width() * Const.pixel_size

        self.y = Const.game_height - self.diameter
        self.__vspeed = 0
        self.bounced = False
        self.hit_bottom = False

        self.id = uuid.uuid4()

    def update(self, context: Context, sprites: Sprites):
        self.x -= context.x_delta
        if self.bounced:
            self.move_by_gravity(context)

    def render(self, surface: pygame.Surface, size_factor: float):
        rect = self.box.to_pygame(size_factor, False)
        if rect.width <= 0 or rect.height <= 0:
            return

        img = self.image.scale(rect.width, rect.height)
        surface.blit(img, (rect.left, rect.top))

    def bounce(self, velocity: float):
        self.bounced = True
        self.__vspeed = -velocity / 2

    def move_by_gravity(self, context: Context):

        # time in s
        t = context.time_factor / Const.fps
        # gravity in m/(s**2)
        a = context.gravity
        self.y = 1 / 2 * a * (t ** 2) + \
                 self.__vspeed * t + \
                 self.y
        self.__vspeed = a * t + self.__vspeed
        if self.y + self.diameter >= Const.game_height + self.diameter * 0.3 and not self.hit_bottom:
            self.__vspeed = -self.__vspeed * self.bounciness()
            self.hit_bottom = True
        elif self.y + self.diameter < Const.game_height + self.diameter * 0.3 and self.hit_bottom:
            self.hit_bottom = False

    @property
    def box(self) -> GameRect:
        offset = max(0, (self.y + self.diameter) - Const.game_height)
        y_delta = 0
        if offset > self.diameter * 0.3:
            y_delta = offset - self.diameter * 0.3
            offset = self.diameter * 0.3

        return GameRect(self.x, self.y - y_delta, self.diameter, self.diameter - offset)

    def type(self) -> Type:
        return Type.BALL

    def can_delete(self) -> bool:
        return self.x <= -1

    @abstractmethod
    def filename(self) -> str:
        pass

    @abstractmethod
    def bounciness(self) -> float:
        """
        :return: by how much the velocity of the player is multiplied when he hits the ball
        """
        pass

    @abstractmethod
    def immediate_speed_increase(self) -> float:
        pass

    @abstractmethod
    def desired_speed_increase(self) -> float:
        pass