Python gyerekeknek - űrhajós játék - jönnek a szellemek!

Kategória: Python gyerekeknek.

Valósítsuk meg azt, hogy jönnek a szellemek! Ezt három lépésre osztjuk.

Függőlegesen jönnek a szellemek

Töltsük be szellem képét! Ezt az űrhajó képének betöltéséhez hasonlóan tudjuk megtenni, és az alá tehetjük: ghost_image = PhotoImage(file='ghost.png'). Képet vagy keressünk a neten, és méretezzük át, vagy használhatjuk az alábbit is.

ghost.png

Ahhoz, hogy a szellem egy véletlen helyről induljon, szükség lesz egy véletlen szám generátorra. Írjuk be a program elejére a következőt: import random

Egyszerre több szellemet fogunk látni. Ezt egy kell menteni egy listába. Ezt hozzuk létre globális változóként, az elején: ghosts = [].

Ha minden lépésben létre hoznánk egy újabb szellemet, akkor másodpercenként 500 jönne létre. Igazából elég csak minden századik lépésben végrehajtani. Emiatt létrehozunk egy számlálót, amit az elején kinullázunk (counter = 0), majd mindegyik lépésben növelünk (a play() függvény elején global counter, majd counter = counter + 1).

Ha épp a századik lépésnél tartunk, létrehozunk egy szellemet egy véletlen helyen felül, és beletesszük a szellemek listájába:

    if counter % 100 == 0:        
        ghost = canvas.create_image(random.randint(0, 480), 0, image=ghost_image)
        ghosts.append(ghost)

Mindegyik lépésben (tehát nemcsak minden századikban) végiglépkedünk a szellemeken ha még nem érte el az alját, akkor lefelé mozgatjuk, azaz növeljük az y koordinátát. Egyébként letöröljük a vászonról. A ghosts listából is ki kell törölni azokat a szellemeket, amelyeket a képernyőről töröltünk. Ehhez a "szellemes" ciklus előtt létrehozunk egy üres tömböt, majd miután az else ágban töröltök a szellemet a képernyőről, hozzáadjuk a listához. A ciklus után pedig egyesével kitöröljük. Ezek megvalósítása:

    if counter % 100 == 0:        
        ghost = canvas.create_image(random.randint(0, 480), 0, image=ghost_image)
        ghosts.append(ghost)
    deleted_ghosts = []
    for ghost in ghosts:
        ghost_coords = canvas.coords(ghost)
        if ghost_coords[1] < 360:
            canvas.move(ghost, 0, 1)
        else:
            canvas.delete(ghost)
            deleted_ghosts.append(ghost)
    for deleted_ghost in deleted_ghosts:
        ghosts.remove(deleted_ghost)

A program most úgy működik, hogy jönnek függőlegesen a szellemek:

urhajo_szellem.png

Átlósan is jönnek a szellemek

Módosítsuk a kódot úgy, hogy ne csak függőlegesen jöjjenek a szellemek! Az ötlet a következő: ahelyett, hogy csak a szellemet tároljuk, hozzunk létre egy olyan struktúrát, ami a szellem mellett tárolja annak irányát is. Az irány legyen véletlenszerű. Ehhez az apróságnak tűnő lépéshez egész sok mindent kell módosítani:

  • Miután létrehoztuk a szellemet (ghost = canvas.create_image(…)), határozzunk meg egy véletlen irányt: direction = random.randint(-2, 2).
  • Utána szótár formájában hozzunk létre egy szellem struktúrát (ghost_struct = {), melyhez hozzáadjuk a szellemet ('ghost': ghost,) és az irányt ('direction': direction,), majd lezárjuk a szótárat (}).
  • A következő sort, melyben elmentjük a szellemet, úgy módosítjuk, hogy a szellem struktúrát mentse el: ghosts.append(ghost)ghosts.append(ghost_struct).
  • Mivel most már a szellem struktúrákon lépkedünk végig, és nem a szellemeken, ennek megfelelően módosítjuk a ciklust for ghost in ghosts:for ghost_struct in ghosts:.
  • Utána a ciklusmagban lekérdezzük a struktúrából a szellemet: ghost = ghost_struct['ghost'].
  • Kiolvassuk a struktúrából az irányt is: direction = ghost_struct['direction'].
  • Most jön a lényeg: abban a sorban, amelyben mozgatjuk a szellemet, nem lefelé mozgatjuk, hanem az iránynak megfelelően: canvas.move(ghost, direction, 1)canvas.move(ghost, direction, 1).
  • A törölt szellemekhez nem magát a szellemet kell beletenni, hanem a szellem struktúrát: deleted_ghosts.append(ghost)deleted_ghosts.append(ghost_struct).

Minden irányban egyforma sebességgel jönnek a szellemek

A probléma a fentivel az, hogy aránytalan a szellemek sebessége különböző irányokba. Gondoljunk bele: ha függőlegesen halad, akkor egy lépésben 0 képpontnyit halad oldalra, és 1 képpontnyit lefelé, azaz összesen 1 képpontnyit. Ha viszont kettőt lép oldalra, akkor a Pitagorasz-tételt használva $\sqrt{1^2+2^2} = \sqrt{5} \approx 2,24$ lépést tesz meg, azaz több mint kétszeres sebességgel halad.

A szellemek mozgatását (canvas.move(ghost, direction, 1)) cseréljük le az alábbira:

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)

Ha az irány:

  • függőleges, akkor egyet lépünk lefelé, ahogy idáig is tettük.
  • nem függőleges, akkor - csökkentve az oldalirányú sebességet - elosztjuk hárommal. (Kikísérletezve így jött ki játszhatónak.)
  • 1 vagy -1: nagyon picit csökkentjük a lefelé irányt, hogy - a Pitagorasz tételt használva - körülbelül ugyanakkor legyen a szellem abszolút sebessége, mint amekkora a függőleges szellemé.
  • 2 vagy -2: kicsit jobban csökkentjük, hasonló okokból, mint fent.

Azt kaptuk tehát, hogy a szellemek látszólag össze-vissza röpködnek, egyenes pályán, kb. egyenletes sebességgel. Egyelőre még nem lesz "bajunk" attól, ha nekünk jön a szellem; itt folytatjuk a következő lépésben.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License