如何解决Pygame:蛇的身体需要跟随头部
我一直在使用PyGame用Python开发蛇类游戏。它是众所周知的默认传统蛇游戏... 我正在进入第1期,我找不到一种使蛇的身体跟随头部的工作方法。我尝试了很多事情,总是得到相同的结果。
有人可以帮助我找到使身体跟随头部的方法吗? :)
蛇的每个身体部位都包含一个列表,[xPos,yPos,方向,nextDirection]
我现在正在用这段代码移动主体,但这不能正常工作:
if i == 0:
pass
elif i == 1:
snake[i][3] = snake[0][2]
else:
snake[i][3] = snake[i-1][2]
完整代码:
import sys
import random
def drawBackground():
evenOdd = False
global screenW,screenH,screen,block
for y in range(int(screenH/block)):
for x in range(int(screenW/block)):
if evenOdd == False:
color = (170,215,81)
evenOdd = True
else:
color = (162,209,73)
evenOdd = False
pygame.draw.rect(screen,color,(x * block,y * block,block,block))
def moveSnake():
global nextDir,snake
for i in range(len(snake)):
if snake[i][3] == "LEFT" and snake[i][1] % block == 0:
snake[i][2] = "LEFT"
snake[i][3] = ""
if snake[i][3] == "RIGHT" and snake[i][1] % block == 0:
snake[i][2] = "RIGHT"
snake[i][3] = ""
if snake[i][3] == "UP" and snake[i][0] % block == 0:
snake[i][2] = "UP"
snake[i][3] = ""
if snake[i][3] == "DOWN" and snake[i][0] % block == 0:
snake[i][2] = "DOWN"
snake[i][3] = ""
if snake[i][2] == "LEFT":
snake[i][0] -= 2
elif snake[i][2] == "UP":
snake[i][1] -= 2
elif snake[i][2] == "RIGHT":
snake[i][0] += 2
elif snake[i][2] == "DOWN":
snake[i][1] += 2
for i in range(len(snake)):
if i == 0:
pass
elif i == 1:
snake[i][3] = snake[0][2]
else:
snake[i][3] = snake[i-1][2]
pygame.init()
screen = pygame.display.set_mode((600,600))
clock = pygame.time.Clock()
screenW,screenH = pygame.display.get_surface().get_size()
block = 40
snake = [[200,160,"DOWN",""],[200,120,80,""]]
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT and snake[0][2] != "RIGHT":
snake[0][3] = "LEFT"
if event.key == pygame.K_UP and snake[0][2] != "DOWN":
snake[0][3] = "UP"
if event.key == pygame.K_RIGHT and snake[0][2] != "LEFT":
snake[0][3] = "RIGHT"
if event.key == pygame.K_DOWN and snake[0][2] != "UP":
snake[0][3] = "DOWN"
moveSnake()
drawBackground()
for i in range(len(snake)):
if i == 0:
pygame.draw.rect(screen,(70,115,232),(snake[i][0],snake[i][1],block))
else:
pygame.draw.rect(screen,(200,100,block))
pygame.display.update()
clock.tick(120)
解决方法
这是您需要的算法的指针-您在正确的轨道上。
认为蛇的身体是(x,y)坐标的数组,对应于蛇的每个片段。第一项(segment[0]
)是头。第二项(segment[1]
)是身体的第一部分,依此类推,直到到达尾部(segment[N]
)。
当蛇移动一帧时,头部向用户指定的某个方向前进。问题是如何处理其余部分(segment[1] - segment[n]
)?他们跟随头部,每个片段都跟随其前的片段。
所以,一招之后:
- 段0(头部)移动到用户方向指定的位置
- 第1段移动到之前由第0段占据的位置
- 第2段移动到之前由第1段占据的位置
- ...等等...
- 第N段移到第N-1段之前占据的位置。
因此,在伪代码中,这看起来像这样:
on a new frame:
iterating through the segments,starting with the end:
update segment[n] to have the coordinates of segment[n-1]
update segments[0] to the new coordinates specified by DIRECTION
希望可以帮助您了解可行的方法。
,我已对您的代码进行了一些修改,以使用class Snake
而不是原始列表来表示蛇体的当前位置。
代替跟踪所有身体部位的方向和下一方向,只需创建头部的下一个位置并去除身体的尾巴即可绘制,这将是更为简单的算法。为此,我使用了deque
容器,用户可以从左右两端追加并弹出。
目前,class snake
具有3个变量。direction
:蛇(头)的当前方向body
:使用deque
容器表示蛇体的当前位置。 [0]作为蛇的头。timer
:使蛇每1/3秒移动一次(如您所愿)
蛇还具有3个功能changeDirection()
/ moveSnake()
/ drawSnake()
。changeDirection()
:它的工作原理与您解析键击相同。
moveSnake()
:它根据头部的当前位置和方向来计算下一个头部应该在哪里。
之后,您只需要将下一个位置附加到body
(双端队列)的左侧,然后弹出body
的最后一个元素,该元素应为主体的尾部。这将模仿蛇的运动。drawSnake()
:它只是将蛇的身体吸引到屏幕上。
希望您靠近class Snake
并找到一些有用的东西。
import sys
import random
import pygame
from collections import deque
class Snake:
def __init__(self):
self.direction = "DOWN"
self.body = deque([[200,160],[200,120],80]])
self.timer = 0
self.directionChangable = True
def changeDirection(self,input):
if not self.directionChangable:
return
if input == "LEFT" and self.direction != "RIGHT":
self.direction = "LEFT"
if input == "UP" and self.direction != "DOWN":
self.direction = "UP"
if input == "RIGHT" and self.direction != "LEFT":
self.direction = "RIGHT"
if input == "DOWN" and self.direction != "UP":
self.direction = "DOWN"
self.directionChangable = False
def moveSnake(self):
self.timer += 1
if self.timer % block != 0:
return
self.directionChangable = True
self.timer = 0
nx,ny = self.body[0]
if self.direction == "UP":
ny -= block
if (ny < 0):
ny = screenH
elif self.direction == "DOWN":
ny += block
if (ny > screenH):
ny = 0
elif self.direction == "LEFT":
nx -= block
if (nx < 0):
nx = screenH
elif self.direction == "RIGHT":
nx += block
if (nx > screenW):
nx = 0
self.body.appendleft([nx,ny])
self.body.pop()
def drawSnake(self):
pygame.draw.rect(screen,(70,115,232),(self.body[0][0],self.body[0][1],block,block))
for pos in self.body:
pygame.draw.rect(screen,(200,100,(pos[0],pos[1],block))
def drawBackground():
evenOdd = False
global screenW,screenH,screen,block
for y in range(int(screenH/block)):
for x in range(int(screenW/block)):
if evenOdd is False:
color = (170,215,81)
evenOdd = True
else:
color = (162,209,73)
evenOdd = False
pygame.draw.rect(screen,color,(x * block,y * block,block))
pygame.init()
screen = pygame.display.set_mode((600,600))
clock = pygame.time.Clock()
screenW,screenH = pygame.display.get_surface().get_size()
block = 40
if __name__ == '__main__':
snake = Snake()
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
snake.changeDirection("LEFT")
if event.key == pygame.K_UP:
snake.changeDirection("UP")
if event.key == pygame.K_RIGHT:
snake.changeDirection("RIGHT")
if event.key == pygame.K_DOWN:
snake.changeDirection("DOWN")
snake.moveSnake()
drawBackground()
snake.drawSnake()
pygame.display.update()
clock.tick(120)
,
问题是,当您检查每个线段是否在拐角处(% block == 0
)时,所有线段都通过检查,因此所有线段都改变了方向。
要解决此问题,请只允许一个线段在循环中改变方向,以便其他线段继续越过拐角。
这是更新的代码:
def moveSnake():
global nextDir,snake
switch = False # segment changed direction
for i in range(len(snake)):
if not switch:
if snake[i][3] == "LEFT" and snake[i][1] % block == 0:
snake[i][2] = "LEFT"
snake[i][3] = ""
switch = True
if i<len(snake)-1: snake[i+1][3] = "LEFT"
if snake[i][3] == "RIGHT" and snake[i][1] % block == 0:
snake[i][2] = "RIGHT"
snake[i][3] = ""
switch = True
if i<len(snake)-1: snake[i+1][3] = "RIGHT"
if snake[i][3] == "UP" and snake[i][0] % block == 0:
snake[i][2] = "UP"
snake[i][3] = ""
switch = True
if i<len(snake)-1: snake[i+1][3] = "UP"
if snake[i][3] == "DOWN" and snake[i][0] % block == 0:
snake[i][2] = "DOWN"
snake[i][3] = ""
switch = True
if i<len(snake)-1: snake[i+1][3] = "DOWN"
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。