88 Spraidid

Sprait (sprite) on visuaalne objekt, mis liigub mängus. Näiteks mängija tegelaskuju on sprait, vastaseid on spraidid, kui mängus on vaja korjata aardeid, siis need on spraidid jne.

PyGame’is on sprait visuaalne element, mis joonistatakse ekraanile ning mida saab liigutada. Spraidi loomiseks tuleb luua klass, mis laiendab pygame.sprite.Sprite klassi. Spraidiga defineeritakse ära rect objekt (ristkülik, mis näitab spraidi asukohta ja suurust ekraanil) ja pilt (või kujutis, näiteks võib see olla värvitud ristkülik). Spraidi asukohta saab muuta programmis. Näiteks kui mängija nooltega tegelaskuju liigutab, siis spraidi positsioon võib muutuda. Või näiteks juhitakse spraidi liikumist programmi poolt – kuulid lendavad ettemääratud suunas.

PyGame’is kasutatakse spraitide gruppe, et koondada spraidid näiteks väljajoonistamiseks ühte kogumisse. Grupp on pygame.sprite.Group objekt, kuhu sisse saab spraite lisada ja neid sealt kustutada. Grupp on see, mille saab joonistada ekraanile. Grupi ekraanile joonistamise puhul joonistatakse kõik selle grupi spraidid ekraanile. Üks sprait võib olla ka mitmes grupis.

Näiteks väljajoonistamiseks on mugav, kui kõik spraidid on ühes grupis (näiteks all_sprites). Samas oleks hea hoida pahad tegelased eraldi grupis ja näiteks korjatavad objektid eraldi. Sedasi saab ühe grupi seest elemente läbi käia ja nendega midagi teha (näiteks nende positsiooni muuta).

Koodinäide

Teeme koodinäite, kus meil on mängija Player ja paar raketti Rocket. Mängija ise liigub pidevalt vasakult paremale. Kui satub raketi peale, “korjatakse” rakett üles (rakett kaob ekraanilt).

import pygame
pygame.init()


class Rocket(pygame.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()

        self.image = pygame.image.load("rocket_small.png")
        self.rect = self.image.get_rect()
        self.rect.x = pos[0]
        self.rect.y = pos[1]


class Player(pygame.sprite.Sprite):
    def __init__(self, pos):
        super().__init__()

        self.image = pygame.Surface((30, 30))
        self.image.fill((0, 0, 255))
        self.rect = self.image.get_rect()


rocket_list = pygame.sprite.Group()
all_sprites_list = pygame.sprite.Group()

screen = pygame.display.set_mode((600, 800))

clock = pygame.time.Clock()
running = True

# create rockets
rocket1 = Rocket((50, 1))
rocket2 = Rocket((100, 3))

# add rockets to rockets list
rocket_list.add(rocket1)
rocket_list.add(rocket2)
# add rockets to all sprites list
all_sprites_list.add(rocket1)
all_sprites_list.add(rocket2)

# create player and add to all sprites list
player = Player((0, 0))
all_sprites_list.add(player)

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

    screen.fill((255, 255, 255))

    # whether player collides with one of the rockets
    collide_index = player.rect.collidelist(rocket_list.sprites())
    if collide_index != -1:
        print("Found a rocket!")
        rocket = rocket_list.sprites()[collide_index]
        # remove rocket from all the groups
        rocket_list.remove(rocket)
        all_sprites_list.remove(rocket)

    all_sprites_list.draw(screen)

    player.rect.x += 10

    pygame.display.flip()
    clock.tick(1)

Alguses loome kaks eraldi klassi – üks raketi jaoks ja teine mängija jaoks. Raketi jaoks kasutame pilti, mängija on lihtsalt sinine ristkülik. Spraidi puhul peame ära defineerima kaks väärtust: image ja rect. Seda teemegi mõlema klassi puhul konstruktoris. Mõlemad spraidid oleme nii loonud, et objekti loomisel saab määrata, mis positsioonile see ekraanil pannakse (pos parameeter).

Edasi loome kaks spraitide gruppi: rocket_list ja all_sprites_list. Loome kaks raketi objekti ja lisame need mõlemasse gruppi. Loome ühe mängija objekti ja lisame selle vaid all_sprites_list gruppi. Rakette on mugav eraldi grupis hoida, kuna siis saame hiljem kontrollida mängija kokkupuutumist nendega.

Mängutsüklis toimub mängija asukoha muutumine (player.rect.x += 10). Ehk siis iga tsükliga liigub mängija positsioon 10 piksli võrra paremale. Ühtlasi kontrollitakse igas tsüklis, kas mängija puutub kokku mõne raketiga. Selleks kasutame Rect objekti meetodit collidelist. Sinna anname kaasa raketi spraitide listi, mille saame eelnevalt loodud grupi käest. See meetod tagastab indeksi, millise elemendiga kokkupuude toimub. Kui tagastatakse -1, siis kokkupuudet ei toimu. Kui tulemus ei ole -1, siis järelikult toimus kokkupuude. Kasutame saadud indeksit, et leida see objekt üles (rocket = rocket_list.sprites()[collide_index])`. Ja nüüd eemaldame selle spraidi nii rakettide kui ka kõikide spraitide grupist. See on vajalik selleks, et edaspidi seda enam ekraanile ei kuvata.

Siin kuvatõmmis koodist, kui üks rakett on ära “korjatud”:

Mängu näide
Kuvatõmmis mängust

Proovi koodi täiendada:

  1. Lisa mängijale pilt
  2. Lisa võimalus mängijat juhtida
  3. Lisa rohkem rakette
  4. Lisa kood, et raketid ilmuvad suvalistele positsioonidele
  5. Lisa kood, et kui üks rakett on võetud, ilmub uus (suvalisele kohale)
  6. Lisa kood, et rakett on ekraanil vaid teatud aja (näiteks peale teatud tsüklite arvu kaob ära)
  7. Lisa kood, et mängija saab rakettide korjamise eest punkte

Litsents

Icon for the Creative Commons Attribution 4.0 International License

Tarkvaraarendus. 2. trükk on loodud Eno Tõnisson, Tauno Palts, Kaarel Tõnisson, Heidi Meier, Merilin Säde, Ago Luberg, Birgy Lorenz, Einar Kivisalu, Meelis Antoi, ja Säde Mai Krusberg poolt Creative Commons Attribution 4.0 International License litsentsi alusel, kui pole teisiti märgitud.

Jaga seda raamatut