Páginas

domingo, 3 de março de 2013

skribu-kun-python-cxap18

fonto: http://inventwithpython.com/chapter18.html

Temoj Kovritaj En tiu ĉapitro:

  • Kolizio Detección
  • Ne Modifu a Listo Dum ripetanta Over It
  • Klavaro Eniro en Pygame
  • Muso Eniro en Pygame
Tre komuna konduto en plej grafikaj ludoj estas kolizio detekto. Kolizio detekto estas decidi kiam du aĵoj en la ekrano tuŝis (tio estas, karambolis kun) alia. Tiu estas uzata tre ofte en komputilaj ludoj. Ekzemple, se la ludanto tuŝas malamiko ili povas perdi sano aŭ ludo vivo. Aŭ ni volas scii kiam la ludanto tuŝis moneron por ke ili aŭtomate repreni ĝin. Kolizio detekto povas helpi determini se la ludo karaktero staras sur solida tero, aŭ se ne estas nenio sed malplena aero sub ili. En niaj ludoj, kolizio detekto estas determini se du rektanguloj estas parte kovranta reciproke aŭ ne. Nia sekva ekzemplo programo kovros tiu baza tekniko.
Poste en ĉi tiu ĉapitro, ni rigardu kiel nian Pygame programoj povas akcepti enigon el la uzanto tra la klavaro kaj la muso. Estas iom pli komplika ol nomi la enigo () funkcio kiel ni faris por nia teksto programoj. Sed uzante la klavaron estas multe pli interaga en GUI programoj, kaj uzante la muso estas eĉ ebla en nia teksto ludoj. Sciante tiujn du konceptojn faros niaj ludoj pli progresintaj kaj ekscita!

La Collision Detection Programo de Fonta Kodo

Granda parto de tiu kodo estas simila al la kuraĝigo programo, tiel ke ni salti super klarigante kiel fari la bouncer movado kaj rebotar ekstere de la muroj. (Vidu la kuraĝigo programo en la antaŭa ĉapitro por klarigo de tiu kodo.) Ni uzos listo de pygame.Rect objektoj por reprezenti la manĝo kvadratoj. Ĉiu pygame.Rect objekto en la listo reprezentas sola nutraĵo kvadrato. Sur ĉiu ripeto tra la ludo buklo, nia programo legos ĉiun pygame.Rect objekto en la liston kaj desegni verda kvadrato sur la fenestro. Ĉiu kvardek iteraciones tra la ludo buklo ni aldonos novajn pygame.Rect al la listo por ke la ekrano senĉese havas novajn manĝo kvadratoj en ĝi.
La bouncer estas reprezentita de vortaro. La vortaro havas ŝlosilon nomita 'rect' (kies valoro estas pygame.Rect objekto) kaj ŝlosila nomita 'dir' (kies valoro estas unu el la konstanta direkto variabloj samkiel ni havis en lasta ĉapitro de Kuraĝigo programo). Kiel la bouncer rebota ĉirkaŭ la fenestro, ni kontrolu ĉu ĝi koliziis kun iu el la nutraĵo kvadratoj. Se jes, ni forviŝi ke nutraĵo kvadrata por ke ĝi ne plu esti desegnita sur la ekrano.
Tajpu la sekvan en nova dosiero kaj konservi ĝin kiel collisionDetection.py. Se vi ne volas tajpi ĉio ĉi kodon, vi povas elŝuti la fonto de la libro de afiŝinto ĉe http://inventwithpython.com/chapter18 .
collisionDetection.py
Tiu kodo estas elŝutebla el http://inventwithpython.com/collisionDetection.py
Se vi ricevas erarojn post tajpi tiun kodon en, kompari ĝin al la libro kodo kun la linio malsamoj ilo en http://inventwithpython.com/diff aŭ retpoŝtu la aŭtoro en al@inventwithpython.com
  1. importado pygame, sys, hazarda
  2. el pygame.locals importado *

  3. def doRectsOverlap (rect1, rect2):
  4. por a, b en [(rect1, rect2), (rect2, rect1)]:
  5. # Kontroli se la anguloj estas ene b
  6. se ((isPointInsideRect (a.left, a.top, b)) aŭ
  7. (IsPointInsideRect (a.left, a.bottom, b)) aŭ
  8. (IsPointInsideRect (a.right, a.top, b)) aŭ
  9. (IsPointInsideRect (a.right, a.bottom, b))):
  10. revenu Vera

  11. revenu Falsaj

  12. def isPointInsideRect (x, y, rect):
  13. if (x> rect.left) kaj (x <rect.right) kaj (y> rect.top) kaj (y <rect.bottom):
  14. revenu Vera
  15. alie:
  16. revenu Falsaj


  17. # Starigis pygame
  18. pygame.init ()
  19. mainClock = pygame.time.Clock ()

  20. # Starigis la fenestro
  21. WINDOWWIDTH = 400
  22. WINDOWHEIGHT = 400
  23. windowSurface = pygame.display.set_mode ((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
  24. pygame.display.set_caption ('Collision Detection')

  25. # Starigis direkto variabloj
  26. DOWNLEFT = 1
  27. DOWNRIGHT = 3
  28. UPLEFT = 7
  29. Piuloj = 9

  30. MOVESPEED = 4

  31. # Starigis la koloroj
  32. NIGRA = (0, 0, 0)
  33. VERDA = (0, 255, 0)
  34. WHITE = (255, 255, 255)

  35. # Starigis bouncer kaj manĝo datumstrukturoj
  36. foodCounter = 0
  37. NEWFOOD = 40
  38. FOODSIZE = 20
  39. bouncer = {'rect': pygame.Rect (300, 100, 50, 50), 'dir': UPLEFT}
  40. nutraĵoj = []
  41. por i en gamo (20):
  42. foods.append (pygame.Rect (random.randint (0, WINDOWWIDTH - FOODSIZE), random.randint (0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE))

  43. # Ruli la ludon buklo
  44. dum Vera:
  45. # Kontroli por la quit okazaĵo
  46. por evento en pygame.event.get ():
  47. se event.type == QUIT:
  48. pygame.quit ()
  49. sys.exit ()

  50. foodCounter + = 1
  51. se foodCounter> = NEWFOOD:
  52. # Aldoni novajn manĝo
  53. foodCounter = 0
  54. foods.append (pygame.Rect (random.randint (0, WINDOWWIDTH - FOODSIZE), random.randint (0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE))

  55. # Desegni la nigra fono sur la surfaco
  56. windowSurface.fill (BLACK)

  57. # Movi la bouncer datumstrukturo
  58. se bouncer ['dir'] == DOWNLEFT:
  59. bouncer ['rect']. maldekstra - = MOVESPEED
  60. bouncer ['rect']. supro + = MOVESPEED
  61. se bouncer ['dir'] == DOWNRIGHT:
  62. bouncer ['rect']. maldekstra + = MOVESPEED
  63. bouncer ['rect']. supro + = MOVESPEED
  64. se bouncer ['dir'] == UPLEFT:
  65. bouncer ['rect']. maldekstra - = MOVESPEED
  66. bouncer ['rect']. supro - = MOVESPEED
  67. se bouncer ['dir'] == virtuloj:
  68. bouncer ['rect']. maldekstra + = MOVESPEED
  69. bouncer ['rect']. supro - = MOVESPEED

  70. # Kontrolu se la bouncer estas movi tra la fenestro
  71. se bouncer ['rect']. supro <0:
  72. # Bouncer movis preter la supro
  73. se bouncer ['dir'] == UPLEFT:
  74. bouncer ['dir'] = DOWNLEFT
  75. se bouncer ['dir'] == virtuloj:
  76. bouncer ['dir'] = DOWNRIGHT
  77. se bouncer ['rect']. fundo> WINDOWHEIGHT:
  78. # Bouncer movis preter la malsupro
  79. se bouncer ['dir'] == DOWNLEFT:
  80. bouncer ['dir'] = UPLEFT
  81. se bouncer ['dir'] == DOWNRIGHT:
  82. bouncer ['dir'] = honesta
  83. se bouncer ['rect']. lasis <0:
  84. # Bouncer movis preter la maldekstra flanko
  85. se bouncer ['dir'] == DOWNLEFT:
  86. bouncer ['dir'] = DOWNRIGHT
  87. se bouncer ['dir'] == UPLEFT:
  88. bouncer ['dir'] = honesta
  89. se bouncer ['rect']. dekstra> WINDOWWIDTH:
  90. # Bouncer movis preter la dekstra flanko
  91. se bouncer ['dir'] == DOWNRIGHT:
  92. bouncer ['dir'] = DOWNLEFT
  93. se bouncer ['dir'] == virtuloj:
  94. bouncer ['dir'] = UPLEFT

  95. # Desegni la bouncer sur la surfaco
  96. pygame.draw.rect (windowSurface, BLANKA, bouncer ['rect'])

  97. # Kontrolu se la bouncer havas intersecan kun ajna manĝo kvadratoj.
  98. por manĝo en nutraĵoj [:]:
  99. se doRectsOverlap (bouncer ['rect'], nutraĵo):
  100. foods.remove (manĝo)

  101. # Desegni la manĝo
  102. por i en gamo (len (nutraĵoj)):
  103. pygame.draw.rect (windowSurface, VERDA, nutraĵoj [i])

  104. # Desegni la fenestro sur la ekrano
  105. pygame.display.update ()
  106. mainClock.tick (40)
Kiam vi kuros ĉi tiu kodo, ĉi tiu estas kion la programo aspektas. La blanka kvadrato (la bouncer) estos rebotar ĉirkaŭ la fenestro, kaj kiam koliziis kun la verdaj kvadratoj (la manĝo) malaperos el la ekrano.

Figuro 18-1: La Collision Detection programo.

Importi la Moduloj

  1. importado pygame, sys, hazarda
  2. el pygame.locals importado *
La kolizio detekto programo importas la sama aĵoj kiel la Animation programo en la lasta ĉapitro, kune kun la hazarda modulo.

La Collision Detection Funkcio

  1. def doRectsOverlap (rect1, rect2):
Por fari kolizio detekto, ni bezonos funkcio kiu povas determini se du rektanguloj sekci unu la alian aŭ ne. Jen foto de sekcanta rektanguloj (maldekstre) kaj ortanguloj kiu ne sekci (dekstre):

Figuro 18-2: Ekzemploj de sekcanta rektanguloj (maldekstre) kaj ortanguloj kiu ne sekci (dekstre).
Ni faros sola funkcio kiu estas pasita du pygame.Rect celoj. La funkcio, doRectsOverlap (), revenos True se ili faras kaj Falsa se ​​ili ne estas.
Estas tre simpla regulo oni povas sekvi por determini se rektanguloj sekci (tio estas, kolizias). Rigardu ĉiu el la kvar anguloj sur ambaŭ rektanguloj. Se almenaŭ unu el tiuj ok anguloj estas ene de la aliaj ortangulo, tiam ni scias ke la du rektanguloj esti karambolis. Ni uzos tiun fakton por determini se doRectsOverlap () redonas VeraFalsa.
  1. por a, b en [(rect1, rect2), (rect2, rect1)]:
  2. # Kontroli se la anguloj estas ene b
  3. se ((isPointInsideRect (a.left, a.top, b)) aŭ
  4. (IsPointInsideRect (a.left, a.bottom, b)) aŭ
  5. (IsPointInsideRect (a.right, a.top, b)) aŭ
  6. (IsPointInsideRect (a.right, a.bottom, b))):
  7. revenu Vera
Supre estas la kodo kiu kontrolas se unu rektangulo de anguloj estas ene alia. Poste ni kreos funkcio nomita isPointInsideRect () kiu redonas True se la XY kunordigas de la punkto estas ene de la rektangulo. Ni nomas tiun funkcion por ĉiu de la ok anguloj, kaj se iu el tiuj alvokoj reveni Vera, la operatoroj faros la tuta kondiĉo Vera.
La parametroj por doRectsOverlap () estas rect1 kaj rect2. Ni unue volas kontroli ĉu rect1-ejon anguloj estas ene rect2 kaj poste kontrolu ĉu rect2-ejon anguloj estas en rect1.
Ni ne volas ripeti la kodo kiu kontrolas la kvar anguloj por ambaŭ rect1 kaj rect2, do anstataŭe ni uzi a kaj b en linioj 7 al 10. La por buklo sur linio 5 uzas la multnombraj asigno lertaĵo por ke je la unua ripeto, a estas aro al rect1 kaj b estas agordita por rect2. Sur la dua iteracio tra la ciklo, ĝi estas la malo. A estas aro al rect2 kaj b estas agordita por rect1.
Ni tion faras ĉar tiam ni nur devas tajpi la kodon por la se komunikaĵo linio 7 unufoje. Tiu estas bona, ĉar tio estas tre longa se aserto. La malpli kodo ni devas tajpi por nia programo, des pli bone.
  1. revenu Falsaj
Se ni neniam revenos Vera de la antaŭa se deklaroj, tiam neniu el la ok anguloj ni kontrolis estas en la alia rektangulo. En tiu kazo, la rektanguloj ne kolizias kaj ni revenos False.

Determini se Punkto estas Ene de ortangulo

  1. def isPointInsideRect (x, y, rect):
  2. if (x> rect.left) kaj (x <rect.right) kaj (y> rect.top) kaj (y <rect.bottom):
  3. revenu Vera
La isPointInsideRect () funkcio estas uzita de la doRectsOverlap () funkcio. IsPointInsideRect () revenos True se la XY koordinatoj pasis ĝin kiel la unua kaj dua parametroj estas lokitaj "ene" la pygame.Rect celo kiu pasis kiel la tria parametro . Alie, ĉi tiu funkcio False.
Figuro 18-3 estas ekzemplo bildo de rektangulo kaj pluraj punktoj. La punktoj kaj la anguloj de la ortangulo estas etikedita kun koordinatoj.
La mastro, ke punktoj ene ortangulo havas estas X-koordinato, kiu estas pli granda ol la X-koordinato de la maldekstra flanko kaj malpli ol la X-koordinato de la dekstra flanko, kaj Y-koordinato, kiu estas pli granda ol la Y-koordinato de la supro flanko kaj malpli ol la Y-koordinato de la fundo flanko. Se iu el tiuj kondiĉoj estas falsa, do la punkto estas ekster la rektangulo.
Ni kombini ĉiujn kvar de tiuj kondiĉoj en la se aserto estas kondiĉo kun kaj operatoroj ĉar ĉiuj kvar de la kondiĉoj devas esti vera.

Figuro 18-3: Ekzemplo de koordinatoj ene kaj ekstere
de rektangulo. La (50, 30), (85, 30) kaj (50, 50) punktoj
estas ene de la rektangulo, kaj ĉiuj aliaj estas ekstere.
  1. alie:
  2. revenu Falsaj
Se nur unu el la kvar esprimoj en la kondiĉo sur linio 16 estas Falsa, tiam ni devus isPointInsideRect () redonas la valoron False.
Ĉi tiu funkcio estos nomita de la doRectsOverlap () funkcion por vidi se iu el la anguloj en la du pygame.Rect celoj estas ene de ĉiu alia. Ĉi tiuj du funkcioj donos al ni la povon por fari kolizio detekto inter du rektanguloj.

La pygame.time.Clock Objekto kaj tick () Metodo

Multe da linioj 22 al 43 faru la samon ke Animation programo en la lasta ĉapitro faris: pravalorizi la Pygame biblioteko, turnu WINDOWHEIGHT kaj WINDOWWIDTH, kaj kunmetis la koloro kaj direkto konstantoj. Tamen, linio 24 estas nova:
  1. mainClock = pygame.time.Clock ()
En la antaŭa Animation programo, ni havis alvokon al time.sleep (0.02) ene de la ludo buklo por prokrasti la programo sufiĉas por ke ni povis vidi la blokoj moviĝas. La problemo kun ĉi tiu estas ke la programo povu kuri tro rapide sur rapidaj komputiloj kaj tro malrapida en malrapidaj komputiloj. Ni volas limigi la maksimuma nombro de ripetoj, ripetas tra la ludo buklo estas por dua.
Al pygame.time.Clock objekto povas fari tion por ni. Vi povas vidi sur linio 125, ke ni nomas mainClock.tick (40) ene la ludo buklo. Tiu alvoko al la Horloĝo objekto tick () metodo kontrolos se ni ripetita tra la ludo buklo pli ol 40 fojojn en la lasta sekundo. Se jes, ĝi metas mallonga dormo en la programo por ni bazita sur ofte tik () estas nomata. Tio certigas, ke la ludo neniam kuras pli rapide ol ni atendis. Certe nomi tick () nur unufoje en la ludo buklo.

Lancxi vian La Fenestro kaj Datumoj Strukturoj

  1. pygame.display.set_caption ('Collision Detection')

  2. # Starigis bouncer kaj manĝo datumstrukturoj
  3. foodCounter = 0
  4. NEWFOOD = 40
  5. FOODSIZE = 20
Ni tuj starigis kelkajn variabloj por la manĝo blokoj kiuj aperas sur la ekrano. FoodCounter komencos je la valoro 0, NEWFOOD je 40, kaj FOODSIZE je 20.
  1. bouncer = {'rect': pygame.Rect (300, 100, 50, 50), 'dir': UPLEFT}
Ni tuj starigis novan datumstrukturo nomata bouncer. Bouncer estas vortaro kun du klavoj. La valoro stokita en la 'rect' klavo estos pygame.Rect objekto kiu reprezentas la bouncer la grandeco kaj pozicio. La valoro stokita en la 'dir' klavo estos direkto kiun la bouncer estas nun moviĝas. La bouncer movos la sama maniero la blokoj faris en nia antaŭa kuraĝigo programo: movante en diagonala direktoj kaj _bouncing_ for de la flankoj de la fenestro.
  1. nutraĵoj = []
  2. por i en gamo (20):
  3. foods.append (pygame.Rect (random.randint (0, WINDOWWIDTH - FOODSIZE), random.randint (0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE))
Nia programo konservos spuro de ĉiu manĝaĵo kvadrato kun listo de pygame.Rect objektoj nomitaj nutraĵoj. Je la komenco de la programo, ni volas krei dudek manĝo kvadratoj hazarde metis ĉirkaŭ la ekrano. Ni povas uzi la random.randint () funkcio veni supren kun hazarda XY koordinatoj.

Figuro 18-4: Por 20 por 20 ortangulo, havante la supro forlasis
angulo ĉe (400, 200) en 400 por 400 fenestro metus
la rektangulo ekster la fenestro. Esti ene, la
supre maldekstre angulo devus esti je (380, 200) anstataŭe.
On line 52, nomos la pygame.Rect () konstruilo funkcio reveni nova pygame.Rect objekto kiu reprezentos la pozicio kaj grandeco de la manĝo kvadrato. La unuaj du parametrojn por pygame.Rect () estas la XY koordinatoj de la supro maldekstro angulo. Ni volas ke la hazarda koordinato esti inter 0 kaj la grandecon de la fenestro minus la grandeco de la manĝo kvadrato. Se ni havis la hazarda koordinato inter 0 kaj la grandeco de la fenestro, tiam la manĝaĵo kvadrata povus esti pelita ekstere de la fenestro en aro. Ekzemple, vidu la diagramon en Figuro 18-4.
La kvadrato maldekstre havas X-koordinato de gxia supro maldekstra angulo en 380. Ĉar la nutraĵo kvadrato estas 20 rastrumeroj larĝa, la dekstra rando de la manĝo kvadrato estas ĉe 400. (Ĉi tiu estas ĉar 380 + 20 = 400). La kvadrato sur la dekstra an X-koordinato de lia supro maldekstra angulo en 400. Ĉar la nutraĵo kvadrato estas 20 rastrumeroj larĝa, la dekstra rando de la manĝo kvadrato estas ĉe 420, kiu metas en la tuta placo ekstere de la fenestro (kaj ne videblas por la uzanto).
La tria parametro por pygame.Rect () estas opo kiu enhavas la largxeco kaj alteco de la manĝo kvadrato. Tiel la larĝeco kaj alteco estos egala al la valoro en la FOODSIZE konstanto.

Desegno la Bouncer sur la ekrano

Linioj 71 al 109 kaŭzi la bouncer movi ĉirkaŭ la fenestro kaj rebotar off de la randoj de la fenestro. Tiu kodo estas tre simila al linioj 44 al 83 de nia kuraĝigo programo en la lasta ĉapitro, do ni ne iros sur ili denove tie.
  1. # Desegni la bouncer sur la surfaco
  2. pygame.draw.rect (windowSurface, BLANKA, bouncer ['rect'])
Post kopii la bouncer, ni nun volas desegni ĝin sur la fenestro en lia nova pozicio. Ni nomas la pygame.draw.rect () funkcion por desegni rektangulo. La windowSurface pasis por la unua parametro rakontas la komputilo kiu pygame.Surface objekto por desegni la rektangulo plu. La WHITE variablo, kiu havas (255, 255, 255) stokitaj en ĝi, diros la komputilon por desegni blanka ortangulo. La pygame.Rect objekto stokitaj en la bouncer vortaro ĉe la 'rect' klavo rakontas la pozicio kaj grandeco de la rektangulo desegni. Jen ĉiuj informoj necesaj por desegni blanka ortangulo sur windowSurface.
Memoru, ni ne faris lotadon aĵoj sur la windowSurface objekto ankoraŭ. Ni ankoraŭ bezonas por desegni verda kvadrato por ĉiu manĝo kvadrato en la nutraĵoj listo. Kaj ni nur "desegni" rektanguloj sur la windowSurface objekto, ne sur la ekrano. Ĉi pygame.Surface objekto estas nur ene de la komputilo memoro, kiu estas multe pli rapida modifi ol la rastrumeroj sur la ekrano. La fenestro sur la ekrano ne estos ĝisdatigita ĝis ni nomas la pygame.display.update () funkcio.

Karamboli kun la Food Squares

  1. # Kontrolu se la bouncer havas intersecan kun ajna manĝo kvadratoj.
  2. por manĝo en nutraĵoj [:]:
Antaŭ ol ni desegni la manĝo kvadratoj, ni volas vidi, ĉu la bouncer havas solapan iu el la nutraĵo kvadratoj. Se ĝi havas, ni forigos ke nutraĵo kvadrato de la nutraĵoj listo. Tiamaniere, la komputilo ne desegni ajna manĝo kvadratoj kiuj la bouncer estas "manĝata".
Sur ĉiu ripeto tra la por ciklo, la nuna manĝo kvadrato de la nutraĵoj (pluralo) listo estos stokitaj ene variablo nomata manĝo (unuopa).

Ne Aldoni al aŭ Forigu el Listo dum ripetanta Over It

Rimarku, ke ekzistas io iomete malsama kun ĉi por buklo. Se vi rigardas atente ĉe linio 116, ni ne ripetanta super nutraĵojn sed fakte sur nutraĵoj [:]. Ĝuste kiel nutraĵoj [: 2] revenus kopion de la listo kun la artikoloj de la komenco kaj ĝis (sed ne inkludita) la artikolon en indekso 2, kaj ĝuste kiam nutraĵoj [3:] revenus kopion de la listo kun la artikoloj de indekso 3 al la fino de la listo, nutraĵoj [:] donos al vi kopion de la listo kun la artikoloj de la komenco ĝis la fino. Esence, nutraĵoj [:] kreas novan liston kun kopio de ĉiuj la artikoloj en la nutraĵoj. (Ĉi tiu estas pli mallonga maniero kopii liston ol nia getBoardCopy () funkcio en la Tic Tac Toe ludo.)
Kial ni volas persisti super kopion de la listo anstataŭ la listo mem? Estas ĉar ni ne povas aldoni aŭ forigi elementojn el listo dum ni ripetanta super ĝi. Pitono povas perdi spuro de kio la venonta valoro de nutraĵoj variablo devus esti se la grandeco de la nutraĵoj listo estas ĉiam ŝanĝas. Pensu pri kiel malfacile estus por vi se vi provus kalkulu la numeron de jelly fazeoloj en poto dum iu estis aldonante aŭ forigi ĵeleo faboj. Sed se ni persisti super kopion de la listo (kaj la kopio neniam ŝanĝas), tiam adicianta aŭ forigi erojn el la originala listo ne estos problemo.

Forigante la Manĝo Squares

  1. se doRectsOverlap (bouncer ['rect'], nutraĵo):
  2. foods.remove (manĝo)
Linio 116 estas kie nia doRectsOverlap () funkcio kiu ni difinis pli frue venas en oportuna. Ni pasos du pygame.Rect celoj por doRectsOverlap (): la bouncer kaj la aktuala manĝo kvadrato. Se tiuj du rektanguloj interkovriĝas, tiam doRectsOverlap () revenos Vera kaj ni forigos la solapando manĝo kvadratoj de nutraĵoj listo.

Desegno la Food Squares sur la ekrano

  1. # Desegni la manĝo
  2. por i en gamo (len (nutraĵoj)):
  3. pygame.draw.rect (windowSurface, VERDA, nutraĵoj [i])
La kodo de la linioj 120 kaj 121 estas tre simila al kiel ni tiris la blanka kvadrato por la ludanto. Ni faros buklo tra ĉiu manĝo kvadrataj en la nutraĵoj listo, kaj tiam tiri la rektangulo sur la windowSurface surfaco. Ĉi tiu pruvo de kolizio detekto estas sufiĉe facila. Tiu programo estis tre simila al nia _bouncing_ programo en la antaŭa ĉapitro, krom nun la _bouncing_ kvadrato estos "manĝi" la alia kvadratoj kiel ĝi pasas super ili.
Tiuj lastaj programoj estas interese spekti, sed la uzanto ne ricevas por fakte kontroli nenion. En ĉi sekva programo, ni lernos kiel akiri enigo de la klavaro. Klavaro enigo estas manipulita en Pygame uzante okazaĵoj.

La Klavaro Eniro Programo de Fonta Kodo

Komencu novan dosieron kaj tajpu la sekvajn kodo, tiam konservi ĝin kiel pygameInput.py.
pygameInput.py
Tiu kodo estas elŝutebla el http://inventwithpython.com/pygameInput.py
Se vi ricevas erarojn post tajpi tiun kodon en, kompari ĝin al la libro kodo kun la linio malsamoj ilo en http://inventwithpython.com/diff aŭ retpoŝtu la aŭtoro en al@inventwithpython.com
  1. importado pygame, sys, hazarda
  2. el pygame.locals importado *

  3. # Starigis pygame
  4. pygame.init ()
  5. mainClock = pygame.time.Clock ()

  6. # Starigis la fenestro
  7. WINDOWWIDTH = 400
  8. WINDOWHEIGHT = 400
  9. windowSurface = pygame.display.set_mode ((WINDOWWIDTH, WINDOWHEIGHT), 0, 32)
  10. pygame.display.set_caption ('Enigo')

  11. # Starigis la koloroj
  12. NIGRA = (0, 0, 0)
  13. VERDA = (0, 255, 0)
  14. WHITE = (255, 255, 255)

  15. # Starigis la ludanto kaj manĝo datumstrukturo
  16. foodCounter = 0
  17. NEWFOOD = 40
  18. FOODSIZE = 20
  19. ludanto = pygame.Rect (300, 100, 50, 50)
  20. nutraĵoj = []
  21. por i en gamo (20):
  22. foods.append (pygame.Rect (random.randint (0, WINDOWWIDTH - FOODSIZE), random.randint (0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE))

  23. # Starigis movadon variabloj
  24. moveLeft = False
  25. moveRight = False
  26. moveUp = False
  27. moveDown = False

  28. MOVESPEED = 6


  29. # Ruli la ludon buklo
  30. dum Vera:
  31. # Kontroli por eventoj
  32. por evento en pygame.event.get ():
  33. se event.type == QUIT:
  34. pygame.quit ()
  35. sys.exit ()
  36. se event.type == KEYDOWN:
  37. # Ŝanĝi la klavaron variabloj
  38. se event.key == K_LEFT aŭ event.key == Ord ('a'):
  39. moveRight = False
  40. moveLeft = True
  41. se event.key == K_RIGHT aŭ event.key == Ord ('d'):
  42. moveLeft = False
  43. moveRight = True
  44. se event.key == K_UP aŭ event.key == Ord ('w'):
  45. moveDown = False
  46. moveUp = True
  47. se event.key == K_DOWN aŭ event.key == Ord ('s'):
  48. moveUp = False
  49. moveDown = True
  50. se event.type == KEYUP:
  51. se event.key == K_ESCAPE:
  52. pygame.quit ()
  53. sys.exit ()
  54. se event.key == K_LEFT aŭ event.key == Ord ('a'):
  55. moveLeft = False
  56. se event.key == K_RIGHT aŭ event.key == Ord ('d'):
  57. moveRight = False
  58. se event.key == K_UP aŭ event.key == Ord ('w'):
  59. moveUp = False
  60. se event.key == K_DOWN aŭ event.key == Ord ('s'):
  61. moveDown = False
  62. se event.key == Ord ('x'):
  63. player.top = random.randint (0, WINDOWHEIGHT - player.height)
  64. player.left = random.randint (0, WINDOWWIDTH - player.width)

  65. se event.type == MOUSEBUTTONUP:
  66. foods.append (pygame.Rect (event.pos [0], event.pos [1], FOODSIZE, FOODSIZE))

  67. foodCounter + = 1
  68. se foodCounter> = NEWFOOD:
  69. # Aldoni novajn manĝo
  70. foodCounter = 0
  71. foods.append (pygame.Rect (random.randint (0, WINDOWWIDTH - FOODSIZE), random.randint (0, WINDOWHEIGHT - FOODSIZE), FOODSIZE, FOODSIZE))

  72. # Desegni la nigra fono sur la surfaco
  73. windowSurface.fill (BLACK)

  74. # Movi la ludanto
  75. se moveDown kaj player.bottom <WINDOWHEIGHT:
  76. player.top + = MOVESPEED
  77. se moveUp kaj player.top> 0:
  78. player.top - = MOVESPEED
  79. se moveLeft kaj player.left> 0:
  80. player.left - = MOVESPEED
  81. se moveRight kaj player.right <WINDOWWIDTH:
  82. player.right + = MOVESPEED

  83. # Desegni la ludanto sur la surfaco
  84. pygame.draw.rect (windowSurface, BLANKA, ludanto)

  85. # Kontrolu se la ludanto intersecan kun ajna manĝo kvadratoj.
  86. por manĝo en nutraĵoj [:]:
  87. se player.colliderect (manĝaĵo):
  88. foods.remove (manĝo)

  89. # Desegni la manĝo
  90. por i en gamo (len (nutraĵoj)):
  91. pygame.draw.rect (windowSurface, VERDA, nutraĵoj [i])

  92. # Desegni la fenestro sur la ekrano
  93. pygame.display.update ()
  94. mainClock.tick (40)
Ĉi tiu programo aspektas identa al la kolizio detekto programo pli frue en ĉi tiu ĉapitro. Sed en tiu programo, la bouncer nur movas ĉirkaŭ kiam ni premadu klavoj sur la klavaro. Premante la "W" klavo movas la bouncer supren. La "A" klavo movas la bouncer al la maldekstra kaj la "D" klavo movas la bouncer al dekstre. La "S" klavo movas la bouncer sube. Vi ankaŭ povas movi la bouncer per tenas la sagoklavoj sur la klavaro. La uzanto povas ankaŭ uzi la klavaron de sagoklavoj.
Ni povas ankaŭ klaku ie ajn en la GUI fenestro kaj krei novajn manĝo objektoj ĉe la koordinatoj kie ni klakis. Krome, la ESC klavo estos quit la programo kaj la "X" ŝlosilo estos teletransportarse la bouncer al hazarda loko sur la ekrano.

Lancxi vian La Fenestro kaj Datumoj Strukturoj

Unue, ni starigis la apudskribo de la fenestro la titolon trinkejo al la ĉeno por 'muso' on line 12. Ni starigis la apudskribo de la fenestro kun alvoko al pygame.display.set_caption () la sama maniero kiel ni faris en nia antaŭa Pygame programoj. Ni tuj volas starigi kelkajn variabloj kiuj spuri la movadon de la bouncer.
  1. # Starigis movadon variabloj
  2. moveLeft = False
  3. moveRight = False
  4. moveUp = False
  5. moveDown = False
Ni tuj uzos kvar malsamaj Bulea variablo por kontroli kiu faras kion el la sagoklavoj estas tenis malsupren. Ekzemple, kiam la uzanto pelas la maldekstra sago ŝlosilon sur ŝia klavaro, ni starigos la moveLeft variablo al True. Kiam ŝi lasas iri de la ŝlosilo, ni starigos la moveLeft variablo reen al False. La "W" ŝlosilo tuŝas la moveUp variablo, la "S" ŝlosilo tuŝas la moveDown variablo, kaj la "D" ŝlosilo tuŝas la moveRight variablo en simila maniero.
Linioj 34 al 43 estas identaj al kodon en la antaŭa Pygame programoj. Tiuj linioj manipuli la komenco de la ludo buklo kaj uzado, kion fari, kiam la uzanto volas lasi la programon. Ni preteriru la ekspliko por ĉi tiu kodo tie kiel ni jam kovris ĝin en la lasta ĉapitro.

Okazaĵoj kaj Uzado la KEYDOWN Eventon

Tabelo 18-1: Eventoj, kaj kio kaŭzas ilin esti generita.
Okazaĵo Priskribo
QUIT Generita kiam la uzanto fermas kun fenestro.
KEYDOWN Generita kiam la uzanto premitan ŝlosilo. Havas ŝlosilon atributo kiu rakontas kion ŝlosilo estis premita. Havas ankaŭ mod atributo kiu rakontas se la Shift, Ktrl, Alt, aŭ aliaj klavoj estis tenataj malsupren kiam ĉi ŝlosilo estis premita.
KEYUP Generita kiam la uzanto liberigas ŝlosilo. Havas ŝlosilon kaj mod atributo kiu estas simila al tiuj por KEYDOWN.
MOUSEMOTION Generita ĉiufoje kiam la muso moviĝas super la fenestro. Havas post atributo kiu revenas opo (x, y) por la koordinatojn de kie la muso estas en la fenestro. La rel atributo ankaŭ redonas (x, y) opo, sed donas kunordigas parenco de la lasta MOUSEMOTION evento. Ekzemple, se la muso movas lasita de kvar rastrumeroj el (200, 200) por (196, 200), tiam rel estos (-4, 0). La butonoj atributo revenas opo de tri entjeroj. La unua entjero en la opo estas por la maldekstra musbutono, la dua entjera por la mezan musbutonon (se estas meza musbutono), kaj la tria entjero estas por la dekstra musbutono. Tiuj entjeroj estos 0 se ili ne estas premita suben kiam la muso kopiis kaj 1, se ili premis malsupren.
MOUSEBUTTONDOWN Generita kiam musbutono estas premita suben en la fenestron. Tiu okazaĵo havas post atributo kiu estas (x, y) opo por la koordinatojn de kie la muso estis kiam la butono estis premita. Ankaŭ estas butono atributo kiu estas entjero de 1 al 5 kiu diras kion musbutonon estis premita:
Valoro de butono Muso Buton
1 Maldekstra butono
2 Meza butono
3 Dekstra butono
4 Ruluma rado movis supren
5 Ruluma rado kopiis malsupren
MOUSEBUTTONUP Generita kiam la musbutono estas liberigita. Ĉi tio havas la samajn atributojn kiel MOUSEBUTTONDOWN
La kodo por manipuli la ŝlosilo gazetaro kaj ŝlosilo ĵeto eventoj estas pli sube. Sed en la komenco de la programo, ni starigos ĉiu el ĉi tiuj variabloj al False.
  1. se event.type == KEYDOWN:
Pygame havas alian okazaĵon tipo nomita KEYDOWN. On line 41, ni kontrolu ĉu la event.type atributo estas egala al la QUIT valoro por kontroli se ni devus eliri de la programo. Sed estas aliaj eventoj kiuj Pygame povas generi. Mallonga listo de la okazaĵoj kiuj povus revenis por pygame.event.get () estas en tabelo 18-1.

Lancxi la Kvar Klavaro Variabloj

  1. # Ŝanĝi la klavaron variabloj
  2. se event.key == K_LEFT aŭ event.key == Ord ('a'):
  3. moveRight = False
  4. moveLeft = True
  5. se event.key == K_RIGHT aŭ event.key == Ord ('d'):
  6. moveLeft = False
  7. moveRight = True
  8. se event.key == K_UP aŭ event.key == Ord ('w'):
  9. moveDown = False
  10. moveUp = True
  11. se event.key == K_DOWN aŭ event.key == Ord ('s'):
  12. moveUp = False
  13. moveDown = True
Se la evento tipo estas KEYDOWN, tiam la okazaĵo objekto havos ŝlosilo atributo kiu diros al ni kion ŝlosilo estis premita suben. On line 46, ni povas kompari ĉi tiun valoron al K_LEFT, kiu reprezentas la maldekstra sago klavo de la klavaro. Ni faros tion por cxiu el la sagoklavoj: K_LEFT, K_RIGHT, K_UP, K_DOWN.
Kiam unu el tiuj klavoj estas premita suben, ni starigos la responda movado variablo al True. Ni eliris en la movado variablo de la kontraŭa direkto al False. Ekzemple, la programo ekzekutas linioj 47 kaj 48 kiam la maldekstra sago ŝlosilo estis premata. En ĉi tiu kazo, ni aro moveLeft al Vera kaj moveRight al False (kvankam moveRight povus jam esti Falsa, ni starigis gxin al falsa nur por esti certa).
Vi eble rimarkos ke sur linio 46, en event.key povas ĉu esti egala al K_LEFTOrd ('a'). La valoron en event.key estas agordita por la entjera ASCII valoro de la ŝlosilo kiu estis premita sur la klavaro. (Ne estas Askio valoro por la sagoklavoj, tial ni uzas la konstanta variablo K_LEFT.) Vi povas uzi la Ord () funkcion por atingi la ASCII valoro de ajna unuopa signo kompari ĝin kun event.key.
Por ekzekuti la kodon de la linioj 47 kaj 48 se la klavofrapo estis aŭ K_LEFTOrd ('a'), ni faras la maldekstra sago ŝlosilo kaj la Kerna fari la samon. Vi eble rimarkos ke la W, A, S, kaj D klavoj estas ĉiuj uzataj kiel alterna por ŝanĝi la movado variabloj. Ĉi tiu estas ĉar iuj personoj povas voli uzi sian maldekstran manon por premi la WASD klavoj anstataŭ ilia dekstra mano premas la sagoklavoj. Nia programo proponas ilin ambaŭ!

Uzado la KEYUP Eventon

  1. se event.type == KEYUP:
Kiam la uzanto liberigas la ŝlosilo kiu ili tenas, a KEYUP okazaĵo estas generita.
  1. se event.key == K_ESCAPE:
  2. pygame.quit ()
  3. sys.exit ()
Se la ŝlosilon kiun la uzanto liberigis estis la Esk ŝlosilo, do ni volas nuligi la programo. Memoru, en Pygame vi devas alvoki pygame.quit () funkcio antaux nomante la sys.exit () funkcio. Ni volas fari ĉi tion kiam la uzanto liberigas la Esk ŝlosilo, ne kiam ili unue Esk ŝlosilo sube.
Linioj 62 al 69 starigos movado variablo al falsa se ​​tiu direkto la ŝlosilo estis lasita.
  1. se event.key == K_LEFT aŭ event.key == Ord ('a'):
  2. moveLeft = False
  3. se event.key == K_RIGHT aŭ event.key == Ord ('d'):
  4. moveRight = False
  5. se event.key == K_UP aŭ event.key == Ord ('w'):
  6. moveUp = False
  7. se event.key == K_DOWN aŭ event.key == Ord ('s'):
  8. moveDown = False

Teleporting la Ludanto

Se la uzanto liberigis unu el la klavoj kiuj movas la ludanto, kaj poste ni volas establi la movado variablo kiu korespondas kun la ŝlosilo al False. Ĉi diros la postaj partoj de nia programo por ne plu movi la ludanto kvadrato sur la ekrano.
  1. se event.key == Ord ('x'):
  2. player.top = random.randint (0, WINDOWHEIGHT - player.height)
  3. player.left = random.randint (0, WINDOWWIDTH - player.width)
Ni ankaŭ aldonos teletransportación al nia ludo. Se la uzanto premas la "X" ŝlosilo, poste ni metos la pozicio de la uzanto kvadrato al hazarda loko sur la fenestro. Tio donas al la uzanto la kapablo transporti ĉirkaŭ la fenestro puŝante "X" ŝlosilo (kvankam ili ne povas kontroli kie ili teletransportarse: ĝi estas tute hazarda).

Uzado la MOUSEBUTTONUP Eventon

  1. se event.type == MOUSEBUTTONUP:
  2. foods.append (pygame.Rect (event.pos [0], event.pos [1], FOODSIZE, FOODSIZE))
Muso enigo estas manipulita de eventoj samkiel klavaro enigo estas. La MOUSEBUTTONUP evento okazas kiam la uzanto klakoj a musbutono ie en nia fenestro, kaj liberigas la musbutonon. La post atributo en la Eventon objekto estas agordita por opo de du entjeroj por la XY koordinatoj. On line 75, la X-koordinato estas stokita en event.pos [0] kaj la Y-koordinato estas stokita en event.pos [1]. Ni kreos novan Rect objekto por reprezenti novajn manĝo kaj meti ĝin kie la MOUSEBUTTONUP evento okazis. Por aldoni novan Rect celo al la nutraĵoj listo, nova manĝo kvadrato estos montrata en la ekrano.

Movante la Bouncer Ĉirkaŭ la ekrano

  1. # Movi la ludanto
  2. se moveDown kaj player.bottom <WINDOWHEIGHT:
  3. player.top + = MOVESPEED
  4. se moveUp kaj player.top> 0:
  5. player.top - = MOVESPEED
  6. se moveLeft kaj player.left> 0:
  7. player.left - = MOVESPEED
  8. se moveRight kaj player.right <WINDOWWIDTH:
  9. player.right + = MOVESPEED
Ni starigis la movado variabloj (moveDown, moveUp, moveLeft, kaj moveRight) por VeraFalsa depende kion klavoj la uzanto premas. Nun ni reale movi la ludanto kvadrato (kiu estas reprezentita de la pygame.Rect objekto stokitaj en ludanto) ĉirkaŭ modifu la XY kunordigas de ludanto. Se moveDown estas agordita por Vera (kaj la fundo de la ludanto kvadrato estas ne sub la fundo rando de la fenestro), tiam ni movas la ludanto kvadrata sube por aldonante MOVESPEED al la ludanto nuna supro atributo. Ni faras la samon por la aliaj tri direktoj ankaŭ.

La colliderect () metodo

    
# Kontrolu se la ludanto intersecan with ajna tenilo kvadratoj.
    
Por tenilo eo nutraĵoj [:]:
    
se player.colliderect (manĝaĵo):
    
foods.remove (tenilo)
Eo Nia antaŭa Collision Detection programo, nek havis Nian propran funkcion Por kontroli se la oni ortangulo estis karambolis with aliaj aĵoj. Tiu funkcio estis inkludita eo CI tiu libro, Por Ke vidis povus kompreni Kiel la Kodo malantaŭ kolizio detekto funkcias. Eo CI tiu programo, nek povas Uzi la kolizio detekto funkcio kiu venas with Pygame. La colliderect () metodon por pygame.Rect celoj estas pasita alia pygame.Rect objekto kiel argumento kaj redonas True se la du rektanguloj kolizias kaj Falsa se ili ne estas. Ĉi tio estas la ĝusta sama konduto kiel la doRectsOverlap () funkcion en nia antaŭa Collision Detection programo.

    
mainClock.tick (40)
La resto de la kodo estas simila al la kodon en la Eniro programo estas simila al la pli frua Collision Detection programo: desegni la manĝo kvadratoj kaj la ludanto kvadratoj al la windowSurface surfaco, foje aldoni novan manĝaĵon kvadrato ĉe hazarda loko por la nutraĵoj listo , kontrolu se la ludanto placo karambolis kun iu el la nutraĵo kvadratoj, kaj nomas mainClock.tick (40) fari la programon funkcii en taŭga rapido.Resumo: Collision Detection kaj Pygame Eniro
Ĉi tiu ĉapitro enkondukis la koncepton de kolizio detekto, kiu estas uzita en plej grafikaj ludoj. Detekti kolizioj inter du rektanguloj estas facila: ni simple kontroli ĉu la kvar anguloj de ĉu rektangulo estas ene de la aliaj rektangulo. Tiu estas tia komuna afero por kontroli por tiu Pygame havigas ĝia propra kolizio detekto metodo nomata colliderect () por pygame.Rect celoj.
La unuaj kelkaj ludoj de ĉi tiu libro estis teksto bazita. La programo eligo estis teksto presita al la ekrano kaj la eniro estis teksto tajpita de la uzanto sur la klavaro. Sed GUI programoj povas akcepti klavaro kaj muso enigoj. Plue, GUI programoj povas respondi al simpla keystrokes kiam la uzanto pelas malsupren aŭ supren lasas sola ŝlosilo. La uzanto ne devas tajpi en tuta respondo kaj premas Ret. Ĉi tiu permesas por tuja sugestoj kiam la ludanto premas malsupren ajna klavo de la klavaro kaj multe pli interaga ludoj.
La Pygame programoj ni montris ĝis nun nomis la rektanguloj, linioj, cirkloj, kaj eĉ individuo rastrumeroj al la ekrano. Tiuj estas nomataj desegnante primitivoj. Sed ni ankaŭ volas uzi fotojn kaj bildojn anstataŭ simpla desegno primitivoj. La venonta ĉapitro diros al vi kiom ŝarĝi bildojn kaj desegni ilin sur la ekrano. Ni ankaŭ lerni kiel ludi sonoj kaj muziko por la ludanto aŭdi.
 

Nenhum comentário:

Postar um comentário