效果图~新鲜出炉

  • 开始界面
  • 游戏中
  • 结束界面

一、pygame模块概览

模块名称

功能

pygame.cdrom

访问光驱

pygame.cursors

加载光标

pygame.display

访问显示设备

pygame.draw

绘制形状、线和点

pygame.event

管理事件

pygame.font

使用字体

pygame.image

加载和存储图片

pygame.joystick

使用游戏手柄或类似的东西

pygame.key

读取键盘按键

pygame.mixer

声音

pygame.mouse

鼠标

pygame.movie

播放视频

pygame.music

播放音频

pygame.overlay

访问高级视频叠加

pygame

目前学习的

pygame.rect

管理矩形区域

pygame.sndarray

操作声音数据

pygame.sprite

操作移动图像

pygame.surface

管理图像和屏幕

pygame.surfarray

管理点阵图像数据

pygame.time

管理时间和帧信息

pygame.transform

缩放和移动图像

二、核心代码

思路

  1. 首页面:会涉及图片和文字提示的显示,进入(任意键)或退出(ESC)游戏;
  2. 游戏页面:主要涉及食物的创建绘制,蛇的移动和显示,蛇是否吃到食物或者是否撞到边界或自身,再者就是音效的实现(背景音乐+gameover音效);
  3. 结束页面:会涉及图片和文字提示的显示,重来(任意键)或退出(ESC)游戏。

核心代码

  • 主函数
def main():
    pygame.init()
    # 创建Pygame时钟对象,控制每个循环多长时间运行一次。
    # 例如:snake_speed_clock(60)代表每秒内循环要运行的 60 次
    # 每秒60个循环(或帧)时,每个循环需要1000/60=16.66ms(大约17ms)如果循环中的代码运行时间超过17ms,
    # 在clock指出下一次循环时当前循环将无法完成。
    snake_speed_clock = pygame.time.Clock()
    screen = pygame.display.set_mode((windows_width, windows_height))
    screen.fill(white)

    pygame.display.set_caption("贪吃蛇~")
    show_start_info(screen)
    while True:
        music()
        running_game(screen, snake_speed_clock)
        show_end_info(screen)
  • 游戏运行代码
def running_game(screen,snake_speed_clock):
    start_x = random.randint(3, map_width - 8) #开始位置
    start_y = random.randint(3, map_height - 8)
    snake_coords = [{'x': start_x, 'y': start_y},  #初始贪吃蛇
                  {'x': start_x - 1, 'y': start_y},
                  {'x': start_x - 2, 'y': start_y}]

    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:
            gameover_music()
            break     #蛇死了. 游戏结束
        snake_is_eat_food(snake_coords, food) #判断蛇是否吃到食物

        screen.fill(BG_COLOR)
        draw_snake(screen, snake_coords)
        draw_food(screen, food)
        show_score(screen, len(snake_coords) - 3)
        pygame.display.update()
        snake_speed_clock.tick(snake_speed) #控制fps
  • 食物绘制
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_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 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)
  • 判断蛇死没有死
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
  • 判断蛇是否吃到食物
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 get_random_location():
    return {'x':random.randint(0, map_width - 1),'y':random.randint(0, map_height - 1)}
  • 开始信息显示
def show_start_info(screen):
    # 创建Font字体对象,使用render方法写字
    font = pygame.font.Font("simsun.ttc", 40)
    tip = font.render('按任意键开始游戏', True,(65,105,255))
    # 加载图片
    gamestart = pygame.image.load('startlogo.jpg').convert()
    # 通过blit方法输出在屏幕上
    screen.blit(gamestart,(140, 30))
    screen.blit(tip,(240, 550))
    ## 刷新屏幕
    pygame.display.update()

    while True:  # 监听键盘
        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            elif event.type == KEYDOWN:  # 任意键按下
                return
                if (event.key == K_ESCAPE):  # 若为ESC,则终止程序
                    terminate()
                else:
                    return
  • 声音设置
def music():
    pygame.mixer.init()
    pygame.mixer.music.load('111.mp3')
    pygame.mixer.music.play(1, 0)

def gameover_music():
    pygame.mixer.init()
    pygame.mixer.music.load('gameover.mp3')
    pygame.mixer.music.play(1,0)
  • 结束信息显示
def show_end_info(screen):
    font = pygame.font.Font("simsun.ttc", 40)
    tip = font.render("按ESC退出游戏,按任意键重新开始游戏",True,(65,105,255))
    # gamestart = pygame.image.load('gameover.png')
    # screen.blit(gamestart,(60, 0))
    screen.blit(tip,(80, 300))
    pygame.display.update()

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    terminate()
                else:
                    return
  • 成绩信息显示
def show_score(screen, score):
    font = pygame.font.Font("simsun.ttc", 30)
    scoreSurf = font.render("得分:%s" % score, True, green)
    scoreRect = scoreSurf.get_rect()
    scoreRect.topleft = (windows_width - 120, 10)
    screen.blit(scoreSurf,scoreRect)
  • 程序终止
def terminate():
    pygame.quit()
    sys.exit()