Skapa ett eget spel i Python med Pygame


Nyckelord: Pygame

PyGame är ett bibliotek i python som innehåller bland annat funktioner för att skapa datorgrafik och ljud.

I denna artikel går vi igenom steg för steg hur man kan skapa ett eget spel med biblioteket pygame. Artikeln innehåller följande delar:

  • Pygame
  • Game-loopen
  • Tangenttryckningar
  • Logik

Hur skapar man ett spel i Python?

Det finns många sätt att programmera spel i Python. När man programmerar ett spel är det ofta flera klasser och objekt som samverkar med varandra för att allt ska fungera som det ska, så kallad objektorienterad programmering. Ett bibliotek som innehåller många färdiga funktioner för att sköta datagrafiken är pygame. Vi kommer därför att använda oss av pygame för att på så sätt förenkla skapandet av spelet.

Vad är pygame?

Pygame är ett bibliotek som innehåller flera funktioner som vi kommer använda oss av när vi programmerar vårt spel. Bland annat har pygame funktioner för att hantera tangenttryck som gör att vi kan maöverera spelaren. Pygame har även flera funktioner för att hantera grafiken på spelet, så som inladdning och positionering av  bilder.

Exempel: Programmera ett spel i Python

Vårt spel går ut på att man manövrerar en spelare med piltangenterna där målet är att ta sig förbi så många fallande väggar som möjligt. Hålet på väggarna kommer slumpmässigt och väggen faller snabbare och snabbare neråt. Om man rör väggen får man game over. Det är även en räknare som håller koll på antal väggar man har klarat av att passera. Pygame kommer hjälpa oss med tangenttryckningarna och all grafik. Det kommer se ut ungefär såhär:

Ett spel behöver vara aktivt hela tiden. Spelet ska dels rita ut all grafik, dels lyssna till tangentryckningar och hantera all logik beroende på vad som händer i spelet. Detta hanterar vi med en game-loop.

Del 1: Skapa en Game-loop till Pygame

Vi ska nu skapa skelettet till spelet, en så kallad game-loop som hanterar all logik och hantering av spelplanen. Game-loopen ska även hantera input av tangenttryckningar. Mycket av detta kommer gratis i biblioteket pygame.

1: Importera biblioteket pygame

Vi börjar med att importera Pygame:

# 1: Importa biblioteket 
pygame import 
pygame from pygame.locals import *

Du kan nu använda funktioner från Pygame. Pygame.locals innehåller exempelvis funktioner för att känna av tangenttryckningar.

2: Initiera Pygame-modulen

Vi kan sedan initiera alla moduler som vi kommer använda oss av.

# 2: initiera pygame-modulen 
pygame.init() 
pygame.font.init()

pygame.init() initierar alla moduler som vi tidigare har importerat och pygame.font.init() gör så att vi kan använda oss av fonter, det vill säga skriva ut texter på spelplanen. Man kan säga att vi har aktiverat de moduler som vi vill använda oss av.

3: Bestäm storleken på spelplanen

Vi ska nu bestämma storleken på spelplanen. För att underlätta, delar vi in spelplanen i ett rutnät där varje ruta är 64 x 64 pixlar stor. Vi bestämmer att bredden ska vara 10 rutor, och höjgden 8 rutor.

# 3: Bestäm storleken på spelplanen 
width, height = 64*10, 64*8

Vi kan sedan skapa spelplanen i pygame genom att anropa

screen = pygame.display.set_mode((width, height))

4: Skapa x- och y-position för spelaren

När vi ska rita ut vår spelare, behöver vi en x- och en y-position. Vi skapar helt enkelt två variabler som bestämmer var på som spelaren ska ritas ut.

# 4: Skapa x och y position för spelaren 
player_x = 200 
player_y = 200

Observera att koordinaten (0,0) är högst upp i vänstra hörnet i Pygame.

5: Ladda in bilder

Vi börjar med att ladda in bilden på spelaren. Bilden är i detta fall 64 x 64 pixlar stor. Det innebär alltså att bilden kommer vara exakt lika stor som en ruta i spelplanen.

# 5: Ladda in bilder 
player = pygame.image.load("hero.png")

Bilden på spelare “hero.png”, lägger vi i samma mapp som vi sparat våran kod för att bilden ska hittas vid inläsningen.

6: Skapa en evighetsloop

Nu är allt initierat. Vi kan nu skapa en evighetsloop som upprepas för alltid.

while 1:

Denna loop kommer alltid vara uppfylld. Den kommer alltså pågå för alltid. I denna loop kan vi nu sköta all logik och rita ut spelplanen.

7-9: Rita ut alla objekt

I while-loopen kan vi nu rita ut alla objekt genom att anropa pygames funktioner.

 # 7: Rita ut en vit spelplan 
screen.fill((255,255,255)) 

# 8: Rita ut bilden player på en x, y koordinat 
screen.blit(player, (player_x, player_y)) 

# 9: Updatera spelplanen 
pygame.display.flip()

10: Gå igenom alla event

Pygame.event innehåller alla event som skett sen senaste loop. Det är här vi senare kommer känna av tangenttryckningar. Just nu kollar vi enbart om spelplanen har stängts ner (pygame.QUIT). I så fall avbryter vi programmet (exit(0)) och spelet (while-loopen bryts och spelet slutförs).

 # 10: Gå igenom alla nya event 
for event in pygame.event.get(): # Kolla om spelplanen stängs ner. I så fall, stäng av programmet 
    if event.type == pygame.QUIT: # if it is quit the game 
        pygame.quit()
        exit(0)

Sammanställer vi all kod, ser den ut såhär:

# 1: Importa biblioteket pygame
import pygame
from pygame.locals import *

# 2: initiera pygame-modulen 
pygame.init()
pygame.font.init()

# 3: Bestäm storleken på spelplanen
width, height = 64*10, 64*8
screen=pygame.display.set_mode((width, height))

# 4: Skapa x och y position för spelaren
player_x = 200
player_y = 200

# 5: Ladda in bilder
player = pygame.image.load("hero.png")

# 6: Skapa en evighetsloop som aldrig tar slut
while 1:
    # 7: Rita ut en vit spelplan
    screen.fill((255,255,255))

    # 8: Rita ut bilden player på en x, y koordinat
    screen.blit(player, (player_x, player_y))

    # 9: Updatera spelplanen
    pygame.display.flip()

    # 10: Gå igenom alla nya event 
    for event in pygame.event.get():
        # Kolla om spelplanen stängs ner. I så fall, stäng av programmet
        if event.type == pygame.QUIT:
            # if it is quit the game
            pygame.quit() 
            exit(0)

Om vi kör programmet kommer enbart spelaren ritas ut på position (200,200). Stänger man av programmet så avbryts while-loopen och programmet stängs av.

gameloop för ett spel i pygame

Del 2: Hantera tangenttryckningar

Pygame kan läsa av events från användaren, exempelvis tangenttryckningar. Vi kan alltså låta saker hända, beroende vilken knapp på tangentbordet man trycker på. 

Vi ska nu fortsätta genom att kunna styra spelaren med piltangenterna.

Hur använder man tangenttryckningar i PyGame?

Vi har redan visat hur pygame har inbyggda funktioner för att läsa av event (pygame.event.get() ). Denna funktion kan även känna av tangenttryckningar. Vi börjar med att skapa en array som hanterar de fyra piltangenterna:

keys = [False, False, False, False]

Där indexen är är ordnade enligt [upp, vänster, ner, höger]. False innebär att tangenten inte är nedtryckt och True betyder att tangenten är nedtryckt. Exempelvis betyder:

keys = [False, True, False, False]

att vänster piltangent är nedtryckt och alla andra är släppta.

Vi kan nu använda oss av pygames event-funktion för att avgöra om en tangent är nedtryckt eller släppt

if event.type == pygame.KEYDOWN:  #  Avgör om en tangent har trycks ner
 if event.type == pygame.KEYUP:  #  Avgör om en tangent har släppts

Vi kan använda dessa två kommandon och uppdatera arrayen varje gång rätt tangent trycks ner:

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

Det vill säga, när en tangent blir nedtryckt, sätter vi True på den plats i arrayen som tangenten tillhör.

På samma sätt avgör vi om en tangent släpps och sätter dess plats till False:

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

Vi kan nu uppdatera positionen på spelaren genom att kolla om tangenknappen är nedtryckt eller inte. Först hanterar vi y-positionen:

# 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

Sedan x-positionen på motsvarande sätt:

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

Kör vi spelet nu, kommer vi kunna styra spelaren med piltangenterna:

Testa själv! Här är all kod!

# 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

Del 3: Logik till spelet

Vi kan även införa logik i spelet. Beroende på vad som händer i spelet, ska något nytt hända!

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 än så länge:

Visa kod

# 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

Skapa en fallande vägg

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.

Programmera flera lika dana objekt i python

Gör så att väggen faller

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.


Sätt game-over om spelaren krockar med väggen

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.


Byt till meny-läge vid game-over

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

Skapa en räknare

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 &gt; 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 &gt;= wall_y and player_y &lt;= wall_y + 64) and\
        ((player_x &gt; 0 and player_x &lt;= rand_wall*64) or (player_x &gt; (rand_wall+1)*64 and player_x &lt; 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 &gt; 0:
                player_y -= 15
        elif keys[2]:
            if player_y &lt; height-64: 
                player_y += 15 
        if keys[1]: 
            if player_x &gt; 0:
                player_x -= 15
        elif keys[3]:
            if player_x &lt; width-64:
                player_x += 15

Avslutande ord

Hoppas du tyckte det var roligt och lärorikt att programmera ett spel i Python. Det finns oändliga möjligheter och varianter på hur man lär sig att programmera och att programmera ett enkelt spel är ett roligt sätt där man snabbt lär sig. Det kan uppfattas som mycket kod och möjligtvis ganska svårt att förstå all logik i spelet. Men mitt tips till dig är att påbörja ett eget spel och bygg upp din egna logik efter hand. Då kommer du steg för steg lära dig, och lösa de problem som uppstår allt eftersom du programmerar.

To top