玩蛇系列之Pygame教程(十)-- Simon西蒙游戏

** Simon 西蒙游戏**

游戏玩法介绍:
经典的重复游戏,电脑会给出一些打乱的序列顺序,然后你要把序列重复出来
随着游戏的难度不断增大,序列的长度也会不断增长,相应的把序列完整的重复出来的难度也变大

先上个图(●'◡'●)

玩蛇系列之Pygame教程(十)-- Simon西蒙游戏_第1张图片

** 游戏主要思路 **

1,绘制一个640*480的窗口

2,设置方块大小,计算边距

3,定义一个 pattern 数组,用来储存模板颜色的序列

4,加载4个音频文件

5,绘制四个方块,绘制提示文字,分数

6,根据 waitingForInput 变量来确定接下来是电脑演示,还是玩家模拟

7,如果是电脑演示,就随机从四个颜色中选一个添加到 pattern 序列末尾,然后从头开始取出序列中的每一个颜色,并闪动相应的按钮,完成以上操作后,设置为等待玩家模拟

8,如果是玩家模拟,则进行事件处理,播放四个按钮对应的音频

9,鼠标事件处理,记录点击的按钮

10,键盘事件处理,Q为黄色;W为蓝色;A为红色;S为绿色;ESC键为退出

11,如果上一步中记录的按钮是 pattern 序列中当前所指的按钮:
就把 currentStep 往后移一位,并判断是否为 pattern 序列的最后一步,如果是,分数加一分,播放成功模拟动画,表示已经成功模仿完整个 pattern 序列,不是就继续判断下一个事件

12,如果上一步中记录的按钮不是 pattern 序列中当前所指的按钮,或者是在模仿的过程中超时:
播放游戏结束动画,重置所有的变量

资源下载链接

beep1.ogg http://pan.baidu.com/s/1cxecMy

beep2.ogg http://pan.baidu.com/s/1b4WfCy

beep3.ogg http://pan.baidu.com/s/1skHsJpV

beep4.ogg http://pan.baidu.com/s/1qYRK0DQ

** 国际惯例,上代码:**

# -*- coding: UTF-8 -*-
'''
Created on 2016年11月29日

@author: 小峰峰
'''

import random, sys, time, pygame
from pygame.locals import *


FPS = 30 # 帧率
WINDOWWIDTH = 640 # 窗口宽度
WINDOWHEIGHT = 480 # 窗口高度
FLASHSPEED = 500 # 闪动的速度(毫秒)
FLASHDELAY = 200 # 闪动的延时(毫秒)
BUTTONSIZE = 200 # 方块的大小
BUTTONGAPSIZE = 20 # 方块间距
TIMEOUT = 4 # 超时(秒) seconds before game over if no button is pushed.

# 定义几个颜色
# R G B
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
BRIGHTRED = (255, 0, 0)
RED = (155, 0, 0)
BRIGHTGREEN = ( 0, 255, 0)
GREEN = ( 0, 155, 0)
BRIGHTBLUE = ( 0, 0, 255)
BLUE = ( 0, 0, 155)
BRIGHTYELLOW = (255, 255, 0)
YELLOW = (155, 155, 0)
DARKGRAY = ( 40, 40, 40)

bgColor = BLACK # 设置背景色 (黑色)

# 方块与窗口之间的间距
XMARGIN = int((WINDOWWIDTH - (2 * BUTTONSIZE) - BUTTONGAPSIZE) / 2)
YMARGIN = int((WINDOWHEIGHT - (2 * BUTTONSIZE) - BUTTONGAPSIZE) / 2)


# 四个方块的Rect属性
YELLOWRECT = pygame.Rect(XMARGIN, YMARGIN, BUTTONSIZE, BUTTONSIZE)
BLUERECT = pygame.Rect(XMARGIN + BUTTONSIZE + BUTTONGAPSIZE, YMARGIN, BUTTONSIZE, BUTTONSIZE)
REDRECT = pygame.Rect(XMARGIN, YMARGIN + BUTTONSIZE + BUTTONGAPSIZE, BUTTONSIZE, BUTTONSIZE)
GREENRECT = pygame.Rect(XMARGIN + BUTTONSIZE + BUTTONGAPSIZE, YMARGIN + BUTTONSIZE + BUTTONGAPSIZE, BUTTONSIZE, BUTTONSIZE)


# 主函数
def main():
    
    # 定义几个全局变量
    global FPSCLOCK, DISPLAYSURF, BASICFONT, BEEP1, BEEP2, BEEP3, BEEP4

    pygame.init() # 初始化pygame 
    
    FPSCLOCK = pygame.time.Clock() # 获得pygame时钟
    
    DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT)) # 设置窗口大小
    
    pygame.display.set_caption('Simon') # 设置标题

    BASICFONT = pygame.font.Font('PAPYRUS.ttf', 16) # 设置字体及大小

    # 绘制提示信息
    infoSurf = BASICFONT.render('Match the pattern by clicking on the button or using the Q, W, A, S keys.', 1, DARKGRAY)
    infoRect = infoSurf.get_rect()
    infoRect.topleft = (10, WINDOWHEIGHT - 25)
    
    # 加载音频文件
    BEEP1 = pygame.mixer.Sound('beep1.ogg')
    BEEP2 = pygame.mixer.Sound('beep2.ogg')
    BEEP3 = pygame.mixer.Sound('beep3.ogg')
    BEEP4 = pygame.mixer.Sound('beep4.ogg')
    
    # Initialize some variables for a new game
    pattern = [] # 用来储存模板颜色的序列
    currentStep = 0 # 玩家下一步需要按的颜色
    lastClickTime = 0 # 玩家最后按下按钮的时间戳
    score = 0 # 分数
    
    # 当waitingForInput为False时,表示播放模板;为True时表示等待用户点击
    waitingForInput = False
    
    while True: # 游戏主循环
        clickedButton = None # 当前按下的按钮(YELLOW, RED, GREEN, or BLUE)
        
        DISPLAYSURF.fill(bgColor) # 绘制背景色
        
        drawButtons() # 绘制四个按钮

        # 绘制分数
        scoreSurf = BASICFONT.render('Score: ' + str(score), 1, WHITE)
        scoreRect = scoreSurf.get_rect()
        scoreRect.topleft = (WINDOWWIDTH - 100, 10)
        DISPLAYSURF.blit(scoreSurf, scoreRect) 

        DISPLAYSURF.blit(infoSurf, infoRect) # 绘制提示信息
        
        
        for event in pygame.event.get(): # 事件处理
            
            if event.type == MOUSEBUTTONUP: # 处理鼠标点击事件
                
                mousex, mousey = event.pos # 获得鼠标点击的像素位置
                
                clickedButton = getButtonClicked(mousex, mousey) # 根据像素位置获得点击的按钮
                
            elif event.type == KEYDOWN: # 处理按键事件
                
                # Q为黄色;W为蓝色;A为红色;S为绿色;ESC键为退出
                if event.key == K_q:
                    clickedButton = YELLOW
                elif event.key == K_w:
                    clickedButton = BLUE
                elif event.key == K_a:
                    clickedButton = RED
                elif event.key == K_s:
                    clickedButton = GREEN
                elif event.key == K_ESCAPE:
                    pygame.quit()
                    sys.exit()
            
            elif event.type == QUIT:
                pygame.quit()
                sys.exit()

        if not waitingForInput: # 播放模板
            
            pygame.display.update()
            pygame.time.wait(1000)
            
            # 随机从四个颜色中选一个添加到pattern序列中
            pattern.append(random.choice((YELLOW, BLUE, RED, GREEN)))
            
            for button in pattern: # 从序列中取出每一个颜色并闪动相应的按钮
                flashButtonAnimation(button)
                pygame.time.wait(FLASHDELAY)
            
            # 等待用户点击    
            waitingForInput = True
            
        else:
            # 等待玩家按按钮
            if clickedButton and clickedButton == pattern[currentStep]:
                # 如果按的是pattern序列中currentStep所指的按钮
                flashButtonAnimation(clickedButton)
                currentStep += 1 # currentStep往后移一位
                lastClickTime = time.time() # 给lastClickTime赋值当前的时间
                
                if currentStep == len(pattern): 
                    # 如果为pattern序列的最后一步
                    changeBackgroundAnimation() # 播放背景闪动的动画,表示已经成功模仿完整个pattern序列
                    score += 1 # 分数加一分
                    waitingForInput = False # 设置为播放模板状态
                    currentStep = 0 # 将currentStep退回最前面
                    
            elif (clickedButton and clickedButton != pattern[currentStep]) or (currentStep != 0 and time.time() - TIMEOUT > lastClickTime):
                # 两个条件,按了错误的按钮或者超时
                
                # 超时是指,在根据序列模仿的过程中,按下两个按钮的时间间隔超过4秒
                
                gameOverAnimation() # 播放游戏结束动画
                
                # 重置所有的变量
                pattern = []
                currentStep = 0
                waitingForInput = False
                score = 0
                pygame.time.wait(1000)
                changeBackgroundAnimation()
         
        # 更新屏幕        
        pygame.display.update()
        # 设置帧率
        FPSCLOCK.tick(FPS)        



# 闪动按钮的动画
def flashButtonAnimation(color, animationSpeed=50):
    # 如果是红色按钮
    if color == YELLOW:
        sound = BEEP1
        flashColor = BRIGHTYELLOW
        rectangle = YELLOWRECT
    # 如果是蓝色按钮
    elif color == BLUE:
        sound = BEEP2
        flashColor = BRIGHTBLUE
        rectangle = BLUERECT
    # 如果是红色按钮
    elif color == RED:
        sound = BEEP3
        flashColor = BRIGHTRED
        rectangle = REDRECT
    # 如果是绿色按钮
    elif color == GREEN:
        sound = BEEP4
        flashColor = BRIGHTGREEN
        rectangle = GREENRECT
        
        
    origSurf = DISPLAYSURF.copy() # 拷贝一份原来的Surface
    flashSurf = pygame.Surface((BUTTONSIZE, BUTTONSIZE)) # 闪动的部分
    flashSurf = flashSurf.convert_alpha() # 转变为有透明度的Surface
    r, g, b = flashColor
    
    sound.play() #播放音效 
    
    
    for start, end, step in ((0, 255, 1), (255, 0, -1)): # 通过改变 alpha值 透明度实现动画
        
        # 在循环中第一次是将透明度从0到255,step为1;第二次是从255到0,step为-1
        
        for alpha in range(start, end, animationSpeed * step):
            
            DISPLAYSURF.blit(origSurf, (0, 0))
            
            flashSurf.fill((r, g, b, alpha))
            
            DISPLAYSURF.blit(flashSurf, rectangle.topleft)
            
            pygame.display.update()
            FPSCLOCK.tick(FPS)
            
    DISPLAYSURF.blit(origSurf, (0, 0))


# 绘制四个按钮
def drawButtons():
    pygame.draw.rect(DISPLAYSURF, YELLOW, YELLOWRECT)
    pygame.draw.rect(DISPLAYSURF, BLUE, BLUERECT)
    pygame.draw.rect(DISPLAYSURF, RED, REDRECT)
    pygame.draw.rect(DISPLAYSURF, GREEN, GREENRECT)
    

# 改变游戏背景的动画    
def changeBackgroundAnimation(animationSpeed=40):
    
    global bgColor
    
    # 随机出一个新的颜色
    newBgColor = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))

    newBgSurf = pygame.Surface((WINDOWWIDTH, WINDOWHEIGHT))
    
    newBgSurf = newBgSurf.convert_alpha()
    
    r, g, b = newBgColor 
    
    for alpha in range(0, 255, animationSpeed): # 改变alpha值 
        
        DISPLAYSURF.fill(bgColor)

        newBgSurf.fill((r, g, b, alpha)) # 设置透明度
        
        DISPLAYSURF.blit(newBgSurf, (0, 0))

        drawButtons() # 在新的背景上重绘四个按钮

        pygame.display.update() # 更新屏幕
        
        FPSCLOCK.tick(FPS) # 设置帧率
        
    bgColor = newBgColor # 赋值新的背景色
    
    
# 游戏结束动画    
def gameOverAnimation(color=WHITE, animationSpeed=50):
    
    origSurf = DISPLAYSURF.copy()
    flashSurf = pygame.Surface(DISPLAYSURF.get_size())
    flashSurf = flashSurf.convert_alpha()
    
    # 同时播放所有的四个音效
    BEEP1.play()
    BEEP2.play()
    BEEP3.play()
    BEEP4.play()
    
    r, g, b = color  
    
    for i in range(3): # 闪动3次背景
        for start, end, step in ((0, 255, 1), (255, 0, -1)):
            # 在循环中第一次是将透明度从0到255,step为1;第二次是从255到0,step为-1,依此下去
            for alpha in range(start, end, animationSpeed * step): 
                # alpha 为透明度. 255为不透明, 0为透明
                flashSurf.fill((r, g, b, alpha))
                DISPLAYSURF.blit(origSurf, (0, 0))
                DISPLAYSURF.blit(flashSurf, (0, 0))
                drawButtons()
                pygame.display.update()
                FPSCLOCK.tick(FPS)


# 根据像素坐标获得点击的按钮    
def getButtonClicked(x, y):
    if YELLOWRECT.collidepoint( (x, y) ):
        return YELLOW
    elif BLUERECT.collidepoint( (x, y) ):
        return BLUE
    elif REDRECT.collidepoint( (x, y) ):
        return RED
    elif GREENRECT.collidepoint( (x, y) ):
        return GREEN
    return None



if __name__ == '__main__':
    main()

** 运行结果: **

玩蛇系列之Pygame教程(十)-- Simon西蒙游戏_第2张图片

不静下心来还真打不到8分以上 ** (〜 ̄△ ̄)〜 **

你可能感兴趣的:(玩蛇系列之Pygame教程(十)-- Simon西蒙游戏)