如何在Pygame上使用瓷砖碰撞使用精灵的瓷砖地图?
我需要帮助找出目前在Pygame中制作的平台游戏的瓷砖碰撞。我有运动,重力工作以及瓷砖地图,但我真的不明白如何与精灵碰撞。我确实列出了一个列表,将所有不是0(1或2)的图块附加到一个名为Tile_collisisions的列表中(请参阅第113行),但我真的不知道该怎么办。另外,您可以忽略评论的代码,这只是一次失败的尝试。我正在尝试使这一点尽可能简单,而没有课程,因为这些作业不允许这样做。
^如果没有所有PNG,就不会运行“ main.py”文件,因此,如果您想运行它,则可能必须下载所有PNG,对不起!
import pygame as py
from tile_map import map
# Pygame setup
py.init()
clock = py.time.Clock()
# COLOURS
bg_colour = (110, 121, 228)
sky_colour = (190, 220, 255)
start_colour = (225, 225, 225)
screen_width = 1280
screen_height = 720
screen = py.display.set_mode((screen_width, screen_height))
p_sprite = py.image.load("plant_drone.png")
p_rect = p_sprite.get_rect()
p_rect.centery = screen_height - 32
grass_block = py.image.load("grass_block.png")
dirt_block = py.image.load("dirt_block.png")
# def collisions(rect, tiles):
# collider_list = []
# for tile in tiles:
# if rect.colliderect(tile):
# collider_list.append(tile)
# return collider_list
#
# def move(rect, movement, tiles):
# collision_types = {"top": False, "bottom": False, "right": False, "left": False}
#
# rect.x += movement[0]
# collider_list = collisions(rect, tile)
# for tile in collider_list:
# if movement[0] > 0:
# rect.right = tile.left
# collision_types["right"] = True
# elif movement[0] < 0:
# rect.left = tile.right
# collision_types["left"] = True
#
# rect.y += movement[1]
# collider_list = collisions(rect, tile)
# for tile in collider_list:
# if movement[1] > 0:
# rect.bottom = tile.top
# collision_types["bottom"] = True
# elif movement[1] < 0:
# rect.top = tile.bottom
# collision_types["top"] = True
#
# return rect, collision_types
# MAIN MENU
def menu():
py.display.set_caption("Game Menu")
while True:
start()
py.display.update()
clock.tick(60)
# START OPTION (BLINKING TEXT)
def start():
start_font = py.font.Font('Halogen.otf', 50)
bg = py.image.load("GM Treble Quest V2.png")
bg_rect = py.Rect((0, 0), bg.get_size())
screen.blit(bg, bg_rect)
n = 0
while True:
start = start_font.render(("Press Enter To Play"), True, start_colour)
if n % 2 == 0:
screen.blit(start, (450, 625))
clock.tick(50000)
else:
screen.blit(bg, bg_rect)
n += 0.5
py.display.update()
clock.tick(3)
for event in py.event.get():
if event.type == py.QUIT:
exit()
elif event.type == py.KEYDOWN:
if event.key == py.K_RETURN:
play()
# GAME
def play():
py.display.set_caption("Treble Quest")
player_y, player_x = p_rect.bottom, 32
velocity_x, velocity_y = 5, 0
ground = 480
gravity_factor = 0.35
acl_factor = -12
while True:
clock.tick(100)
vertical_acl = gravity_factor
screen.fill(sky_colour)
screen.blit(p_sprite, p_rect)
# TILE MAP
tile_collisions = []
y = 0
for row in map:
x = 0
for tile in row:
if tile == 1:
screen.blit(dirt_block, (x * 32, y * 32))
if tile == 2:
screen.blit(grass_block, (x * 32, y * 32))
if tile != 0:
tile_collisions.append(py.Rect(x * 32, y * 32, 32, 32))
x += 1
y += 1
screen.blit(p_sprite, p_rect)
# player_movement = [0, 0]
# if moving_right == True:
# player_movement[0] += 2
# if moving_left == True:
# player_movement[0] -= 2
# player_movement[1] += player
# MOVEMENT
for event in py.event.get():
if event.type == py.QUIT:
exit()
if event.type == py.KEYDOWN:
if velocity_y == 0 and event.key == py.K_w:
vertical_acl = acl_factor
velocity_y += vertical_acl
player_y += velocity_y
if player_y > ground:
player_y = ground
velocity_y = 0
vertical_acl = 0
p_rect.bottom = round(player_y)
keys = py.key.get_pressed()
player_x += (keys[py.K_d] - keys[py.K_a]) * velocity_x
p_rect.centerx = player_x
py.display.update()
menu()
I need help figuring out tile collisions for a platformer I'm currently making in Pygame. I have movement, with gravity working, as well as a tile map, but I don't really understand how to get collisions with the sprites working. I did make a list that appends all of the tiles that aren't 0 (so 1 or 2) into a list called tile_collisions (see line 113) but I don't really know what to do with that. Also, you can ignore the commented-out code, that was just a failed attempt. I'm trying to make this as simple as possible, without classes, because those aren't allowed for this assignment.
https://github.com/Night-28/Treble-Quest.git
^ The "main.py" file won't run without all of the pngs so if you do want to run it, you might have to download all of them, sorry!
import pygame as py
from tile_map import map
# Pygame setup
py.init()
clock = py.time.Clock()
# COLOURS
bg_colour = (110, 121, 228)
sky_colour = (190, 220, 255)
start_colour = (225, 225, 225)
screen_width = 1280
screen_height = 720
screen = py.display.set_mode((screen_width, screen_height))
p_sprite = py.image.load("plant_drone.png")
p_rect = p_sprite.get_rect()
p_rect.centery = screen_height - 32
grass_block = py.image.load("grass_block.png")
dirt_block = py.image.load("dirt_block.png")
# def collisions(rect, tiles):
# collider_list = []
# for tile in tiles:
# if rect.colliderect(tile):
# collider_list.append(tile)
# return collider_list
#
# def move(rect, movement, tiles):
# collision_types = {"top": False, "bottom": False, "right": False, "left": False}
#
# rect.x += movement[0]
# collider_list = collisions(rect, tile)
# for tile in collider_list:
# if movement[0] > 0:
# rect.right = tile.left
# collision_types["right"] = True
# elif movement[0] < 0:
# rect.left = tile.right
# collision_types["left"] = True
#
# rect.y += movement[1]
# collider_list = collisions(rect, tile)
# for tile in collider_list:
# if movement[1] > 0:
# rect.bottom = tile.top
# collision_types["bottom"] = True
# elif movement[1] < 0:
# rect.top = tile.bottom
# collision_types["top"] = True
#
# return rect, collision_types
# MAIN MENU
def menu():
py.display.set_caption("Game Menu")
while True:
start()
py.display.update()
clock.tick(60)
# START OPTION (BLINKING TEXT)
def start():
start_font = py.font.Font('Halogen.otf', 50)
bg = py.image.load("GM Treble Quest V2.png")
bg_rect = py.Rect((0, 0), bg.get_size())
screen.blit(bg, bg_rect)
n = 0
while True:
start = start_font.render(("Press Enter To Play"), True, start_colour)
if n % 2 == 0:
screen.blit(start, (450, 625))
clock.tick(50000)
else:
screen.blit(bg, bg_rect)
n += 0.5
py.display.update()
clock.tick(3)
for event in py.event.get():
if event.type == py.QUIT:
exit()
elif event.type == py.KEYDOWN:
if event.key == py.K_RETURN:
play()
# GAME
def play():
py.display.set_caption("Treble Quest")
player_y, player_x = p_rect.bottom, 32
velocity_x, velocity_y = 5, 0
ground = 480
gravity_factor = 0.35
acl_factor = -12
while True:
clock.tick(100)
vertical_acl = gravity_factor
screen.fill(sky_colour)
screen.blit(p_sprite, p_rect)
# TILE MAP
tile_collisions = []
y = 0
for row in map:
x = 0
for tile in row:
if tile == 1:
screen.blit(dirt_block, (x * 32, y * 32))
if tile == 2:
screen.blit(grass_block, (x * 32, y * 32))
if tile != 0:
tile_collisions.append(py.Rect(x * 32, y * 32, 32, 32))
x += 1
y += 1
screen.blit(p_sprite, p_rect)
# player_movement = [0, 0]
# if moving_right == True:
# player_movement[0] += 2
# if moving_left == True:
# player_movement[0] -= 2
# player_movement[1] += player
# MOVEMENT
for event in py.event.get():
if event.type == py.QUIT:
exit()
if event.type == py.KEYDOWN:
if velocity_y == 0 and event.key == py.K_w:
vertical_acl = acl_factor
velocity_y += vertical_acl
player_y += velocity_y
if player_y > ground:
player_y = ground
velocity_y = 0
vertical_acl = 0
p_rect.bottom = round(player_y)
keys = py.key.get_pressed()
player_x += (keys[py.K_d] - keys[py.K_a]) * velocity_x
p_rect.centerx = player_x
py.display.update()
menu()
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您的代码几乎在那里。
进行碰撞的一种简单方法是通过处理地图图块时创建的一束矩形进行迭代。检查每个矩形,以查看是否会与玩家的位置相交。
当您的播放器需要移动时,请计算移动打算要去的位置(实际上还没有移动玩家)。然后检查目标位置是否将与任何阻止者瓷砖重叠。如果没有重叠,请移动播放器。否则玩家停止。
在下面的示例代码中,我已经实现了其中的说明版本。尽管此方法很简单并且(主要是),但它遇到了一些问题:
实际上,您应该测试以解决这些失败。第二个问题很容易通过计算播放器沿所需方向移动多远,而只需移动较少的量即可。
请注意,我并不真正了解您的运动算法。似乎有速度,但没有停止。鉴于我只是在说明碰撞,所以我将其入侵了某种适合我需要显示的工作状态。
Your code is almost there.
A simple way to do collisions is to iterate through the bunch of rectangles created when you process the map tiles. Check each rectangle to see if it would intersect the player's position.
When your player needs to move, calculate where the move intends to go (don't actually move the player yet). Then check if the target location will overlap with any of the blocker-tiles. If there is no overlap, then move the player. Otherwise the player stops.
In the example code below, I've implemented a illustrative version of this. While this method is simple, and works (mostly), it suffers from a few issues:
Really you should test to cover these failures. The second issue is easy to fix by calculating how far the player can move in the desired direction, and only move this lesser amount.
Note that I didn't really understand your movement algorithm. There seems to be a velocity, but no stopping. Given I was just illustrating collisions, I hacked it into some kind of working state that suited what I needed to show.