用Python和Pygame写游戏-从入门到精通(4)

By | 2011/05/08

不过5月上旬,气温居然就到了33℃,这日子真是不让人活了……

另外今天是母亲节啊,不知道上什么图片就上这张吧~~

今天说明字体模块和一些错误处理。

使用字体模块

就像上一次说的,一个游戏,再怎么寒碜也得有文字,俄罗斯方块还有个记分数的呢;印象中没有文字的电子游戏只有电脑刚刚诞生的那种打乒乓的了。Pygame可以直接调用系统字体,或者也可以使用TTF字体,稍有点电脑知识的都知道这是什么。为了使用字体,你得先创建一个Font对象,对于系统自带的字体:

my_font = pygame.font.SysFont("arial", 16)

第一个参数是字体名,第二个自然就是大小,一般来说“Arial”字体在很多系统都是存在的,如果找不到的话,就会使用一个默认的字体,这个默认的字体和每个操作系统相关,你也可以使用pygame.font.get_fonts()来获得当前系统所有可用字体。还有一个更好的方法的,使用TTF的方法:

my_font = pygame.font.Font("my_font.ttf", 16)

这个语句使用了一个叫做“my_font.ttf”,这个方法之所以好是因为你可以把字体文件随游戏一起分发,避免用户机器上没有需要的字体。。一旦你创建了一个font对象,你就可以使用render方法来写字了,然后就能blit到屏幕上:

text_surface = my_font.render("Pygame is cool!", True, (0,0,0), (255, 255, 255))

第一个参数是写的文字;第二个参数是个布尔值,以为这是否开启抗锯齿,就是说True的话字体会比较平滑,不过相应的速度有一点点影响;第三个参数是字体的颜色;第四个是背景色,如果你想没有背景色(也就是透明),那么可以不加这第四个参数。

下面是一个小例子演示下文字的使用,不过并不是显示在屏幕上,而是存成一个图片文件

my_name = "Will McGugan"
import pygame
pygame.init()
my_font = pygame.font.SysFont("arial", 64)
name_surface = my_font.render(my_name, True, (0, 0, 0), (255, 255, 255))
pygame.image.save(name_surface, "name.png")

追加说明一下如何显示中文,这在原书可是没有的哦:) 简单来说,首先你得用一个可以使用中文的字体,宋体、黑体什么的,或者你直接用中文TTF文件,然后文字使用unicode,即u”中文的文字”这种,最后不要忘了源文件里加上一句关于文件编码的“魔法注释”,具体的可以查一下Python的编码方面的文章。举一个这样的例子:

# -*- coding: utf-8 -*-
# 记住上面这行是必须的,而且保存文件的编码要一致!
import pygame
from pygame.locals import *
from sys import exit

pygame.init()
screen = pygame.display.set_mode((640, 480), 0, 32)

#font = pygame.font.SysFont("宋体", 40)
#上句在Linux可行,在我的Windows 7 64bit上不行,XP不知道行不行
#font = pygame.font.SysFont("simsunnsimsun", 40)
#用get_fonts()查看后看到了这个字体名,在我的机器上可以正常显示了
font = pygame.font.Font("simsun.ttc", 40)
#这句话总是可以的,所以还是TTF文件保险啊
text_surface = font.render(u"你好", True, (0, 0, 255))

x = 0
y = (480 - text_surface.get_height())/2

background = pygame.image.load("sushiplate.jpg").convert()

while True:
    for event in pygame.event.get():
        if event.type == QUIT:
            exit()

    screen.blit(background, (0, 0))

    x -= 2  # 文字滚动太快的话,改改这个数字
    if x < -text_surface.get_width():
        x = 640 - text_surface.get_width()

    screen.blit(text_surface, (x, y))

    pygame.display.update()

Pygame的错误处理

程序总会出错的,比如当内存用尽的时候Pygame就无法再加载图片,或者文件根本就不存在。再比如下例:

>>> import pygame
>>> screen = pygame.display.set_mode((640, -1))
---------------------------------
Traceback (most recent call last):
  File "<interactive input>", line 1, in ?
pygame.error: Cannot set 0 sized display mode
----------------------------------

对付这种错误一个比较好的方法:

try:
    screen = pygame.display.set_mode(SCREEN_SIZE)
except pygame.error, e:
    print "Can't create the display :-("
    print e
    exit()

其实就是Python的标准的错误捕捉方法就是了,实际的游戏(或者程序)中,错误捕捉实在太重要了,如果你写过比较大的应用,应该不用我来说明这一点,Pygame中也是一样的。

Pygame的基础就到这里,后面我们会进行一些高级的介绍,下一次的话,就开始讲画东西了~

>> 用Python和Pygame写游戏-从入门到精通(5)

58 thoughts on “用Python和Pygame写游戏-从入门到精通(4)

  1. fliks

    xp下font = pygame.font.SysFont(“宋体”, 40) 是可以的

    Reply
  2. thompson2011

    这节能不能提供源码,我在win7 64 下试了很久,也没有成功

    Reply
  3. Bug

    很喜欢那张母亲节的图片,收藏了…
    坚持看完这的系列教程:)

    Reply
  4. 走流沙

    这句话在我的XP上不能用,报错IOError: unable to read font file ‘simsun.ttc’
    把它换成”宋体”和 “simsunnsimsun” 就可以。

    Reply
  5. 走流沙

    但是如果要把这一句font = pygame.font.Font(“simsun.ttc”, 40)中的“Font”换成“SysFont”,就可以运行了,但窗口里出现的不是字体,而是两个小方块在移动

    Reply
    1. xishui Post author

      可惜,还差一点你就能触摸到真理了!IOError: unable to read font file ‘simsun.ttc’是说找不到这个文件,所以你需要把这个文件找到(自己系统搜,或者网上搜),放到代码目录下执行才可以;而将Font改为SysFont,虽然不会报错,但是实际上系统并没有这样的字体,所以只能出现小方块了。。。革命尚未成功,同志还需努力啊!

      Reply
  6. bambotus

    @xishui: 我的开始也是小方块。
    然后把# -*- coding: utf-8 -*-换成# -*- coding:gbk-*-
    把u”你好”,改为”你好”后就正常了。(win7 32位 py2.5)

    Reply
  7. JJin

    请问,我一下的代码
    self.text4 = self.font.render(‘abcn bcd’, True, (0, 0, 0))
    输出不出回车,而是个方形怎么办?

    Reply
  8. JJin

    请问,我一下的代码
    self.text4 = self.font.render(‘abcn bcd’, True, (0, 0, 0))
    输出不出回车,而是个方形怎么办?

    Reply
  9. good

    a good course, i finally know c++’s game lib’s shortcoming compared to python

    Reply
  10. criss

    请问字体设置好后,字体的大小怎么更改?总不能每种大小都要设一种字体吧?

    Reply
    1. xishui Post author

      您说对了,每一种大小就应该新建立一个字体对象:)这是非常普遍的做法。

      Reply
  11. lzy

    你好,我是一PY初学者。我试用了你使用中文字的那节代码
    但是PY显示源代码的倒数第4行那个分号是错的,请问是怎么回事?
    我电脑是64位的,PY2.7

    Reply
    1. xishui Post author

      是这样的,我把自己博客更新了一遍后,代码中所有的>变成了&gt;,<成了&gt;,现在我又修改了一下,应该是正确的了,如果没有,请手动改一下吧!

      Reply
  12. miku

    你好 请问为什么有时候它会提示 Text has zero width但是有时候又不会?

    Reply
    1. 我是100分

      不知道你解决没有,我用的Python 3.7 ,发现了一个解决方法是,在exit()语句前加上del my_font

      Reply
  13. cqq626

    File “C:UserslenovoDesktoptemp.py”, line 31
    if x < -text_surface.get_width():
    ^
    SyntaxError: invalid syntax
    这是怎么回事呐

    Reply
  14. QXX

    字的移动速度不稳定,忽快忽慢是为啥??

    Reply
    1. happy球

      出现的不是中文,而是Aa-A什么的像代码一样的是什么情况啊?

      Reply
    2. 张伟

      x -= 2 # 文字滚动太快的话,改改这个数字
      这一行单改这个数字肯定还是移动太快,需要加fps限制功能.
      在while循环上方加入,
      fclock = pygame.time.Clock()
      Fps = 60
      在while循环内加入
      fclock.tick(Fps)
      就能滚动稳定

      Reply
  15. 燕妮

    刚开始是一定的两个小方块,在C:\Windows\Fonts下拷贝出相应ttf文件到源文件夹下后,显示正常

    Reply
    1. 燕妮

      刚开始是移动的两个小方块,在C:\Windows\Fonts下拷贝出相应ttf文件到源文件夹下后,显示正常

      Reply
  16. 无名侠

    想请教一下。 如何获取字体的宽度?
    因为我需要绘制气泡提示框,但是不知道该如何获取字体的宽度。

    Reply
  17. Rain

    请问为什么我把宋体改成楷体,出现的字的字体并没有发生变化呢?

    Reply
  18. yang123

    我觉得可能第32行改为x=640更好一点

    Reply
  19. yang123

    如果用event.wait()接收事件也挺好玩的

    Reply
    1. 张伟

      对, 上一节 显示那一章学的, 具体什么时候用哪个不知道怎样?for循环和wait()方法. ??

      Reply
  20. 周辉

    去掉screen.blit(background, (0, 0))的效果,能发现什么宝藏?说明了什么?

    Reply
  21. 华南分类传媒

      《画江湖之不良人》真人版网剧正在热播中,开播后就引起网友们的关注和喜爱。网友们想知道黑白无常究竟是什么关系?那么黑白无常结局是什 理财教程 么? 关注微信号:cweipan 手机也能炒白银原油,快来试试吧  超级网剧《画江湖之不良人》集合了传统武侠剧的热血宏大,也融入了时下流行的年轻文化气息,人物造型和设置上集合动画元素,新派武侠创意十足,这就是一部最合适时下年轻人看的武侠剧。最重要的是,《画江湖之不良人》情节尊重于原著故事线发展,不拖沓不滥改,这也是网友们纷纷路转粉,和动画迷们一起”自来水”推荐的主要原因。  超级网剧《画江湖之不良人》打造了一个新派武侠概念,为传统意义上的武侠剧,注入了

    Reply
  22. 综投网

      自从参加了爸爸去哪儿,鲍蕾和陆毅的女儿 理财小知识 贝儿就走入了观众的视野,有一对颜值高的父母让贝儿也乖巧伶俐, 童趣活泼的性格也给小姑娘增粉不少。而前几天贝儿刚刚过完自己的8岁生日,恭喜我们的小公举又长大一岁啦!  10月26日,陆毅在微博晒为女儿庆生的照片,小公主贝儿身着白色裙子,派对现场以粉色为主题,好似童话场景。不过也有网友觉得太奢华。  10月26日,陆毅在微博晒为女儿庆生的照片,小公主贝儿身着白色裙子,派对现场以粉色为主题,好似童话场景。不过也有网友觉得太奢华。  10月26日,陆毅在微博晒为女儿庆生的照片,小公主贝儿身着白色裙子,派对现场以粉色为主题,好似童话场景。不过也有网友觉得太奢华

    Reply
  23. Pingback: 用Python和Pygame写游戏-从入门到精通(4) – 小猫编程站

  24. Pingback: 用Python和Pygame写游戏-从入门到精通(4) | 演道网

  25. zhangzhen

    系统win7
    python 3.5
    运行字体循环程序。
    切换到其他窗口后,再点击pygame的窗口。程序就 不响应 了 。必须关掉,重新运行程序。
    怎么解决?有知道麻烦回复一下。

    Reply
  26. xqq

    你好,非常感谢你作者大大的无私奉献和卓越水平
    经过copy你的代码,并且看了底下的热烈评论,以下操作可以输出正确的字符,供后来的朋友看哦

    系统:win7,64位
    C:\Windows\Fonts这里看到有哪些字体

    # -*- coding: utf-8 -*-这句需要
    font = pygame.font.SysFont(“宋体”, 40)亲测可以,
    text_surface = font.render(u”来吃我啊”, True, (0, 0, 255))这句里的u不用去掉

    ^_^

    Reply
    1. xishui Post author

      这么多年了,没想到还是有人在学习这个系列并且有所收获,感觉好欣慰啊^_^

      Reply
      1. 杀足戒

        谢谢大大这个教程,我从第一课看到现在的,感觉时光匆匆,从11年我本科一年级到现在工作之后又开始读硕士,中国计算机正因为有你们这些人,会继续进步!

        Reply
    2. 张伟

      但是我Win10 , 64位, Python3.7
      font = pygame.font.SysFont(“宋体”, 40) 显示方块, 宋体的实名是simsunnsimsun
      #font = pygame.font.SysFont(“simsunnsimsun”, 40)
      #用get_fonts()查看后看到了这个字体名,在我的机器上可以正常显示了
      博主文中说了
      text_surface = font.render(u”来吃我啊”, True, (0, 0, 255))
      python3根本不需要加u和# -*- coding: utf-8 -*-

      Reply
      1. Danjw

        我也是Win10 , 64位, Python3.7,怎么都调试不成功,能发全码给我学习一下吗

        Reply
  27. waitingZhou

    x -= 2 # 文字滚动太快的话,改改这个数字

    这里改成
    x -= 2
    time.sleep(0.1)
    感觉更好

    Reply
    1. 王箫航

      感谢,我的文字就是太快一直不知道怎么办,顺便补充下需要加载time模块

      Reply
  28. mengxin

    大佬还在吗?pygame.font方法里貌似没有字体旋转的参数。有什么办法吗

    Reply
  29. rainy

    原代码
    x -= 2 # 文字滚动太快的话,改改这个数字
    if x < -text_surface.get_width():
    x = 640 – text_surface.get_width()

    screen.blit(text_surface, (x, y))
    亲测速度太快,不适合观察,在看到教程后的评论了解到了可以使用time模块,time.sleep()
    ,这个函数可以使程序延迟运行,起到减速的效果,而不是用修改x的每次运行减少的值,但是这个应该取决于电脑的运行速度,目前以我目前的所学只能是根据不同的情况进行手动修改。
    除此之外我进行了自己的修改,因为如果自己的窗口的大小不是远远大于字体的长度,那么字体的移动就会显得非常尴尬,所以我又进行了新的screen.blit(),并设置了新的坐标参数,新的代码为:
    x1-=2
    time.sleep(0.01)

    if x1<-text_surface.get_width():
    x1=360-text_surface.get_width()
    x2=360
    elif x1<0:
    x2 -= 2
    screen.blit(text_surface, (x2, y1))
    这样的效果个人感觉比较好。

    Reply
    1. rainy

      我修改的代码是我写其他程序突发奇想的,并不是以文章中的代码为母版修改,所以具体的数据并不是与原文相似,但是思想是不变的。

      Reply
    2. 张伟

      用pygame的Clock对象的tick()方法控制fps更简单

      Reply
  30. Pingback: pygame实现文本转图片 | Mr.Cpp

  31. Alvin

    SysFont、Font有什么区别?谁能说的详细点?我用SysFont显示方框,Font可以正常显示

    Reply

发表评论

您的电子邮箱地址不会被公开。