Dette er del fem av en femdelers serie av opplæringsprogrammer om å lage spill med Python 3 og PyGame. I del fire oppdaget vi kollisjoner, reagerte på ballen som slo forskjellige spillobjekter, og opprettet en spillmeny med egendefinerte knapper.
I denne siste delen skal vi dekke ulike emner som sluttspillet, styre liv og score, lydeffekter, musikk og til og med et fleksibelt spesialdesigningssystem. Til dessert diskuterer vi potensielle forbedringer og fremtidige retninger.
Til slutt må spillet avsluttes. I denne versjonen av Breakout slutter spillet på to måter: enten spilleren mister alle livene sine eller de treffer alle mursteinene. Det er ikke noe neste nivå (selv om det ville være enkelt å legge til).
Game_over feltet i Game klassen er satt til False i __i det__()
metode for spillklassen. Hovedløkken går rundt og rundt til spillet er slutt
variabel er satt til True:
klassespill: def __init __ (selvbilde, bredde, høyde, back_image_filename, frame_rate): ... self.game_over = False ... def run (selv): mens ikke self.game_over: self.surface.blit (self.background_image, , Selv)
Det skjer alt i Breakout-klassen i følgende tilfeller:
Def on_quit (knapp): self.game_over = True self.is_game_running = False def handle_ball_collisions (selv): ... # Hit gulv hvis self.ball.top> c.screen_height: self.lives - = 1 hvis self.lives == 0 : self.game_over = True if not self.bricks: self.show_message ('DU VIL !!!', sentralisert = True) self.is_game_running = False self.game_over = True return def oppdatering (selv): ... hvis ikke selv. murstein: self.show_message ('DU VIL!', sentralisert = True) self.is_game_running = False self.game_over = Sann tilbake
Vanligvis når spillet slutter, vil vi ikke at spillvinduet bare skal forsvinne i tynn luft. Unntaket er hvis du klikket på QUIT-knappen i menyen. Når spilleren mister sitt siste liv, viser Breakout den tradisjonelle "GAME OVER!" melding, og når spilleren vinner, viser den 'DU VIN!'
De Vis melding()
funksjonen brukes i begge tilfeller. Den viser teksten på toppen av den nåværende skjermen (spillet blir pauset) og venter i noen sekunder før du returnerer. I neste iterasjon av spillsløyfen, sjekken for spillet er slutt
feltet vil avgjøre det er sant, og programmet vil avslutte.
Her er Vis melding()
funksjon:
def display_message (selv, tekst, farge = colors.WHITE, font_name = "Arial", font_size = 20, sentralisert = False): message = TextObject (c.screen_width // 2, c.screen_height // 2, lambda: tekst, farge, font_name, font_size) self.draw () message.draw (self.surface, sentralisert) pygame.display.update () time.sleep (c.message_duration)
I denne versjonen holder jeg ikke høy poengsum fordi det er bare ett nivå, og alles score blir det samme hvis de sletter alle mursteinene. Generelt kan det gjøres lokalt ved å lagre høy score i en fil og deretter vise en annen melding hvis spilleren brøt høy poengsum.
Spill er en audiovisuell opplevelse. De fleste spill har lydeffekter som er korte lydbyte som spilles når spilleren dreper et monster, finner litt skatt eller eksploderer forferdelig. Noen spill har også bakgrunnsmusikk, noe som bidrar til atmosfæren. Breakout har bare lydeffekter, men jeg vil vise deg hvordan du spiller bakgrunnsmusikk i spillene dine.
Du trenger lydfiler (ligner på bildefiler) for å spille som lydeffekter. Disse filene kan være i .wav, .mp3 eller .ogg-formater. Breakout beholder lydeffekter i lydeffekter
mappe:
~ / git / pygame-breakout> tre sound_effects / sound_effects / ├── brick_hit.wav ├── effect_done.wav ├── level_complete.wav └── paddle_hit.wav
La oss se hvordan disse lydeffekter lastes og spilles til rett tid. Først, for å spille av lydeffekter (eller bakgrunnsmusikk) må du initialisere lydsystemet til Pygame. Det skjer i spillet klassen: pygame.mixer.pre_init (44100, 16, 2, 4096)
Da, i Breakout-klassen, lastes alle lydeffekter fra config til pygame.mixer.Sound
objekt og lagres i en ordbok:
# I config.py sounds_effects = dict (brick_hit = "sound_effects / brick_hit.wav", effect_done = "sound_effects / effect_done.wav", paddle_hit = "sound_effects / paddle_hit.wav", level_complete = "sound_effects / level_complete.wav" # I breakout.py klasse Breakout (Spill): def __init __ (selv): ... self.sound_effects = navn: pygame.mixer.Sound (lyd) for navn, lyd i c.sounds_effects.items () ...
Nå kan vi spille lydeffekter når det skjer noe interessant. For eksempel når ballen treffer en murstein:
# Hit murstein for murstein i selv.bricks: kant = skjær (murstein, selvball) hvis ikke kant: fortsett selv.sound_effects ['brick_hit']. Play ()
Lydeffekten spiller asynkront, noe som betyr at spillet ikke fryser mens lyden spiller. Flere lydeffekter kan spilles samtidig.
Opptak av lydeffekter er både enkelt og givende. I motsetning til visuell eiendomsdesign, tar det ikke mye talent. Noen kan si "Kaboom!" eller "Boing" eller rop "Du er død. Bedre flaks neste gang!"
Jeg ber ofte barna mine å ta opp lydeffekter, samt talemeldinger som følger med tekstmeldinger som "DU VIN!" eller "GAME OVER!" Din fantasi er den eneste begrensningen.
Bakgrunnsmusikk bør spille konstant. I teorien kan du ha en veldig loooooooong lydeffekt, men en mer vanlig tilnærming er bare å spille bakgrunnsmusikken i en loop. Musikkfiler kan være .wav, .mp3 eller .midi format. Slik er det gjort:
music = pygame.mixer.music.load ('background_music.mp3') pygame.mixer.music.play (-1, 0.0)
Du kan bare ha ett stykke bakgrunnsmusikk som spilles av gangen. Men flere lydeffekter kan spille over bakgrunnsmusikken. Det handler om blanding.
La oss bli fancy. Bryte murstein med en ball er kult, men det blir gammelt ganske fort. Hva med et generisk spesialeffekter system? Vi utvikler et utvidbart system med spesialeffekter som er knyttet til visse murstein og aktiveres når ballen treffer mursteinen.
Her er planen. Effekter har en levetid. Effekten starter når mursteinen går i stykker og slutter når effekten varer. Hva skjer hvis ballen rammer en annen spesiell effekt murstein? I teorien kan du ha sammensatte effekter, men for å forenkle ting for den første implementeringen, vil den aktive effekten stoppe, og den nye effekten vil ta sin plass.
En spesiell effekt kan defineres på den mest generiske måten som to funksjoner. Den første funksjonen aktiverer effekten, og den andre funksjonen nullstiller den. Vi ønsker å legge ved effekter til murstein og gjøre det klart for spilleren hvilke murstein er spesielle, så de kan prøve å treffe eller unngå dem på visse punkter.
Følgende dikt fra breakout.py-modulen definerer våre spesialeffekter. Hver effekt har et navn (for eksempel long_paddle) og en verdi, som består av fargen sin murstein vil ha, så vel som de to funksjonene. Funksjonene er definert som lambda-funksjoner som tar et spill-eksempel, som inkluderer alt en spesiell effekt i Breakout vil kanskje endre.
special_effects = dict (long_paddle = (colors.ORANGE, lambda g: g.paddle.bounds.inflate_ip (c.paddle_width // 2, 0), lambda g: g.paddle.bounds.inflate_ip (-c.paddle_width // 2 , 0)), slow_ball = (colors.AQUAMARINE2, lambda g: g.change_ball_speed (-1), lambda g: g.change_ball_speed (1)), tripple_points = (colors.DARKSEAGREEN4, lambda g: g.set_points_per_brick (3) , lambda g: g.set_points_per_brick (1)), extra_life = (colors.GOLD1, lambda g: g.add_life (), lambda g: None))
Når mursteinene er opprettet, har de en endring som skal tilordnes en av spesialeffektene. Her er koden:
def create_bricks (selv): w = c.brick_width h = c.brick_height brick_count = c.screen_width // (w + 1) offset_x = (c.screen_width - brick_count * (w + 1)) // 2 murstein = [] for rad i rekkevidde (c.row_count): for kol i rekkevidde (brick_count): effekt = Ingen brick_color = c.brick_color index = random.randint (0, 10) hvis indeks < len(special_effects): x = list(special_effects.values())[index] brick_color = x[0] effect = x[1:] brick = Brick(offset_x + col * (w + 1), c.offset_y + row * (h + 1), w, h, brick_color, effect) bricks.append(brick) self.objects.append(brick) self.bricks = bricks
The Brick-klassen har et effektfelt som vanligvis er None, men kan få (30% sjanse) en av de spesielle effektene som er definert ovenfor. Merk at denne koden ikke er klar over hvilke effekter som er tilgjengelige. Det blir bare effekten og mursteinens farge og tilordner dem om nødvendig.
I denne versjonen av Breakout utløser jeg bare effekter når en murstein er rammet, men du kan forestille deg andre scenarier som kan utløse hendelser. Den forrige effekten tilbakestilles (hvis det var en), og den nye effekten lanseres. Tilbakestillingsfunksjonen og effektstarttidspunktet lagres for senere.
hvis brick.special_effect ikke er None: # Tilbakestill forrige effekt hvis noen hvis self.reset_effect ikke er None: self.reset_effect (self) # Trigger spesiell effekt self.effect_start_time = datetime.now () brick.special_effect [self # Still inn tilbakestillingseffektfunksjon self.reset_effect = brick.special_effect [1]
Hvis ingen ny effekt ble utløst, må vi fortsatt nullstille gjeldende hendelse når den utløper. Det skjer i Oppdater()
metode. I hver ramme ble tilbakestillingsfunksjonen til den gjeldende effekten tilordnet til reset_effect
felt. Hvis tiden siden den nåværende effekten startet, oversteg effektens varighet, og deretter reset_effect ()
funksjon kalles og reset_effect
feltet er satt til None (som betyr at det ikke er noen aktiv effekt akkurat nå).
# Tilbakestill spesiell effekt hvis nødvendig hvis self.reset_effect: elapsed = datetime.now () - self.effect_start_time hvis det er gått> = timedelta (sekunder = c.effect_duration): self.reset_effect (selv) self.reset_effect = Ingen
Den lange padleffekten virker ved å oppblåse padleen med 50%. Nullstillingsfunksjonen justerer størrelsen på den til normal. Teglfarge er oransje:
long_paddle = (colors.ORANGE, lambda g: g.paddle.bounds.inflate_ip (c.paddle_width // 2, 0), lambda g: g.paddle.bounds.inflate_ip (-c.paddle_width // 2, 0)),
En annen effekt som hjelper til med å jakte på ballen er langsom ball-effekten, som bare bremser ballen fart med en enhet. Mursteinens farge er Aquamarine.
slow_ball = (colors.AQUAMARINE2, lambda g: g.change_ball_speed (-1), lambda g: g.change_ball_speed (1)),
Hvis du vil ha store tall, vil du like trippelpunktseffekten som gir deg tre poeng for hver murstein du treffer i stedet for det vanlige punktet. Teglfarge er mørkegrønn.
tripple_points = (colors.DARKSEAGREEN4, lambda g: g.set_points_per_brick (3), lambda g: g.set_points_per_brick (1)),
Endelig er en svært nyttig effekt ekstra livseffekt. Det gir deg bare et ekstra liv. Ingen tilbakestilling trengs egentlig. Mursteinens farge er gull.
extra_life = (colors.GOLD1, lambda g: g.add_life (), lambda g: None))
Det er flere naturlige veibeskrivelser for å utvide Breakout. Hvis du er interessert i å prøve hånden din ved å legge til flere funksjoner og funksjoner, er det noen ideer.
For å gjøre Breakout til et seriøst spill, trenger det nivåer. Å spille bare en skjerm er ikke nok. På begynnelsen av hvert nivå, vil du tilbakestille skjermen, men hold poengsummen og leve som det er. For å gjøre kampen vanskeligere, kan du øke ballhastigheten på hvert nivå eller legge til et annet lag med murstein.
Å legge til en andre ball som en midlertidig effekt er bundet til å skape mye kaos. Den vanskelige delen her er å behandle begge ballene like like, uavhengig av hvilken som var originalen. Når en ball er borte, fortsetter spillet med enkeltballen som ble igjen. Ingen liv er tapt.
Når du har nivåer med økende vanskelighet, blir høy poengsum en ettertraktet premie. Du kan holde høy poengsum i en fil for å fortsette mellom spill. Når en spiller bryter høy poengsum, kan du legge til en liten pizazz eller la dem skrive navnet sitt (tradisjonelt bare tre tegn).
I den nåværende implementeringen er alle spesial effekter knyttet til murstein, men du kan legge til effekter (bra og dårlige) som faller fra himmelen og spilleren må samle dem eller unngå dem.
Utvikling av Breakout ved hjelp av Python 3 og Pygame var en super givende opplevelse. Det er en veldig kraftig kombinasjon for 2D-spill (og 3D-spill også). Hvis du liker Python og vil lage dine egne spill, kan du ikke gå galt med Pygame.
Jeg planlegger definitivt å lage flere spill med Python og Pygame.
Til slutt, husk at vi har masse Python-innhold tilgjengelig for salg og for studier i Envato Market.