Vi kan även införa logik i spelet. Beroende på vad som händer i spelet, ska något nytt hända!
I föregående avsnitt visade vi hur man kan skapa en game-loop för att skapa basen för ett spel i pygame. Vi har även visat hur man kan använda piltangenterna för att styra spelaren. Nu behövs lite logik i spelet. Vi ska programmera en fallande vägg med ett hål i. Målet är att styra spelaren igenom hålet. Om man nuddar väggen, får man game-over. Vi ska även lägga till en räknare, som håller reda på hur många hål vi passerat. Vi utgår från koden som vi skapat i tidigare avsnitt:
# 1 - Import library import pygame from pygame.locals import * # 2 - Initialize the game pygame.init() pygame.font.init() # you have to call this at the start, # if you want to use this module. width, height = 64*10, 64*8 screen=pygame.display.set_mode((width, height)) player_x = 200 player_y = 200 keys = [False, False, False, False] # 3 - Load images player = pygame.image.load("hero.png") # 4 - keep looping through while 1: # 5 - clear the screen before drawing it again screen.fill((255,255,255)) # 6 - draw the screen elements screen.blit(player, (player_x, player_y)) # 7 - update the screen pygame.display.flip() # 8 - loop through the events for event in pygame.event.get(): # check if the event is the X button if event.type == pygame.QUIT: # if it is quit the game pygame.quit() exit(0) if event.type == pygame.KEYDOWN: if event.key==K_UP: keys[0]=True elif event.key==K_LEFT: keys[1]=True elif event.key==K_DOWN: keys[2]=True elif event.key==K_RIGHT: keys[3]=True if event.type == pygame.KEYUP: if event.key==pygame.K_UP: keys[0]=False elif event.key==pygame.K_LEFT: keys[1]=False elif event.key==pygame.K_DOWN: keys[2]=False elif event.key==pygame.K_RIGHT: keys[3]=False # Updatera y-positionen if keys[0]: # Om uppåtknappen är intryckt if player_y > 0: # Om koordinaten är större än 0 (ej utanför spelplanen) player_y -= 15 # Ändra y-positionen med 15 pixlar. Spelaren åker uppåt elif keys[2]: # Om nedåttangenten är intryckt if player_y < height-64: # Om koodinaten är mindre än höjden på spelplanen (ej utanför spelplanen) player_y += 15 # Ändra y-positionen med 15 pixlar. Spelaren åker nedåt if keys[1]: # Om vänster tangent är nedtryckt if player_x > 0: # Om spelaren är innanför spelplanen player_x -= 15 # Minska positionen i x-led. Spelaren åker vänster elif keys[3]: # Om höger tangent är nedtryckt if player_x < width-64: # Om spelaren är innanför spelplanen player_x += 15 # Öka positionen i x-led. Spelaren åker höger
Vi laddar in en bild som är 64 x 64 pixlar stor. Detta är en ruta i spelet.
Eftersom spelet är 10 x 64 pixlar bred, vet vi att det får plats 10 väggblock på spelplanen. Därför skapar vi 8 objekt av wall, vilket innebär att hålet blir två rutor bred.
def wall_render(rand, wall_y): # Rand är ett random heltal mellan 0-9 for i in range(0, 10): # Loopa 10 gånger if not (i == rand or i == rand + 1): # Rita inte på två efterföljande random rutor screen.blit(wall, (i*64, wall_y)) # Rita ut blocket på rätt position
Koden ovan kommer rita ut ett block på åtta platser på samma höjd, med 64 pixlar mellan varje ruta. Det kommer bli ett hål som är två rutor stort.
Gör så att väggen faller genom att öka wall_y som hanterar y-positionen på väggen. När väggen har fallit hela vägen till botten av spelplanen, börjar den om från toppen igen.
def wall_handler(wall_y, rand, nmbr_of_walls, wall_speed): wall_y += wall_speed # Öka y-positionen för väggen. Väggen "faller" if wall_y > height: # Om väggen har åkt hela vägen ner i botten, börja om från toppen wall_y = -64 # Hela väggen är i toppen av spelet rand = randint(0,8) # Slumpa ett heltal mellan 0 och 8. Hålet kommer på en ny plats nmbr_of_walls += 1 # Håll räkningen hur många väggar man passerat wall_speed +=1 # Öka hastigheten på väggen # Returnera alla uppdateringar return wall_y, rand, nmbr_of_walls, wall_speed
Väggen faller nu neråt hela tiden och hålet kommer bytas varje gång väggen har kommit till marken.
Om spelaren åker in i väggen får vi game-over. Vi kollar om spelarens position krockar med väggen med följande kod:
def collide(player_x, player_y, wall_y, rand_wall): if (player_y >= wall_y and player_y <= wall_y + 64) and\ ((player_x > 0 and player_x <= rand_wall*64) or (player_x > (rand_wall+1)*64 and player_x < width+64)): return True else: return False
Om spelarens x- och y-koordinat är innanför väggens koordinater så returneras True, annars False.
Vi kan blanda mellan meny-läge och spel-läge med variabeln is_game. Om man trycker på Enter i meny-läget, startas ett nytt spel.
while 1: if not is_game: screen.fill((255,255,255)) # Rita ut en vit spelplan textsurface = myfont.render("Press enter to start", False, (0, 0, 0)) # Skapa en textrad screen.blit(textsurface,(180, 200)) # Rita ut textraden på en viss position pygame.display.flip() # Uppdatera spelplanen for event in pygame.event.get(): # Undersök alla event - Exempelvis knapptryckningar if event.type == pygame.QUIT: # Om man kryssar ner spelplanen pygame.quit() # Avsluta spelet exit(0) # Stäng av programmet if event.type == pygame.KEYDOWN: # Kolla om en tangent trycks ner if event.key==K_RETURN: # Om Enter trycks ner, uppdatera alla variablet player_x = 256 # Startposition i x-led för spelaren player_y = 440 # Startposition i y-led för spelaren wall_y = -64 # Sätt väggen i toppen av spelplanen rand_wall = randint(0,8) # Slumpa ett nytt hål nmbr_of_walls = 0 # Sätt antal klarade väggar till 0 keys = [False, False, False, False] # Nollställ alla knapptryck wall_speed = 2 # Sätt en starthastighet is_game = True # Starta spelet
Slutligen skapar vi en räknare som håller koll på hur många väggar vi har passerat:
textsurface = myfont.render(str(nmbr_of_walls), False, (0, 0, 0)) screen.blit(textsurface,(10, 0))
Där nmbr_of_walls är antal passerade väggar som uppdateras i funktionen wall_handler.
Spelet är nu klart! All kod hittar du nedan! Testa själv!
# 1 - Import library import pygame from pygame.locals import * from random import randint # 2 - Initialize the game pygame.init() pygame.font.init() # you have to call this at the start, # if you want to use this module. myfont = pygame.font.SysFont('Comic Sans MS', 30) width, height = 64*10, 64*8 screen=pygame.display.set_mode((width, height)) player_x = 256 player_y = 440 keys = [False, False, False, False] wall_y = -64 rand_wall = randint(0,8) nmbr_of_walls = 0 wall_speed = 2 is_game = False # 3 - Load images player = pygame.image.load("hero.png") wall = pygame.image.load("wall.png") def wall_render(rand, wall_y): # Rand är ett random heltal mellan 0-9 for i in range(0, 10): # Loopa 10 gånger if not (i == rand or i == rand + 1): # Rita inte på två efterföljande random rutor screen.blit(wall, (i*64, wall_y)) # Rita ut blocket på rätt position def wall_handler(wall_y, rand, nmbr_of_walls, wall_speed): wall_y += wall_speed # Öka y-positionen för väggen. Väggen "faller" if wall_y > height: # Om väggen har åkt hela vägen ner i botten, börja om från toppen wall_y = -64 # Hela väggen är i toppen av spelet rand = randint(0,8) # Slumpa ett heltal mellan 0 och 8. Hålet kommer på en ny plats nmbr_of_walls += 1 # Håll räkningen hur många väggar man passerat wall_speed +=1 # Öka hastigheten på väggen # Returnera alla uppdateringar return wall_y, rand, nmbr_of_walls, wall_speed def collide(player_x, player_y, wall_y, rand_wall): if (player_y >= wall_y and player_y <= wall_y + 64) and\ ((player_x > 0 and player_x <= rand_wall*64) or (player_x > (rand_wall+1)*64 and player_x < width+64)): return True else: return False # 4 - keep looping through while 1: if not is_game: screen.fill((255,255,255)) # Rita ut en vit spelplan textsurface = myfont.render("Press enter to start", False, (0, 0, 0)) # Skapa en textrad screen.blit(textsurface,(180, 200)) # Rita ut textraden på en viss position pygame.display.flip() # Uppdatera spelplanen for event in pygame.event.get(): # Undersök alla event - Exempelvis knapptryckningar if event.type == pygame.QUIT: # Om man kryssar ner spelplanen pygame.quit() # Avsluta spelet exit(0) # Stäng av programmet if event.type == pygame.KEYDOWN: # Kolla om en tangent trycks ner if event.key==K_RETURN: # Om Enter trycks ner, uppdatera alla variablet player_x = 256 # Startposition i x-led för spelaren player_y = 440 # Startposition i y-led för spelaren wall_y = -64 # Sätt väggen i toppen av spelplanen rand_wall = randint(0,8) # Slumpa ett nytt hål nmbr_of_walls = 0 # Sätt antal klarade väggar till 0 keys = [False, False, False, False] # Nollställ alla knapptryck wall_speed = 2 # Sätt en starthastighet is_game = True # Starta spelet else: # 5 - clear the screen before drawing it again screen.fill((255,255,255)) # 6 - draw the screen elements screen.blit(player, (player_x, player_y)) textsurface = myfont.render(str(nmbr_of_walls), False, (0, 0, 0)) screen.blit(textsurface,(10, 0)) wall_y, rand_wall, nmbr_of_walls, wall_speed = wall_handler(wall_y, rand_wall, nmbr_of_walls, wall_speed) wall_render(rand_wall, wall_y) if collide(player_x, player_y, wall_y, rand_wall): is_game = False # 7 - update the screen pygame.display.flip() # 8 - loop through the events for event in pygame.event.get(): # check if the event is the X button if event.type == pygame.QUIT: # if it is quit the game pygame.quit() exit(0) if event.type == pygame.KEYDOWN: if event.key==K_UP: keys[0]=True elif event.key==K_LEFT: keys[1]=True elif event.key==K_DOWN: keys[2]=True elif event.key==K_RIGHT: keys[3]=True if event.type == pygame.KEYUP: if event.key==pygame.K_UP: keys[0]=False elif event.key==pygame.K_LEFT: keys[1]=False elif event.key==pygame.K_DOWN: keys[2]=False elif event.key==pygame.K_RIGHT: keys[3]=False if keys[0]: if player_y > 0: player_y -= 15 elif keys[2]: if player_y < height-64: player_y += 15 if keys[1]: if player_x > 0: player_x -= 15 elif keys[3]: if player_x < width-64: player_x += 15