diff --git a/images/GoblinWorker/spritePics/19.png b/images/GoblinWorker/spritePics/19.png deleted file mode 100644 index afe0dc1..0000000 Binary files a/images/GoblinWorker/spritePics/19.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/21.png b/images/GoblinWorker/spritePics/21.png deleted file mode 100644 index 3ed9020..0000000 Binary files a/images/GoblinWorker/spritePics/21.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/22.png b/images/GoblinWorker/spritePics/22.png deleted file mode 100644 index 7814784..0000000 Binary files a/images/GoblinWorker/spritePics/22.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/23.png b/images/GoblinWorker/spritePics/23.png deleted file mode 100644 index 894e6c1..0000000 Binary files a/images/GoblinWorker/spritePics/23.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/24.png b/images/GoblinWorker/spritePics/24.png deleted file mode 100644 index 1695f4c..0000000 Binary files a/images/GoblinWorker/spritePics/24.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/25.png b/images/GoblinWorker/spritePics/25.png deleted file mode 100644 index 3ad79ea..0000000 Binary files a/images/GoblinWorker/spritePics/25.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/26.png b/images/GoblinWorker/spritePics/26.png deleted file mode 100644 index f2f192f..0000000 Binary files a/images/GoblinWorker/spritePics/26.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/27.png b/images/GoblinWorker/spritePics/27.png deleted file mode 100644 index 203fce1..0000000 Binary files a/images/GoblinWorker/spritePics/27.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/29.png b/images/GoblinWorker/spritePics/29.png deleted file mode 100644 index 16f4a97..0000000 Binary files a/images/GoblinWorker/spritePics/29.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/30.png b/images/GoblinWorker/spritePics/30.png deleted file mode 100644 index 7ed4b22..0000000 Binary files a/images/GoblinWorker/spritePics/30.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/32.png b/images/GoblinWorker/spritePics/32.png deleted file mode 100644 index f337bfc..0000000 Binary files a/images/GoblinWorker/spritePics/32.png and /dev/null differ diff --git a/images/GoblinWorker/spritePics/07.png b/images/GoblinWorker/spritePics/Jump.png similarity index 100% rename from images/GoblinWorker/spritePics/07.png rename to images/GoblinWorker/spritePics/Jump.png diff --git a/images/GoblinWorker/spritePics/36.png b/images/GoblinWorker/spritePics/death1.png similarity index 100% rename from images/GoblinWorker/spritePics/36.png rename to images/GoblinWorker/spritePics/death1.png diff --git a/images/GoblinWorker/spritePics/35.png b/images/GoblinWorker/spritePics/death2.png similarity index 100% rename from images/GoblinWorker/spritePics/35.png rename to images/GoblinWorker/spritePics/death2.png diff --git a/images/GoblinWorker/spritePics/34.png b/images/GoblinWorker/spritePics/death3.png similarity index 100% rename from images/GoblinWorker/spritePics/34.png rename to images/GoblinWorker/spritePics/death3.png diff --git a/images/GoblinWorker/spritePics/28.png b/images/GoblinWorker/spritePics/death4.png similarity index 100% rename from images/GoblinWorker/spritePics/28.png rename to images/GoblinWorker/spritePics/death4.png diff --git a/images/GoblinWorker/spritePics/33.png b/images/GoblinWorker/spritePics/hurt1.png similarity index 100% rename from images/GoblinWorker/spritePics/33.png rename to images/GoblinWorker/spritePics/hurt1.png diff --git a/images/GoblinWorker/spritePics/31.png b/images/GoblinWorker/spritePics/hurt2.png similarity index 100% rename from images/GoblinWorker/spritePics/31.png rename to images/GoblinWorker/spritePics/hurt2.png diff --git a/images/GoblinWorker/spritePics/16.png b/images/GoblinWorker/spritePics/walkleft.png similarity index 100% rename from images/GoblinWorker/spritePics/16.png rename to images/GoblinWorker/spritePics/walkleft.png diff --git a/images/GoblinWorker/spritePics/08.png b/images/GoblinWorker/spritePics/walkright.png similarity index 100% rename from images/GoblinWorker/spritePics/08.png rename to images/GoblinWorker/spritePics/walkright.png diff --git a/images/walk.png b/images/walk.png deleted file mode 100644 index a332a2b..0000000 Binary files a/images/walk.png and /dev/null differ diff --git a/main.py b/main.py index c847971..1b3bd2b 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ import pygame import sys pygame.init() +pygame.mixer.init() # ===================================================== # НАСТРОЙКИ @@ -13,7 +14,10 @@ pygame.display.set_caption("Goblin & Knight") CLOCK = pygame.time.Clock() BLACK = (0, 0, 0) -GRAVITY = 1 +GRAVITY = 0.9 +GROUND_Y = HEIGHT - 60 + +FPS = 60 # ===================================================== # ЗАГРУЗКА ФОНОВ @@ -23,16 +27,24 @@ BACKGROUND = pygame.image.load("images/back.png") BACK_MAIN = pygame.image.load("images/back_main.jpg") BACK_MAIN = pygame.transform.scale(BACK_MAIN, (WIDTH, HEIGHT)) -# ===================================================== -# ФУНКЦИЯ ВЫРЕЗКИ СПРАЙТОВ -# ===================================================== +# Попытаться загрузить музыку/звуки, если есть +BG_MUSIC = None +try: + BG_MUSIC = pygame.mixer.music + pygame.mixer.music.load('music/theme.mp3') + pygame.mixer.music.set_volume(0.5) +except Exception: + BG_MUSIC = None -def get_image(sheet, frame_x, frame_y, width, height, scale, color): - image = pygame.Surface((width, height)).convert_alpha() - image.blit(sheet, (0, 0), (frame_x * width, frame_y * height, width, height)) - image = pygame.transform.scale(image, (width * scale, height * scale)) - image.set_colorkey(color) - return image +# Шрифты и HUD +FONT = pygame.font.SysFont(None, 32) + +# Игровые счётчики +score_goblin = 0 +score_knight = 0 + +# Пауза +paused = False # ===================================================== @@ -40,34 +52,39 @@ def get_image(sheet, frame_x, frame_y, width, height, scale, color): # ===================================================== class Player: - def __init__(self, x, y, sprite_sheet, frame_size, scale, controls): + def __init__(self, x, y, sprites, scale, controls): self.start_x = x self.start_y = y - self.x = x - self.y = y + self.x = float(x) + self.y = float(y) - self.y_velocity = 0 - self.jump_power = 20 + self.y_velocity = 0.0 + self.jump_power = 18 self.jumping = False self.facing_right = True self.moving = False + self.speed = 5.5 self.controls = controls self.anim_counter = 0 self.ANIM_SPEED = 8 - w, h = frame_size + # Загрузка спрайтов из файлов + self.stand = pygame.image.load(sprites["stand"]).convert_alpha() + self.walk_left = pygame.image.load(sprites["walk_left"]).convert_alpha() + self.walk_right = pygame.image.load(sprites["walk_right"]).convert_alpha() + self.jump_img = pygame.image.load(sprites["jump"]).convert_alpha() - # Анимации - self.stand = get_image(sprite_sheet, 0, 0, w, h, scale, BLACK) - self.walk1 = get_image(sprite_sheet, 1, 0, w, h, scale, BLACK) - self.walk2 = get_image(sprite_sheet, 2, 0, w, h, scale, BLACK) - self.jump_img = get_image(sprite_sheet, 3, 0, w, h, scale, BLACK) + # Масштабирование + self.stand = pygame.transform.scale(self.stand, (int(self.stand.get_width() * scale), int(self.stand.get_height() * scale))) + self.walk_left = pygame.transform.scale(self.walk_left, (int(self.walk_left.get_width() * scale), int(self.walk_left.get_height() * scale))) + self.walk_right = pygame.transform.scale(self.walk_right, (int(self.walk_right.get_width() * scale), int(self.walk_right.get_height() * scale))) + self.jump_img = pygame.transform.scale(self.jump_img, (int(self.jump_img.get_width() * scale), int(self.jump_img.get_height() * scale))) self.surface = self.stand - self.rect = self.surface.get_rect(center=(self.x, self.y)) + self.rect = self.surface.get_rect(midbottom=(self.x, self.y)) # ------------------------- # СБРОС ПЕРСОНАЖА @@ -80,7 +97,7 @@ class Player: self.moving = False self.anim_counter = 0 self.facing_right = True - self.rect = self.surface.get_rect(center=(self.x, self.y)) + self.rect = self.surface.get_rect(midbottom=(self.x, self.y)) # ------------------------- # УПРАВЛЕНИЕ @@ -89,18 +106,18 @@ class Player: self.moving = False if keys[self.controls["right"]]: - self.x += 5 + self.x += self.speed self.facing_right = True self.moving = True if keys[self.controls["left"]]: - self.x -= 5 + self.x -= self.speed self.facing_right = False self.moving = True if keys[self.controls["jump"]] and not self.jumping: self.jumping = True - self.y_velocity = self.jump_power + self.y_velocity = -self.jump_power # Ограничение по экрану if self.x < 0: @@ -112,11 +129,11 @@ class Player: # ГРАВИТАЦИЯ # ------------------------- def apply_gravity(self): - self.y_velocity -= GRAVITY - self.y -= self.y_velocity + self.y_velocity += GRAVITY + self.y += self.y_velocity - if self.y >= HEIGHT: - self.y = HEIGHT + if self.y >= GROUND_Y: + self.y = GROUND_Y self.y_velocity = 0 self.jumping = False @@ -129,14 +146,14 @@ class Player: elif self.moving: self.anim_counter += 1 frame = (self.anim_counter // self.ANIM_SPEED) % 2 - self.surface = self.walk1 if frame == 0 else self.walk2 + self.surface = self.walk_left if frame == 0 else self.walk_right else: self.surface = self.stand if not self.facing_right: self.surface = pygame.transform.flip(self.surface, True, False) - self.rect = self.surface.get_rect(center=(self.x, self.y)) + self.rect = self.surface.get_rect(midbottom=(int(self.x), int(self.y))) # ------------------------- # ОТРИСОВКА @@ -145,17 +162,16 @@ class Player: screen.blit(self.surface, self.rect) -# ===================================================== -# ЗАГРУЗКА СПРАЙТОВ -# ===================================================== -goblin_sheet = pygame.image.load("images/GoblinWorker/GoblinWorker.png").convert_alpha() -knight_sheet = pygame.image.load("images/sprites/knight.png").convert_alpha() goblin = Player( - 200, 800, - goblin_sheet, - (48, 48), + 200, GROUND_Y, + { + "stand": "images/GoblinWorker/spritePics/stand_gob.png", + "walk_left": "images/GoblinWorker/spritePics/walkleft.png", + "walk_right": "images/GoblinWorker/spritePics/walkright.png", + "jump": "images/GoblinWorker/spritePics/Jump.png" + }, 3, { "left": pygame.K_a, @@ -165,9 +181,13 @@ goblin = Player( ) knight = Player( - 500, 800, - knight_sheet, - (32, 32), + 500, GROUND_Y, + { + "stand": "images/sprites/knight.png", + "walk_left": "images/sprites/knight.png", + "walk_right": "images/sprites/knight.png", + "jump": "images/sprites/knight.png" + }, 3, { "left": pygame.K_KP4, @@ -199,6 +219,7 @@ def restart_level(): # ===================================================== level = 0 +level_start_time = None while True: @@ -206,6 +227,12 @@ while True: if event.type == pygame.QUIT: pygame.quit() sys.exit() + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE and level == 1: + paused = not paused + if event.key == pygame.K_r: + restart_level() + level = 0 keys = pygame.key.get_pressed() mouse_pos = pygame.mouse.get_pos() @@ -217,38 +244,72 @@ while True: SCREEN.blit(BACK_MAIN, (0, 0)) SCREEN.blit(button_play, button_rect) + title_surf = FONT.render('Goblin & Knight', True, (255,255,255)) + SCREEN.blit(title_surf, (WIDTH//2 - title_surf.get_width()//2, 120)) + if button_rect.collidepoint(mouse_pos) and pygame.mouse.get_pressed()[0]: restart_level() level = 1 + level_start_time = pygame.time.get_ticks() + if BG_MUSIC: + try: + pygame.mixer.music.play(-1) + except Exception: + pass # ================= GAME ================= elif level == 1: - SCREEN.blit(BACKGROUND, (0, 0)) SCREEN.blit(door_image, door_rect) - # --- Goblin --- - goblin.handle_input(keys) - goblin.apply_gravity() - goblin.update_animation() - goblin.draw(SCREEN) + if not paused: + # --- Goblin --- + goblin.handle_input(keys) + goblin.apply_gravity() + goblin.update_animation() - # --- Knight --- - knight.handle_input(keys) - knight.apply_gravity() - knight.update_animation() + # --- Knight --- + knight.handle_input(keys) + knight.apply_gravity() + knight.update_animation() + + # Draw players (even when paused) + goblin.draw(SCREEN) knight.draw(SCREEN) + elapsed = 0 + if level_start_time: + elapsed = (pygame.time.get_ticks() - level_start_time) // 1000 + hud_g = FONT.render(f'Goblin: {score_goblin}', True, (255,255,255)) + hud_k = FONT.render(f'Knight: {score_knight}', True, (255,255,255)) + hud_t = FONT.render(f'Time: {elapsed}s', True, (255,255,255)) + SCREEN.blit(hud_g, (20, 20)) + SCREEN.blit(hud_k, (WIDTH - hud_k.get_width() - 20, 20)) + SCREEN.blit(hud_t, (WIDTH//2 - hud_t.get_width()//2, 20)) + + if paused: + p = FONT.render('PAUSED - press ESC to resume', True, (255,255,0)) + SCREEN.blit(p, (WIDTH//2 - p.get_width()//2, HEIGHT//2 - 20)) # Победа if goblin.rect.colliderect(door_rect) and keys[pygame.K_e]: - print("Goblin wins!") + score_goblin += 1 restart_level() level = 0 + if BG_MUSIC: + try: + pygame.mixer.music.stop() + except Exception: + pass if knight.rect.colliderect(door_rect) and keys[pygame.K_KP5]: - print("Knight wins!") + score_knight += 1 restart_level() level = 0 + if BG_MUSIC: + try: + pygame.mixer.music.stop() + except Exception: + pass pygame.display.update() - CLOCK.tick(60) \ No newline at end of file + CLOCK.tick(FPS) \ No newline at end of file