2017-09-14 5 views
1

J'essaie de créer un jeu avec l'art ASCII dans Pygame 2.7. Si je vais à la console Idle et tapez simplement:Affichage des caractères non imprimables dans Pygame

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

Je reçois près de 255 caractères distincts. Cependant, si j'essaye une cascade similaire dans 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() 

La plupart de ces cascades sont simplement vides. Pourquoi la divergence? J'ai essayé de changer les polices, même en utilisant celle utilisée par Idle; J'ai essayé de l'analyser comme unicode; rien ne semble fonctionner. Cela ne me dérangerait pas si je ne dis pas que, comme je l'ai dit, il imprime très bien dans Idle, et certains des caractères que je ne peux pas obtenir sont présents dans d'autres jeux ASCII que je joue, donc ça doit être rendable.

Quelqu'un peut-il conseiller? Je suis un amateur/autodidacte enseigné par google, et préfèrerais honnêtement ne pas avoir à télécharger des modules supplémentaires si cela est évitable. Si rien d'autre, je vais me contenter d'une explication du double standard apparent de mon ordinateur sur cette question.

Merci beaucoup.

Répondre

0

Je pense que le problème principal est que Pygame et Idle utilisent différents encodages par défaut pour interpréter vos chaînes. Les cordes en Python 2 sont difficiles à comprendre, alors portez-moi un peu. Aussi, corrigez-moi si je me trompe, mais je suppose que vous utilisez Python 2, qui gère les chaînes très différemment de Python 3.

Les chaînes dans Python 2 sont juste des séries d'octets. Les octets dans Python 2 peuvent être exprimés en octets littéraux en créant un objet bytes ou en ajoutant une chaîne avec b.

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

chr(i) "Retourne une chaîne d'un caractère dont le code ASCII est le nombre entier i." (Docs) Si une chaîne est une série d'octets, chr renvoie des octets. Regardons ce que chr rendements si nous l'appelons dans l'interpréteur Python 2:

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

La raison pour laquelle ces lettres apparaissent dans la sortie de l'interpréteur est que l'encodage par défaut de Python 2 est ASCII, donc quand il voit une valeur d'octet correspond à un symbole sur le tableau ASCII, il remplace l'octet avec ce symbole. ASCII est limité aux symboles correspondant aux valeurs 0 à 127. This chart montre à quel symbole correspond chaque valeur. 97 est 'a' et 120 est 'x'.

Vous remarquerez que 0-31 et 127 sont des "caractères de contrôle" qui ne représentent pas des symboles, mais communiquent des choses à la machine en lisant le texte. Par exemple, dans le langage C, la fin d'une chaîne est désignée par le caractère nul, qui est le code 0 en ASCII.

chr accepte un argument de 0 à 255. Que se passe-t-il si nous transmettons un entier à chr qui représente un caractère de contrôle en ASCII? Que faire si nous lui passons un nombre entier supérieur à 127?

chr(4) 
>>>'\x04' 
chr(163) 
>>>'\xa3' 

\x dans une chaîne en Python dit l'interprète que les deux caractères suivants représentent une valeur hexadecimal. Lorsque la valeur de l'octet n'a pas de symbole correspondant en ASCII, l'interpréteur affiche simplement la valeur de l'octet sous la forme d'un nombre hexadécimal. Dans les coulisses, 'a' est juste '\x61', mais l'interpréteur utilise ASCII pour nous montrer ce que '\ x61' représente.

Il existe beaucoup d'encodages en plus de l'ASCII. UTF-8 est un très commun dont vous avez probablement entendu parler. Comme ASCII, il relie les valeurs numériques aux symboles. This chart montre les 256 premiers points de code en UTF-8. Ils correspondent exactement à ce qui est sortie par votre code pygame:

pygame output

Donc vous passez octets à la fonction drawtext, et il utilise UTF-8 pour interpréter les octets comme des symboles. Quand il obtient une valeur qui correspond à un caractère de contrôle, il sort simplement le carré à la place.

La raison Idle vous montre différents symboles parce qu'il utilise un codage par défaut différent de celui de Pygame. Sans savoir de quels symboles il sort, je ne peux pas dire quel encodage il est. ISO-8859-1 et Windows-1252 sont deux autres codages très courants. Vous pouvez vérifier quel codage Idle utilise en allant dans Preferences> General et en regardant l'option "Default Source Encoding".

Alors, que faites-vous à ce sujet? Si vous voulez vraiment vous limiter aux symboles ASCII, vous pouvez utiliser le module string, qui contient des listes de caractères utiles. Vous pouvez obtenir tous les caractères ASCII non-blancs avec le code suivant:

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

Si vous souhaitez utiliser plus que ces personnages, Pygame ne seront jamais capables de rendre les caractères de contrôle de UTF-8. Voici 2 options que je vois.

  1. Passez une chaîne unicode contenant le caractère souhaité. Cette option vous oblige à déclarer un encodage par défaut différent sur la première ligne de votre fichier en utilisant un commentaire magique:

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

  2. Passez une chaîne unicode contenant la désignation unicode pour le symbole vouloir. Cela ne nécessite pas le commentaire magique de l'option 1.

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

+0

Merci beaucoup! Je pense que j'ai tiré plus de votre message que des semaines à regarder la documentation. :) (Je pense que les docs de python supposent une base de connaissance de programmation qui est légèrement au-delà de ce que j'ai actuellement, mais j'arrive là!) – queenofthecapes

+0

Vous êtes les bienvenus! J'ai commencé comme programmeur autodidacte en utilisant pygame, donc je suis très heureux d'aider. C'est une excellente question aussi. J'ai beaucoup appris en lisant sur la façon dont les chaînes fonctionnent en Python. Bonne chance avec le jeu! En passant, si ce que j'ai écrit répond à votre question, cela vous dérangerait-il de l'accepter comme réponse? C'est ainsi que les sites Stack Exchange vous encouragent à donner votre avis sur les réponses. [étiquette de réponse] (https://meta.stackexchange.com/questions/19448/etiquette-for-selecting-answers). Merci! – ryanh119