I'm trying to move my character through a maze using bitmap. I'm not very good with python yet, so I don't know if this is obvious or not.
The code looks like this:
# the code that works
def movePlayerRight(self):
next_tile_x = self.player_tile_x + 1
if next_tile_x > NUM_TILE_ROWS:
return
elif self.bitmap[self.player_tile_y][next_tile_x] == -1:
return
else:
self.player_tile_x = next_tile_x
# the code that doesn't
def movePlayerUp(self):
next_tile_y = self.player_tile_y - 1
if next_tile_y < 0:
return
elif self.bitmap[self.player_tile_x][next_tile_y] == 1:
return
I couldn't think of a way to search this online besides here so...?
EDIT: I put that in, but the character was clipping through walls and, at certain points, saying the index was out of range?
Also one person said they wanted to see the whole code so:
import pygame
WHITE = ((255,255,255))
BLACK = ((0,0,0))
RED = ((255,0,0))
BLUE = ((0,0,255))
DISPLAY_HEIGHT = 600
DISPLAY_WIDTH = 800
map_bitmap = [[ 1, 1 , 1, 1, 1, 1, 1, 1],
[ 1, 1 , 0, 0, 0, 0, 0, 1],
[ 1, 1 , 1, 0, 1, 0, 0, 1],
[ 1, 0 , 0, 0, 0, 0, 0, 1],
[ 1, 0 , 0, 0, 0, 0, 0, 1],
[ 1, 1 , 1, 1, 1, 1, 1, 1]]
# These start at 0. So if there's 11 columns, it's 0 to 10
MAP_START_TILE_X = 3
MAP_START_TILE_Y = 4
MAP_END_TILE_X = 0
MAP_END_TILE_Y = 2
# Number of tiles per row/column we have
NUM_TILE_COLUMNS = len(map_bitmap[0])
NUM_TILE_ROWS = len(map_bitmap)
# Determines in pixels how wide/tall our tiles are
TILE_WIDTH = int(DISPLAY_WIDTH / NUM_TILE_COLUMNS)
TILE_HEIGHT = int(DISPLAY_HEIGHT / NUM_TILE_ROWS)
# This function is going to draw a bitmap to a surface
def draw_map(surface, bitmap):
# Loop through all indexes in our Y coordinate
for y in range(NUM_TILE_ROWS):
# Each list in this list represents a row
row = bitmap[y]
# Loop through all indexes in our X coordinate
for x in range(NUM_TILE_COLUMNS):
draw_tile = bitmap[y][x]
# If the tile value is 1, we have a wall. Draw a rectangle
if draw_tile == 1:
# render a rectangle
# Rect(left, top, width, height) -> Rect
wall_tile = pygame.Rect(TILE_WIDTH * x, TILE_HEIGHT * y, TILE_WIDTH, TILE_HEIGHT)
pygame.draw.rect(surface, BLACK, wall_tile)
# This function takes a surface and an X/Y coord and draws a red rectangle
# This rectangle represents our player.
# TODO: Figure out how to blit an image instead
def draw_player(surface, tile_x, tile_y):
# Translate tiles to pixels to draw our rectangle
player_tile = pygame.Rect(TILE_WIDTH * tile_x, TILE_HEIGHT * tile_y, TILE_WIDTH, TILE_HEIGHT)
# Draw the tile. Right now
pygame.draw.rect(surface, RED, player_tile)
def draw_fog_of_war(surface, tile_x, tile_y, radius):
# Define some new colors
TRANSPARENT = (0,0,255,0)
GREY = (220,220,220,255)
# Build our overlay surface
overlay_surface = pygame.Surface((DISPLAY_WIDTH, DISPLAY_HEIGHT), pygame.SRCALPHA)
overlay_surface.fill(GREY)
# Convert from tile position to pixels
# Note that we need to consider the CENTER of the tile, not the top-left
center_x = (tile_x * TILE_WIDTH) + (int(TILE_WIDTH / 2))
center_y = (tile_y * TILE_HEIGHT) + (int(TILE_HEIGHT / 2))
center = (center_x, center_y)
# Draw transparent circle on overlay surface
pygame.draw.circle(overlay_surface, TRANSPARENT, center, radius)
# Cover original surface with overlay surface
# blit(source, dest, area=None, special_flags=0) -> Rect
surface.blit(overlay_surface, (0,0))
# Notes:
# Don't forget "self" :)
# Methods (class functions) serve as was to change/get information about the object
# All methods have AT LEAST one parameter: self
# __init__ is called implicitly during instantiation. This is where you configure your object's attributes (class variables)
# Don't forget "self" :)
class Maze:
surface = None
bitmap = []
player_tile_x = -1
player_tile_y = -1
end_tile_x = 4
end_tile_y = 0
def __init__(self, surface, bitmap, start_tile_x, start_tile_y, end_tile_x, end_tile_y):
self.surface = surface
self.bitmap = bitmap
self.player_tile_x = start_tile_x
self.player_tile_y = start_tile_y
self.end_tile_x = end_tile_x
self.end_tile_y = end_tile_y
print("Player at: (%d, %d)" % (self.player_tile_x, self.player_tile_y))
def render(self):
# Recreate our world
self.surface.fill(WHITE)
draw_map(self.surface, self.bitmap)
draw_player(self.surface, self.player_tile_x, self.player_tile_y)
# Kinda arbitrarily setting radius, adjust as needed
radius = TILE_WIDTH * 2
# NOTE: Comment out the draw_fog_of_war to disable this
# Useful when you need to look at the whole map
draw_fog_of_war(self.surface, self.player_tile_x, self.player_tile_y, radius)
def movePlayerLeft(self):
# Shifting left means subtracting X coord by 1
next_tile_x = self.player_tile_x - 1
# Check to see if we run off the map
if next_tile_x < 0:
# Do nothing, return
return
# Check to see if we bump into a tile occupied by a wall
elif self.bitmap[self.player_tile_y][next_tile_x] == 1:
# Do nothing, return
return
# Should be an empty, available tile to move into
else:
# Update our player's X coord position
self.player_tile_x = next_tile_x
def movePlayerRight(self):
next_tile_x = self.player_tile_x + 1
if next_tile_x > NUM_TILE_ROWS:
return
elif self.bitmap[self.player_tile_y][next_tile_x] == -1:
return
else:
self.player_tile_x = next_tile_x
def movePlayerUp(self):
next_tile_y = self.player_tile_y - 1
if next_tile_y < 0:
return
elif self.bitmap[self.player_tile_x][next_tile_y] == -1:
return
else:
self.player_tile_y = next_tile_y
def movePlayerDown(self):
next_tile_y = self.player_tile_y + 1
if next_tile_y > NUM_TILE_COLUMNS:
return
elif self.bitmap[self.player_tile_y][next_tile_y] == 1:
return
else:
self.player_tile_y = next_tile_y
# How we can determine if a player has reached the file tile
def isPlayerAtEnd(self):
if (self.player_tile_x == self.end_tile_x) and (self.player_tile_y == self.end_tile_y):
return True
else:
return False
def main():
# Initialize the module
pygame.init()
# Create a display, returns the default surface to draw on which matches
# the defined resolution
surface = pygame.display.set_mode((DISPLAY_WIDTH,DISPLAY_HEIGHT))
# Create our maze
# __init__(self, surface, bitmap, start_tile_x, start_tile_y, end_tile_x, end_tile_y):
maze = Maze(surface, map_bitmap, MAP_START_TILE_X, MAP_START_TILE_Y, MAP_END_TILE_X, MAP_END_TILE_Y)
# Render the objects onto the surface
maze.render()
# Update the display
pygame.display.update()
running = True
while running:
# Wait for an event. This is different then the timer method
# We are not updating anything until an event is triggered
event = pygame.event.wait()
print(event)
if event.type == pygame.QUIT:
running = False
# Check all key press events.
# Only left movement is implemented right now
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
elif event.key == pygame.K_LEFT:
maze.movePlayerLeft()
elif event.key == pygame.K_RIGHT:
maze.movePlayerRight()
elif event.key == pygame.K_UP:
maze.movePlayerUp()
elif event.key == pygame.K_DOWN:
maze.movePlayerDown()
# Re-render our world
maze.render()
# Update the display
pygame.display.update()
# Did we win? For now, we'll just quit
# TODO: do something more elegant here
if maze.isPlayerAtEnd():
# We won! Exit
running = False
if __name__ == "__main__":
main()
pygame.quit()
quit()
You are missing the else
statement in your movePlayerUp
function.
def movePlayerUp(self):
next_tile_y = self.player_tile_y - 1
if next_tile_y < 0:
return
elif self.bitmap[self.player_tile_x][next_tile_y] == 1:
return
else:
self.player_tile_y = next_tile_y
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.