Loading...
墨滴

十八

2021/04/18  阅读:157  主题:默认主题

十分钟写一个Python小游戏

十分钟写一个Python小游戏

最近玩游戏玩到累了,作为一个游戏爱好者,自己就想着自己来写一个游戏吧,又这么巧,在网上看到了pygame,就打算用pygame写一个贪吃蛇的小游戏,童年让人玩的停不下来来的一款游戏,接下来,我们一起来完成贪吃蛇这个小游戏吧(PS这是我第一次写游戏)。

先上一张实现图:

image-20210417113652108
image-20210417113652108

游戏的整体目录如下

image-20210417113848556
image-20210417113848556

默默哔哔一声,这该死的波浪线。

在每一个模块开始分析的时候,我们先来明确我们的开发思路是怎样的。

image-20210417114340818
image-20210417114340818

开始每一个模块进行分析

#主函数
def main():
 pygame.init() # 模块初始化
 snake_speed_clock = pygame.time.Clock() # 创建Pygame时钟对象
 screen = pygame.display.set_mode((windows_width, windows_height)) #
 screen.fill(white)

 pygame.display.set_caption("CookDev 贪吃蛇小游戏"#设置标题
 show_start_info(screen)               #欢迎信息
 while True:
  running_game(screen, snake_speed_clock)
  show_gameover_info(screen)
  • init为初始化pygame的设置,方便我们后边调用

  • clock()的调用主要是方便我们刷新帧率,减少CPU的占用率

  • pygame.display.set_mode((windows_width, windows_height))

    生成windows窗口,pygame.display.set_mode(resolution=(0,0),flags=0,depth=0)。返回的是一个surface对象(surface对象是用于表示图像的图像,只要指定尺寸,就可以利用),resolution可以控制生成windows窗口的大小,flags代表的是扩展选项,depath不推荐设置。

    flags标志位控制你想要什么样的显示屏,主要有下面几个,这几个量相当于是全局的常量,使用的时候可以from pygame.locals import *导入:

    • pygame.FULLSCREEN,控制全屏,0或者1来控制
    • pygame.HWSURFACE 控制是否进行硬件加速
    • pygame.RESIZABLE 控制窗口是否可以调节大小
  • set_caption ()则是涉及标题

  • fill()为填充颜色

  • 接下来就是不断的循环,调用我们的主体游戏运行

  • 我们的设定是,当Gameover后,我们可以按任意键重新开始游戏,或者提出

开始信息显示

#开始信息显示
def show_start_info(screen):
 font = pygame.font.Font('myfont.ttf'40)
 tip = font.render('按任意键开始游戏~~~'True, (65105225))
 gamestart = pygame.image.load('gamestart.png')
 screen.blit(gamestart, (14030))
 screen.blit(tip, (240550))
 pygame.display.update()

 while True:  #键盘监听事件
  for event in pygame.event.get():  # event handling loop
   if event.type == QUIT:
    terminate()     #终止程序
   elif event.type == KEYDOWN:
    if (event.key == K_ESCAPE):  #终止程序
     terminate() #终止程序
    else:
     return #结束此函数, 开始游戏
  • 字体显示,先创建一个Font对象,然后有了Font对象后就可以用render来写出来,最后通过blit方法来实现在屏幕显示
  • load加载㲏信息
  • 最后监听键盘,按任意键继续或者ESC结束。

开始游戏

#游戏运行主体
def running_game(screen,snake_speed_clock):
 startx = random.randint(3, map_width - 8#开始位置
 starty = random.randint(3, map_height - 8)
 snake_coords = [{'x': startx, 'y': starty},  #初始贪吃蛇
                  {'x': startx - 1'y': starty},
                  {'x': startx - 2'y': starty}]

 direction = RIGHT       #  开始时向右移动

 food = get_random_location()     #实物随机位置

 while True:
  for event in pygame.event.get():
   if event.type == QUIT:
    terminate()
   elif event.type == KEYDOWN:
    if (event.key == K_LEFT or event.key == K_a) and direction != RIGHT:
     direction = LEFT
    elif (event.key == K_RIGHT or event.key == K_d) and direction != LEFT:
     direction = RIGHT
    elif (event.key == K_UP or event.key == K_w) and direction != DOWN:
     direction = UP
    elif (event.key == K_DOWN or event.key == K_s) and direction != UP:
     direction = DOWN
    elif event.key == K_ESCAPE:
     terminate()

  move_snake(direction, snake_coords) #移动蛇

  ret = snake_is_alive(snake_coords)
  if not ret:
   break #蛇跪了. 游戏结束
  snake_is_eat_food(snake_coords, food) #判断蛇是否吃到食物

  screen.fill(BG_COLOR)
  #draw_grid(screen)
  draw_snake(screen, snake_coords)
  draw_food(screen, food)
  draw_score(screen, len(snake_coords) - 3)
  pygame.display.update()
  snake_speed_clock.tick(snake_speed) #控制fps

这个模块是游戏的主要功能模块。

  • 对于贪吃蛇,我们采用一个元组存储蛇的身体各个部分的坐标,最后再写一个方法把他展示出来

  • 食物也是这样画出来

  • 移动 监听键盘,根据用户按键,用direction变量记录移动方向。然后更新贪吃蛇元组里面的坐标(其实每次移动只用更新头尾就行)。最后统一画出来。移动做法具体是,我们把每次头部移动的新坐标插入贪吃蛇元组,然后删掉尾部一节(注意,删除尾部我们放在了另外一个函数里做)。

#移动贪吃蛇
def move_snake(direction, snake_coords):
    if direction == UP:
        newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] - 1}
    elif direction == DOWN:
        newHead = {'x': snake_coords[HEAD]['x'], 'y': snake_coords[HEAD]['y'] + 1}
    elif direction == LEFT:
        newHead = {'x': snake_coords[HEAD]['x'] - 1'y': snake_coords[HEAD]['y']}
    elif direction == RIGHT:
        newHead = {'x': snake_coords[HEAD]['x'] + 1'y': snake_coords[HEAD]['y']}

    snake_coords.insert(0, newHead)
  1. 一开始我们先把贪吃蛇和食物的坐标随机生成,贪吃蛇一开始3节长,先设置向右移动
  2. 移动贪吃蛇,监听键盘,用户按下键盘然后被坚挺到,再用move_snake函数来封信蛇的坐标,如果不按则一直向前走
  3. 判断蛇是不是死了
    1. 头坐标超出地图的范围
    2. 头坐标等于身体某节坐标
#判断蛇死了没
def snake_is_alive(snake_coords):
 tag = True
 if snake_coords[HEAD]['x'] == -1 or snake_coords[HEAD]['x'] == map_width or snake_coords[HEAD]['y'] == -1 or \
   snake_coords[HEAD]['y'] == map_height:
  tag = False # 蛇碰壁啦
 for snake_body in snake_coords[1:]:
  if snake_body['x'] == snake_coords[HEAD]['x'and snake_body['y'] == snake_coords[HEAD]['y']:
   tag = False # 蛇碰到自己身体啦
 return tag

判断贪吃蛇是否迟到食物,表现为:

  1. 头坐标等于食物坐标,那么吃到食物。这时候注意,我们就不用删尾部一节了,因为吃到食物变长了嘛。
  2. 如果没有吃到食物,那么是正常移动,删掉尾部一节坐标。
    #判断贪吃蛇是否吃到食物
def snake_is_eat_food(snake_coords, food):  #如果是列表或字典,那么函数内修改参数内容,就会影响到函数体外的对象。
    if snake_coords[HEAD]['x'] == food['x'and snake_coords[HEAD]['y'] == food['y']:
        food['x'] = random.randint(0, map_width - 1)
        food['y'] = random.randint(0, map_height - 1# 实物位置重新设置
    else:
        del snake_coords[-1]  # 如果没有吃到实物, 就向前移动, 那么尾部一格删掉

最后画出游戏,调用相关函数

画出贪吃蛇

def draw_snake(screen, snake_coords):
 for coord in snake_coords:
  x = coord['x'] * cell_size
  y = coord['y'] * cell_size
  wormSegmentRect = pygame.Rect(x, y, cell_size, cell_size)
  pygame.draw.rect(screen, dark_blue, wormSegmentRect)
  wormInnerSegmentRect = pygame.Rect(                #蛇身子里面的第二层亮蓝色色
   x + 4, y + 4, cell_size - 8, cell_size - 8)
  pygame.draw.rect(screen, blue, wormInnerSegmentRect)

画出食物

#将食物画出来
def draw_food(screen, food):
 x = food['x'] * cell_size
 y = food['y'] * cell_size
 appleRect = pygame.Rect(x, y, cell_size, cell_size)
 pygame.draw.rect(screen, Red, appleRect)

画出成绩

#画成绩
def draw_score(screen,score):
 font = pygame.font.Font('myfont.ttf'30)
 scoreSurf = font.render('得分: %s' % score, True, Green)
 scoreRect = scoreSurf.get_rect()
 scoreRect.topleft = (windows_width - 12010)
 screen.blit(scoreSurf, scoreRect)

如果大家想要源码可以微信搜一下,Cookdev,回复snake即可获取到源码,或者加入Python交流群也可获得源码。 群号:993078776

十八

2021/04/18  阅读:157  主题:默认主题

作者介绍

十八