在Pygame中显示不可打印的Characers

时间:2017-09-14 20:33:42

标签: python pygame character ascii rendering

我正在尝试在Pygame 2.7中创建一个带有ASCII艺术的游戏。如果我进入空闲控制台并输入:

for i in range(255):
    print str(i) + ' - ' + str(chr(i))

我得到近255个不同的角色。但是,如果我在Pygame中尝试类似的特技:

import pygame, os, string, sys
from pygame.locals import * 
pygame.init()

class Prog:
    def __init__(self):
        self.title = 'Text'
        self.screen_size = (800, 600)
        self.screen = pygame.display.set_mode(self.screen_size)
        self.bg_color = (255, 255, 255)
        self.text_color = (0,0,0)
        self.text_font = 'Times New Roman'
        self.text_size = 20
        self.font = pygame.font.SysFont(self.text_font, self.text_size)

    def draw_text(self, text, x, y):
        textobj = self.font.render(text, 1, self.text_color)
        textrect = textobj.get_rect()
        textrect.center = (x,y)
        self.screen.blit(textobj, textrect)
    def main(self):
        rec = self.screen.get_rect()
        done = False
        while not done:
            for event in pygame.event.get():
                if event.type == QUIT:
                    done = True

            self.screen.fill(self.bg_color)
            x = 20
            y = 100
            n = 1
            for i in range(1, 255):
                self.draw_text(chr(i), x, y)
                x += 20
                n += 1
                if n > 25:
                    n = 1
                    x = 20
                    y += 30
            pygame.display.flip()

大多数只是空盒子。为什么会出现差异?我尝试过改变字体,甚至使用Idle使用的字体;我尝试将其解析为unicode;似乎没什么用。如果不是因为我没说,它在Idle中打印就好了,并且我无法获得的一些字符出现在我播放的其他ASCII游戏中,所以它必须以某种方式渲染。

任何人都可以提供建议吗?我是一个自我/谷歌教的业余爱好者,如果可以避免的话,老实说他们不想下载额外的模块。如果没有别的,我会解释我的计算机在这个问题上明显的双重标准。

非常感谢。

1 个答案:

答案 0 :(得分:0)

我认为主要问题是Pygame和Idle使用不同的默认编码来解释你的字符串。 Python 2中的字符串很难理解,所以请耐心等待一下。另外,如果我错了,请纠正我,但我假设您使用的是Python 2,它处理的字符串与Python 3的处理方式大不相同。

Python 2中的字符串只是一系列字节。 Python 2中的字节可以通过创建bytes对象或在b前面添加字符串来表示为字节文字。

'a' == b'a' == bytes(a)
>>>True

chr(i)"返回一个字符串,其ASCII码为整数i。" (Docs)如果字符串是一系列字节,chr返回字节。如果我们在Python 2解释器中调用它,那么让我们看一下chr返回的内容:

chr(97)
>>>'a'
chr(120)
>>>'x'

这些字母出现在解释器输出中的原因是Python 2的默认编码是ASCII,因此当它看到与ASCII图表上的符号对应的字节值时,它会用该符号替换该字节。 ASCII仅限于与值0到127对应的符号。This chart显示每个值对应的符号。 97是' a'和120是' x'。

你会注意到0-31和127是"控制字符"不代表符号,但将内容传达给阅读文本的机器。例如,在C语言中,字符串的结尾由空字符表示,该字符是ASCII中的代码点0。

chr接受0到255之间的参数。如果我们将一个整数传递给代表ASCII中控制字符的chr,会发生什么?如果我们传递一个大于127的整数怎么办?

chr(4)
>>>'\x04'
chr(163)
>>>'\xa3'
Python中的字符串中的

\x告诉解释器接下来的两个字符代表hexadecimal值。当字节值在ASCII中没有相应的符号时,解释器只是将字节值显示为十六进制数。在幕后,'a'只是'\x61',但解释程序使用ASCII向我们展示' \ x61'表示。

除了ASCII之外还有很多编码。 UTF-8是您可能听说过的非常常见的一种。与ASCII一样,它将数值与符号联系起来。 This chart显示UTF-8中的前256个代码点。它们完全对应于pygame代码输出的内容:

pygame output

所以你将字节传递给drawtext函数,并且它使用UTF-8将这些字节解释为符号。当它获得一个与控制字符对应的值时,它只是输出正方形。

Idle显示不同符号的原因是因为它使用与Pygame不同的默认编码。在不知道它输出什么符号的情况下,我无法说出它是哪种编码。 ISO-8859-1和Windows-1252是另外两种非常常见的编码。您可以通过转到“首选项”>来检查空闲使用的编码。一般并查看"默认源编码"选项。

那你怎么办呢?如果您真的想将自己限制为ASCII符号,可以使用string模块,其中包含有用的字符列表。您可以使用以下代码获取所有非空白ASCII字符:

import string
ascii_characters = string.digits + string.letters + string.punctuation
print ascii_characters

如果你想使用的不仅仅是那些字符,Pygame将永远无法呈现UTF-8的控制字符。以下是我看到的两个选项。

  1. 传递包含所需字符的unicode字符串。此选项要求您使用魔术注释在文件的第一行声明不同的默认编码:

    # -*- coding: utf-8 -*-
    ...
    self.drawtext(u"€", x, y)

  2. 传递包含所需符号的unicode指定的unicode字符串。这不需要选项1中的魔术评论。

    self.draw_text(u'\u20ac', x, y)