提问人:ButterySpirit 提问时间:11/13/2023 更新时间:11/13/2023 访问量:55
冲突的“if”语句
Conflicting "if" statements
问:
因此,我正在尝试与我的播放器一起实现适当的墙壁碰撞检测,类似于 isaac 的绑定工作原理(您在按下两个键时撞到墙上,当您撞到墙上时,向墙的移动被禁用,但您可以继续沿另一个键的方向在墙上滑动)。因此,我尝试在我的播放器类的 update 方法中创建两个不同的 if 语句,分别处理左/右冲突和上/下冲突,但似乎 if 语句的顺序似乎相互冲突
def update(self,dt)
prev_x = self.x
prev_y = self.y
# Update the player's position
self.world_x += dx
self.world_y += dy
self.x += dx
self.y += dy
# Check for collisions with the "Walls" layer for horizontal movement
if self.detect_collision_with_walls(self.walls_layer) and self.moving_left:
self.x = prev_x
self.world_x = self.x
if self.detect_collision_with_walls(self.walls_layer) and self.moving_right:
self.x = prev_x
self.world_x = self.x
# Check for collisions with the "Walls" layer for vertical movement
if self.detect_collision_with_walls(self.walls_layer) and self.moving_up:
self.y = prev_y
self.world_y = self.y
if self.detect_collision_with_walls(self.walls_layer) and self.moving_down:
self.y = prev_y
self.world_y = self.y
问题是只有前两个语句语句按应有的方式执行,当后两个语句运行时,它们会与顶部语句发生冲突,因为两者在技术上同时是正确的。它将玩家锁定在原位,直到导致碰撞的钥匙被释放,因为它本质上是这样做的:
# Check for collisions with the "Walls" layer for vertical movement
if self.detect_collision_with_walls(self.walls_layer) and self.moving_up:
self.y = prev_y
self.world_y = self.y
self.x = prev_x
self.world_x = self.x
if self.detect_collision_with_walls(self.walls_layer) and self.moving_down:
self.y = prev_y
self.world_y = self.y
self.x=prev_x
self.world_x = self.x
我尝试了 elif 语句,这似乎没有帮助,因为当执行优先级较低的语句时,这两个条件在技术上仍然是正确的
答:
0赞
Brayden
11/13/2023
#1
为了防止锁定,同时仍然能够靠墙滑动,您需要知道要取消的方向(x 或 y)。您需要执行以下操作:
if self.colliding_with_wall(self.walls_layer, Direction.LEFT) and self.moving_left:
self.x = prev_x
self.world_x = self.x
if self.colliding_with_wall(self.walls_layer, Direction.RIGHT) and self.moving_right:
self.x = prev_x
self.world_x = self.x
# Check for collisions with the "Walls" layer for vertical movement
if self.colliding_with_wall(self.walls_layer, Direction.ABOVE) and self.moving_up:
self.y = prev_y
self.world_y = self.y
if self.colliding_with_wall(self.walls_layer, Direction.BELOW) and self.moving_down:
self.y = prev_y
self.world_y = self.y
确保同时实现该函数:
from enum import Enum, unique
@unique
class Direction(Enum):
ABOVE = "above"
BELOW = "below"
LEFT = "left"
RIGHT = "right"
def colliding_with_wall(walls, from_direction: Direction) -> bool:
# Do the same loop to iterate over the walls as before but
# add an additional check for which direction the player
# hit the wall from.
# Save the positions of the wall that the player encountered.
# I'm not sure if you have 2D or 3D walls in your game so I'll just
# do a 3D version and you can remove the extra code if yours is
# only 2D.
# Make a tuple of the wall's coordinates
# I used ((top_left_x, top_left_y), (bottom_right_x, bottom_right_y))
# Used made-up numbers here. Make sure you replace it with the
# actual coordinates of the wall.
wall = ((5, 10), (6, 14))
# I assume that your player isn't single point so you're gonna need
# to do something similar for the player.
# Unless, of course, your game works on a tile system where the grid
# is something like 8x8. In that case, the player only has one
# coordinate.
player = ((3, 9), (5, 11))
# Here, I'll assume that the origin of your game (0, 0) is in the
# top-left corner of the window. And that y increases going down.
# I'll also assume that you use a `return false` before this point if
# The player is not touching a wall at all.
if from_direction == Direction.ABOVE:
# Without more information about how your coordinate system works
# (if it's like Minecraft's position system where the coordinate
# values are floats/a large number with lots of precision, or
# if it uses a tile map where you jump from tile to tile)
# Check if the player is within the edges of the wall
if player[0][0] < wall[1][0] and player[1][0] > wall[0][0]:
# We're checking if the player hit the wall so the player
# must be below the wall.
# Use the threshold value (5 in this case) to adjust the
# collision sensitivity based on how much your player moves
# between function calls.
if abs(player[0][1] - wall[1][1]) < 5:
return true
elif from_direction == Direction.BELOW:
if player[0][0] < wall[1][0] and player[1][0] > wall[0][0]:
if abs(player[1][1] - wall[0][1]) < 5:
return true
elif from_direction == Direction.LEFT:
if player[0][1] < wall[1][1] and player[1][1] > wall[0][1]:
if abs(player[0][0] - wall[1][0]) < 5:
return true
elif from_direction == Direction.RIGHT:
if player[0][1] < wall[1][1] and player[1][1] > wall[0][1]:
if abs(player[1][0] - wall[0][0]) < 5:
return true
else:
# An invalid direction was entered so you can throw an error
# here or just remove `else:` and ignore it.
# If you remove `else:`, you must return either true of false.
如果不想对 Direction 枚举的值进行硬编码,也可以使用 .根据 Python 的枚举文档所说的话,您不应该在这里需要。auto
@unique
from enum import Enum, auto
class Direction(Enum):
ABOVE = auto()
BELOW = auto()
LEFT = auto()
RIGHT = auto()
这应该可以让你防止穿过墙壁,同时仍然能够向另一个方向移动。请记住,StackOverflow 并不完全是一个 IDE,我的意思是没有语法检查,我没有时间实际测试它,所以请确保检查并测试此代码。
另外,我会将移动更改为仅在不接触墙壁时移动,而不是移动,如果您正在触摸墙壁,则向后移动。这在我的脑海中更有意义,但这种方式也很好。
评论
if
elif
else
elif