我正在尝试在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游戏中,所以它必须以某种方式渲染。
任何人都可以提供建议吗?我是一个自我/谷歌教的业余爱好者,如果可以避免的话,老实说他们不想下载额外的模块。如果没有别的,我会解释我的计算机在这个问题上明显的双重标准。
非常感谢。
答案 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代码输出的内容:
所以你将字节传递给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的控制字符。以下是我看到的两个选项。
传递包含所需字符的unicode字符串。此选项要求您使用魔术注释在文件的第一行声明不同的默认编码:
# -*- coding: utf-8 -*-
...
self.drawtext(u"€", x, y)
传递包含所需符号的unicode指定的unicode字符串。这不需要选项1中的魔术评论。
self.draw_text(u'\u20ac', x, y)