Elämät ja pisteet
Pelissä on nyt kiviä ja kolikoita, mutta ne eivät vielä tee mitään. Lisätään peliin elämät, jotka vähenevät kun kivi osuu leppikseen, ja pisteet, jotka nousevat, kun kolikko osuu leppikseen.
Määritellään koodin alkuun muuttujat elämille ja pisteille:
leppis_image = pygame.image.load("leppis.png")
leppis_x = 350
leppis_y = ground_start_y - leppis_image.get_height() + 12
leppis_speed = 7
lives = 10
score = 0
Sitten nämä pitäisi saada näkymään näytöllä. Käynnistetään ensin pygamen fonttimoduuli, ja määritellään fontti, jota haluamme käyttää.
pygame.font.init()
font = pygame.font.SysFont(None, 30)
fontColor = (234,100,176)
pygame.font.SysFont
-komento lataa käytettäväksi fontin, joka sinulla on asennettuna tietokoneellesi.
Sen ensimmäiseksi argumentiksi voi laittaa None
, jos haluat käyttää oletusfonttia, tai jonkun tietyn
fontin nimen, esimerkiksi "Comic Sans MS" tai "Chilanka". Toiseksi argumentiksi laitetaan fontin koko.
Jos käytät Linuxia, voit nähdä tietokoneellasi olevat fontit gnome-font-viewer -ohjelman avulla. Se
löytyy hausta nimellä Fonts. Jos sinulla ei ole sitä, niin voit ladata sen komennolla sudo apt install gnome-font-viewer
.
Jos haluat käyttää jotain fonttia, jonka olet ladannut netistä, niin voit käyttää samalla tavalla
pygame.font.Font
-komentoa, joka ottaa argumentiksi fonttitiedoston nimen ja fontin koon. Fontin täytyy
olla .ttf-muodossa.
Sitten piirretään ikkunaan elämät ja pisteet. Laitetaan nämä rivit while-silmukan sisälle kaiken muun piirtämisen jälkeen.
scoreText = font.render("pisteet: " + str(score), True, fontColor)
livesText = font.render("elämät: " + str(lives), True, fontColor)
window.blit(scoreText, (20,20))
window.blit(livesText, (20,60))
Ensin määritellään muuttuja scoreText, joka sisältää ikkunaan piirrettävän tekstin, joka kertoo pisteet.
Teksti renderöidään font.render
-komennolla. Huomaa, että font on aiemmin määrittelemämme muuttuja, joka
sisältää tietyn kokoisen fontin. Tämä funktio ottaa ensimmäiseksi argumentikseen tekstin, jonka haluamme
renderöidä. Ensimmäinen teksti on muotoa "pisteet: 0". Huomaa, miten merkkijonoon "pisteet: " voidaan
lisätä toinen merkkijono. Huomaa myös, että kokonaislukumuotoista muuttujaa score ei voi suoraan lisätä
merkkijonoon, vaan se täytyy muuntaa merkkijonoksi komennolla str()
. Renderöintifunktio ottaa toiseksi
argumentikseen totuusarvon, joka kertoo, haluatko pehmentää kirjainten reunoja. Tähän kannattaa yleensä
laittaa True
. Voit kokeilla laittaa toiseen kutsuun True ja toiseen False, jotta näet eron. Sitten
kolmanteen renderöintifunktion argumenttiin laitetaan fontin väri. fontColor
on siis muuttuja, jonka
määrittelimme alussa. Voit tehdä toisenkin muuttujan, jos haluat elämille ja pisteille eri värit.
Sitten kun olemme tallentaneet nämä renderöidyt tekstirivit muuttujiin, voimme piirtää ne ikkunaan.
Piirtäminen tapahtuu taas blit
-komennolla, joka ottaa argumentiksi piirrettävän tekstin, ja tekstin
sijainnin tuplena.
Nyt ikkunan vasemmassa yläkulmassa pitäisi näkyä elämät ja pisteet. Sitten kirjoitetaan koodi, joka muuttaa näitä.
Kirjoitetaan ensin funktio, joka tunnistaa, osuuko kivi leppikseen. On ehkä helpompi ajatella tätä siltä kannalta, että tunnistetaan milloin kivi ei osu leppikseen, ja jos mikään näistä ehdoista ei toteudu, niin sitten kivi varmaan osuu leppikseen.
Kivi ei osu leppikseen, jos sen oikea reuna on leppiksen vasemman reunan vasemmalla puolella.
Kivi ei osu leppikseen, jos sen vasen reuna on leppiksen oikean reunan oikealla puolella.
Kivi ei osu leppikseen, jos sen alareuna on leppiksen yläpuolella.
Muuten kivi osuu leppikseen.
Kirjoitetaan tämä funktioksi, joka ottaa argumentiksi listan, joka sisältää kiven koordinaatit:
def rock_hitting_leppis(rockCoords):
if rockCoords[0] > leppis_x + leppis_image.get_width() - 16:
return False
elif rockCoords[0] + rock_image.get_width() < leppis_x:
return False
elif rockCoords[1] + rock_image.get_height() < leppis_y:
return False
return True
Vähensin leppiksen leveyttä 16 pikselillä, jotta leppis ei menetä elämiä siitä, että kivet osuvat sen tuntosarviin.
Kirjoitetaan samanlainen funktio kolikoille:
def coin_hitting_leppis(coinCoords):
if coinCoords[0] > leppis_x + leppis_image.get_width():
return False
elif coinCoords[0] + coin_image.get_width() < leppis_x:
return False
elif coinCoords[1] + coin_image.get_height() < leppis_y:
return False
return True
Sitten käytetään näitä funktioita silmukoissa, jotka liikuttavat kiviä ja kolikoita. Eli silmukassa kiveä liikutetaan. Sitten jos kivi osuu maahan, niin kivi poistetaan listasta. Jos kivi ei osu maahan, niin tarkistetaan osuuko se leppikseen. Jos osuu, niin vähennetään yksi elämä ja lisätään kivi poistettavien listaan. Koko looppi näyttää tältä:
for rock_coords in rocks:
rock_coords[1] += gravity
if rock_coords[1] > ground_start_y - rock_image.get_height():
deleted_rocks.append(rock_coords)
elif rock_hitting_leppis(rock_coords):
lives -= 1
deleted_rocks.append(rock_coords)
Muokataan kolikoiden liikuttamissilmukkaa samalla tavalla, mutta jos kolikko osuu leppikseen, niin lisätään pisteisiin 10:
for coin_coords in coins:
coin_coords[1] += gravity
if coin_coords[1] > ground_start_y - coin_image.get_height():
deleted_coins.append(coin_coords)
elif coin_hitting_leppis(coin_coords):
score += 10
deleted_coins.append(coin_coords)
Nyt kun leppis osuu kiviin, niin elämät vähenevät, ja kun se osuu kolikoihin, niin pisteet kasvavat. Koko koodi näyttää tältä (lisäsin myös kommentteja selkeyttämään koodia, sinunkin kannattaa):
import pygame
import random
pygame.font.init()
font = pygame.font.SysFont(None, 30)
fontColor = (234,100,176)
window_width = 1000
window_height = 800
window = pygame.display.set_mode((window_width, window_height))
pygame.display.set_caption("Leppispeli")
fps = 60
clock = pygame.time.Clock()
white = (255, 255, 255)
ground_color = (171, 237, 130)
ground_start_y = 550
ground = pygame.Rect(0, ground_start_y, window_width, window_height - ground_start_y)
leppis_image = pygame.image.load("leppis.png")
leppis_x = 350
leppis_y = ground_start_y - leppis_image.get_height() + 12
leppis_speed = 7
lives = 10
score = 0
rock_image = pygame.image.load("rock.png")
coin_image = pygame.image.load("coin.png")
# get a random x coordinate for new rocks and coins
def random_x():
return random.randint(0, window_width - rock_image.get_width())
rocks = [ [random_x(), -50] ]
coins = [ [random_x(), -50] ]
gravity = 6
def rock_hitting_leppis(rockCoords):
if rockCoords[0] > leppis_x + leppis_image.get_width() - 16:
return False
elif rockCoords[0] + rock_image.get_width() < leppis_x:
return False
elif rockCoords[1] + rock_image.get_height() < leppis_y:
return False
return True
def coin_hitting_leppis(coinCoords):
if coinCoords[0] > leppis_x + leppis_image.get_width():
return False
elif coinCoords[0] + coin_image.get_width() < leppis_x:
return False
elif coinCoords[1] + coin_image.get_height() < leppis_y:
return False
return True
running = True
# do everything inside this loop 60 times a second
while running:
# limit fps
clock.tick(fps)
# handle input
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
pressed_keys = pygame.key.get_pressed()
if pressed_keys[pygame.K_LEFT] and leppis_x - leppis_speed > 0:
leppis_x = leppis_x - leppis_speed
right_boundary = window_width - leppis_image.get_width()
if pressed_keys[pygame.K_RIGHT] and leppis_x + leppis_speed < right_boundary:
leppis_x = leppis_x + leppis_speed
# make new rocks and coins
rand_num = random.randint(0,100)
if rand_num < 5:
rocks.append([random_x(), -50])
elif rand_num > 95:
coins.append([random_x(), -50])
# move rocks and coins
deleted_rocks = []
for rock_coords in rocks:
rock_coords[1] += gravity
if rock_coords[1] > ground_start_y - rock_image.get_height():
deleted_rocks.append(rock_coords)
elif rock_hitting_leppis(rock_coords):
lives -= 1
deleted_rocks.append(rock_coords)
for rock in deleted_rocks:
rocks.remove(rock)
deleted_coins = []
for coin_coords in coins:
coin_coords[1] += gravity
if coin_coords[1] > ground_start_y - coin_image.get_height():
deleted_coins.append(coin_coords)
elif coin_hitting_leppis(coin_coords):
score += 10
deleted_coins.append(coin_coords)
for coin in deleted_coins:
coins.remove(coin)
# draw white background, ground, and leppis
window.fill(white)
pygame.draw.rect(window, ground_color, ground)
window.blit(leppis_image, (leppis_x, leppis_y))
# draw rocks and coins
for rock_coords in rocks:
window.blit(rock_image, rock_coords)
for coin_coords in coins:
window.blit(coin_image, coin_coords)
# draw lives and score text
scoreText = font.render("pisteet: " + str(score), True, fontColor)
livesText = font.render("elämät: " + str(lives), True, fontColor)
window.blit(scoreText, (20,20))
window.blit(livesText, (20,60))
# show the new frame
pygame.display.update()