Menu
CoddyTech

Her Vuruşta Kıvılcımlar

Coddy'nin Pygame Journey'sinin Ses ve Oyun Hissi bölümünün bir parçası. Ders 21 / 23.

Patlayan bir düşman gerçekten patlamış gibi hissettirmeli. Kıvılcımlarla başlayın: düşmanın bulunduğu yerde parçacık patlaması oluşturun.

Patlamalar iki durumda gerçekleşir: lazer isabetinde ve çarpışmada. Bu yüzden patlamayı bir işleve yerleştirin:

def burst(center):
    for i in range(16):
        particles.append({"x": center[0], "y": center[1],
                          "vx": random.uniform(-4, 4), "vy": random.uniform(-4, 4),
                          "life": random.randint(15, 30)})

İşlev yalnızca kıvılcımları oluşturur. Onları hareket ettirmek her karede yapılması gereken bir iştir; Particles bölümünde olduğu gibi: her birini hareket ettirin, ömrünü azaltın ve yalnızca hâlâ yaşayanları tutun.

Bunu explosions.update() satırının yanına, if lives > 0 ... koşulunun dışına ekleyin. Oyunu bitiren çarpışma da bir patlama oluşturur ve Game over sonrasında da kıvılcımlar uçmaya devam etmelidir. Kıvılcımları patlamalardan sonra çizin; böylece üstte görünürler.

challenge icon

Görev

Orta
  1. Döngüden önce particles = [] oluştur.
  2. burst(center) işlevini yaz: center konumunda 16 parçacık oluştur; vx ve vy değerlerini random.uniform(-4, 4) ile, life değerini ise random.randint(15, 30) ile belirle.
  3. Lazer bir düşmanı yok ettiğinde ve bir düşman gemiye çarptığında burst(enemy.rect.center) çağrısı yap.
  4. explosions.update() satırının yanına parçacıkları hareket ettiren, ömürlerini azaltan ve ömrü bitenleri kaldıran kodu ekle.
  5. Patlamalardan sonra her parçacığı, yarıçapı life // 10 + 1 olan turuncu (255, 170, 60) bir daire olarak çiz.

Kendin dene

import random
import pygame

pygame.init()
screen = pygame.display.set_mode((640, 480))
pygame.display.set_caption("Star Patrol")
clock = pygame.time.Clock()
font = pygame.font.Font(None, 32)

ship_image = pygame.image.load("assets/images/ship.png").convert_alpha()
laser_image = pygame.image.load("assets/images/laser.png").convert_alpha()
red_image = pygame.image.load("assets/images/enemy_red.png").convert_alpha()
green_image = pygame.image.load("assets/images/enemy_green.png").convert_alpha()
yellow_image = pygame.image.load("assets/images/enemy_yellow.png").convert_alpha()
explosion_frames = []
for number in range(1, 5):
    explosion_frames.append(pygame.image.load(f"assets/images/explosion_{number}.png").convert_alpha())

laser_sound = pygame.mixer.Sound("assets/sounds/laser.ogg")
laser_sound.set_volume(0.4)
explosion_sound = pygame.mixer.Sound("assets/sounds/explosion.ogg")
hit_sound = pygame.mixer.Sound("assets/sounds/hit.ogg")

WAVES = [(red_image, 6, 2), (green_image, 8, 2), (yellow_image, 10, 3)]


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super().__init__()
        self.image = ship_image
        self.rect = self.image.get_rect(midbottom=(320, 470))
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        keys = pygame.key.get_pressed()
        if keys[pygame.K_LEFT]:
            self.rect.x -= 6
        if keys[pygame.K_RIGHT]:
            self.rect.x += 6
        self.rect.clamp_ip(screen.get_rect())


class Laser(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = laser_image
        self.rect = self.image.get_rect(midbottom=(x, y))
        self.mask = pygame.mask.from_surface(self.image)

    def update(self):
        self.rect.y -= 10
        if self.rect.bottom < 0:
            self.kill()


class Enemy(pygame.sprite.Sprite):
    def __init__(self, image, x, y, speed):
        super().__init__()
        self.image = image
        self.rect = self.image.get_rect(center=(x, y))
        self.mask = pygame.mask.from_surface(self.image)
        self.speed = speed

    def update(self):
        self.rect.y += self.speed


class Explosion(pygame.sprite.Sprite):
    def __init__(self, center):
        super().__init__()
        self.index = 0
        self.timer = 0
        self.image = explosion_frames[0]
        self.rect = self.image.get_rect(center=center)

    def update(self):
        self.timer += 1
        if self.timer == 5:
            self.timer = 0
            self.index += 1
            if self.index == len(explosion_frames):
                self.kill()
            else:
                self.image = explosion_frames[self.index]


def play_music(path, loops=-1):
    pygame.mixer.music.load(path)
    pygame.mixer.music.play(loops)


def spawn_wave(image, count, speed):
    for i in range(count):
        x = random.randint(40, 600)
        enemies.add(Enemy(image, x, -40 - i * 120, speed))


player = Player()
lasers = pygame.sprite.Group()
enemies = pygame.sprite.Group()
explosions = pygame.sprite.Group()
last_shot = 0
score = 0
lives = 3
wave = 0
image, count, speed = WAVES[wave]
spawn_wave(image, count, speed)
pygame.mixer.music.set_volume(0.5)
play_music("assets/music/level.ogg")

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    if lives > 0 and wave < len(WAVES):
        player.update()
        keys = pygame.key.get_pressed()
        now = pygame.time.get_ticks()
        if keys[pygame.K_SPACE] and now - last_shot >= 250:
            lasers.add(Laser(player.rect.centerx, player.rect.top))
            last_shot = now
            laser_sound.play()
        lasers.update()
        enemies.update()
        for enemy in enemies:
            if enemy.rect.top > 480:
                enemy.kill()
                lives -= 1
                hit_sound.play()
        hits = pygame.sprite.groupcollide(enemies, lasers, True, True, pygame.sprite.collide_mask)
        for enemy in hits:
            score += 10
            explosion_sound.play()
            explosions.add(Explosion(enemy.rect.center))
        crashes = pygame.sprite.spritecollide(player, enemies, True, pygame.sprite.collide_mask)
        for enemy in crashes:
            lives -= 1
            hit_sound.play()
            explosions.add(Explosion(enemy.rect.center))
        if not enemies:
            wave += 1
            if wave < len(WAVES):
                image, count, speed = WAVES[wave]
                spawn_wave(image, count, speed)
            else:
                play_music("assets/music/win.ogg", 0)
        if lives <= 0:
            play_music("assets/music/lose.ogg", 0)
    explosions.update()

    screen.fill((12, 14, 30))
    enemies.draw(screen)
    lasers.draw(screen)
    screen.blit(player.image, player.rect)
    explosions.draw(screen)
    score_text = font.render(f"Score: {score}", True, (240, 240, 240))
    screen.blit(score_text, (10, 10))
    lives_text = font.render(f"Lives: {max(lives, 0)}", True, (240, 240, 240))
    screen.blit(lives_text, lives_text.get_rect(topright=(630, 10)))
    if wave < len(WAVES):
        wave_text = font.render(f"Wave {wave + 1}", True, (240, 240, 240))
        screen.blit(wave_text, wave_text.get_rect(midtop=(320, 10)))
    if lives <= 0:
        message = font.render("Game over", True, (240, 240, 240))
        screen.blit(message, message.get_rect(center=(320, 240)))
    elif wave == len(WAVES):
        message = font.render("You win!", True, (240, 240, 240))
        screen.blit(message, message.get_rect(center=(320, 240)))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
quiz iconKendini test et

Bu ders kısa bir quiz içerir. Soruları yanıtlamak ve ilerlemeni kaydetmek için derse başla.

Ses ve Oyun Hissi bölümündeki tüm dersler

Kendi başına pratik yap: Pygame playground