【编程】零基础Pygame小游戏开发-05

欢迎关注我的专栏( つ•̀ω•́)つ【人工智能通识】


素材文件,百度网盘下载链接 密码:y1cp

中文字体

在上一节中我们只使用了英文字体,怎么显示中文字体呢?

直接下载网盘里面的文件,放在你的main.py一起,将原来的

score_font = pygame.font.SysFont('微软雅黑', 30)

修改为:

score_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf', 30) 

然后在render里面使用中文就可以正常显示了:

end_sur = score_font.render("你的得分:{}/{}!".format(score,times_max), False, (255, 0, 0))

另外,也可以使用系统的中文字体,但是我们不清楚系统里面到底装了哪些字体,可以用print(pygame.font.get_fonts())将所有系统字体都打印出来,然后只能从名字猜出哪些是中文字体了,注意系统字体还是要用font.SysFont而不只是font.Font

显示背景图片

这是我们的背景图片dds-map.jpg

我们可以用map=pygame.image.load('dds-map.jpg')把图片读取到代码里面。
更多官方关于图片的操作说明看这里
注意pygame.image.load()得到的是一个表面surface,我们可以直接把它blit到窗口wind,也可以把它blit到。

这里是完整代码:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠标事件类型

pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 设定窗口

sur = pygame.Surface([600, 400])  # 绘制背景容器
clr = (0, 0, 255)
posAll = [[100, 150], [300, 150], [500, 150], [
    200, 300], [400, 300]]  # 六个位置
rad = 50
tick = 0  # 计数器
pos = posAll[0]  # 外面记录圆的位置

# 分数
score = 0  # 分数计数
pygame.font.init()  # 初始化文字
score_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf', 30)  # !!设定字体和字号
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成计数表面

# 鼠标
pygame.mouse.set_visible(False)  # !!隐藏鼠标
mpos = [300, 200]  # !!记录鼠标位置

times = 0  # 地鼠跳出的次数
times_max=10 #最多次数
tick_max=30 #地鼠每次跳多少帧
map=pygame.image.load('dds-map.jpg')#!!读取图片

while 1:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠标按下事件
            dis = pygame.math.Vector2(
                mpos[0]-pos[0], mpos[1]-pos[1])  # 计算坐标差
            len = pygame.math.Vector2.length(dis)  # 计算距离
            if len < rad:
                tick = 1000  # 立即变换位置
                score = score+1  # 计分增加
        elif event.type == MOUSEMOTION:  # 当鼠标移动的时候
            mpos = pygame.mouse.get_pos()  # 更新鼠标位置        

    if times >= times_max:
        # 显示结束画面
        sur.fill((0, 0, 0)) #!!结束时候仍然用黑色清空画面
        pygame.mouse.set_visible(True) 
        end_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf',48) # !!设定字体和字号
        end_sur = score_font.render("你的分数是:{}/{}!".format(score,times_max), True, (255, 0, 0))  # !!生成计数表面
        window.blit(sur, (0, 0))
        window.blit(end_sur, (100, 100))  # 增加分数表面
    else:
        sur.blit(map, (0, 0)) #!!添加背景图片
        # 每帧循环执行的代码
        if tick > tick_max:  # 每50次刷新变换一次
            times=times+1 #增加计次
            score_sur = score_font.render(
                "分数:{}/{}!".format(score,times), False, (255, 0, 0))  # 重新生成分数文字表面        
            a = random.randint(0, 4)  # 随机0到4
            pos = posAll[a]  # 更新外部记录的圆的位置        
            tick = 0  # 重置计数器
        else:  # 不刷新变换的时候
            tick = tick+1  # 增加计数器      

        # 绘制鼠标
        pygame.draw.circle(sur, clr, pos, 50)  # 使用随机位置画地鼠            
        pygame.draw.circle(sur, (255, 0, 0), mpos, 10)  # !在鼠标位置画红色圆

    # 刷新画面            
    window.blit(sur, (0, 0))
    window.blit(score_sur, (200, 10))  # 增加分数表面
    pygame.display.flip() #刷新画面

注意我们先把图片读取,然后在每帧里面决定是否使用。运行后如下图:


使用动态图片

地鼠和锤子各有两个状态,正常的地鼠和被击打的地鼠,正常的锤子和砸下的锤子,如下图所示(下图无法直接使用,请从网盘下载):


我们可以先把四个图片都load读取进来成为rat1,rat2,ham1,ham2,然后我们使用ratsurhamsur表示真正要使用的表面,当鼠标按下的时候我们设定hamsur=ham2是砸下图片,当鼠标点击位置距离地鼠小于地鼠半径的时候我们使用ratsur=rat2被砸中的图片。最后我们再分别把地鼠和锤头blitsur上面。

改造后的代码如下:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠标事件类型
import time


pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 设定窗口

sur = pygame.Surface([600, 400])  # 绘制背景容器
clr = (0, 0, 255)
posAll = [[100, 150], [300, 150], [500, 150], [
    200, 300], [400, 300]]  # 六个位置
rad = 50
tick = 0  # 计数器
pos = posAll[0]  # 外面记录圆的位置

# 分数
score = 0  # 分数计数
pygame.font.init()  # 初始化文字
score_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf', 30)  # !!设定字体和字号
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成计数表面

# 鼠标
pygame.mouse.set_visible(False)  # !!隐藏鼠标
mpos = [300, 200]  # !!记录鼠标位置

times = 0  # 地鼠跳出的次数
times_max=10 #最多次数
tick_max=30 #地鼠每次跳多少帧
map=pygame.image.load('dds-map.jpg')#!!读取图片
rat1=pygame.image.load('rat1.png')#!!读取地鼠图片
rat2=pygame.image.load('rat2.png')#!!读取被砸地鼠图片
ham1=pygame.image.load('hammer1.png')#!!读取锤子图片
ham2=pygame.image.load('hammer2.png')#!!读取砸下锤子图片

while 1:
    hamsur=ham1
    ratsur=rat1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠标按下事件
            hamsur=ham2 #!!使用下落锤子
            mpos = pygame.mouse.get_pos()  # 获取鼠标位置
            dis = pygame.math.Vector2(
                mpos[0]-pos[0], mpos[1]-pos[1])  # 计算坐标差
            len = pygame.math.Vector2.length(dis)  # 计算距离
            if len < rad:
                tick = 1000  # 立即变换位置
                score = score+1  # 计分增加
                ratsur=rat2 #!!使用被砸地鼠
        elif event.type == MOUSEMOTION:  # 当鼠标移动的时候
            mpos = pygame.mouse.get_pos()  # 更新鼠标位置        

    if times >= times_max:
        # 显示结束画面
        sur.fill((0, 0, 0)) #结束时候仍然用黑色清空画面
        pygame.mouse.set_visible(True) 
        end_font = pygame.font.Font('MicrosoftYaqiHeiLight-2.ttf',48) # !!设定字体和字号
        end_sur = score_font.render("你的分数是:{}/{}!".format(score,times_max), True, (255, 0, 0))  # !!生成计数表面
        window.blit(sur, (0, 0))
        window.blit(end_sur, (100, 100))  # 增加分数表面
    else:
        sur.blit(map, (0, 0)) #添加背景图片
        # 每帧循环执行的代码
        if tick > tick_max:  # 每50次刷新变换一次
            times=times+1 #增加计次
            score_sur = score_font.render(
                "分数:{}/{}!".format(score,times), False, (255, 0, 0))  # 重新生成分数文字表面        
            a = random.randint(0, 4)  # 随机0到4
            pos = posAll[a]  # 更新外部记录的圆的位置        
            tick = 0  # 重置计数器
        else:  # 不刷新变换的时候
            tick = tick+1  # 增加计数器
        
        sur.blit(ratsur,(pos[0]-50,pos[1]-70)) #绘制地鼠
        sur.blit(hamsur,(mpos[0]-50,mpos[1]-100)) #绘制锤头

    # 刷新画面            
    window.blit(sur, (0, 0))
    window.blit(score_sur, (200, 10))  # 增加分数表面
    pygame.display.flip() #刷新画面
    time.sleep(0.04) #!!保持画面一点时间

注意这里的import timetime.sleep(0.04)这是让每一帧停留一点点时间,0.04秒,每秒25帧(假设每帧画图不需要时间的话)。
另外我们再blit的时候使用了(pos[0]-50,pos[1]-50)这样的偏移,因为图片总是用左上角作为位置的起点,这样偏移之后就变到了图片中心,实际上我们又故意让地鼠和锤子更高一些,就使用了(pos[0]-50,pos[1]-70)

运行之后的样子如下图:


让游戏重新开始

每次显示最终成绩之后,能不能让游戏3秒后重新开始呢?

我们设定一个gameover=0,游戏结束后每帧都增加这个数字,如果gameover>100,就是过了100帧,那么我们就重新开始。
重新开始必须意味着各种数据(分数,计时什么的)和画面都要重置到原来的状态。
修改后的整体代码如下:

import pygame
import sys
import random
from pygame.locals import *  # 引入鼠标事件类型
import time


pygame.init()  # 初始化
window = pygame.display.set_mode([600, 400])  # 设定窗口

sur = pygame.Surface([600, 400])  # 绘制背景容器
clr = (0, 0, 255)
posAll = [[100, 150], [300, 150], [500, 150], [200, 300], [400, 300]]  # 六个位置
rad = 50
tick = 0  # 计数器
pos = posAll[0]  # 外面记录圆的位置

# 分数
score = 0  # 分数计数
pygame.font.init()  # 初始化文字
score_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 30)  # !!设定字体和字号
score_sur = score_font.render(str(score), False, (255, 0, 0))  # !!生成计数表面

# 鼠标
pygame.mouse.set_visible(False)  # !!隐藏鼠标
mpos = [300, 200]  # !!记录鼠标位置

times = 0  # 地鼠跳出的次数
times_max = 10  # 最多次数
tick_max = 30  # 地鼠每次跳多少帧
map = pygame.image.load("dds-map.jpg")  # !!读取图片
rat1 = pygame.image.load("rat1.png")  # !!读取地鼠图片
rat2 = pygame.image.load("rat2.png")  # !!读取被砸地鼠图片
ham1 = pygame.image.load("hammer1.png")  # !!读取锤子图片
ham2 = pygame.image.load("hammer2.png")  # !!读取砸下锤子图片

gameover = 0 #!!结束计时
gameover_max = 100 #!!结束计时最大值,超过这个值就重新开始

while 1:
    hamsur = ham1
    ratsur = rat1
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            sys.exit()
        elif event.type == MOUSEBUTTONDOWN:  # 如果是鼠标按下事件
            hamsur = ham2  # !!使用下落锤子
            mpos = pygame.mouse.get_pos()  # 获取鼠标位置
            dis = pygame.math.Vector2(mpos[0] - pos[0], mpos[1] - pos[1])  # 计算坐标差
            len = pygame.math.Vector2.length(dis)  # 计算距离
            if len < rad:
                tick = 1000  # 立即变换位置
                score = score + 1  # 计分增加
                ratsur = rat2  # !!使用被砸地鼠
        elif event.type == MOUSEMOTION:  # 当鼠标移动的时候
            mpos = pygame.mouse.get_pos()  # 更新鼠标位置

    if times >= times_max:
        # 显示结束画面
        sur.fill((0, 0, 0))  # 结束时候仍然用黑色清空画面
        pygame.mouse.set_visible(True)
        end_font = pygame.font.Font("MicrosoftYaqiHeiLight-2.ttf", 48)  # !!设定字体和字号
        end_sur = score_font.render(
            "你的分数是:{}/{}!".format(score, times_max), True, (255, 0, 0)
        )  # !!生成计数表面
        sur.blit(end_sur, (100, 150))
        cd = int((gameover_max - gameover) / 10)
        cd_sur = score_font.render(
            "重新开始倒计时{}".format(cd), True, (255, 0, 0)
        )  # !!生成计数表面
        sur.blit(cd_sur, (100, 200))  # 增加分数表面
        gameover = gameover + 1 #!!增加结束计时
    else:
        sur.blit(map, (0, 0))  # 添加背景图片
        score_sur = score_font.render(
            "分数:{}/{}!".format(score, times + 1), False, (255, 0, 0)
        )  # 重新生成分数文字表面
        sur.blit(score_sur, (200, 10))  # 增加分数表面
        if tick > tick_max:  # 每50次刷新变换一次
            times = times + 1  # 增加计次
            a = random.randint(0, 4)  # 随机0到4
            pos = posAll[a]  # 更新外部记录的圆的位置
            tick = 0  # 重置计数器
        else:  # 不刷新变换的时候
            tick = tick + 1  # 增加计数器
        if tick > 5:  # 开始几帧不显示地鼠
            sur.blit(ratsur, (pos[0] - 50, pos[1] - 70))  # 绘制地鼠
        sur.blit(hamsur, (mpos[0] - 50, mpos[1] - 100))  # 绘制锤头

    # 刷新画面
    window.blit(sur, (0, 0))
    pygame.display.flip()  # 刷新画面
    time.sleep(0.04)  # !!保持画面一点时间

    # !!重置游戏
    if gameover > gameover_max:
        pygame.mouse.set_visible(False)
        times = 0
        score = 0
        gameover = 0

运行这个代码就能反复玩游戏了。
到这里游戏看上去好了很多,但是还没有背景音乐,打地鼠的时候也没有音效,下一节我们继续添加声音。

【编程】零基础Pygame小游戏开发(索引)

<未完待续>


欢迎关注我的专栏( つ•̀ω•́)つ【人工智能通识】


每个人的智能新时代

如果您发现文章错误,请不吝留言指正;
如果您觉得有用,请点喜欢;
如果您觉得很有用,欢迎转载~


END

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容