Search code examples
pythonpygamecollisionmotion

How to make a character and move it with collisisions?


I'm making a 2D game on replit and so far, I'm doing pretty well. My last question is about making the map.

Here's the code for the map:

import pygame, sys

BLUE = (0, 0, 255)
SAND = (194, 176, 128)
GRASS = (124, 252, 0)
FOREST = (0, 100, 0)

TileColor = {'W': BLUE, 'S': SAND, 'G': GRASS, 'F': FOREST}

map1 = ["WWWWWWWWWWWWWWWWWWWWWWW",
        "WWWWWWWWWGGGWWWWWWWWWWW",
        "WWWWWGGGGGGGGGGGWWWWWWW", 
        "WWWWGGGGGFFFGGGGGGWWWWW",
        "WWWGGGGGFFFFFFGGGGGWWWW", 
        "WWWGGGGGGFFFFFGGGGGGWWW",
        "WWGGGGGGGGGFFGGGGGGGWWW", 
        "WWGGGGGGGGGGGGGGGGGGGWW",
        "WWGGGGGGSSSSSSSGGGGGGGW", 
        "WWGGGGSSSSSSSSSSGGGGGGW",
        "WGGGGGGGSSGGGGGGGGGGGSW", 
        "WGGGGGGGGGGGGGGGGGGGSSW",
        "WSGGGGGGGGFFGGGGGGGGSSW", 
        "WSSGGGGGGFFFGGGGGFFGGSW",
        "WSSGGGGGFFFFFFGGFFFFFGW", 
        "WSGGGGFFFFFFFFFFFFFFGGW",
        "WWGGGGGFFFFFFFFFFFFGGWW", 
        "WWGGGGGGGFFFFFFFFGGGWWW",
        "WWWWGGGGGGGGFFGGGGGWWWW", 
        "WWWWWWSSSSSGGGGSSSWWWWW",
        "WWWWWWWWWSSSSSSSSWWWWWW", 
        "WWWWWWWWWWWWWWSWWWWWWWW",
        "WWWWWWWWWWWWWWWWWWWWWWW"
        ]

TILESIZE = 22
MAPWIDTH = 23
MAPHEIGHT = 23

pygame.init()
DISPLAY = pygame.display.set_mode((MAPWIDTH * TILESIZE, MAPHEIGHT * TILESIZE))

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    for row in range(MAPHEIGHT):
        for col in range(MAPWIDTH):
            pygame.draw.rect(
                DISPLAY, TileColor[map1[row][col]],
                (col * TILESIZE, row * TILESIZE, TILESIZE, TILESIZE))

    pygame.display.update()

Which got me this:

My Map

Now I want to make a little person moving around when I press the arrow keys, and then I want to make it not be able to move onto to blue (water). Any suggestions on how I could do that?


Solution

  • The character is represented by a row an column in the grid:

    character = [5, 11]
    

    Use the keyboard events to change the position of the character (see How to get keyboard input in pygame?). Skip character movement if new character position is not on grass (map1[c_row][c_col] == 'G'):

    run = True
    while run:
        c_col, c_row = character
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    c_col += 1  
                if event.key == pygame.K_LEFT:
                    c_col -= 1
                if event.key == pygame.K_UP:
                    c_row -= 1  
                if event.key == pygame.K_DOWN:
                    c_row += 1   
    
        if 0 <= c_col < MAPWIDTH and 0 <= c_row < MAPHEIGHT:
            if map1[c_row][c_col] == 'G':
                character = [c_col, c_row]
    

    Draw a rectangle at the character's position:

    run = True
    while run:
        # [...]
    
        pygame.draw.rect(
            DISPLAY, (255, 0, 0),
            (character[0] * TILESIZE, character[1] * TILESIZE, TILESIZE, TILESIZE))
    

    Complete example:

    import pygame, sys
    
    BLUE = (0, 0, 255)
    SAND = (194, 176, 128)
    GRASS = (124, 252, 0)
    FOREST = (0, 100, 0)
    
    TileColor = {'W': BLUE, 'S': SAND, 'G': GRASS, 'F': FOREST}
    
    map1 = ["WWWWWWWWWWWWWWWWWWWWWWW",
            "WWWWWWWWWGGGWWWWWWWWWWW",
            "WWWWWGGGGGGGGGGGWWWWWWW", 
            "WWWWGGGGGFFFGGGGGGWWWWW",
            "WWWGGGGGFFFFFFGGGGGWWWW", 
            "WWWGGGGGGFFFFFGGGGGGWWW",
            "WWGGGGGGGGGFFGGGGGGGWWW", 
            "WWGGGGGGGGGGGGGGGGGGGWW",
            "WWGGGGGGSSSSSSSGGGGGGGW", 
            "WWGGGGSSSSSSSSSSGGGGGGW",
            "WGGGGGGGSSGGGGGGGGGGGSW", 
            "WGGGGGGGGGGGGGGGGGGGSSW",
            "WSGGGGGGGGFFGGGGGGGGSSW", 
            "WSSGGGGGGFFFGGGGGFFGGSW",
            "WSSGGGGGFFFFFFGGFFFFFGW", 
            "WSGGGGFFFFFFFFFFFFFFGGW",
            "WWGGGGGFFFFFFFFFFFFGGWW", 
            "WWGGGGGGGFFFFFFFFGGGWWW",
            "WWWWGGGGGGGGFFGGGGGWWWW", 
            "WWWWWWSSSSSGGGGSSSWWWWW",
            "WWWWWWWWWSSSSSSSSWWWWWW", 
            "WWWWWWWWWWWWWWSWWWWWWWW",
            "WWWWWWWWWWWWWWWWWWWWWWW"
            ]
    
    TILESIZE = 22
    MAPWIDTH = 23
    MAPHEIGHT = 23
    
    pygame.init()
    DISPLAY = pygame.display.set_mode((MAPWIDTH * TILESIZE, MAPHEIGHT * TILESIZE))
    clock = pygame.time.Clock()
    
    character = [5, 11]
    
    run = True
    while run:
        c_col, c_row = character
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RIGHT:
                    c_col += 1  
                if event.key == pygame.K_LEFT:
                    c_col -= 1
                if event.key == pygame.K_UP:
                    c_row -= 1  
                if event.key == pygame.K_DOWN:
                    c_row += 1   
    
        if 0 <= c_col < MAPWIDTH and 0 <= c_row < MAPHEIGHT:
            if map1[c_row][c_col] == 'G':
                character = [c_col, c_row]            
    
    
        for row in range(MAPHEIGHT):
            for col in range(MAPWIDTH):
                pygame.draw.rect(
                    DISPLAY, TileColor[map1[row][col]],
                    (col * TILESIZE, row * TILESIZE, TILESIZE, TILESIZE))
    
        pygame.draw.rect(
            DISPLAY, (255, 0, 0),
            (character[0] * TILESIZE, character[1] * TILESIZE, TILESIZE, TILESIZE))
    
        pygame.display.update()
        clock.tick(100)
    
    pygame.quit()
    sys.exit()