Lord_Zane 55 Lord_Zane 55 - 1 month ago 11
Python Question

Python tile based game (2d array) player movement

I'm making a rougelike in pygame, and I'm having trouble with player movement in a grid. This sample program shows how I plan to do it:

class P:

def __init__(self, standing_on):
self.standing_on = standing_on
self.row, self.column = 4, 4

def __str__(self):
return "@"


class G:
walkable = True

def __str__(self):
return "█"


class W:
walkable = False

def __str__(self):
return "|"

p = P(G())
game_map = [
[W(), W(), W(), W(), W(), W(), W(), W(), W(), W()],
[W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
[W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
[W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
[W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
[W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
[W(), G(), p, G(), G(), G(), G(), G(), G(), W()],
[W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
[W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
[W(), W(), W(), W(), W(), W(), W(), W(), W(), W()]
]


def print_map():
for column in range(10):
for row in range(10):
print(game_map[column][row], end="")
print()


def move_up():
temp = p.row - 1
if game_map[temp][p.column].walkable:
game_map[p.column][p.row] = p.standing_on
p.column -= 1
p.standing_on = game_map[p.column][p.row]
game_map[p.column][p.row] = p


print_map()
print(p.row, p.column, "\n")
move_up()
print_map()
print(p.row, p.column, "\n")
move_up()
print_map()
print(p.row, p.column, "\n")



  • p = player

  • g = grass

  • w = wall



and the output:

||||||||||
|████████|
|████████|
|████████|
|████████|
|████████|
|█@██████|
|████████|
|████████|
||||||||||
4 4

||||||||||
|████████|
|████████|
|███@████|
|████████|
|████████|
|█@██████|
|████████|
|████████|
||||||||||
4 3

||||||||||
|████████|
|███@████|
|████████|
|████████|
|████████|
|█@██████|
|████████|
|████████|
||||||||||
4 2


The numbers under the map represent the players coordinates. I start at 4, 4 (note that its 0 indexed) and move up twice. When displayed the map is completely wrong though, and I have tested it in my actual game and get the same bug, using images instead of text. Any idea whats going on?

Answer

The problem is your starting position. You need to draw a map without your player and then place the player on the map. Here is the solution that works:

class P:
   def __init__(self, standing_on):
       self.standing_on = standing_on
       self.row, self.column = 4, 4

   def __str__(self):
       return "@"


class G:
    walkable = True

    def __str__(self):
        return "█"


class W:
    walkable = False

    def __str__(self):
        return "|"

p = P(G())
game_map = [
    [W(), W(), W(), W(), W(), W(), W(), W(), W(), W()],
    [W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
    [W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
    [W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
    [W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
    [W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
    [W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
    [W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
    [W(), G(), G(), G(), G(), G(), G(), G(), G(), W()],
    [W(), W(), W(), W(), W(), W(), W(), W(), W(), W()]
]


def print_map():
    game_map[p.column][p.row] = p
    for column in range(10):
        for row in range(10):
            print(game_map[column][row], end="")
        print()

def move_up():
    temp = p.row - 1
    if game_map[temp][p.column].walkable:
        game_map[p.column][p.row] = p.standing_on
        p.column -= 1
        p.standing_on = game_map[p.column][p.row]


print_map()
print(p.row, p.column, "\n")
move_up()
print_map()
print(p.row, p.column, "\n")
move_up()
print_map()
print(p.row, p.column, "\n")