我正在尝试用python制作蛇游戏,我希望当用户按下WASD键时蛇的片段能够流动,而不是让片段捕捉到用户所需的方向
import pygame
import random
import time
pygame.init()
win = pygame.display.set_mode((800,600))
pygame.display.set_caption("Pygame")
clock = pygame.time.Clock()
x = 30
y = 30
x2 = x
y2 = random.randrange(1,601-30)
vel = 2
run = True
facing = 0
direction = 0
text = pygame.font.SysFont('Times New Roman',30)
score = 0
segments = []
green = ((0,128,0))
white = ((255,255,255))
counting = 0
segmentTime = time.time()
class segmentClass():
def __init__(self,x,y,pos,color):
self.x = x
self.y = y
self.pos = pos
self.color = color
def draw(self,win):
pygame.draw.rect(win,(self.color),(self.x,self.y,30,30))
def gameOver():
global run
run = False
def segmentGrowth():
global x2
global y2
global score
global vel
global ammount
segments.append(segmentClass(x,y,len(segments)+1,green))
ammount = 0
x2 = random.randrange(1,801-30)
y2 = random.randrange(1,601-30)
score += 1
print(vel)
while run:
currentTime = time.time()
clock.tick(60)
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
vel += (score*0.0001)
keys = pygame.key.get_pressed()
if keys[pygame.K_w]:
if direction != 1:
direction = 1
facing = -1
if keys[pygame.K_s]:
if direction != 1:
direction = 1
facing = 1
if keys[pygame.K_a]:
if direction != 0:
direction = 0
facing = -1
if keys[pygame.K_d]:
if direction != 0:
direction = 0
facing = 1
if direction == 1:
y += (vel*facing)
else:
x += (vel*facing)
if x > x2 and x < x2 + 30 or x + 30 > x2 and x + 30 < x2 + 30:
if y == y2:
segmentGrowth()
if y > y2 and y < y2 + 30 or y + 30 > y2 and y + 30 < y2 + 30:
segmentGrowth()
if y > y2 and y < y2 + 30 or y + 30 > y2 and y + 30 < y2 + 30:
if x == x2:
segmentGrowth()
if x > x2 and x < x2 + 30 or x + 30 > x2 and x + 30 < x2 + 30:
segmentGrowth()
if x > 800-30 or y > 600-30 or x < 0 or y < 0:
gameOver()
win.fill((0,0,0))
for segment in segments:
if direction == 0: #X value
if facing == 1: #Right
segment.x = x - (35 * segment.pos)
segment.y = y
else: #Left
segment.x = x + (35 * segment.pos)
segment.y = y
else: #Y value
if facing == -1: #Up
segment.y = y + (35 * segment.pos)
segment.x = x
else:#Down
segment.y = y - (35 * segment.pos)
segment.x = x
for segment in segments:
segment.draw(win)
scoreDisplay = text.render(str(score),1,(255,255,255))
win.blit(scoreDisplay,(760,0))
pygame.draw.rect(win,(0,128,0),(x,y,30,30))
pygame.draw.rect(win,(255,0,0),(x2,y2,30,30))
pygame.display.update()
pygame.quit()
它是如何工作的,有一个段列表和一个用于每个段信息(即x,y等)的类。每当用户与红色多维数据集发生碰撞时,我都会在该列表中追加一个细分类的实例。我有以下代码:
for segment in segments:
if direction == 0: #X value
if facing == 1: #Right
segment.x = x - (35 * segment.pos)
segment.y = y
else: #Left
segment.x = x + (35 * segment.pos)
segment.y = y
else: #Y value
if facing == -1: #Up
segment.y = y + (35 * segment.pos)
segment.x = x
else:#Down
segment.y = y - (35 * segment.pos)
segment.x = x
当玩家决定他们想要蛇移动的方向时,这将一次移动蛇的所有部分。但是,这些片段会立即捕捉到头部的x位置,而不是一次平滑地移动一个。如果有人可以帮助我,那就太好了。谢谢!
最佳答案
不错的游戏。我建议创建一个点列表,这是蛇头位置((x, y)
)的元组列表。将每个位置添加到列表中:
pts = []
while run:
# [...]
pts.append((x, y))
创建一个函数,该函数通过计算到蛇首的索引(
i
)来计算蛇的一部分的位置。到头部的距离必须为lenToI = i * 35
。到点之间的距离可以通过Euclidean distance(
math.sqrt((px-pnx)*(px-pnx) + (py-pny)*(py-pny))
,其中点是(px, py)
和(pnx, pny)
来计算。如果点之间的距离(lenAct
)的总和超过到点的长度( lenToI
),然后找到零件i
的位置:def getPos(i):
global pts
lenToI = i * 35
lenAct = 0
px, py = pts[-1]
for j in reversed(range(len(pts)-1)):
px, py = pts[j]
pnx, pny = pts[j+1]
lenAct += math.sqrt((px-pnx)*(px-pnx) + (py-pny)*(py-pny))
if lenAct >= lenToI:
break
return (px, py)
编写另一个函数
cutPts
,该函数将从列表中删除点,而不再需要这些点:def cutPts(i):
global pts
lenToI = i * 35
lenAct = 0
cut_i = 0
px, py = pts[0]
for j in reversed(range(len(pts)-1)):
px, py = pts[j]
pnx, pny = pts[j+1]
lenAct += math.sqrt((px-pnx)*(px-pnx) + (py-pny)*(py-pny))
if lenAct >= lenToI:
break
cut_i = j
del pts[:cut_i]
更新循环中线段的位置:
pts.append((x, y))
for i in range(len(segments)):
segments[i].x, segments[i].y = getPos(len(segments)-i)
cutPts(len(segments)+1)
关于评论:
如果蛇的头部触碰到任何段,我该如何调用
gameOver()
函数?我尝试使用if语句使用segment.x和segment.y来检查碰撞(与对苹果相同),但是由于蛇的第二个部分在蛇移动时始终与头部重叠,因此无法正常工作。请注意,除非将方向更改为相反方向,否则头部永远无法“触摸”第一段,但是这种情况可以通过额外的测试轻松进行。
检查头部是否“击中”了除与头部相连的第一节以外的任何节段就足够了。
使用
pygame.Rect.colliderect
检查矩形线段的交点:def selfCollide():
for i in range(len(segments)-1):
s = segments[i]
if pygame.Rect(x, y, 30, 30).colliderect(pygame.Rect(s.x, s.y, 30, 30)):
return True
return False
if selfCollide():
gameOver()
关于python - Python:蛇段“流动”而不是“捕捉”到蛇的头部位置,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54273041/