Parla ve Sayacı Artır
Coddy'nin Pygame Journey'sinin Ses ve Oyun Hissi bölümünün bir parçası. Ders 23 / 23.
Son iki dokunuş. Oyuncu bir can kaybettiğinde tüm ekran bir anlığına kırmızı yanıp söner; böylece kaybı fark etmemek imkânsız olur. Puan kazandığında ise sayı bir anda değişmek yerine artarak yükselir.
Kırmızı flaş, pencere boyutlarında, kırmızıya boyanmış ve set_alpha() ile saydamlaştırılmış bir Surface’tir; 0 (görünmez) ile 255 (opak) arasında bir değer alır. Döngüden önce bir kez oluştur:
red = pygame.Surface((640, 480))
red.fill((255, 0, 0))
red.set_alpha(90)Bir can kaybedildiğinde flash = 12 ayarlanır. Her karede bu değer azaltılır ve 0’dan büyük olduğu sürece oyun, metinden önce red yüzeyini oyun dünyasının üzerine çizer.
Puan için ikinci bir sayı olan shown_score değerini tut ve her karede gerçek puana doğru yaklaştır:
shown_score += (score - shown_score) * 0.2round(shown_score) değerini çiz. Oyun, her şeyi hâlâ score ile belirler; yalnızca ekrandaki değer yumuşakça değişir. Bu bölümdeki tüm görsel ve işitsel iyileştirmelerin kuralı budur: oyuncunun gördüklerini ve duyduklarını değiştirirler, kuralları asla değiştirmezler.
Görev
Orta- Döngüden önce:
flash = 0, alfa değeri 90 olan kırmızı Surface veshown_score = 0. - Can kaybedilen her iki yerde de
flash = 12ayarla. explosions.update()yanına:flash0'dan büyük olduğu sürece değerini 1 azalt veshown_scoredeğerini 0.2 ilescoredeğerine yaklaştır.- Dünyayı blit ettikten sonra,
flash0'dan büyük olduğu süreceredöğesini(0, 0)konumuna blit et. - Skor yerine
Score: {round(shown_score)}göster.
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 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),
})
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()
world = pygame.Surface((640, 480))
particles = []
shake = 0
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()
burst(enemy.rect.center)
shake = min(shake + 6, 15)
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))
burst(enemy.rect.center)
shake = 15
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()
for p in particles:
p["x"] += p["vx"]
p["y"] += p["vy"]
p["life"] -= 1
particles = [p for p in particles if p["life"] > 0]
world.fill((12, 14, 30))
enemies.draw(world)
lasers.draw(world)
world.blit(player.image, player.rect)
explosions.draw(world)
for p in particles:
pygame.draw.circle(world, (255, 170, 60), (p["x"], p["y"]), p["life"] // 10 + 1)
offset = (0, 0)
if shake > 0:
amount = shake // 3
offset = (random.randint(-amount, amount), random.randint(-amount, amount))
shake -= 1
screen.fill((0, 0, 0))
screen.blit(world, offset)
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()
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
4Ekran Sarsıntısı ve Darbe Parlaması
Ekran SarsıntısıDarbe ParlamasıDarbe DurdurmasıAbartıdan Kaçının6Yıldız Devriyesini Geliştir
Yıldız Devriyesi SesleriHer Vuruşta KıvılcımlarKendi başına pratik yap: Pygame playground