没有错误,但在 x 轴上添加碰撞后精灵已完全消失
No error but sprite has completely disappeared after adding collision in the x-axis
我找不到找回它的方法,我什至把它弄得非常大,但它仍然不存在,none 在编码时触摸了图像加载或绘制到屏幕上碰撞所以我真的很困惑。有人可以看看并告诉我发生了什么事吗?
完整代码在这里:
import pygame
pygame.init()
clock = pygame.time.Clock()
size = width, height = 1000, 750
screen = pygame.display.set_mode(size)
ScreenRect = screen.get_rect()
pygame.display.set_caption("Snail Platformer")
#Game variables
TileSize = 50
#load background
bg = pygame.image.load('bg.png')
class Player():
def __init__(self, x, y):
self.SnailRight = []
self.SnailLeft = []
self.index = 0
self.counter = 0
for num in range(1, 3):
right = pygame.image.load(f'right{num}.png')
right = pygame.transform.scale(right, (128, 128))
left = pygame.transform.flip(right, True, False)
self.SnailRight.append(right)
self.SnailLeft.append(left)
self.image = self.SnailRight[self.index]
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.width = self.image.get_width
self.height = self.image.get_height
self.vel_y = 0
self.jump = False
self.direct = 0
def draw(self):
x1 = 0
y1 = 0
Anim = 10
#move snail
Keys = pygame.key.get_pressed()
if Keys[pygame.K_LEFT]:
x1 -= 2
self.counter += 1
self.direct = -1
if Keys[pygame.K_RIGHT]:
x1 += 2
self.counter += 1
self.direct = 1
if Keys[pygame.K_LEFT] == False and Keys[pygame.K_RIGHT] == False:
self.counter = 0
self.index = 0
if self.direct == 1:
self.image = self.SnailRight[self.index]
if self.direct == -1:
self.image = self.SnailLeft[self.index]
if Keys[pygame.K_SPACE] or Keys[pygame.K_UP] and self.jump == False:
self.vel_y = -15
self.jump = True
if Keys[pygame.K_SPACE] or Keys[pygame.K_UP] == False:
self.jump = False
#Animation
self.counter += 1
if self.counter > Anim:
self.counter = 0
self.index += 1
if self.index >= len(self.SnailRight):
self.index = 0
if self.direct == 1:
self.image = self.SnailRight[self.index]
if self.direct == -1:
self.image = self.SnailLeft[self.index]
#Gravity
self.vel_y += 1
if self.vel_y > 10:
self.vel_y = 10
y1 += self.vel_y
#Collision Detection
for tile in world.TileList:
if tile[1].colliderect(pygame.Rect(self.rect.x + x1, self.rect.y, self.width, self.height)):
x1 = 0
if self.vel_y < 0:
y1 = tile[1].bottom - self.rect.top
if self.vel_y >= 0:
y1 = tile[1].top - self.rect.bottom
self.rect.x += x1
self.rect.y += y1
if self.rect.bottom > height:
self.rect.bottom = height
y1 = 0
#draw snail
screen.blit(self.image, self.rect)
pygame.draw.rect(screen, (255, 255, 255), self.rect, 2)
class World():
def __init__(self, data):
self.TileList = []
#load platforms images
dirt = pygame.image.load('dirt.png')
grass = pygame.image.load('grass.png')
rowCount = 0
for row in data:
columnCount = 0
for tile in row:
if tile == 1:
img = pygame.transform.scale(dirt, (TileSize, TileSize))
img_rect = img.get_rect()
img_rect.x = columnCount * TileSize
img_rect.y = rowCount * TileSize
tile = (img, img_rect)
self.TileList.append(tile)
if tile == 2:
img = pygame.transform.scale(grass, (TileSize, TileSize))
img_rect = img.get_rect()
img_rect.x = columnCount * TileSize
img_rect.y = rowCount * TileSize
tile = (img, img_rect)
self.TileList.append(tile)
columnCount += 1
rowCount += 1
def draw(self):
for tile in self.TileList:
screen.blit(tile[0], tile[1])
pygame.draw.rect(screen, (255, 255, 255), tile[1], 2)
WorldData = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1],
[1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1],
[1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 2, 2, 1],
[1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
Snail = Player(25, height - 130)
world = World(WorldData)
#main loop
run = True
while run:
clock.tick(60)
screen.blit(bg, (0, 0))
world.draw()
Snail.draw()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.update()
pygame.quit()
(这个答案的第一部分已经在this other question的评论中给出了。)
它并没有完全消失:它在墙内生成并向上发射。
一个潜在的解决方法是让你的播放器变小并稍微移动它,这样它就不会在墙内生成,并且还可以按照我在你的其他问题中建议的那样修复你的碰撞检测部分。
总结一下:
将您的碰撞检测编辑为:
# Collision Detection
for tile in world.TileList:
if tile[1].colliderect(pygame.Rect(self.rect.x + x1, self.rect.y, self.rect.width, self.rect.height)):
x1 = 0
if tile[1].colliderect(pygame.Rect(self.rect.x, self.rect.y + y1, self.rect.width, self.rect.height)):
y1 = 0
if self.vel_y < 0:
y1 = tile[1].bottom - self.rect.top
if self.vel_y >= 0:
y1 = tile[1].top - self.rect.bottom
在 Player 的构造函数中,修改此行:
right = pygame.transform.scale(right, (128, 128))
对此:
right = pygame.transform.scale(right, (32, 32))
就在你的主循环之上,修改这一行:
Snail = Player(25, height - 130)
对此:
Snail = Player(50, height - 130)
一旦您确认这有效,您就可以使用实际值并根据自己的喜好进行调整。我们在这里所做的只是让玩家变小,将其移出墙外,实际上是修改碰撞检测。
另请注意,您又忘记了 self.width
和 self.height
中的 rect
。 :)
pygame.Surface.get_width
and pygame.Surface.get_height
是方法。您必须使用括号 (()
) 来调用方法。
self.width = self.image.get_width
self.height = self.image.get_height
self.width = self.image.get_width()
self.height = self.image.get_height()
无论如何,您根本不需要 width
和 height
属性。宽度和高度存储在 rect
属性中:
if tile[1].colliderect(pygame.Rect(self.rect.x + x1, self.rect.y, self.rect.width, self.rect.height)):
# [...]
您也可以使用pygame.Rect.move
方法。此方法 returns 一个新的移动的矩形:
if tile[1].colliderect(self.rect.move(x1, 0)):
# [...]
为了让您的代码正常工作,您必须将碰撞检测与 x 轴和 y 轴分开:
class Player():
# [...]
def draw(self):
# [...]
for tile in world.TileList:
if tile[1].colliderect(self.rect.move(x1, 0)):
if x1 > 0:
self.rect.right = tile[1].left
elif x1 < 0:
self.rect.left = tile[1].right
x1 = 0
break
for tile in world.TileList:
if tile[1].colliderect(self.rect.move(x1, y1)):
if self.vel_y < 0:
y1 = tile[1].bottom - self.rect.top
if self.vel_y >= 0:
y1 = tile[1].top - self.rect.bottom
self.rect.x += x1
self.rect.y += y1
# [...]
并且你必须为玩家找到一个不与网格边界碰撞的起始位置。例如:
Snail = Player(25, height - 130)
Snail = Player(50, height - 130)
或
Snail = Player(width // 2, height // 2)
我找不到找回它的方法,我什至把它弄得非常大,但它仍然不存在,none 在编码时触摸了图像加载或绘制到屏幕上碰撞所以我真的很困惑。有人可以看看并告诉我发生了什么事吗?
完整代码在这里:
import pygame
pygame.init()
clock = pygame.time.Clock()
size = width, height = 1000, 750
screen = pygame.display.set_mode(size)
ScreenRect = screen.get_rect()
pygame.display.set_caption("Snail Platformer")
#Game variables
TileSize = 50
#load background
bg = pygame.image.load('bg.png')
class Player():
def __init__(self, x, y):
self.SnailRight = []
self.SnailLeft = []
self.index = 0
self.counter = 0
for num in range(1, 3):
right = pygame.image.load(f'right{num}.png')
right = pygame.transform.scale(right, (128, 128))
left = pygame.transform.flip(right, True, False)
self.SnailRight.append(right)
self.SnailLeft.append(left)
self.image = self.SnailRight[self.index]
self.rect = self.image.get_rect()
self.rect.x = x
self.rect.y = y
self.width = self.image.get_width
self.height = self.image.get_height
self.vel_y = 0
self.jump = False
self.direct = 0
def draw(self):
x1 = 0
y1 = 0
Anim = 10
#move snail
Keys = pygame.key.get_pressed()
if Keys[pygame.K_LEFT]:
x1 -= 2
self.counter += 1
self.direct = -1
if Keys[pygame.K_RIGHT]:
x1 += 2
self.counter += 1
self.direct = 1
if Keys[pygame.K_LEFT] == False and Keys[pygame.K_RIGHT] == False:
self.counter = 0
self.index = 0
if self.direct == 1:
self.image = self.SnailRight[self.index]
if self.direct == -1:
self.image = self.SnailLeft[self.index]
if Keys[pygame.K_SPACE] or Keys[pygame.K_UP] and self.jump == False:
self.vel_y = -15
self.jump = True
if Keys[pygame.K_SPACE] or Keys[pygame.K_UP] == False:
self.jump = False
#Animation
self.counter += 1
if self.counter > Anim:
self.counter = 0
self.index += 1
if self.index >= len(self.SnailRight):
self.index = 0
if self.direct == 1:
self.image = self.SnailRight[self.index]
if self.direct == -1:
self.image = self.SnailLeft[self.index]
#Gravity
self.vel_y += 1
if self.vel_y > 10:
self.vel_y = 10
y1 += self.vel_y
#Collision Detection
for tile in world.TileList:
if tile[1].colliderect(pygame.Rect(self.rect.x + x1, self.rect.y, self.width, self.height)):
x1 = 0
if self.vel_y < 0:
y1 = tile[1].bottom - self.rect.top
if self.vel_y >= 0:
y1 = tile[1].top - self.rect.bottom
self.rect.x += x1
self.rect.y += y1
if self.rect.bottom > height:
self.rect.bottom = height
y1 = 0
#draw snail
screen.blit(self.image, self.rect)
pygame.draw.rect(screen, (255, 255, 255), self.rect, 2)
class World():
def __init__(self, data):
self.TileList = []
#load platforms images
dirt = pygame.image.load('dirt.png')
grass = pygame.image.load('grass.png')
rowCount = 0
for row in data:
columnCount = 0
for tile in row:
if tile == 1:
img = pygame.transform.scale(dirt, (TileSize, TileSize))
img_rect = img.get_rect()
img_rect.x = columnCount * TileSize
img_rect.y = rowCount * TileSize
tile = (img, img_rect)
self.TileList.append(tile)
if tile == 2:
img = pygame.transform.scale(grass, (TileSize, TileSize))
img_rect = img.get_rect()
img_rect.x = columnCount * TileSize
img_rect.y = rowCount * TileSize
tile = (img, img_rect)
self.TileList.append(tile)
columnCount += 1
rowCount += 1
def draw(self):
for tile in self.TileList:
screen.blit(tile[0], tile[1])
pygame.draw.rect(screen, (255, 255, 255), tile[1], 2)
WorldData = [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 1],
[1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 2, 2, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 7, 0, 5, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 1],
[1, 7, 0, 0, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 7, 0, 0, 2, 2, 1],
[1, 0, 2, 0, 0, 7, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 2, 0, 0, 4, 0, 0, 0, 0, 2, 0, 0, 3, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
]
Snail = Player(25, height - 130)
world = World(WorldData)
#main loop
run = True
while run:
clock.tick(60)
screen.blit(bg, (0, 0))
world.draw()
Snail.draw()
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.update()
pygame.quit()
(这个答案的第一部分已经在this other question的评论中给出了。)
它并没有完全消失:它在墙内生成并向上发射。
一个潜在的解决方法是让你的播放器变小并稍微移动它,这样它就不会在墙内生成,并且还可以按照我在你的其他问题中建议的那样修复你的碰撞检测部分。
总结一下:
将您的碰撞检测编辑为:
# Collision Detection
for tile in world.TileList:
if tile[1].colliderect(pygame.Rect(self.rect.x + x1, self.rect.y, self.rect.width, self.rect.height)):
x1 = 0
if tile[1].colliderect(pygame.Rect(self.rect.x, self.rect.y + y1, self.rect.width, self.rect.height)):
y1 = 0
if self.vel_y < 0:
y1 = tile[1].bottom - self.rect.top
if self.vel_y >= 0:
y1 = tile[1].top - self.rect.bottom
在 Player 的构造函数中,修改此行:
right = pygame.transform.scale(right, (128, 128))
对此:
right = pygame.transform.scale(right, (32, 32))
就在你的主循环之上,修改这一行:
Snail = Player(25, height - 130)
对此:
Snail = Player(50, height - 130)
一旦您确认这有效,您就可以使用实际值并根据自己的喜好进行调整。我们在这里所做的只是让玩家变小,将其移出墙外,实际上是修改碰撞检测。
另请注意,您又忘记了 self.width
和 self.height
中的 rect
。 :)
pygame.Surface.get_width
and pygame.Surface.get_height
是方法。您必须使用括号 (()
) 来调用方法。
self.width = self.image.get_width
self.height = self.image.get_height
self.width = self.image.get_width()
self.height = self.image.get_height()
无论如何,您根本不需要 width
和 height
属性。宽度和高度存储在 rect
属性中:
if tile[1].colliderect(pygame.Rect(self.rect.x + x1, self.rect.y, self.rect.width, self.rect.height)):
# [...]
您也可以使用pygame.Rect.move
方法。此方法 returns 一个新的移动的矩形:
if tile[1].colliderect(self.rect.move(x1, 0)):
# [...]
为了让您的代码正常工作,您必须将碰撞检测与 x 轴和 y 轴分开:
class Player():
# [...]
def draw(self):
# [...]
for tile in world.TileList:
if tile[1].colliderect(self.rect.move(x1, 0)):
if x1 > 0:
self.rect.right = tile[1].left
elif x1 < 0:
self.rect.left = tile[1].right
x1 = 0
break
for tile in world.TileList:
if tile[1].colliderect(self.rect.move(x1, y1)):
if self.vel_y < 0:
y1 = tile[1].bottom - self.rect.top
if self.vel_y >= 0:
y1 = tile[1].top - self.rect.bottom
self.rect.x += x1
self.rect.y += y1
# [...]
并且你必须为玩家找到一个不与网格边界碰撞的起始位置。例如:
Snail = Player(25, height - 130)
Snail = Player(50, height - 130)
或
Snail = Player(width // 2, height // 2)