Händelser
Hittills har våra huvudloopar bara kört förutbestämda animationer och reagerat på händelser av typen pygame.QUIT
, trots att loopen får en lista över alla händelser från operativsystemet. Låt oss nu ta itu med några andra typer av händelser.
Hantering av händelser
Det här programmet skriver ut information om alla händelser som skickas från operativsystemet till programmet pygame, medan det körs:
import pygame
pygame.init()
fonster = pygame.display.set_mode((640, 480))
while True:
for handelse in pygame.event.get():
print(handelse)
if handelse.type == pygame.QUIT:
exit()
Låt oss anta att programmet kördes ett tag och att man sedan klickade på avslutningsknappen. Programmet skriver ut följande information:
<Event(4-MouseMotion {'pos': (495, 274), 'rel': (495, 274), 'buttons': (0, 0, 0), 'window': None})>
<Event(4-MouseMotion {'pos': (494, 274), 'rel': (-1, 0), 'buttons': (0, 0, 0), 'window': None})>
<Event(4-MouseMotion {'pos': (492, 274), 'rel': (-2, 0), 'buttons': (0, 0, 0), 'window': None})>
<Event(4-MouseMotion {'pos': (491, 274), 'rel': (-1, 0), 'buttons': (0, 0, 0), 'window': None})>
<Event(5-MouseButtonDown {'pos': (491, 274), 'button': 1, 'window': None})>
<Event(6-MouseButtonUp {'pos': (491, 274), 'button': 1, 'window': None})>
<Event(2-KeyDown {'unicode': 'a', 'key': 97, 'mod': 0, 'scancode': 38, 'window': None})>
<Event(3-KeyUp {'key': 97, 'mod': 0, 'scancode': 38, 'window': None})>
<Event(2-KeyDown {'unicode': 'b', 'key': 98, 'mod': 0, 'scancode': 56, 'window': None})>
<Event(3-KeyUp {'key': 98, 'mod': 0, 'scancode': 56, 'window': None})>
<Event(2-KeyDown {'unicode': 'c', 'key': 99, 'mod': 0, 'scancode': 54, 'window': None})>
<Event(3-KeyUp {'key': 99, 'mod': 0, 'scancode': 54, 'window': None})>
<Event(12-Quit {})>
De första händelserna gäller musanvändningen, därefter kommer några händelser från tangentbordet och slutligen stänger den sista händelsen programmet. Varje händelse har åtminstone en typ, men de kan också innehålla annan identifierande information, till exempel var muspekaren befinner sig eller vilken tangent som trycktes in.
Du kan leta efter händelsebeskrivningar i pygame-dokumentationen, men det kan ibland vara enklare att skriva ut händelser med koden ovan och leta efter den händelse som inträffar när något du vill reagera på händer.
Tangentbordshändelser
Detta program kan behandla händelser där användaren trycker på piltangenten antingen till höger eller till vänster på sitt tangentbord. Programmet skriver ut vilken tangent som trycktes in.
import pygame
pygame.init()
fonster = pygame.display.set_mode((640, 480))
while True:
for handelse in pygame.event.get():
if handelse.type == pygame.KEYDOWN:
if handelse.key == pygame.K_LEFT:
print("vänster")
if handelse.key == pygame.K_RIGHT:
print("höger")
if handelse.type == pygame.QUIT:
exit()
Konstanterna pygame.K_LEFT
och pygame.K_RIGHT
avser piltangenterna till vänster och höger. Konstanterna för pygame-tangenterna för de olika tangenterna på ett tangentbord anges i Pygame dokumentationen.
Om användaren t.ex. trycker på piltangenten till höger två gånger, sedan den vänstra en gång och sedan den högra en gång till, skriver programmet ut
höger
höger
vänster
höger
Vi har nu alla verktyg som behövs för att flytta en karaktär, eller sprite, på skärmen till höger och vänster med piltangenterna. Följande kod kommer att uppnå detta:
import pygame
pygame.init()
fonster = pygame.display.set_mode((640, 480))
robot = pygame.image.load("robot.png")
x = 0
y = 480-robot.get_height()
while True:
for handelse in pygame.event.get():
if handelse.type == pygame.KEYDOWN:
if handelse.key == pygame.K_LEFT:
x -= 10
if handelse.key == pygame.K_RIGHT:
x += 10
if handelse.type == pygame.QUIT:
exit()
fonster.fill((0, 0, 0))
fonster.blit(robot, (x, y))
pygame.display.flip()
Beroende på hur du använder piltangenterna kunde programmet köra på följande sätt:
I koden ovan har vi variablerna x
och y
som innehåller sprite-koordinaterna. Variabeln y
är inställd så att spriten visas längst ned i fönstret. Värdet för y
ändras inte under hela körningen av programmet. x
-värdet ökar däremot med 10 när användaren trycker på piltangenten till höger och minskar med 10 när användaren trycker på piltangenten till vänster.
Programmet fungerar i övrigt ganska bra, men tangenten måste tryckas in igen varje gång vi vill förflytta oss igen. Det skulle vara bättre om rörelsen var kontinuerlig när tangenten hölls nedtryckt. Följande program erbjuder denna funktionalitet:
import pygame
pygame.init()
fonster = pygame.display.set_mode((640, 480))
robot = pygame.image.load("robot.png")
x = 0
y = 480-robot.get_height()
hoger = False
vanster = False
klocka = pygame.time.Clock()
while True:
for handelse in pygame.event.get():
if handelse.type == pygame.KEYDOWN:
if handelse.key == pygame.K_LEFT:
vanster = True
if handelse.key == pygame.K_RIGHT:
hoger = True
if handelse.type == pygame.KEYUP:
if handelse.key == pygame.K_LEFT:
vanster = False
if handelse.key == pygame.K_RIGHT:
hoger = False
if handelse.type == pygame.QUIT:
exit()
if hoger:
x += 2
if vanster:
x -= 2
fonster.fill((0, 0, 0))
fonster.blit(robot, (x, y))
pygame.display.flip()
klocka.tick(60)
Koden innehåller nu variablerna hoger
och vanster
. Dessa innehåller vetskap om huruvida spriten ska röra sig åt höger eller vänster vid ett givet tillfälle. När användaren trycker ner en piltangent blir värdet som lagras i den relevanta variabeln True
. När tangenten släpps ändras värdet till False
.
Klockan används för att tidsbestämma spritens rörelser, så att de potentiellt sker 60 gånger per sekund. Om en piltangent trycks ned förflyttas spriten två pixlar åt höger eller vänster. Detta innebär att spriten rör sig 120 pixlar per sekund om tangenten hålls nedtryckt.
Händelser med musen
Följande kod reagerar på händelser där en musknapp trycks ned medan markören befinner sig inom fönsterområdet:
import pygame
pygame.init()
fonster = pygame.display.set_mode((640, 480))
while True:
for handelse in pygame.event.get():
if handelse.type == pygame.MOUSEBUTTONDOWN:
print("du tryckte knappen", handelse.button, "på lokationen", handelse.pos)
if handelse.type == pygame.QUIT:
exit()
Exekveringen av detta program borde mer eller mindre se ut så här:
du tryckte knappen 1 på lokationen (82, 135)
du tryckte knappen 1 på lokationen (369, 135)
du tryckte knappen 1 på lokationen (269, 297)
du tryckte knappen 3 på lokationen (515, 324)
Knapp nummer 1 avser vänster musknapp och knapp nummer 3 avser höger musknapp.
Nästa program kombinerar hantering av mushändelser och ritning av en bild på skärmen. När användaren trycker på en musknapp medan muspekaren befinner sig inom fönstrets gränser ritas en bild av en robot på den platsen.
import pygame
pygame.init()
fonster = pygame.display.set_mode((640, 480))
robot = pygame.image.load("robot.png")
while True:
for handelse in pygame.event.get():
if handelse.type == pygame.MOUSEBUTTONDOWN:
x = handelse.pos[0]-robot.get_width()/2
y = handelse.pos[1]-robot.get_height()/2
fonster.fill((0, 0, 0))
fonster.blit(robot, (x, y))
pygame.display.flip()
if handelse.type == pygame.QUIT:
exit()
Exekveringen av programmet borde se ut så här:
Följande program innehåller en animation där robotspriten följer muspekaren. Spritens position lagras i variablerna robot_x
och robot_y
. När musen rör sig lagras dess position i variablerna mal_x
och mal_y
. Om roboten inte befinner sig på denna plats förflyttar den sig i lämplig riktning.
import pygame
pygame.init()
fonster = pygame.display.set_mode((640, 480))
robot = pygame.image.load("robot.png")
robot_x = 0
robot_y = 0
mal_x = 0
mal_y = 0
klocka = pygame.time.Clock()
while True:
for handelse in pygame.event.get():
if handelse.type == pygame.MOUSEMOTION:
mal_x = handelse.pos[0]-robot.get_width()/2
mal_y = handelse.pos[1]-robot.get_height()/2
if handelse.type == pygame.QUIT:
exit(0)
if robot_x > mal_x:
robot_x -= 1
if robot_x < mal_x:
robot_x += 1
if robot_y > mal_y:
robot_y -= 1
if robot_y < mal_y:
robot_y += 1
fonster.fill((0, 0, 0))
fonster.blit(robot, (robot_x, robot_y))
pygame.display.flip()
klocka.tick(60)
Exekveringen av programmet borde se ut så här:
Se dina poäng genom att klicka på cirkeln nere till höger av sidan.