问题描述
我有一个使用pygame在python中用玩家和墙壁创建的地图即时通讯
I have a map im creating in python using pygame with a player and walls:
import pygame
x = 25
y = 19
collision = [
[0,0,0,37],#vertical
[4,23,4,27],
[12,18,12,25],
[13,0,13,1],
[13,4,13,7],
[13,10,13,11],
[15,13,15,18],
[15,23,15,37],
[19,0,19,13],
[29,25,29,26],
[29,29,29,37],
[35,0,35,9],
[35,12,35,17],
[35,21,35,26],
[35,29,35,37],
[36,17,36,21],
[44,0,44,6],
[44,10,44,17],
[54,0,54,17],
[0,0,19,0],#horizontal
[35,0,46,0],
[52,0,54,0],
[13,5,19,5],
[19,6,24,6],
[30,6,35,6],
[0,13,10,13],
[15,13,21,13],
[25,13,44,13],
[35,17,36,17],
[44,17,54,17],
[35,21,36,21],
[4,23,12,23],
[0,25,4,25],
[19,25,36,25],
[4,27,12,27],
[0,37,35,37],
[14,12,14,12],#dots
[11,14,11,14]
]
white = (255,255,255)
black = (0,0,0)
red = (255,0,0)
pygame.init()
screen = pygame.display.set_mode((200,200))
pygame.display.set_caption('Collision')
screen.fill(white)
for list in collision:#draw map
pygame.draw.line(screen,black,(list[0],list[1]),(list[2],list[3]),1)
pygame.draw.line(screen,red,(x,y),(x,y),1)#draw player
pygame.display.update()
while(True):
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
for list in collision:
#---START OF EQUATION---#
if(list[0]<=list[2] and not(y-1==list[1] and x>=list[0] and x<=list[2])) or (list[0]>list[2] and not(y-1==list[1] and x>=list[2] and x<=list[0])):#updated
#---END OF EQUATION---#
pygame.draw.line(screen,white,(x,y),(x,y),1)
y-=1
pygame.draw.line(screen,red,(x,y),(x,y),1)
break
elif event.key == pygame.K_s:
for list in collision:
if(list[0]<=list[2] and not(y+1==list[1] and x>=list[0] and x<=list[2])) or (list[0]>list[2] and not(y+1==list[1] and x>=list[2] and x<=list[0])):#updated
pygame.draw.line(screen,white,(x,y),(x,y),1)
y+=1
pygame.draw.line(screen,red,(x,y),(x,y),1)
break
elif event.key == pygame.K_a:
for list in collision:
if(list[1]<=list[3] and not(x-1==list[0] and y>=list[1] and y<=list[3])) or (list[1]>list[3] and not(x-1==list[0] and y>=list[3] and y<=list[1])):#updated
pygame.draw.line(screen,white,(x,y),(x,y),1)
x-=1
pygame.draw.line(screen,red,(x,y),(x,y),1)
break
elif event.key == pygame.K_d:
for list in collision:
if(list[1]<=list[3] and not(x+1==list[0] and y>=list[1] and y<=list[3])) or (list[1]>list[3] and not(x+1==list[0] and y>=list[3] and y<=list[1])):#updated
pygame.draw.line(screen,white,(x,y),(x,y),1)
x+=1
pygame.draw.line(screen,red,(x,y),(x,y),1)
break
pygame.display.update()
方程式,以更轻松"的格式读取:
The equation, in an 'easier' to read format:
if (
list[0]<=list[2]
and not(
y-1==list[1]
and
x>=list[0]
and
x<=list[2])
)
or
(
list[0]>list[2]
and not(
y-1==list[1]
and
x>=list[2]
and
x<=list[0]
)
)
向下检测到按键的地方是即时通讯出现问题的地方.我已经对该方法进行了多次测试,但始终会导致错误的功能.
Down where keypresses are being detected is where im having an issue. I have tested this method several times, but it always results in the wrong functionality.
每次用户按下w/a/s/d时,我都会在代码列表中循环遍历墙壁",并测试是否能够在没有墙壁的情况下穿过该空间.假设在此处有一堵墙,红点是玩家.如何通过修改方程式来防止玩家向上或向左移动?
I am having my code loop through a list of 'walls' every time the user presses w/a/s/d, and tests if they are capable of going through that space if no wall is present. Lets say that there is a wall like this here with the red dot being the player. How can I prevent the player from moving up or to the left with modification of the equation?
用于测试碰撞的方程式(每个方向都不同,在这种情况下是向上的方向):
Equation thats being used to test for collision (is different for every direction, in this case is for the up direction):
if(list[0]<=list[2] and not(y-1==list[1] and x>=list[0] and x<=list[2])) or (list[0]>list[2] and not(y-1==list[1] and x>=list[2] and x<=list[0]))
推荐答案
问题是因为它检查了第一堵墙,它可能不会发生碰撞,然后才开始移动-但它没有检查其他可能发生碰撞的墙.
Problem is because it checks first wall and it may not collidate and then it makes move - but it didn't check other walls which can collidate.
在移动播放器之前,您必须检查所有墙壁.
You have to check all walls before you can move player.
所有动作几乎相同-您仅使用不同的x
,y
来检查新位置-因此我创建了一个功能来对其进行检查.
All moves are almost the same - you use only different x
, y
to check new position - so I create one function to check it.
def check_collisions(walls, player_new_x, player_new_y):
for x1, y1, x2, y2 in walls:
if x1 <= player_new_x <= x2 and y1 <= player_new_y <= y2:
print("COLLIDE")
return True
return False
完整代码
import pygame
# --- constants --- (UPPER_CASE_NAMES)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
FPS = 5
# --- functions --- (lower_case_names)
def check_collisions(walls, player_new_x, player_new_y):
for x1, y1, x2, y2 in walls:
if x1 <= player_new_x <= x2 and y1 <= player_new_y <= y2:
print("COLLIDE")
return True
return False
# --- main ---
collision = [
[0,0,0,37],#vertical
[4,23,4,27],
[12,18,12,25],
[13,0,13,1],
[13,4,13,7],
[13,10,13,11],
[15,13,15,18],
[15,23,15,37],
[19,0,19,13],
[29,25,29,26],
[29,29,29,37],
[35,0,35,9],
[35,12,35,17],
[35,21,35,26],
[35,29,35,37],
[36,17,36,21],
[44,0,44,6],
[44,10,44,17],
[54,0,54,17],
[0,0,19,0],#horizontal
[35,0,46,0],
[52,0,54,0],
[13,5,19,5],
[19,6,24,6],
[30,6,35,6],
[0,13,10,13],
[15,13,21,13],
[25,13,44,13],
[35,17,36,17],
[44,17,54,17],
[35,21,36,21],
[4,23,12,23],
[0,25,4,25],
[19,25,36,25],
[4,27,12,27],
[0,37,35,37],
[14,12,14,12],#dots
[11,14,11,14]
]
x = 25
y = 19
# - init -
pygame.init()
screen = pygame.display.set_mode((200,200))
screen.fill(WHITE)
# - draws -
for item in collision:
pygame.draw.line(screen, BLACK, item[:2], item[2:], 1)
pygame.draw.line(screen, RED, (x, y), (x, y), 1)
pygame.display.update()
# - mainloop -
clock = pygame.time.Clock()
while True:
moved = False
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
new_x = x
new_y = y - 1
collide = check_collisions(collision, new_x, new_y)
if not collide:
pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
x = new_x
y = new_y
pygame.draw.line(screen, RED, (x, y), (x, y), 1)
elif event.key == pygame.K_s:
new_x = x
new_y = y + 1
collide = check_collisions(collision, new_x, new_y)
if not collide:
pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
x = new_x
y = new_y
pygame.draw.line(screen, RED, (x, y), (x, y), 1)
elif event.key == pygame.K_a:
new_x = x - 1
new_y = y
collide = check_collisions(collision, new_x, new_y)
if not collide:
pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
x = new_x
y = new_y
pygame.draw.line(screen, RED, (x, y), (x, y), 1)
elif event.key == pygame.K_d:
new_x = x + 1
new_y = y
collide = check_collisions(collision, new_x, new_y)
if not collide:
pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
x = new_x
y = new_y
pygame.draw.line(screen, RED, (x, y), (x, y), 1)
pygame.display.update()
clock.tick(FPS) # to display less frame and use less CPU
版本,您可以在其中按住键,它会移动-无需多次按下
version in which you can keep key pressed and it will move - you don't have to press many times
import pygame
# --- constants --- (UPPER_CASE_NAMES)
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
FPS = 5
# --- functions --- (lower_case_names)
def check_collisions(walls, player_new_x, player_new_y):
for x1, y1, x2, y2 in walls:
if x1 <= player_new_x <= x2 and y1 <= player_new_y <= y2:
print("COLLIDE")
return True
return False
# --- main ---
collision = [
[0,0,0,37],#vertical
[4,23,4,27],
[12,18,12,25],
[13,0,13,1],
[13,4,13,7],
[13,10,13,11],
[15,13,15,18],
[15,23,15,37],
[19,0,19,13],
[29,25,29,26],
[29,29,29,37],
[35,0,35,9],
[35,12,35,17],
[35,21,35,26],
[35,29,35,37],
[36,17,36,21],
[44,0,44,6],
[44,10,44,17],
[54,0,54,17],
[0,0,19,0],#horizontal
[35,0,46,0],
[52,0,54,0],
[13,5,19,5],
[19,6,24,6],
[30,6,35,6],
[0,13,10,13],
[15,13,21,13],
[25,13,44,13],
[35,17,36,17],
[44,17,54,17],
[35,21,36,21],
[4,23,12,23],
[0,25,4,25],
[19,25,36,25],
[4,27,12,27],
[0,37,35,37],
[14,12,14,12],#dots
[11,14,11,14]
]
x = 25
y = 19
# - init -
pygame.init()
screen = pygame.display.set_mode((200,200))
screen.fill(WHITE)
# - draws -
for item in collision:
pygame.draw.line(screen, BLACK, item[:2], item[2:], 1)
pygame.draw.line(screen, RED, (x, y), (x, y), 1)
pygame.display.update()
# - mainloop -
clock = pygame.time.Clock()
move_x = 0
move_y = 0
while True:
# - events -
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_w:
move_y = -1
elif event.key == pygame.K_s:
move_y = 1
elif event.key == pygame.K_a:
move_x = -1
elif event.key == pygame.K_d:
move_x = 1
elif event.type == pygame.KEYUP:
if event.key == pygame.K_w:
move_y = 0
elif event.key == pygame.K_s:
move_y = 0
elif event.key == pygame.K_a:
move_x = 0
elif event.key == pygame.K_d:
move_x = 0
# - update -
if move_x != 0 or move_y != 0:
new_x = x + move_x
new_y = y + move_y
collide = check_collisions(collision, new_x, new_y)
if not collide:
pygame.draw.line(screen, WHITE, (x, y), (x, y), 1)
x = new_x
y = new_y
pygame.draw.line(screen, RED, (x, y), (x, y), 1)
pygame.display.update()
clock.tick(FPS) # to display less frame and use less CPU
这篇关于pygame列表冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!