(原) 码农家的孩子:学字母

原创文章,请后转载,并注明出处。

由于疫情的影响,两个孩子在家,天天在家都快翻天了。

计划中的学字母,但孩子总是兴趣不大。只能用游戏来吸引了。

似乎有两三年没用Python了,代码也就是能玩的程度,也没有太多优化之类。最初就是网友的一个打字游戏,在此基本上添加了一些音效、背景之类的东西。

视频嵌入没发起,点击看视频

No1

# -*- coding=utf-8 -*-
import pygame,time,random,datetime
from pygame.locals import *

#获取随机字符
def get_random_word():
    color = (random.randint(0, 255),random.randint(0, 255),random.randint(0, 255)) # 颜色随机
    x = random.randint(100, w-100)                                                 # x坐标从左右边距各100之间随机
    y = 0
    word = random.randint(65, 90)
    return x,y,word,color

def Kill():
    global PlayState,arr,plane,bullet,boom,Sound
    #显示飞机
    plane.update()
    if PlayState==1:
        plane.xto=arr[0][0]
        if plane.over:
            PlayState=2
            bullet.over=False
            Sound["fire"].play()
 
    #显示子弹
    if PlayState==2:
        bullet.update(plane.x,arr[0][1])
        if bullet.over:
            PlayState=3
            boom.over=False
            Sound["bomb"].play()
 
    #显示爆炸
    if PlayState==3:      
        boom.update(arr[0][0],arr[0][1])
        if boom.over:
           arr.pop(0)
           PlayState=0    

#爆炸显示
class Boom(pygame.sprite.Sprite):
    def __init__(self,screen):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.image.load("./res/boom.png").convert_alpha()
        self.image.set_colorkey((0,0,0))
        self.rect=self.image.get_rect()
        self.num=0.1
        self.local=[(214,46,234,68),(210,126,252,172),(214,2,254,44),(74,2,138,70),(2,2,72,66),(144,2,212,64),
                    (2,174,66,234),(144,66,208,128),(2,68,60,116),(64,68,124,114),(210,68,266,110)]
        self.screen=screen
        self.over=True
        self.no=0.6
    def update(self,lx,ly):
        x1,y1,x2,y2 = self.local[int(self.num)]
        x = (x2 - x1)/2
        y = (y2 - y1)/2      
        self.screen.blit(self.image,(lx-x-20,ly-y+40),(x1,y1,x2,y2))  #显示爆炸图
        self.num+=self.no

        if self.num > 10:
            self.num = 0.1   
            self.over = True
    def uplevel(self):
        self.no+=0.1

#子弹
class Bullet(pygame.sprite.Sprite):
    def __init__(self,screen):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.image.load("./res/bullet0.png").convert_alpha()      #子弹
        self.image.set_colorkey((255,255,255))
        self.rect=self.image.get_rect()
        self.screen=screen
        self.x = 0
        self.y = screen.get_height()-150
        self.over = True
        self.no = 0
    def update(self,lx,ly):   #lx,ly目标位置
        self.x=lx
        self.y-=(15+self.no)
        if self.y>ly:
           self.screen.blit(self.image,(self.x+10,self.y+60))
        else:
           self.over = True
           self.y = screen.get_height()-150
    def uplevel(self):
        self.no+=1
        #超过20关,应该添加一个终胜利显示
        self.image=pygame.image.load("./res/bullet" + str(self.no) + ".png")      #子弹
        self.image.set_colorkey((255,255,255))
        self.rect=self.image.get_rect()        

#等级
class Level(pygame.sprite.Sprite):
    def __init__(self,screen):
        self.image=pygame.image.load("./res/gold.png").convert_alpha()
        self.image.set_colorkey((255,255,255))
        self.rect=self.image.get_rect()
        self.screen=screen
        self.level = 1
    def update(self):
        for i in range(0,self.level):
            self.screen.blit(self.image,(i*20+10,10))

#背景
class Background(pygame.sprite.Sprite):
    def __init__(self,screen):
        self.level = 1
        bg = pygame.image.load("./res/bg_level" + str(self.level) +".jpg").convert()
        self.image = pygame.transform.scale2x(bg)
        self.rect = self.image.get_rect()
        self.screen = screen
        self.bgy = 0
    def uplevel(self):
        self.level+=1
        self.bgy=0
        if self.level>7:
            self.level = 1
        bg=pygame.image.load("./res/bg_level" + str(self.level) +".jpg").convert()
        #self.image= pygame.transform.scale(bg, (bg.get_width()*2, bg.get_height()*2))
        self.image = pygame.transform.scale2x(bg)
        self.rect=self.image.get_rect()
    def get_width(self):
        return self.image.get_width()
    def get_height(self):
        return self.image.get_height()
    def image(self):
        return self.image
    def update(self):
        self.bgy-=0.2
        if -self.bgy>self.image.get_height()-screen.get_height():                                       #第一幅背景下方超出
           screen.blit(self.image,(0,screen.get_height()+self.bgy+(self.image.get_height()-screen.get_height()))) #第二幅背景补齐
        if self.bgy==-self.image.get_height():                                #第一幅出背景
           self.bgy=0
        screen.blit(self.image,(0,self.bgy))                            #正常情况下  

#飞机
class Plane(pygame.sprite.Sprite):
    def __init__(self,screen):
        self.level = 1
        self.image = pygame.image.load("./res/plane" + str(self.level) +".png")       
        self.rect = self.image.get_rect()
        self.screen = screen
        self.xto = 0
        self.x = screen.get_width()/2-self.image.get_width()/2
        self.over = True
    def update(self):
        if self.xto!=0:
            if self.xto>self.x:
                self.x+=(5+self.level)
            elif abs(self.xto-self.x)<5+self.level:
                self.over=True
                self.xto=0
            else:
                self.x-=(5+self.level)
        self.screen.blit(self.image,(self.x-20,screen.get_height()-self.image.get_height()-10))             
        
    def uplevel(self):
        self.level += 1
        if self.level > 5:
            self.level = 5
        self.image = pygame.image.load("./res/plane" + str(self.level) +".png")        
        self.rect=self.image.get_rect()        

#星空
class Star(pygame.sprite.Sprite):
    def __init__(self,screen,width,height):
        self.image=pygame.image.load("./res/explode" + str(random.randint(1, 3))+ ".jpg").convert()
        self.image.set_colorkey((0,0,0))
        self.image.set_alpha(random.randint(100, 250))
        self.rect=self.image.get_rect()
        self.screen=screen
        self.x=random.randint(10, width-10)
        self.y=random.randint(10, height-10)
        self.speed=random.random()/5
        self.maxwidth=width
        self.maxheight=height
    def update(self):
        self.y-=self.speed
        if self.y<0:
            self.x=random.randint(10, self.maxwidth-10)
            self.y=self.maxheight+10
            self.speed=random.random()/5
            self.image=pygame.image.load("./res/explode" + str(random.randint(1, 3))+ ".jpg").convert()
            self.image.set_colorkey((0,0,0))
            self.image.set_alpha(random.randint(100, 250))            
        self.screen.blit(self.image,(self.x,self.y))

#初始化
w,h = 1024,1200
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode((w, h), RESIZABLE)
clock = pygame.time.Clock()
pygame.display.set_caption(u'打字等级:1')                    #标题

#载入相关资源
myfont = pygame.font.Font("./res/ObelixPro.ttf",80)         #字体设置
pygame.mixer.music.load("./res/start.ogg")                  #背景音乐
pygame.mixer.music.set_volume(0.4)
pygame.mixer.music.play(-1)
Sound = {} 
jp = pygame.image.load("res/jp.jpg").convert()              #键盘图 
Sound["win"] = pygame.mixer.Sound("res/Completed.wav")
Sound["lost"] = pygame.mixer.Sound("res/Failed.wav")
Sound["fire"] = pygame.mixer.Sound("res/fire.wav")
Sound["bomb"] = pygame.mixer.Sound("res/bomb.wav")
for i in range(1,27):                                       #载入字母音频
    Sound[chr(i+96)] = pygame.mixer.Sound("res/" + chr(i+96) + ".wav")

#变量初始
fullscreen = False
diff_ticks = 100                                            #字母下落速度
LevelNum = 20                                               #30个字母升一级
ticks = pygame.time.get_ticks() + diff_ticks
word_diff_ticks = 5000
word_ticks = pygame.time.get_ticks() + word_diff_ticks
clear_word=0                                                #已消除多少字母
game_state=1                                                #1.进行中 2.游戏失败
sign=1                                                      #字符闪烁
PlayState = 0
arr=[]                                                      #随机添加一个字符
arr.append(get_random_word())
showKey = False

boom = Boom(screen)                                         #一个炸弹
bullet = Bullet(screen)
level = Level(screen)
bg = Background(screen)
plane = Plane(screen)

while True:   
    clock.tick(60)  # 每秒循环60次
    
    #按键捕获
    for event in pygame.event.get():

        #处理屏幕大小
        if event.type == VIDEORESIZE:
            w,h = event.size
            screen = pygame.display.set_mode((w,h), RESIZABLE)

        if event.type == pygame.QUIT:
            pygame.quit()
            exit()

        if event.type == KEYDOWN: 
           if event.key == pygame.K_F1:
                fullscreen=not fullscreen
                if fullscreen:
                    screen=pygame.display.set_mode((w,h),FULLSCREEN)
                else:
                    screen=pygame.display.set_mode((w,h),RESIZABLE)
           if event.key == pygame.K_F2:
                showKey = not showKey


        if game_state==1 and len(arr)>0 and event.type == KEYDOWN:
            if event.key==pygame.K_ESCAPE:   #ESC退出
                pygame.quit()
                exit()

            if event.key == arr[0][2]+32 and PlayState==0:    #小写字母差32
                Sound[chr(event.key)].play() #响应按键声音
                clear_word += 1              #清除字母计数
                PlayState = 1
                plane.over=False
 
                if clear_word >= level.level*LevelNum:   #升级
                    level.level+=1
                    pygame.display.set_caption(u'打字等级:%d' % level.level)
                    diff_ticks=diff_ticks*0.9
                    word_diff_ticks=word_diff_ticks*0.95
                    Sound["win"].play()    
                    bullet.uplevel()                      #子弹样式升级 
                    boom.uplevel()
                    bg.uplevel()
                    plane.uplevel()
                    if 255-level.level*20>0:       #每升一级,键盘表就暗一点
                        jp.set_alpha(255-level.level*20)     
                    

    bg.update()                    #背景处理

    if showKey:
        screen.blit(jp,(w-jp.get_width()-10,h-jp.get_height()-10))  #绘制键盘图

    level.update()                 #绘金币

    #绘制字母
    for i in range(len(arr)):     
        x, y, word, c = arr[i]
        if i==0 and sign:         #要闪烁字符
            c = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
        textImage = myfont.render(chr(word), True, c)
        screen.blit(textImage, (x, y))

    #游戏失败
    if game_state == 2:
        textImage = myfont.render(u"等级%d失败"%level.level, True, (255,0,0))
        sw,sh = textImage.get_size()
        screen.blit(textImage, ((w-sw)/2, (h-sh)/2)) # 居中显示
        Sound["lost"].play()
        time.sleep(5)
        exit()

    #游戏进行中
    if game_state == 1:
        if pygame.time.get_ticks()>=word_ticks: # 计时增加新字母
            word_ticks +=word_diff_ticks
            arr.append(get_random_word())

        #移动字符
        if pygame.time.get_ticks() >= ticks:
            ticks += diff_ticks
            sign=1-sign
            for i in range(len(arr)):
                x, y, word, c = arr[i]
                arr[i] = (x, y+1, word, c)
            if len(arr) > 0 and arr[0][1] > h: game_state=2

    Kill()
    pygame.display.update()

No2

增加了一个排行榜,增强学习动力。

可以调节游戏的难度(下落速度等)

游戏背景似乎还有点BUG,暂未处理。

好象附代码有点长,应该附上压缩包

相关文章