Arkanoid

 avatar
unknown
python
5 months ago
5.3 kB
9
Indexable
import pygame
import math
import numpy as np
import sys

# --- Stałe gry ---
SZEROKOSC = 800
WYSOKOSC = 600
KOLOR_TLO = (20, 20, 20)
KOLOR_CEGIELKA = (200, 80, 80)
KOLOR_PALKA = (80, 200, 80)
KOLOR_PILKA = (80, 80, 200)

# Rozmiary paletki
PALETKA_SZER = 100
PALETKA_WYS = 10

# Rozmiary cegiełek
CEGIELKA_SZER = 75
CEGIELKA_WYS = 30

# Parametry piłki
PILKA_PROMIEN = 8
PILKA_PREDKOSC = 5

def generuj_dzwiek(frequency=440, duration=0.2, volume=1.0, sample_rate=44100):
    """
    Tworzy prosty dźwięk sinusoidalny (mono), ale zwraca w formacie stereo
    (aby pasował do domyślnego trybu 2 kanałów w pygame.mixer).
    """
    n_samples = int(sample_rate * duration)
    t = np.linspace(0, duration, n_samples, endpoint=False)

    # Fala sinusoidalna (16-bit)
    wave = 32767 * volume * np.sin(2 * math.pi * frequency * t)
    wave = wave.astype(np.int16)

    # Replikacja do dwóch kanałów (stereo), tak aby uniknąć błędu:
    # "ValueError: Array depth must match number of mixer channels"
    wave_stereo = np.column_stack((wave, wave))

    sound_obj = pygame.sndarray.make_sound(wave_stereo)
    return sound_obj

class Paletka(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((PALETKA_SZER, PALETKA_WYS))
        self.image.fill(KOLOR_PALKA)
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.centery = y
        self.predkosc = 7

    def update(self, keys):
        if keys[pygame.K_LEFT]:
            self.rect.x -= self.predkosc
        if keys[pygame.K_RIGHT]:
            self.rect.x += self.predkosc

        # Zabezpieczenie przed wyjechaniem za ekran
        if self.rect.left < 0:
            self.rect.left = 0
        if self.rect.right > SZEROKOSC:
            self.rect.right = SZEROKOSC

class Pilka(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((PILKA_PROMIEN * 2, PILKA_PROMIEN * 2), pygame.SRCALPHA)
        pygame.draw.circle(self.image, KOLOR_PILKA, (PILKA_PROMIEN, PILKA_PROMIEN), PILKA_PROMIEN)
        self.rect = self.image.get_rect()
        self.rect.center = (x, y)
        self.dx = PILKA_PREDKOSC
        self.dy = -PILKA_PREDKOSC  # startuje w górę

    def update(self):
        self.rect.x += self.dx
        self.rect.y += self.dy

        # Odbicia od lewej i prawej krawędzi
        if self.rect.left <= 0 or self.rect.right >= SZEROKOSC:
            self.dx = -self.dx

        # Odbicie od górnej krawędzi
        if self.rect.top <= 0:
            self.dy = -self.dy

class Cegielka(pygame.sprite.Sprite):
    def __init__(self, x, y):
        super().__init__()
        self.image = pygame.Surface((CEGIELKA_SZER, CEGIELKA_WYS))
        self.image.fill(KOLOR_CEGIELKA)
        self.rect = self.image.get_rect()
        self.rect.x = x
        self.rect.y = y

def main():
    pygame.init()
    # Można jawnie zainicjalizować mikser, ale domyślnie będzie 2-kanałowy (stereo).
    # pygame.mixer.init(frequency=44100, size=-16, channels=2)

    ekran = pygame.display.set_mode((SZEROKOSC, WYSOKOSC))
    pygame.display.set_caption("Prosty Arkanoid")

    zegar = pygame.time.Clock()

    # Przygotowanie obiektów gry
    paletka = Paletka(SZEROKOSC // 2, WYSOKOSC - 30)
    pilka = Pilka(SZEROKOSC // 2, WYSOKOSC // 2)

    paletka_grupa = pygame.sprite.Group()
    paletka_grupa.add(paletka)

    pilka_grupa = pygame.sprite.Group()
    pilka_grupa.add(pilka)

    cegielki_grupa = pygame.sprite.Group()
    # Układ cegiełek w kilku rzędach
    for wiersz in range(5):
        for kolumna in range(10):
            x = 10 + kolumna * (CEGIELKA_SZER + 5)
            y = 50 + wiersz * (CEGIELKA_WYS + 5)
            cegielka = Cegielka(x, y)
            cegielki_grupa.add(cegielka)

    # Proste efekty dźwiękowe - kolizje
    dzwiek_kolizja_cegielka = generuj_dzwiek(frequency=500, duration=0.05, volume=0.5)
    dzwiek_kolizja_paletka = generuj_dzwiek(frequency=200, duration=0.05, volume=0.5)

    running = True
    while running:
        zegar.tick(60)  # 60 FPS
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        # Sterowanie paletką
        keys = pygame.key.get_pressed()
        paletka.update(keys)

        # Aktualizacja piłki
        pilka.update()

        # Sprawdzenie kolizji piłki z paletką
        if pygame.sprite.spritecollide(pilka, paletka_grupa, False):
            pilka.dy = -pilka.dy
            dzwiek_kolizja_paletka.play()

        # Sprawdzenie kolizji piłki z cegiełkami
        trafione_cegielki = pygame.sprite.spritecollide(pilka, cegielki_grupa, True)
        if trafione_cegielki:
            pilka.dy = -pilka.dy
            dzwiek_kolizja_cegielka.play()

        # Sprawdzenie, czy piłka spadła poniżej dolnej krawędzi
        if pilka.rect.top > WYSOKOSC:
            # Tutaj można zakończyć grę, odpalić ekran "Game Over", itp.
            running = False

        # Rysowanie
        ekran.fill(KOLOR_TLO)
        paletka_grupa.draw(ekran)
        pilka_grupa.draw(ekran)
        cegielki_grupa.draw(ekran)
        pygame.display.flip()

    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()
Editor is loading...
Leave a Comment