From a724d6a46cbb66bf78225e3c18a41d8266cdd29b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Arsenijs=20=C4=BBu?= <alu.e@rkg.lv>
Date: Sat, 2 Mar 2024 17:29:05 +0000
Subject: [PATCH] Update Gaame with menu

Explosion sound and Explosion Animation with BotTank and with wall
---
 Gaame with menu | 219 +++++++++++++++++++++++-------------------------
 1 file changed, 105 insertions(+), 114 deletions(-)

diff --git a/Gaame with menu b/Gaame with menu
index 054f585..e3947c7 100644
--- a/Gaame with menu	
+++ b/Gaame with menu	
@@ -30,8 +30,8 @@ pygame.mixer.music.load('music.mp3')
 pygame.mixer.music.play(-1)  # Параметр -1 означает зацикливание музыки
 shot_sound = pygame.mixer.Sound('shot.wav')
 meme_sound = pygame.mixer.Sound("meme_sound.wav")
-
-
+explosion_sound = pygame.mixer.Sound("explosion_sound.wav")
+stoneexplosion_sound = pygame.mixer.Sound("stoneexplosion_sound.wav")
 
 # Загрузка изображений
 background_image = pygame.transform.scale(pygame.image.load("travka_pol.jpeg"), (960, 540))
@@ -40,10 +40,73 @@ stenki = pygame.transform.scale(pygame.image.load("stena.jpeg").convert(), (200,
 tank_image = pygame.transform.scale(pygame.image.load("ntank-removebg-preview.png"), (PLAYER_WIDTH, PLAYER_HEIGHT))
 loh_image = pygame.transform.scale(pygame.image.load("loh.png"), (LOH_WIDTH, LOH_HEIGHT))
 bullet_image = pygame.transform.scale(pygame.image.load("bullet.png"), (BULLET_SIZE, BULLET_SIZE))
+explosion_images = [pygame.image.load(f"explosion_{i}.png") for i in range(1, 48)]
+stoneexplosion_images = [pygame.image.load(f"stoneexplosion_{i}.png") for i in range(1, 6)]
 
 menu_background = pygame.transform.scale(pygame.image.load("menu_background.jpg"), (SCREEN_WIDTH, SCREEN_HEIGHT))
 
 
+class Explosion(pygame.sprite.Sprite):
+    def __init__(self, x, y):
+        super().__init__()
+        self.image = explosion_images[0]
+        self.rect = self.image.get_rect(center=(x, y))
+        self.frame = 0
+        self.last_update = pygame.time.get_ticks()
+        self.frame_rate = 50
+
+    def update(self):
+        now = pygame.time.get_ticks()
+        if now - self.last_update > self.frame_rate:
+            self.last_update = now
+            self.frame += 1
+            if self.frame == 6:
+                self.kill()
+            else:
+                center = self.rect.center
+                self.image = explosion_images[self.frame]
+                self.rect = self.image.get_rect()
+                self.rect.center = center
+
+# Добавление класса для анимации удара о каменную стену
+class StoneExplosion(pygame.sprite.Sprite):
+    def __init__(self, x, y):
+        super().__init__()
+        self.images = stoneexplosion_images
+        self.image = self.images[0]
+        self.rect = self.image.get_rect(center=(x, y))
+        self.frame = 0
+        self.last_update = pygame.time.get_ticks()
+        self.frame_rate = 50
+        stoneexplosion_sound.play()  # Воспроизведение звука удара о стену
+
+    def update(self):
+        now = pygame.time.get_ticks()
+        if now - self.last_update > self.frame_rate:
+            self.last_update = now
+            self.frame += 1
+            if self.frame == len(self.images):
+                self.kill()
+            else:
+                center = self.rect.center
+                self.image = self.images[self.frame]
+                self.rect = self.image.get_rect()
+                self.rect.center = center
+
+
+    def update(self):
+        now = pygame.time.get_ticks()
+        if now - self.last_update > self.frame_rate:
+            self.last_update = now
+            self.frame += 1
+            if self.frame == len(self.images):
+                self.kill()
+            else:
+                center = self.rect.center
+                self.image = self.images[self.frame]
+                self.rect = self.image.get_rect()
+                self.rect.center = center
+
 # Определение класса танка
 class Tank(pygame.sprite.Sprite):
     def __init__(self, x, y):
@@ -75,7 +138,10 @@ class Tank(pygame.sprite.Sprite):
                 self.TANK_SPEED /= self.boost_multiplier
                 self.boosted = False
 
-
+    def move_forward(self):
+        angle_rad = math.radians(self.angle + 270)
+        self.rect.x += self.TANK_SPEED * math.cos(angle_rad)
+        self.rect.y += self.TANK_SPEED * math.sin(angle_rad)
 
     def shoot(self):
         current_time = pygame.time.get_ticks()
@@ -91,14 +157,16 @@ class Tank(pygame.sprite.Sprite):
             bullet = PlayerBullet(self.rect.centerx + offset_x, self.rect.centery + offset_y, self.angle + 270)
             all_sprites.add(bullet)
             bullets.add(bullet)
-            self.last_fire_time = current_time
-            # Обновление времени последнего выстрела
-    def move_forward(self):
-        angle_rad = math.radians(self.angle + 270)
-        self.rect.x += self.TANK_SPEED * math.cos(angle_rad)
-        self.rect.y += self.TANK_SPEED * math.sin(angle_rad)
+            self.last_fire_time = current_time  # Обновление времени последнего выстрела
+
+            # Проверяем столкновение пули с каменными стенами
+            if pygame.sprite.spritecollideany(bullet, walls):
+                stoneexplosion_sound.play()  # Воспроизведение звука столкновения с каменной стеной
+                explosion = StoneExplosion(bullet.rect.centerx, bullet.rect.centery)  # Создание анимации удара о стену
+                all_sprites.add(explosion)  # Добавление анимации удара о стену в группу спрайтов
+                bullet.kill()  # Удаление пули
+
 
-# Определение класса снаряда игрока
 class PlayerBullet(pygame.sprite.Sprite):
     def __init__(self, x, y, angle):
         super().__init__()
@@ -113,7 +181,8 @@ class PlayerBullet(pygame.sprite.Sprite):
         if not screen.get_rect().colliderect(self.rect):
             self.kill()
         if pygame.sprite.spritecollideany(self, walls):
-		            self.kill()  # Удаляем снаряд, если он столкнулся со стеной
+            self.kill()  # Удаляем снаряд, если он столкнулся со стеной
+
 
 # Определение класса снаряда бота
 class BotBullet(pygame.sprite.Sprite):
@@ -130,7 +199,8 @@ class BotBullet(pygame.sprite.Sprite):
         if not screen.get_rect().colliderect(self.rect):
             self.kill()
         if pygame.sprite.spritecollideany(self, walls):
-		            self.kill()  # Удаляем снаряд, если он столкнулся со стеной
+            self.kill()  # Удаляем снаряд, если он столкнулся со стеной
+
 
 # Определение класса для бота
 class Bot(pygame.sprite.Sprite):
@@ -148,7 +218,7 @@ class Bot(pygame.sprite.Sprite):
         self.move_random()
         self.rotate_random()
         self.check_bounds()
-        #self.shoot_random()
+        # self.shoot_random()
 
     def move_random(self):
         # Движение вперёд в направлении текущего угла поворота
@@ -175,15 +245,14 @@ class Bot(pygame.sprite.Sprite):
         elif self.rect.bottom > SCREEN_HEIGHT:
             self.rect.bottom = SCREEN_HEIGHT
 
-    #def shoot_random(self):
-        # Выстрел в направлении дула
-        #current_time = pygame.time.get_ticks()
-        #if current_time - self.last_fire_time > random.randint(1000, 5000):
-            #bullet = BotBullet(self.rect.centerx, self.rect.centery, self.angle + 90)  # Стрельба в направлении дула
-            #all_sprites.add(bullet)
-            #bullets.add(bullet)
-            #self.last_fire_time = current_time
-
+    # def shoot_random(self):
+    # Выстрел в направлении дула
+    # current_time = pygame.time.get_ticks()
+    # if current_time - self.last_fire_time > random.randint(1000, 5000):
+    # bullet = BotBullet(self.rect.centerx, self.rect.centery, self.angle + 90)  # Стрельба в направлении дула
+    # all_sprites.add(bullet)
+    # bullets.add(bullet)
+    # self.last_fire_time = current_time
 
 
 class Wall(pygame.sprite.Sprite):
@@ -199,7 +268,6 @@ tanks = pygame.sprite.Group()
 bullets = pygame.sprite.Group()
 walls = pygame.sprite.Group()  # Группа для всех стен
 
-
 # Создание стен
 wall_positions = [
     (360, 40), (460, 730), (460, 830), (460, 930),
@@ -234,9 +302,6 @@ for pos in wall_stenki_positions:
     all_sprites.add(wall_stenki)
     walls.add(wall_stenki)
 
-
-
-
 # Создание групп спрайтов
 all_sprites = pygame.sprite.Group()
 tanks = pygame.sprite.Group()
@@ -247,8 +312,6 @@ player = Tank(SCREEN_WIDTH // 8, SCREEN_HEIGHT // 7)
 all_sprites.add(player)
 tanks.add(player)
 
-
-
 bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
 all_sprites.add(bot)
 tanks.add(bot)
@@ -261,6 +324,7 @@ bot = Bot(3 * SCREEN_WIDTH // 4, SCREEN_HEIGHT // 2)
 all_sprites.add(bot)
 tanks.add(bot)
 
+
 def draw_menu():
     screen.blit(menu_background, (0, 0))
     # Рисуем текст меню
@@ -279,18 +343,16 @@ def draw_menu():
     return quit_rect  # Возвращаем прямоугольник для кнопки "Выйти"
 
 
-
 def respawn_bot():
     # Создание нового экземпляра бота
     new_bot = Bot(random.randint(0, SCREEN_WIDTH), random.randint(0, SCREEN_HEIGHT))
     all_sprites.add(new_bot)
     tanks.add(new_bot)
 
+
 last_meme_time = 0
 meme_delay = 2000  # Задержка в миллисекундах (2 секунды)
 
-
-
 # Главный цикл программы
 menu_active = True
 while menu_active:
@@ -304,13 +366,9 @@ while menu_active:
                 else:
                     menu_active = False  # Нажата кнопка "Старт"
 
-
-
 # Основной игровой цикл
 clock = pygame.time.Clock()
 running = True
-paused = False  # Флаг для отслеживания состояния паузы
-shooting_enabled = True  # Флаг для отслеживания разрешения стрельбы
 
 while running:
     player_bullets = []
@@ -318,79 +376,12 @@ while running:
 
     current_time = pygame.time.get_ticks()
 
-    for event in pygame.event.get():
-        if event.type == pygame.QUIT:
-            running = False
-        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1 and shooting_enabled:  # Обработка левой кнопки мыши
-            player.shoot()
-
-        if event.type == pygame.KEYDOWN:
-            if event.key == pygame.K_k:
-                if current_time - last_meme_time > meme_delay:  # Проверка задержки
-                    meme_sound.play()
-                    last_meme_time = current_time  # Обновление времени последнего воспроизведения звука
-            elif event.key == pygame.K_ESCAPE:  # Пауза по нажатию на Escape
-                paused = not paused  # Инвертируем состояние паузы
-                if paused:
-                    shooting_enabled = False  # При паузе отключаем стрельбу
-                else:
-                    shooting_enabled = True  # При возврате из паузы включаем стрельбу
-
-    if not paused:
-        # Обновление всех спрайтов только в случае, если игра не на паузе
-        all_sprites.update()
-
-	        # Проверка столкновений пуль с танками
-        for bullet in bullets:
-            if isinstance(bullet, PlayerBullet):
-                tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
-                if tank_hit and isinstance(tank_hit, Bot):
-                    tank_hit.kill()  # Удаляем бота, если попал игрок
-                    bullet.kill()  # Удаляем пулю
-            elif isinstance(bullet, BotBullet):
-                tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
-                if tank_hit and isinstance(tank_hit, Tank):
-                    tank_hit.kill()  # Удаляем игрока, если попал бот
-                    bullet.kill()  # Удаляем пулю
-            if tank_hit and isinstance(tank_hit, Bot):
-                tank_hit.kill()  # Удаляем бота, если попал игрок
-                bullet.kill()  # Удаляем пулю
-                respawn_bot()  # Пересоздаем бота в случайном месте карты
-
-            bullet.update()
-
-        # Отрисовка фона
-        for i in range(2):
-            for j in range(2):
-                screen.blit(background_image, (i * 960, j * 540))
-
-        all_sprites.draw(screen)
-
-        # Отображение стен
-        for wall in walls:
-            screen.blit(wall.image, wall.rect)
-
-        pygame.display.flip()
-        clock.tick(FPS)
-    else:
-        # Если игра на паузе, просто ждем события
-        clock.tick(FPS)
-
-
-while running:
-    player_bullets = []
-    bot_bullets = []
-
-    current_time = pygame.time.get_ticks()
-
-
     for event in pygame.event.get():
         if event.type == pygame.QUIT:
             running = False
         elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:  # Обработка левой кнопки мыши
             player.shoot()
 
-
         if event.type == pygame.KEYDOWN:
             if event.key == pygame.K_k:
                 if current_time - last_meme_time > meme_delay:  # Проверка задержки
@@ -400,24 +391,24 @@ while running:
     # Обновление всех спрайтов
     all_sprites.update()
 
-		    # Проверка столкновений пуль с танками
+    # Проверка столкновений пуль с танками
     for bullet in bullets:
         if isinstance(bullet, PlayerBullet):
             tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
             if tank_hit and isinstance(tank_hit, Bot):
-                tank_hit.kill()  # Удаляем бота, если попал игрок
+                explosion_sound.play()  # Воспроизведение звука взрыва
+                explosion = Explosion(tank_hit.rect.centerx, tank_hit.rect.centery)  # Создание взрыва
+                all_sprites.add(explosion)  # Добавление взрыва в группу спрайтов
                 bullet.kill()  # Удаляем пулю
+                tank_hit.kill()  # Удаляем бота
+                respawn_bot()  # Создаем нового бота
         elif isinstance(bullet, BotBullet):
-            tank_hit = pygame.sprite.spritecollideany(bullet, tanks, pygame.sprite.collide_mask)
-            if tank_hit and isinstance(tank_hit, Tank):
-                tank_hit.kill()  # Удаляем игрока, если попал бот
-                bullet.kill()  # Удаляем пулю
-        if tank_hit and isinstance(tank_hit, Bot):
-            tank_hit.kill()  # Удаляем бота, если попал игрок
-            bullet.kill()  # Удаляем пулю
-            respawn_bot()  # Пересоздаем бота в случайном месте карты
-
-        bullet.update()
+            # Проверяем столкновение пули бота с стенами
+            if pygame.sprite.spritecollideany(bullet, walls):
+                stoneexplosion_sound.play()  # Воспроизведение звука взрыва камня
+                explosion = Explosion(bullet.rect.centerx, bullet.rect.centery)  # Создание взрыва камня
+                all_sprites.add(explosion)  # Добавление взрыва камня в группу спрайтов
+                bullet.kill()  # Удаляем пулю бота
 
     # Отрисовка фона
     for i in range(2):