def __init__(self, game, vel: pg.Vector2, pos: pg.Vector2, health: int = 15, points: int = 150): Combat.__init__(self, health, points=points) pg.sprite.Sprite.__init__(self) self.game = game self.vel = vel self.pos = pos self.attack = 3 self.timer = 0 self.current_frame = 0 self.frames = [ pg.transform.scale( Sheet(Mine.path).get_image(0, 0, 250, 250, alpha=True), (100, 100)), pg.transform.scale( Sheet(Mine.path).get_image(250, 0, 250, 250, alpha=True), (100, 100)) ] self.image = self.frames[0] self.rect = self.image.get_rect() self.add(self.game.all_sprites, self.game.mines) self.image.set_colorkey(Color.black) self.mask = pg.mask.from_surface(self.image)
def __init__(self, screen: pg.Surface, paused: bool = False): """ Constructor for the main menu page. """ self.screen = screen self.paused = paused # SCREEN: 1280x720px = WxH # devided by 5 parts horizontally - W/5 = 256px (slice) # devided by 8 parts vertically - H/8 = 90px (segment) self.slice = WIDTH // 5 # 256px self.segment = HEIGHT // 8 # 90px self.air = self.space = 10 # px self.shift = 20 # px self.sheet = Sheet(str(PurePath(PATH_BUTTONS).joinpath(BUTTONSHEET))) if self.paused: self.background = load(str(PurePath(PATH_BACKGROUNDS).joinpath(BACKGROUND_3))).convert_alpha() else: self.background = load(str(PurePath(PATH_BACKGROUNDS).joinpath(BACKGROUND))).convert_alpha() self.buttons_hover_states = {'play': False, 'options': False, 'about': False, 'exit': False, 'gitlab': False} self.buttons_sprites = { 'play': self.sheet.get_image(0, 0, 384, 70, True), 'options': self.sheet.get_image(0, 70, 320, 70, True), 'about': self.sheet.get_image(0, 140, 320, 70, True), 'exit': self.sheet.get_image(0, 210, 320, 70, True), 'gitlab': self.sheet.get_image(320, 70, 100, 100, True), 'gitlab_h': self.sheet.get_image(320, 170, 100, 100, True)} # LOGO: 768x360px # horizontal - logo takes 3 parts out of 5 - W/5 * 3 = 768px # vertical - logo takes half of H - H/2 = 360px self.logo_rect = pg.Rect(self.slice, 0, self.slice * 3, HEIGHT / 2) self.logo_image = load(str(PurePath(PATH_IMAGES).joinpath(LOGO))).convert_alpha() # PLAY BUTTON (larger) 384x70px # horizontal - one part and half of 5 = W/5 * 1.5 = 384px # vertical - 7 parts of 9 (of the segment) = S/9 * 7 = 70px # (10px for the air on top and the bottom) self.play_button_rect = \ pg.Rect(self.space, self.segment * 4 + self.air, self.slice * 1.5, self.segment - (self.air * 2)) # other buttons 320*70px # horizontal - one part and quarter of 5 = W/5 * 1.25 = 320px # vertical - 7 parts of 9 (of the segment) = S/9 * 7 = 70px # (10px for the air on top and the bottom) self.other_button_rect = \ pg.Rect(self.space, self.segment * 5, self.slice * 1.25, self.segment - (self.air * 2)) self.gitlab_button_rect = pg.Rect(WIDTH - 100 - 20, HEIGHT - 100 - 20, 200, 200) self.buttons_dict = {'options': 5, 'about': 6, 'exit': 7} self.sound = HOVER_SOUND self.sound.set_volume(get_volume()) self.cursor = load(str(PurePath(PATH_CURSORS).joinpath(CURSOR))).convert_alpha() self.cursor2 = load(str(PurePath(PATH_CURSORS).joinpath(CURSOR_HOVER))).convert_alpha() self.once = True
class Intro: def __init__(self, screen: pg.Surface): pg.mixer.init() self.screen = screen self.playing = True self.slides_sheet = Sheet(str(PurePath(PATH_IMAGES).joinpath('slidesheet.png'))) self.slides = [self.slides_sheet.get_image(0, HEIGHT * i, WIDTH, HEIGHT) for i in range(0, 3)] self.voice_clips = [pg.mixer.Sound(str(PurePath(PATH_VOICES).joinpath(i))) for i in os.listdir(str(PurePath(PATH_VOICES)))] volume = get_volume() self.voice_clips[0].set_volume(volume) self.voice_clips[1].set_volume(volume) self.voice_clips[2].set_volume(volume) self.durations = [i.get_length() for i in self.voice_clips] self.durations[0] += 1.5 self.start_time = pg.time.get_ticks() self.index = 0 self.once = True def play(self): current_time = (pg.time.get_ticks() - self.start_time) / 1000 if current_time > self.durations[self.index]: self.index += 1 self.start_time = pg.time.get_ticks() self.once = True if self.index == 3: self.playing = False self._played() return if self.once: self.voice_clips[self.index].play() self.once = False self.screen.blit(self.slides[self.index], (0, 0)) pg.display.flip() def _played(self): import json file = str(PurePath(PATH_PROJECT).joinpath('data.json')) with open(file, 'r') as f: data = json.load(f) data['intro_played'] = True with open(file, 'w') as f: json.dump(data, f)
def __init__(self, screen: pg.Surface): pg.mixer.init() self.screen = screen self.playing = True self.slides_sheet = Sheet(str(PurePath(PATH_IMAGES).joinpath('slidesheet.png'))) self.slides = [self.slides_sheet.get_image(0, HEIGHT * i, WIDTH, HEIGHT) for i in range(0, 3)] self.voice_clips = [pg.mixer.Sound(str(PurePath(PATH_VOICES).joinpath(i))) for i in os.listdir(str(PurePath(PATH_VOICES)))] volume = get_volume() self.voice_clips[0].set_volume(volume) self.voice_clips[1].set_volume(volume) self.voice_clips[2].set_volume(volume) self.durations = [i.get_length() for i in self.voice_clips] self.durations[0] += 1.5 self.start_time = pg.time.get_ticks() self.index = 0 self.once = True
def __init__(self, game, color: str = None): super().__init__() self.game = game self.color = color self.add(self.game.all_sprites, self.game.powerups) self.color_location = { 'red': (0, 0, 130, 130), 'pink': (129, 0, 130, 130), 'purple': (255, 0, 130, 130), 'blue': (385, 0, 130, 130), 'yellow': (0, 130, 130, 130), 'white': (129, 130, 130, 130), 'green': (255, 130, 130, 130), 'w_green': (385, 130, 130, 130) } if self.color is None: self.type = random.choices([ 'red', 'pink', 'purple', 'blue', 'yellow', 'white', 'green', 'w_green' ], weights=[15, 5, 3, 7, 3, 3, 10, 10], k=1)[0] else: self.type = self.color self.image = Sheet(str( PurePath(PATH_IMAGES).joinpath(POWERUPS))).get_image( *self.color_location[self.type]) self.image.set_colorkey(Color.black) self.image = pg.transform.scale(self.image, (35, 35)) self.rect = self.image.get_rect() self.mask = pg.mask.from_surface(self.image) self.rect.center = (random.randint(200, 700), random.randint(200, 700)) logger.debug(f'Spawned a {self.type} powerup at {self.rect.center}')
class Item(pg.sprite.Sprite): """Represents Items such as drops red: + soft hp pink: + full hp purple: temporary double shot x seconds blue: + max shield yellow: temporary immunity white: temporary extra fire rate green: + armor w_green: permanent extra damage """ def __init__(self, game, color: str = None): super().__init__() self.game = game self.color = color self.add(self.game.all_sprites, self.game.powerups) self.color_location = { 'red': (0, 0, 130, 130), 'pink': (129, 0, 130, 130), 'purple': (255, 0, 130, 130), 'blue': (385, 0, 130, 130), 'yellow': (0, 130, 130, 130), 'white': (129, 130, 130, 130), 'green': (255, 130, 130, 130), 'w_green': (385, 130, 130, 130) } if self.color is None: self.type = random.choices([ 'red', 'pink', 'purple', 'blue', 'yellow', 'white', 'green', 'w_green' ], weights=[15, 5, 3, 7, 3, 3, 10, 10], k=1)[0] else: self.type = self.color self.image = Sheet(str( PurePath(PATH_IMAGES).joinpath(POWERUPS))).get_image( *self.color_location[self.type]) self.image.set_colorkey(Color.black) self.image = pg.transform.scale(self.image, (35, 35)) self.rect = self.image.get_rect() self.mask = pg.mask.from_surface(self.image) self.rect.center = (random.randint(200, 700), random.randint(200, 700)) logger.debug(f'Spawned a {self.type} powerup at {self.rect.center}') def apply_powerup(self, character: pg.sprite.Sprite): """ Calls Character functions that handle the powerup effects :param character: pg.sprite.Sprite (Character) """ Timer(self.game, 5, 100, 100, DEFAULT_FONT_NAME, 25, True, _type=self.type) if self.type in ['purple', 'yellow', 'white']: Timer(self.game, POWERUP_EFFECT[self.type], 15, 20, DEFAULT_FONT_NAME, 25, _type=self.type) if self.type == 'red': character.heal(POWERUP_EFFECT[self.type]) character.image_code = 2 if self.type == 'pink': character.heal(POWERUP_EFFECT[self.type]) character.image_code = 3 if self.type == 'purple': character.double_shot(POWERUP_EFFECT[self.type]) character.image_code = 4 if self.type == 'blue': character.heal_shield() if self.type == 'yellow': character.immune(POWERUP_EFFECT[self.type]) character.image_code = 5 if self.type == 'white': character.fast_fire(POWERUP_EFFECT[self.type]) character.image_code = 6 if self.type == 'green': if character.armor >= 4: return character.armor += POWERUP_EFFECT[self.type] character.image_code = 7 if self.type == 'w_green': character.attack += POWERUP_EFFECT[self.type] character.image_code = 8
def __init__(self, game, health: int, defence: int, shield: int = 50, pos: pg.Vector2 = None, acc: pg.Vector2 = None, vel: pg.Vector2 = None, friction: Union[int, float] = 1): Physics.__init__(self, friction) Combat.__init__(self, health, defence, shield=shield) super().__init__(health, defence) self.game = game self.add(self.game.all_sprites) self.image_code = 1 self.images = { 1: pg.transform.scale( Sheet(Character.path).get_image(200, 460, 310, 300, alpha=True), (60, 60)), # red 2: pg.transform.scale( Sheet(Character.path).get_image(200, 760, 310, 300, alpha=True), (60, 60)), # blue 3: pg.transform.scale( Sheet(Character.path).get_image(200, 1060, 310, 300, alpha=True), (60, 60)), # green 4: pg.transform.scale( Sheet(Character.path).get_image(600, 760, 310, 300, alpha=True), (60, 60)), # yellow 5: pg.transform.scale( Sheet(Character.path).get_image(600, 1060, 310, 300, alpha=True), (60, 60)), # orange 6: pg.transform.scale( Sheet(Character.path).get_image(900, 760, 310, 300, alpha=True), (60, 60)), # purple 7: pg.transform.scale( Sheet(Character.path).get_image(900, 1060, 310, 300, alpha=True), (60, 60)), # pink 8: pg.transform.scale( Sheet(Character.path).get_image(1250, 1060, 310, 300, alpha=True), (60, 60)) } # black self.image = self.images[1] self.image.set_colorkey(Color.black) self.player_acc = PLAYER_ACC self.fire_rate = FIRE_RATE self.health = health self.shield = shield self.defense = defence self.projectiles = deque() self.type = 1 self.fire_rate -= 20 self.evil = False self.check_for_double_shot = False self.check_for_immunity = False self.check_for_rapid_fire = False self.time_update = 0 if self.rapid_fire: self.fire_rate -= 100 self.rect = self.image.get_rect() if pos is None: self.pos = pg.Vector2(0, 0) else: self.pos = pos if acc is None: self.acc = pg.Vector2(0, 0) else: self.acc = acc if vel is None: self.vel = pg.Vector2(0, 0) else: self.vel = vel self.friction = friction self.image.set_colorkey(Color.green) self.pos = pg.Vector2(500, 500) self.healthbar = StaticHealthbar(self.game, self, 70, 40) self.mask = pg.mask.from_surface(self.image)
class Home: """ Represents the main menu page. The main menu page contains buttons which lead to playing the game, about page, options page and exiting. """ def __init__(self, screen: pg.Surface, paused: bool = False): """ Constructor for the main menu page. """ self.screen = screen self.paused = paused # SCREEN: 1280x720px = WxH # devided by 5 parts horizontally - W/5 = 256px (slice) # devided by 8 parts vertically - H/8 = 90px (segment) self.slice = WIDTH // 5 # 256px self.segment = HEIGHT // 8 # 90px self.air = self.space = 10 # px self.shift = 20 # px self.sheet = Sheet(str(PurePath(PATH_BUTTONS).joinpath(BUTTONSHEET))) if self.paused: self.background = load(str(PurePath(PATH_BACKGROUNDS).joinpath(BACKGROUND_3))).convert_alpha() else: self.background = load(str(PurePath(PATH_BACKGROUNDS).joinpath(BACKGROUND))).convert_alpha() self.buttons_hover_states = {'play': False, 'options': False, 'about': False, 'exit': False, 'gitlab': False} self.buttons_sprites = { 'play': self.sheet.get_image(0, 0, 384, 70, True), 'options': self.sheet.get_image(0, 70, 320, 70, True), 'about': self.sheet.get_image(0, 140, 320, 70, True), 'exit': self.sheet.get_image(0, 210, 320, 70, True), 'gitlab': self.sheet.get_image(320, 70, 100, 100, True), 'gitlab_h': self.sheet.get_image(320, 170, 100, 100, True)} # LOGO: 768x360px # horizontal - logo takes 3 parts out of 5 - W/5 * 3 = 768px # vertical - logo takes half of H - H/2 = 360px self.logo_rect = pg.Rect(self.slice, 0, self.slice * 3, HEIGHT / 2) self.logo_image = load(str(PurePath(PATH_IMAGES).joinpath(LOGO))).convert_alpha() # PLAY BUTTON (larger) 384x70px # horizontal - one part and half of 5 = W/5 * 1.5 = 384px # vertical - 7 parts of 9 (of the segment) = S/9 * 7 = 70px # (10px for the air on top and the bottom) self.play_button_rect = \ pg.Rect(self.space, self.segment * 4 + self.air, self.slice * 1.5, self.segment - (self.air * 2)) # other buttons 320*70px # horizontal - one part and quarter of 5 = W/5 * 1.25 = 320px # vertical - 7 parts of 9 (of the segment) = S/9 * 7 = 70px # (10px for the air on top and the bottom) self.other_button_rect = \ pg.Rect(self.space, self.segment * 5, self.slice * 1.25, self.segment - (self.air * 2)) self.gitlab_button_rect = pg.Rect(WIDTH - 100 - 20, HEIGHT - 100 - 20, 200, 200) self.buttons_dict = {'options': 5, 'about': 6, 'exit': 7} self.sound = HOVER_SOUND self.sound.set_volume(get_volume()) self.cursor = load(str(PurePath(PATH_CURSORS).joinpath(CURSOR))).convert_alpha() self.cursor2 = load(str(PurePath(PATH_CURSORS).joinpath(CURSOR_HOVER))).convert_alpha() self.once = True def draw(self)-> None: """ Unifying drawing method - draws every element of the main menu. """ x, y = pg.mouse.get_pos() self._draw_background() self._draw_play_button(x, y) self._draw_gitlab_button(x, y) self._draw_other_buttons(x, y) self._play_sound() self._draw_cursor(x, y) pg.display.update() def _draw_background(self)->None: """ Bliting the background image and the game logo on the screen. """ self.screen.blit(self.background, (0, 0)) self.screen.blit(self.logo_image, self.logo_rect) def _draw_cursor(self, x: int, y: int)->None: """ Bliting the cursor on the screen. Classical cursor and finger cursor (if any hoverable element is hovered). """ if any(self.buttons_hover_states.values()): self.screen.blit(self.cursor2, (x, y)) else: self.screen.blit(self.cursor, (x, y)) def _draw_play_button(self, x: int, y: int)-> None: """ Bliting the play button on the screen. Shifting to the right if it is hovered. """ self.play_button_rect.top = self.segment * 4 self.play_button_rect.left = self.space hovered = self._hovered(x, y, self.play_button_rect) if hovered: self.buttons_hover_states['play'] = True self.play_button_rect.left = self.shift self.screen.blit(self.buttons_sprites['play'], self.play_button_rect) else: self.buttons_hover_states['play'] = False self.play_button_rect.left = self.space self.screen.blit(self.buttons_sprites['play'], self.play_button_rect) def _draw_other_buttons(self, x, y): """ Iterating through other buttons and bliting them on the screen. """ for key in self.buttons_dict.keys(): self._draw_other_button(x, y, key) def _draw_other_button(self, x: int, y: int, button: str)-> None: """ Bliting given button on the screen. Shifting to the right if it is hovered. """ self.other_button_rect.top = self.segment * self.buttons_dict[button] hovered = self._hovered(x, y, self.other_button_rect) if hovered: self.buttons_hover_states[button] = True self.other_button_rect.left = self.shift self.screen.blit(self.buttons_sprites[button], self.other_button_rect) else: self.buttons_hover_states[button] = False self.other_button_rect.left = self.space self.screen.blit(self.buttons_sprites[button], self.other_button_rect) def _draw_gitlab_button(self, x: int, y: int)-> None: """ Bliting the GitLab button (link). Bliting hovered version of the button if it is hovered. """ hovered = self._hovered(x, y, self.gitlab_button_rect) if hovered: self.buttons_hover_states['gitlab'] = True self.screen.blit(self.buttons_sprites['gitlab_h'], self.gitlab_button_rect) else: self.buttons_hover_states['gitlab'] = False self.screen.blit(self.buttons_sprites['gitlab'], self.gitlab_button_rect) def _play_sound(self)-> None: """ Playing the hover sound if any hoverable element is hovered. """ if not any(self.buttons_hover_states.values()): self.once = True elif self.once: self.sound.play() self.once = False def update_volume(self)->None: """ Updating the power of the volume if needed. """ self.sound.set_volume(get_volume()) @staticmethod def _hovered(x: int, y: int, button: pg.Rect)-> bool: """ Wrapper for collidepoint (checks if point is in pygame.Rect object). """ return button.collidepoint(x, y) @staticmethod def open_gitlab()-> None: """ Opens the gitlab link in the browser. """ wb.open(GIT_LAB_LINK)