当你学会python,兴趣正浓的时候,是不是迫不及待的想实现些什么,实现什么好呢,好难受,快让我实现些什么。实现个贪吃蛇吧,反正也没啥技术含量(狗头)
实现贪吃蛇的博客真的好多啊,一开始我想复制一个下来,然后看一看,改一改,我就想找一个直接全部复制到pycharm,然后运行就可以的,哎,怎么找了几个都不行…后来去pygame官网看看,随手找到一个贪吃蛇实现,github把代码复制下来,哎,好像就是我想要的东西了。原版的是这个样子的
我们可以修改成这个样子,看起来会不会好一点
是的上面的其实就是改颜色,不过还添加一个有趣地方,当蛇靠近边缘时,会开启“慢动作”比如下面这个
来一起看看是如何实现的,然后我们再给他修改修改,嘿嘿嘿
先来了解下思路,整个游戏过程中,我们应该是不停的在循环检查,每次循环检查蛇是否碰到墙壁,是否碰到自己,是否吃到食物,然后每个结果都执行对应操作,最后更新一下画面,继续循环。蛇如何存呢,程序采用一个列表来存,把蛇的每一节都存在这个列表里,然后蛇的移动,我们只需要把最后一节蛇删除,然后计算出新的蛇头位置,把蛇头更新,说起来可能不太好理解,一看代码就明白了,下面分步来看看(原始的版本),说明全部在代码注释中啦
1、初始化
def __init__(self, windowSizeX=500, windowSizeY=500):
#窗口大小
self.windowSizeX = windowSizeX
self.windowSizeY = windowSizeY
#食物和蛇的单位大小
self.gameUnitSize = 16
#让屏幕和单位大小适配
if (self.windowSizeX % self.gameUnitSize != 0):
self.windowSizeX += self.gameUnitSize - self.windowSizeX % self.gameUnitSize
if (self.windowSizeY % self.gameUnitSize != 0):
self.windowSizeY += self.gameUnitSize - self.windowSizeY % self.gameUnitSize
self.window = pygame.display.set_mode(
[self.windowSizeX, self.windowSizeY])
#标题
pygame.display.set_caption("Snake!")
#填充色
self.window.fill((255, 255, 255))
#初始化字体
pygame.font.init()
#设置字体
self.font = pygame.font.SysFont("bahnschrift", 20)
#设置画面显示的内容
self.text = self.font.render(
"Press Direction key to begin", True, (0, 0, 0))
self.startTextRect = self.text.get_rect(
center=(windowSizeX/2, windowSizeY/2))
#这个就是我们的蛇了
self.snake = [self.startSnake()]
#这是我们的食物
self.food = self.createFood()
#速度
self.speed = self.gameUnitSize
#得分
self.score = 0
#得分显示
self.scoreText = self.font.render(
f"Score: {self.score}", True, (0, 0, 0), None)
#蛇的方向控制
self.snakeDirections = {
'left': (-1, 0), 'right': (1, 0), 'up': (0, -1), 'down': (0, 1)}
#上一次的执行动作,初始化随便给一个
self.previousDirection = self.snakeDirections.get('left')
#循环内容
self.readyScreen()
self.gameLoop()
2、循环部分
#检测键盘事件,当有键盘按键按下时,pygame可以帮我们检测到是什么按键被按下了
def readyScreen(self):
while True:
self.window.blit(self.text, self.startTextRect)
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
keys = pygame.key.get_pressed()
if (keys[K_LEFT]):
self.previousDirection = self.snakeDirections.get('left')
break
if (keys[K_RIGHT]):
self.previousDirection = self.snakeDirections.get('right')
break
if (keys[K_UP]):
self.previousDirection = self.snakeDirections.get('up')
break
if (keys[K_DOWN]):
self.previousDirection = self.snakeDirections.get('down')
break
pygame.display.update()
#循环开始
def gameLoop(self):
while True:
pygame.time.delay(100)
self._input()
self._update()
#方向键被按下时,修改组成蛇的列表
def _input(self):
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
keys = pygame.key.get_pressed()
if (keys[K_LEFT] and self.previousDirection != self.snakeDirections.get('right')):
self.moveSnake(self.snakeDirections.get('left'))
elif (keys[K_RIGHT] and self.previousDirection != self.snakeDirections.get('left')):
self.moveSnake(self.snakeDirections.get('right'))
elif (keys[K_UP] and self.previousDirection != self.snakeDirections.get('down')):
self.moveSnake(self.snakeDirections.get('up'))
elif (keys[K_DOWN] and self.previousDirection != self.snakeDirections.get('up')):
self.moveSnake(self.snakeDirections.get('down'))
else:
self.moveSnake(self.previousDirection)
#更新画面的地方
def _update(self):
self.window.fill((0,0,0))
if (self.intersect() == True):
self.appendSnake()
self.moveFood()
self.score += 1
elif (self.snakeCollidingWithWall() == True or self.snakeCollidingWithSelf() == True):
return self.killSnake()
for link in self.snake:
pygame.draw.rect(self.window, (255,255,255), link)
pygame.draw.rect(self.window, (102, 255, 51), self.food)
self.scoreText = self.font.render(
f"Score: {self.score}", True, (255, 255, 255))
self.scoreTextRect = self.scoreText.get_rect(center=(40, 10))
self.window.blit(self.scoreText, self.scoreTextRect)
#不要忘了这个updata
pygame.display.update()
源码代码汇总如下:
class Game_snake_ex:
def __init__(self, windowsize_x=500, windowsize_y=500):
self.windowsize_x = windowsize_x
self.windowsize_y = windowsize_y
self.gameUnitsize = 16
if (self.windowsize_x % self.gameUnitsize != 0):
self.windowsize_x += self.gameUnitsize - self.windowsize_x % self.gameUnitsize
if (self.windowsize_y % self.gameUnitsize != 0):
self.windowsize_y += self.gameUnitsize - self.windowsize_y % self.gameUnitsize
self.window = pygame.display.set_mode(
[self.windowsize_x, self.windowsize_y])
pygame.display.set_caption("Snake!")
self.window.fill((0, 0, 0))
pygame.font.init()
self.font = pygame.font.SysFont("bahnschrift", 20)
self.text = self.font.render(
"Press Direction key to begin", True, (255, 255, 255))
self.startTextRect = self.text.get_rect(
center=(windowsize_x/2, windowsize_y/2))
self.snake = [self.startSnake()]
self.food = self.createFood()
self.speed = self.gameUnitsize
self.score = 0
self.scoreText = self.font.render(
f"Score: {self.score}", True, (255, 255, 255), None)
self.snakeDirections = {
'left': (-1, 0), 'right': (1, 0), 'up': (0, -1), 'down': (0, 1)}
self.previousDirection = self.snakeDirections.get('left')
self.readyScreen()
self.gameLoop()
def startSnake(self):
snakeNodeX = self.window.get_width() / 2 - self.gameUnitsize
if (snakeNodeX % self.gameUnitsize != 0):
snakeNodeX -= snakeNodeX % self.gameUnitsize
snakeNodeY = self.window.get_height() / 2 - self.gameUnitsize
if (snakeNodeY % self.gameUnitsize != 0):
snakeNodeY -= snakeNodeY % self.gameUnitsize
snakeNodeRectangle = Rect(
(snakeNodeX, snakeNodeY), (self.gameUnitsize, self.gameUnitsize))
return snakeNodeRectangle
def createFood(self):
foodX = randint(0, self.window.get_width() - self.gameUnitsize)
if (foodX % self.gameUnitsize != 0):
foodX -= foodX % self.gameUnitsize
foodY = randint(0, self.window.get_height() - self.gameUnitsize)
if (foodY % self.gameUnitsize != 0):
foodY -= foodY % self.gameUnitsize
foodRectangle = Rect(
(foodX, foodY), (self.gameUnitsize, self.gameUnitsize))
return foodRectangle
def moveFood(self):
self.food.x = randint(0, self.window.get_width() - self.gameUnitsize)
if (self.food.x % self.gameUnitsize != 0):
self.food.x -= self.food.x % self.gameUnitsize
self.food.y = randint(0, self.window.get_height() - self.gameUnitsize)
if (self.food.y % self.gameUnitsize != 0):
self.food.y -= self.food.y % self.gameUnitsize
def createSnake(self):
snakeNodeX = randint(0, self.window.get_width())
if (snakeNodeX % self.gameUnitsize != 0):
snakeNodeX -= snakeNodeX % self.gameUnitsize
snakeNodeY = randint(0, self.window.get_height())
if (snakeNodeY % self.gameUnitsize != 0):
snakeNodeY -= snakeNodeY % self.gameUnitsize
snakeNodeRectangle = Rect(
(snakeNodeX, snakeNodeY), (self.gameUnitsize, self.gameUnitsize))
return snakeNodeRectangle
def appendSnake(self):
# add node to tail
newSnakeLink = Rect((self.snake[len(self.snake) - 1].x, self.snake[len(
self.snake) - 1].y), (self.gameUnitsize, self.gameUnitsize))
self.snake.append(newSnakeLink)
def moveSnake(self, direction):
#蛇尾删掉,更新蛇头,其他不变
x = 0
y = 1
self.snake[len(self.snake) - 1].x = self.snake[0].x + \
direction[x] * self.speed
self.snake[len(self.snake) - 1].y = self.snake[0].y + \
direction[y] * self.speed
self.snake.insert(0, self.snake.pop())
self.previousDirection = direction
def intersect(self):
if self.snake[0].x == self.food.x and self.snake[0].y == self.food.y:
return True
return False
def snakeCollidingWithWall(self):
if self.snake[0].x >= self.windowsize_x or self.snake[0].x < 0 or self.snake[0].y >= self.windowsize_y or self.snake[0].y < 0:
return True
return False
def snakeCollidingWithSelf(self):
for link in self.snake:
if (self.snake[0] is not link):
if self.snake[0].x == link.x and self.snake[0].y == link.y:
return True
return False
def killSnake(self):
return self._gameOverScreen()
def _update(self):
self.window.fill((0,0,0))
if (self.intersect() == True):
self.appendSnake()
self.moveFood()
self.score += 1
elif (self.snakeCollidingWithWall() == True or self.snakeCollidingWithSelf() == True):
return self.killSnake()
for link in self.snake:
pygame.draw.rect(self.window, (255,255,255), link)
pygame.draw.rect(self.window, (102, 255, 51), self.food)
self.scoreText = self.font.render(
f"Score: {self.score}", True, (255, 255, 255))
self.scoreTextRect = self.scoreText.get_rect(center=(40, 10))
self.window.blit(self.scoreText, self.scoreTextRect)
pygame.display.update()
def _input(self):
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
keys = pygame.key.get_pressed()
if (keys[K_LEFT] and self.previousDirection != self.snakeDirections.get('right')):
self.moveSnake(self.snakeDirections.get('left'))
elif (keys[K_RIGHT] and self.previousDirection != self.snakeDirections.get('left')):
self.moveSnake(self.snakeDirections.get('right'))
elif (keys[K_UP] and self.previousDirection != self.snakeDirections.get('down')):
self.moveSnake(self.snakeDirections.get('up'))
elif (keys[K_DOWN] and self.previousDirection != self.snakeDirections.get('up')):
self.moveSnake(self.snakeDirections.get('down'))
else:
self.moveSnake(self.previousDirection)
def readyScreen(self):
while True:
self.window.blit(self.text, self.startTextRect)
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
keys = pygame.key.get_pressed()
if (keys[K_LEFT]):
self.previousDirection = self.snakeDirections.get('left')
break
if (keys[K_RIGHT]):
self.previousDirection = self.snakeDirections.get('right')
break
if (keys[K_UP]):
self.previousDirection = self.snakeDirections.get('up')
break
if (keys[K_DOWN]):
self.previousDirection = self.snakeDirections.get('down')
break
pygame.display.update()
def _gameOverScreen(self):
while True:
self.window.fill((0, 0, 0))
self.text = self.font.render(
f"Game Over, Score: {self.score}", True, (255, 255, 255))
self.startTextRect = self.text.get_rect(
center=(self.windowsize_x/2, self.windowsize_y/2))
self.window.blit(self.text, self.startTextRect)
keys = pygame.key.get_pressed()
if (keys[K_r]):
break
for event in pygame.event.get():
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
exit()
pygame.display.update()
return 1
def gameLoop(self):
while True:
pygame.time.delay(100)
self._input()
self._update()
上面那个是原版,实现方法明白了以后,就可以自己动手来修改修改啦
这个是我添加 颜色变化 和“慢动作” 的版本