86 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”:
Proovi koodi täiendada:
- Lisa mängijale pilt
- Lisa võimalus mängijat juhtida
- Lisa rohkem rakette
- Lisa kood, et raketid ilmuvad suvalistele positsioonidele
- Lisa kood, et kui üks rakett on võetud, ilmub uus (suvalisele kohale)
- Lisa kood, et rakett on ekraanil vaid teatud aja (näiteks peale teatud tsüklite arvu kaob ära)
- Lisa kood, et mängija saab rakettide korjamise eest punkte