Python gyerekeknek - űrhajós játék - kellemetlen találkozás a szellemmel
Kategória: Python gyerekeknek.
A feladat
Az aktuális verzióban ha nekünk jön a szellem, akkor nem történik semmi. De az űrhajók élete nem csak játék és mese! Most megvalósítjuk azt, hogy ha összeütközünk egy szellemmel, akkor veszítsünk életet. Három életünk lesz összesen.
from tkinter import *
import random
counter = 0
rocketship_state = 'stand'
ghosts = []
def key_pressed(event):
global rocketship_state
if event.keysym == 'Left':
rocketship_state = 'left'
if event.keysym == 'Right':
rocketship_state = 'right'
def key_released(event):
global rocketship_state
if event.keysym in ['Left', 'Right']:
rocketship_state = 'stand'
def play():
global counter
counter = counter + 1
rocketship_coords = canvas.coords(rocketship)
if rocketship_state == 'left' and rocketship_coords[0] > 0:
canvas.move(rocketship, -1, 0)
if rocketship_state == 'right' and rocketship_coords[0] < 480:
canvas.move(rocketship, 1, 0)
if counter % 100 == 0:
ghost = canvas.create_image(random.randint(0, 480), 0, image=ghost_image)
direction = random.randint(-2, 2)
ghost_struct = {
'ghost': ghost,
'direction': direction,
}
ghosts.append(ghost_struct)
deleted_ghosts = []
for ghost_struct in ghosts:
ghost = ghost_struct['ghost']
direction = ghost_struct['direction']
ghost_coords = canvas.coords(ghost)
if ghost_coords[1] < 360:
if direction == 0:
canvas.move(ghost, 0, 1)
elif abs(direction) == 1:
canvas.move(ghost, direction/3, 0.95)
else:
canvas.move(ghost, direction/3, 0.75)
else:
canvas.delete(ghost)
deleted_ghosts.append(ghost_struct)
for deleted_ghost in deleted_ghosts:
ghosts.remove(deleted_ghost)
root.after(2, play)
root = Tk()
root.title('Űrhajós játék')
root.bind('<KeyPress>', key_pressed)
root.bind('<KeyRelease>', key_released)
root.after(2, play)
canvas = Canvas(root, width=480, height=360, bg='black')
canvas.pack()
rocketship_image = PhotoImage(file='rocketship.png')
rocketship = canvas.create_image(240, 310, image=rocketship_image)
ghost_image = PhotoImage(file='ghost.png')
root.mainloop()
Ütközés a szellemmel
A Scratch-ben van egy gyakran használt művelet: annak az ellenőrzése, hogy az aktuális szereplő érint-e egy másikat. Ennek a jelentőségét akkor értjük meg igazán, amikor valami hasonló funkcióra van szükségünk egy olyan környezetben, ahol ez nem áll alapból rendelkezésre; a legtöbb grafikus felület egyébként ilyen. Nekünk magunknak kell ezt megvalósítanunk, de leginkább csak arra tudunk hagyatkozni, hogy megvizsgáljuk a szereplők aktuális koordinátáit, és ha túl közel vannak, akkor ütközésnek minősítjük a dolgot. Némi kísérletezés után az jött ki, hogy ha az x és az y koordináta eltérése is legfeljebb 40, akkor azt ütközésnek minősíthetjük.
Hozzunk létre egy logikai változót, amivel azt jelöljük, hogy az aktuális vizsgálat során történt-t ütközés. A for ghost_struct in ghosts ciklus elé írjuk be a következőt: hit = False. A cikluson belül a végére, megfelelően behúzva, írjuk be a következő sorokat:
coord_diff_x = abs(ghost_coords[0] - rocketship_coords[0])
coord_diff_y = abs(ghost_coords[1] - rocketship_coords[1])
if coord_diff_x <= 40 and coord_diff_y <= 40:
hit = True
A végén pedig megvizsgáljuk, hogy történt-e ütközés. Ha igen, akkor kiírunk egy VÉGE feliratot, és a ciklust nem indítjuk újra. Ha nem, akkor újraindul a ciklus.
if hit:
canvas.create_text(240, 180, text='VÉGE', fill='yellow', font=('Helvetica', 50))
else:
root.after(2, play)
from tkinter import *
import random
counter = 0
rocketship_state = 'stand'
ghosts = []
def key_pressed(event):
global rocketship_state
if event.keysym == 'Left':
rocketship_state = 'left'
if event.keysym == 'Right':
rocketship_state = 'right'
def key_released(event):
global rocketship_state
if event.keysym in ['Left', 'Right']:
rocketship_state = 'stand'
def play():
global counter
counter = counter + 1
rocketship_coords = canvas.coords(rocketship)
if rocketship_state == 'left' and rocketship_coords[0] > 0:
canvas.move(rocketship, -1, 0)
if rocketship_state == 'right' and rocketship_coords[0] < 480:
canvas.move(rocketship, 1, 0)
if counter % 100 == 0:
ghost = canvas.create_image(random.randint(0, 480), 0, image=ghost_image)
direction = random.randint(-2, 2)
ghost_struct = {
'ghost': ghost,
'direction': direction,
}
ghosts.append(ghost_struct)
deleted_ghosts = []
hit = False
for ghost_struct in ghosts:
ghost = ghost_struct['ghost']
direction = ghost_struct['direction']
ghost_coords = canvas.coords(ghost)
if ghost_coords[1] < 360:
if direction == 0:
canvas.move(ghost, 0, 1)
elif abs(direction) == 1:
canvas.move(ghost, direction/3, 0.95)
else:
canvas.move(ghost, direction/3, 0.75)
else:
canvas.delete(ghost)
deleted_ghosts.append(ghost_struct)
coord_diff_x = abs(ghost_coords[0] - rocketship_coords[0])
coord_diff_y = abs(ghost_coords[1] - rocketship_coords[1])
if coord_diff_x <= 40 and coord_diff_y <= 40:
hit = True
for deleted_ghost in deleted_ghosts:
ghosts.remove(deleted_ghost)
if hit:
canvas.create_text(240, 180, text='VÉGE', fill='yellow', font=('Helvetica', 50))
else:
root.after(2, play)
root = Tk()
root.title('Űrhajós játék')
root.bind('<KeyPress>', key_pressed)
root.bind('<KeyRelease>', key_released)
root.after(2, play)
canvas = Canvas(root, width=480, height=360, bg='black')
canvas.pack()
rocketship_image = PhotoImage(file='rocketship.png')
rocketship = canvas.create_image(240, 310, image=rocketship_image)
ghost_image = PhotoImage(file='ghost.png')
root.mainloop()
Három élet
Ez így túl gyorsan véget ér; valósítsuk meg azt, hogy a játékosnak 3 élete legyen. Ha eltalálták, akkor csökkenjen az életeinek a száma, és tűnjenek el a szellemek. A VÉGE feliratot csak akkor jelenítse meg, ha a harmadik életét is elveszítette a játékos.
Az elején hozzunk létre egy változót, amiben az életeket tároljuk: lives = 3.
Mivel a fő ciklusban, tehát a play() függvényben ezt módosítani fogjuk, az elejére írjuk be ezt: global lives.
Amikor azt vizsgáljuk, hogy eltalált-e a szellem, azaz a hit = True sor alatt csökkentsük az életek számát; írjuk be ezt: lives = lives - 1.
Miután kitöröltük a ghosts-ból a szellemeket, valójában az összes megmaradtat ki kell törölni, a vászonról is és a ghosts tömbből is:
if hit:
for ghost_struct in ghosts:
canvas.delete(ghost_struct['ghost'])
ghosts.clear()
Csak akkor ér véget a játék, ha már elfogyott az életünk. A play() függvény vége felé az if hit feltételt cseréljük le erre: if lives <= 0. A biztonság kedvéért nem csak egyenlőség vizsgálatot teszünk bele, elvileg ugyanis előfordulhat, hogy egyszerre két szellem is eltalál, és ha pont egy életünk lenne, akkor a 0-t kihagyva negatívba fordulhatna.
from tkinter import *
import random
lives = 3
counter = 0
rocketship_state = 'stand'
ghosts = []
def key_pressed(event):
global rocketship_state
if event.keysym == 'Left':
rocketship_state = 'left'
if event.keysym == 'Right':
rocketship_state = 'right'
def key_released(event):
global rocketship_state
if event.keysym in ['Left', 'Right']:
rocketship_state = 'stand'
def play():
global counter
global lives
counter = counter + 1
rocketship_coords = canvas.coords(rocketship)
if rocketship_state == 'left' and rocketship_coords[0] > 0:
canvas.move(rocketship, -1, 0)
if rocketship_state == 'right' and rocketship_coords[0] < 480:
canvas.move(rocketship, 1, 0)
if counter % 100 == 0:
ghost = canvas.create_image(random.randint(0, 480), 0, image=ghost_image)
direction = random.randint(-2, 2)
ghost_struct = {
'ghost': ghost,
'direction': direction,
}
ghosts.append(ghost_struct)
deleted_ghosts = []
hit = False
for ghost_struct in ghosts:
ghost = ghost_struct['ghost']
direction = ghost_struct['direction']
ghost_coords = canvas.coords(ghost)
if ghost_coords[1] < 360:
if direction == 0:
canvas.move(ghost, 0, 1)
elif abs(direction) == 1:
canvas.move(ghost, direction/3, 0.95)
else:
canvas.move(ghost, direction/3, 0.75)
else:
canvas.delete(ghost)
deleted_ghosts.append(ghost_struct)
coord_diff_x = abs(ghost_coords[0] - rocketship_coords[0])
coord_diff_y = abs(ghost_coords[1] - rocketship_coords[1])
if coord_diff_x <= 40 and coord_diff_y <= 40:
hit = True
lives = lives - 1
for deleted_ghost in deleted_ghosts:
ghosts.remove(deleted_ghost)
if hit:
for ghost_struct in ghosts:
canvas.delete(ghost_struct['ghost'])
ghosts.clear()
if lives <= 0:
canvas.create_text(240, 180, text='VÉGE', fill='yellow', font=('Helvetica', 50))
else:
root.after(2, play)
root = Tk()
root.title('Űrhajós játék')
root.bind('<KeyPress>', key_pressed)
root.bind('<KeyRelease>', key_released)
root.after(2, play)
canvas = Canvas(root, width=480, height=360, bg='black')
canvas.pack()
rocketship_image = PhotoImage(file='rocketship.png')
rocketship = canvas.create_image(240, 310, image=rocketship_image)
ghost_image = PhotoImage(file='ghost.png')
root.mainloop()
Az életek számának kiírása
Most már rendesen működik a három élet, viszont nem tudjuk, hogy éppen mennyi van még hátra. A Scratchben ilyenkor - jobb híján - megjelenítettük az életek változó értékét. A Pythonban viszont van lehetőség arra, hogy ne csak vásznat jelenítsünk meg, hanem más vizuális elemet is. Ehhez hozzunk létre egy keretet (Frame), nevezzük el úgy, hogy info_frame (mást is megfogunk ott jeleníteni a későbbiekben), és arra tegyük rá a szükséges elemeket: egyrészt azt, hogy kiírja, hogy Életek száma:, másrészt a konkrét megmaradt életek számát. Mindezt valahova azt követően, hogy létre jött a root:
info_frame = Frame(root)
lives_str_label = Label(master=info_frame, text='Életek száma:')
lives_str_label.grid(column=0, row=0)
lives_nr_label = Label(master=info_frame, text=str(lives))
lives_nr_label.grid(column=1, row=0)
info_frame.pack()
Azon a ponton, ahol csökken az életek száma (lives = lives - 1), szúrjuk be ezt: lives_nr_label['text'] = str(lives). Most már látni fogjuk azt, hogy hány életünk van hátra.
from tkinter import *
import random
lives = 3
counter = 0
rocketship_state = 'stand'
ghosts = []
def key_pressed(event):
global rocketship_state
if event.keysym == 'Left':
rocketship_state = 'left'
if event.keysym == 'Right':
rocketship_state = 'right'
def key_released(event):
global rocketship_state
if event.keysym in ['Left', 'Right']:
rocketship_state = 'stand'
def play():
global counter
global lives
counter = counter + 1
rocketship_coords = canvas.coords(rocketship)
if rocketship_state == 'left' and rocketship_coords[0] > 0:
canvas.move(rocketship, -1, 0)
if rocketship_state == 'right' and rocketship_coords[0] < 480:
canvas.move(rocketship, 1, 0)
if counter % 100 == 0:
ghost = canvas.create_image(random.randint(0, 480), 0, image=ghost_image)
direction = random.randint(-2, 2)
ghost_struct = {
'ghost': ghost,
'direction': direction,
}
ghosts.append(ghost_struct)
deleted_ghosts = []
hit = False
for ghost_struct in ghosts:
ghost = ghost_struct['ghost']
direction = ghost_struct['direction']
ghost_coords = canvas.coords(ghost)
if ghost_coords[1] < 360:
if direction == 0:
canvas.move(ghost, 0, 1)
elif abs(direction) == 1:
canvas.move(ghost, direction/3, 0.95)
else:
canvas.move(ghost, direction/3, 0.75)
else:
canvas.delete(ghost)
deleted_ghosts.append(ghost_struct)
coord_diff_x = abs(ghost_coords[0] - rocketship_coords[0])
coord_diff_y = abs(ghost_coords[1] - rocketship_coords[1])
if coord_diff_x <= 40 and coord_diff_y <= 40:
hit = True
lives = lives - 1
lives_nr_label['text'] = str(lives)
for deleted_ghost in deleted_ghosts:
ghosts.remove(deleted_ghost)
if hit:
for ghost_struct in ghosts:
canvas.delete(ghost_struct['ghost'])
ghosts.clear()
if lives <= 0:
canvas.create_text(240, 180, text='VÉGE', fill='yellow', font=('Helvetica', 50))
else:
root.after(2, play)
root = Tk()
root.title('Űrhajós játék')
root.bind('<KeyPress>', key_pressed)
root.bind('<KeyRelease>', key_released)
root.after(2, play)
info_frame = Frame(root)
lives_str_label = Label(master=info_frame, text='Életek száma:')
lives_str_label.grid(column=0, row=0)
lives_nr_label = Label(master=info_frame, text=str(lives))
lives_nr_label.grid(column=1, row=0)
info_frame.pack()
canvas = Canvas(root, width=480, height=360, bg='black')
canvas.pack()
rocketship_image = PhotoImage(file='rocketship.png')
rocketship = canvas.create_image(240, 310, image=rocketship_image)
ghost_image = PhotoImage(file='ghost.png')
root.mainloop()