我正在尝试用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 distancemath.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)


python - Python:蛇段“流动”而不是“捕捉”到蛇的头部位置-LMLPHP



关于评论:


  如果蛇的头部触碰到任何段,我该如何调用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/

10-12 18:13