与瓷砖的玩家碰撞不起作用,而是穿过它们掉下去。

huangapple go评论112阅读模式
英文:

Player collision with tiles not working, instead falling through them

问题

基本上,我正在学习Pygame,并且正在从教程中学习。我并没有完全按照教程的方式做,但大部分都是。现在我无法弄清楚为什么教程有效而我的代码不起作用,特别是与图块碰撞的问题。以下是我的代码:

  1. import sys
  2. import pygame
  3. clock = pygame.time.Clock() # 初始化时钟
  4. from pygame.locals import *
  5. pygame.init() # 初始化Pygame
  6. WINDOW = (600, 400)
  7. screen = pygame.display.set_mode(WINDOW, 0, 32)
  8. pygame.display.set_caption("窗口") # 设置窗口标题
  9. display = pygame.Surface((300, 200)) # 创建显示表面,基本上创建另一幅图像,因为所有图像都是表面
  10. player_image = pygame.image.load("images/me1ns.png").convert_alpha() # 加载玩家图像,将其定义为变量
  11. player_y_momentum = 0
  12. grass_image = pygame.image.load("images/grass.png").convert()
  13. dirt_image = pygame.image.load("images/dirt.png").convert()
  14. game_map = [
  15. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  16. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  17. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  18. [0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  19. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  20. [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
  21. [2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2],
  22. [1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
  23. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  24. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  25. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  26. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  27. [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
  28. ]
  29. TILE_SIZE = 16 # 每个图块的大小
  30. def collision_test(rect, tiles):
  31. hit_col = []
  32. for tile in tiles:
  33. if rect.colliderect(tile):
  34. hit_col.append(tile)
  35. return hit_col
  36. def move(rect, movement, tiles):
  37. rect.x += movement[0]
  38. collisions = collision_test(rect, tiles)
  39. for tile in collisions:
  40. if movement[0] > 0:
  41. rect.right = tile.left
  42. elif movement[0] < 0:
  43. rect.left = tile.right
  44. rect.y += movement[1]
  45. collisions = collision_test(rect, tiles)
  46. for tile in collisions:
  47. if movement[1] > 0:
  48. rect.bottom = tile.top
  49. elif movement[1] < 0:
  50. rect.top = tile.bottom
  51. return rect
  52. BLACK = (0, 0, 0)
  53. WHITE = (255, 255, 255)
  54. RED = (255, 0, 0)
  55. GREEN = (0, 255, 0)
  56. BLUE = (0, 0, 255)
  57. GRAY = (128, 128, 128)
  58. LBLUE = (146, 244, 255)
  59. moving_right = False
  60. moving_left = False
  61. player_rect = pygame.Rect(50, 50, player_image.get_width(), player_image.get_height())
  62. while True:
  63. display.fill(LBLUE)
  64. tile_rects = []
  65. y = 0
  66. for row in game_map:
  67. x = 0
  68. for tile in row:
  69. if tile == 2:
  70. display.blit(grass_image, (x * TILE_SIZE, y * TILE_SIZE))
  71. if tile == 1:
  72. display.blit(dirt_image, (x * TILE_SIZE, y * TILE_SIZE))
  73. if tile != 0:
  74. tile_rects.append(
  75. pygame.Rect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
  76. )
  77. x += 1
  78. y += 1
  79. player_movement = [0, 0]
  80. if moving_right:
  81. player_movement[0] += 2
  82. if moving_left:
  83. player_movement[0] -=
  84. <details>
  85. <summary>英文:</summary>
  86. Basically I&#39;m learning pygame. and I&#39;m learning from a tutorial, I&#39;m not doing 100% the same but mostly, now I can&#39;t figure out why the tutorial works and mine doesn&#39;t, in terms of colliding with tiles. Here&#39;s my code:

import sys

import pygame

clock = pygame.time.Clock() # initiate clock
from pygame.locals import *

pygame.init() # initiate pygame

WINDOW = (600, 400)
screen = pygame.display.set_mode(WINDOW, 0, 32)
pygame.display.set_caption("window") # set window name
display = pygame.Surface(
(300, 200)
) # create display surface, basically makes another image, since all images are surfaces.. kinda

you can render one surface onto anoher surface

player_image = pygame.image.load(
"images\me1ns.png"
).convert_alpha() # load player image, degine player image as variable
player_y_momentum = 0

grass_image = pygame.image.load("images\grass.png").convert()
dirt_image = pygame.image.load("images\dirt.png").convert()
game_map = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2],
[1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]
TILE_SIZE = 16 # size of each tile

def collsion_test(rect, tiles):
hit_col = []
for tile in tiles:
if rect.colliderect(tile):
hit_col.append(tile)
return hit_col
# tile collision test, returns a list of tiles that collided with the rect

def move(
rect, movement, tiles
): # thing that's being moved, how it's moved, and what tiles it's colliding with
rect.x += movement[0] # move on the x axis
collsions = collsion_test(
rect, tiles
) # returns a list of tiles that collided with the rect
for tile in collsions:
if movement[0] > 0:
rect.right = tile.left
elif movement[0] < 0:
rect.left = tile.right
# if if right, place on left, if left palce on right
rect.y += movement[1] # move on the x axis
collsions = collsion_test(
rect, tiles
) # returns a list of tiles that collided with the rect
for tile in collsions:
if movement[1] > 0:
rect.bottom = tile.top
elif movement[1] < 0:
rect.top = tile.bottom
# if up place on bottom and vice versa
return rect

colors

BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLUE = (0, 0, 255)
GRAY = (128, 128, 128)
LBLUE = (146, 244, 255)

moving_right = False
moving_left = False
player_rect = pygame.Rect(50, 50, player_image.get_width(), player_image.get_height())

getting the player rect(collision), x,y,w,h

when defining a rect, use pygame.Rect(x,y,w,h), not use pygame.rect(x,y,w,h)

while True:
display.fill(LBLUE) # fills screen with color, put images after this
tile_rects = []
y = 0
for row in game_map:
x = 0
for tile in row:
if tile == 2:
display.blit(grass_image, (x * TILE_SIZE, y * TILE_SIZE))
if tile == 1:
display.blit(dirt_image, (x * TILE_SIZE, y * TILE_SIZE))
if tile != 0:
tile_rects.append(
pygame.Rect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE)
)
x += 1
y += 1
# displays tile map, x and y are the location of the tile. We blit based on what the number is, tile is the individual number in map
# multiple by tile size to get true full size.
# we make a list of all the tiles in the map, then make a rect for each tile, base on the position of the tile, and ofc TILE_SIZE, TILE_SIZE

  1. # update player collision location
  2. # colliderect checks if someting is collidign with something else
  3. # movement
  4. player_movement = [0, 0]
  5. if moving_right:
  6. player_movement[0] += 2
  7. if moving_left:
  8. player_movement[0] -= 2
  9. player_movement[1] += player_y_momentum
  10. player_y_momentum += 0.2
  11. if player_y_momentum &gt; 3:
  12. player_y_momentum = 3
  13. player_rect = move(player_rect, player_movement, tile_rects)
  14. # moves the player, does collision testing, and returns the new rect.
  15. display.blit(player_image, (player_rect.x, player_rect.y))
  16. # puts player image on the screen, at specific location
  17. # by having it so that you make change, and then check, you can hold and still move\
  18. for event in pygame.event.get(): # main loop for pygame events
  19. if event.type == QUIT:
  20. pygame.quit()
  21. print(tile_rects)
  22. sys.exit()
  23. if event.type == KEYDOWN: # loop for key pressed down
  24. if event.key == K_RIGHT:
  25. moving_right = True
  26. if event.key == K_LEFT:
  27. moving_left = True
  28. if event.type == KEYUP: # checks if key is pressed up
  29. if event.key == K_RIGHT:
  30. moving_right = False
  31. if event.key == K_LEFT:
  32. moving_left = False
  33. # changes the size of one thing to another
  34. screen.blit(pygame.transform.scale(display, (600, 400)), (0, 0))
  35. # what to blit and where
  36. pygame.display.update() # updates the screen
  37. clock.tick(60) # 60 fps, has game running at 60 fps
  1. I expect to not fall through the ground and istead just be on top of it. I think I understand how things work, not 100% though.
  2. </details>
  3. # 答案1
  4. **得分**: 1
  5. 你似乎有一个 "早期 `return`" 语句,你错误地将其放在**循环内部**,因此只有在此循环内查看了第一个图块:
  6. ```python
  7. def collsion_test(rect, tiles):
  8. hit_col = []
  9. for tile in tiles:
  10. if rect.colliderect(tile):
  11. hit_col.append(tile)
  12. return hit_col

尝试更改为以下内容(请注意已更正的return语句的缩进):

  1. def collsion_test(rect, tiles):
  2. hit_col = []
  3. for tile in tiles:
  4. if rect.colliderect(tile):
  5. hit_col.append(tile)
  6. return hit_col
英文:

You appear to have an "early return" statement that you mistakenly put inside the loop, so only the first tile is looked at within this loop:

  1. def collsion_test(rect, tiles):
  2. hit_col = []
  3. for tile in tiles:
  4. if rect.colliderect(tile):
  5. hit_col.append(tile)
  6. return hit_col

Try changing to this (note the corrected un-indentation of the return statement:

  1. def collsion_test(rect, tiles):
  2. hit_col = []
  3. for tile in tiles:
  4. if rect.colliderect(tile):
  5. hit_col.append(tile)
  6. return hit_col

huangapple
  • 本文由 发表于 2023年6月22日 06:32:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76527545.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定