Pygame Wall Sprite Collision

我正在制作一个类似Rogue的游戏,但在编码方面我是初学者。我已经有我的角色移动,我的墙壁和地板精灵,但我的代码中有一些错误,允许角色在墙壁中移动。


我用它来在地板和墙砖之间进行选择,我试图用它来识别墙壁,但它并没有真正起作用。block_path


接下来,您可以看到我的代码:


screenWidth = 800

screenHeight = 600

mapHeight = 30

mapWidth = 30

cellWidth = 32

cellHeight = 32


screen = pygame.display.set_mode((screenWidth, screenHeight))

walkRight = [pygame.image.load('model/r1.png'), pygame.image.load('model/r2.png'), pygame.image.load('model/r3.png'), pygame.image.load('model/r4.png'), pygame.image.load('model/r5.png'), pygame.image.load('model/r6.png')]

walkLeft = [pygame.image.load('model/l1.png'), pygame.image.load('model/l2.png'), pygame.image.load('model/l3.png'), pygame.image.load('model/l4.png'), pygame.image.load('model/l5.png'), pygame.image.load('model/l6.png')]

walkUp = [pygame.image.load('model/u1.png'), pygame.image.load('model/u2.png'), pygame.image.load('model/u3.png'), pygame.image.load('model/u4.png'), pygame.image.load('model/u5.png'), pygame.image.load('model/u6.png')]

Floor = pygame.image.load("map/floor.jpg")

wallRight = pygame.image.load("map/rightwall.png")

`


class struc_Tile():

    def __init__(self,block_path):

        self.block_path = block_path`


class player(object):

    def __init__(self,x,y,width,height):

        self.x = x

        self.y = y

        self.width = width

        self.height = height

        self.vel = 5

        self.left = False

        self.right = False

        self.up = False

        self.down = False

        self.walkCount = 0



    def draw(self,screen):

        if self.walkCount + 1 >= 18:

            self.walkCount = 0


        elif self.left:

            screen.blit(walkLeft[self.walkCount//3], (self.x,self.y))

            self.walkCount += 1

        elif self.right:

            screen.blit(walkRight[self.walkCount//3], (self.x,self.y))

            self.walkCount += 1

        elif self.up:

            screen.blit(walkUp[self.walkCount//3], (self.x,self.y))

            self.walkCount += 1

        elif self.down:

            screen.blit(walkDown[self.walkCount//3], (self.x,self.y))


幕布斯6054654
浏览 101回答 1
1回答

呼啦一阵风

将函数更改为类似这样的函数将在地图的钻孔上创建一个 5 像素的缓冲区。我之所以把它做成5像素,是因为这就是你的角色动作。createmap()我建议加入一些实际的角色碰撞,以测试你是否无论速度如何都出界。编辑:我已经包含了完整的代码,因为我所做的更改如果我显示它们,则更容易理解。我已将您的图像列表更改为列表的字典,因为它们更容易以这种方式调用。您要求的网格是 30x30。由于您显示的单元格宽度为 32x32,因此我将地图更改为 960 x 960。我已经扩展了您的移动方法以检查碰撞,以查看它是否可以在发生冲突之前移动。我还删除了您的函数,因为向下移动重绘更容易。如果您愿意,可以将其添加回去,但对于此示例,我将其删除。redraw()import pygame# Based on the paths in your image# This should work for your image pathsimage = pygame.image.load('model/standing1.png')Standing = pygame.transform.scale(image, (32, 32))image = pygame.image.load('map/floor.jpg')Floor = pygame.transform.scale(image, (32, 32))image = pygame.image.load('map/rightwall.png')wallRight = pygame.transform.scale(image, (32, 32))walkLeft = []walkRight = []walkUp = []walkDown = []for i in range(1, 19):&nbsp; &nbsp; image = pygame.image.load('model/r' + str(i) + '.png')&nbsp; &nbsp; walkRight.append(pygame.transform.scale(image, (32, 32)))&nbsp; &nbsp; image = pygame.image.load('model/l' + str(i) + '.png')&nbsp; &nbsp; walkLeft.append(pygame.transform.scale(image, (32, 32)))&nbsp; &nbsp; image = pygame.image.load('model/u' + str(i) + '.png')&nbsp; &nbsp; walkUp.append(pygame.transform.scale(image, (32, 32)))&nbsp; &nbsp; image = pygame.image.load('model/d' + str(i) + '.png')&nbsp; &nbsp; walkDown.append(pygame.transform.scale(image, (32, 32)))class struc_Tile():&nbsp; &nbsp; def __init__(self, block_path):&nbsp; &nbsp; &nbsp; &nbsp; self.block_path = block_pathclass player(object):&nbsp; &nbsp; def __init__(self,x,y,width,height):&nbsp; &nbsp; &nbsp; &nbsp; self.x = x&nbsp; &nbsp; &nbsp; &nbsp; self.y = y&nbsp; &nbsp; &nbsp; &nbsp; self.width = width&nbsp; &nbsp; &nbsp; &nbsp; self.height = height&nbsp; &nbsp; &nbsp; &nbsp; self.vel = 5&nbsp; &nbsp; &nbsp; &nbsp; self.walkCount = 0&nbsp; &nbsp; &nbsp; &nbsp; # do something like this with your images&nbsp; &nbsp; &nbsp; &nbsp; # if you keep your lists in a dict you can avoid&nbsp; &nbsp; &nbsp; &nbsp; # all your boolean direction variables and&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; # the lengthy if else statement&nbsp; &nbsp; &nbsp; &nbsp; self.images = {}&nbsp; &nbsp; &nbsp; &nbsp; self.images['walkleft'] = walkLeft[:]&nbsp; &nbsp; &nbsp; &nbsp; self.images['walkright'] = walkRight[:]&nbsp; &nbsp; &nbsp; &nbsp; self.images['walkup'] = walkUp[:]&nbsp; &nbsp; &nbsp; &nbsp; self.images['walkdown'] = walkDown[:]&nbsp; &nbsp; def draw(self, screen, direction):&nbsp; &nbsp; &nbsp; &nbsp; if self.walkCount + 1 >= 18:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.walkCount = 0&nbsp; &nbsp; &nbsp; &nbsp; # since standing is not in your dict check for that first&nbsp; &nbsp; &nbsp; &nbsp; if direction == 'standing':&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; screen.blit(Standing, (self.x,self.y))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.walkCount = 0&nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; screen.blit(self.images[direction][self.walkCount], (self.x,self.y))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.walkCount += 1&nbsp; &nbsp; def can_move(self, dx, dy):&nbsp; &nbsp; &nbsp; &nbsp; # with the buffer created around the border of the map&nbsp; &nbsp; &nbsp; &nbsp; # you shouldn't have issues with&nbsp; &nbsp; &nbsp; &nbsp; # index out of bounds exceptions&nbsp; &nbsp; &nbsp; &nbsp; # EDIT: added better collision&nbsp; &nbsp; &nbsp; &nbsp; new_x = self.x + dx&nbsp; &nbsp; &nbsp; &nbsp; new_y = self.y + dy&nbsp; &nbsp; &nbsp; &nbsp; if gamemap[new_x][new_y].block_path == False:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if gamemap[new_x + cellWidth][new_y].block_path == False:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if gamemap[new_x][new_y + cellHeight].block_path == False:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if gamemap[new_x + cellWidth][new_y + cellHeight].block_path == False:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.x += dx&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.y += dy&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return Truedef createmap():&nbsp; &nbsp; newmap = [[struc_Tile(False) for y in range(0, mapHeight)] for x in range (0,mapWidth)]&nbsp; &nbsp; # give our upper/left borders a cell width buffer&nbsp; &nbsp; # and our bottom/right borders a 2 cell width buffer&nbsp; &nbsp; # since blit uses the upper left corner this should account&nbsp; &nbsp; # for the sprite width&nbsp; &nbsp; # EDIT: Fixed this to accommodate the better collision&nbsp; &nbsp; for x in range(0, mapWidth):&nbsp; &nbsp; &nbsp; &nbsp; for y in range (0, mapHeight):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if y < 32 or y + cellWidth >= mapHeight:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newmap[x][y].block_path = True&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; elif x < 32 or x + cellWidth >= mapWidth:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; newmap[x][y].block_path = True&nbsp; &nbsp; return newmapdef drawmap(maptodraw):&nbsp; &nbsp; # only blit at cellwidth and height intervals&nbsp; &nbsp; for x in range(0, mapWidth, cellWidth):&nbsp; &nbsp; &nbsp; &nbsp; for y in range(0, mapHeight, cellHeight):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if maptodraw[x][y].block_path == True:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; screen.blit(wallRight, (x, y))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; screen.blit(Floor, (x, y))# Added this function which lets you block or unblock a cell# simply call like gamemap = block_element(5, 10, gamemap)# this will block the 6th cell on the x axis and 11th on the y axis# to unblock a cell call it with block=Falsedef block_element(x, y, maptoblock, block=True):&nbsp; &nbsp; x_cells = int(mapWidth / cellWidth)&nbsp; &nbsp; y_cells = int(mapHeight / cellHeight)&nbsp; &nbsp; start_x = int(x * cellWidth)&nbsp; &nbsp; start_y = int(y * cellHeight)&nbsp; &nbsp; end_x = start_x + cellWidth&nbsp; &nbsp; end_y = start_y + cellHeight&nbsp; &nbsp; print(start_x, end_x)&nbsp; &nbsp; if x >= 0 and x < x_cells:&nbsp; &nbsp; &nbsp; &nbsp; if y >= 0 and y < y_cells:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for x in range(start_x, end_x):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for y in range(start_y, end_y):&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; maptoblock[x][y].block_path = block&nbsp; &nbsp; return maptoblock&nbsp; &nbsp;pygame.init()mapHeight = 960mapWidth = 960cellWidth = 32cellHeight = 32screen = pygame.display.set_mode((mapWidth, mapHeight))gamemap = createmap()# blocking/unblocking examplegamemap = block_element(5, 10, gamemap)gamemap = block_element(0, 8, gamemap, block=False)gamemap = block_element(0, 9, gamemap, block=False)clock = pygame.time.Clock()character = player(64, 64, 32, 32)run = Truewhile run:&nbsp; &nbsp; clock.tick(18)&nbsp; &nbsp; pygame.display.update()&nbsp; &nbsp; for event in pygame.event.get():&nbsp; &nbsp; &nbsp; &nbsp; if event.type == pygame.QUIT:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; run = False&nbsp; &nbsp; # I just used fill since I didn't have a bg image handy&nbsp; &nbsp; screen.fill((0, 0, 0))&nbsp; &nbsp; drawmap(gamemap)&nbsp; &nbsp; # handle the keypresses&nbsp; &nbsp; # first check if the character can move that much&nbsp; &nbsp; # then draw the movement&nbsp; &nbsp; keys = pygame.key.get_pressed()&nbsp; &nbsp; if keys[pygame.K_LEFT] and character.can_move(0 - character.vel, 0):&nbsp; &nbsp; &nbsp; &nbsp; character.draw(screen, 'walkleft')&nbsp; &nbsp; elif keys[pygame.K_RIGHT] and character.can_move(character.vel, 0):&nbsp; &nbsp; &nbsp; &nbsp; character.draw(screen, 'walkright')&nbsp; &nbsp; elif keys[pygame.K_UP] and character.can_move(0, 0 - character.vel):&nbsp; &nbsp; &nbsp; &nbsp; character.draw(screen, 'walkup')&nbsp; &nbsp; elif keys[pygame.K_DOWN] and character.can_move(0, character.vel):&nbsp; &nbsp; &nbsp; &nbsp; character.draw(screen, 'walkdown')&nbsp; &nbsp; else:&nbsp; &nbsp; &nbsp; &nbsp; character.draw(screen, 'standing')
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python