2

私は 1 か月前に Pygame を使い始め、ハイスコア テーブルとプレイヤー名の入力ボックスを使用して、最初のゲームを正常に実行しました。私の問題は、プレイヤーが自分の名前を入力したときにシフトキーが機能するようにすることです。ゲームを台無しにするのではなく、小さなテスト プログラムを作成しました。修飾キーまたはキーパッドを押すたびに、「File "C:\PythonProjects\NameBox\namebox.py", line 61, ask current_string += chr(inkey) ValueError: chr() arg not in range( というエラーが表示されます。 256)」

誰でもこれを機能させるのを手伝ってくれませんか。Web で見つけた多くの提案を試しましたが、どれも機能しません。もっと良い方法があるかもしれませんが、少なくともこれで名前が付けられ (すべて小文字のみ)、スコアと日付と共にハイスコア テーブルの正しい場所に入力されます。

これは私のテストプログラムです。コードを正しく入力したことを願っています。

import pygame, sys, os
os.environ['SDL_VIDEO_CENTERED'] = '1'  # centers Pygame SCREEN on desktop

from pygame.locals import *
pygame.font.init()

SCREENWIDTH = 640
SCREENHEIGHT = 480 
SCREEN = pygame.display.set_mode((SCREENWIDTH+9, SCREENHEIGHT+9))
BASICFONT = pygame.font.Font('freesansbold.ttf', 18, bold = False, italic=False)
WHITE     = (255, 255, 255)
BLACK     = (  0,   0,   0)
GREEN     = (  0, 255,   0)
DARKGREEN = (  0, 128,   0)

def main():
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            elif event.type == KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    terminate()
                elif event.key == pygame.K_n:
                    getname()

        spaceSurf = BASICFONT.render('Press n to enter name', False, WHITE)
        spaceRect = spaceSurf.get_rect()
        spaceRect.midtop = (SCREENWIDTH / 2, SCREENHEIGHT - 30)
        SCREEN.blit(spaceSurf, spaceRect)
        pygame.display.update()

def getname():
    name = ask("Your name")
    SCREEN.fill(BLACK)
    nSurf = BASICFONT.render('Press n to enter name', False, WHITE)
    nRect = nSurf.get_rect()
    nRect.midtop = (SCREENWIDTH / 2, SCREENHEIGHT - 30)
    SCREEN.blit(nSurf, nRect)

    nameSurf = BASICFONT.render('Your name is '+ name, True, WHITE)
    nameRect = nameSurf.get_rect()
    nameRect.midtop = (SCREENWIDTH / 2, SCREENHEIGHT / 2)
    SCREEN.blit(nameSurf, nameRect)

    pygame.display.update()

def ask(question):
    "ask(question) -> answer"
    current_string = ""
    display_box(question + ": " + current_string)
    while 1:
        inkey = get_key()
        if inkey == K_BACKSPACE:
            current_string -= 1
        elif inkey == K_RETURN or inkey == K_KP_ENTER:
            break
        elif inkey == pygame.K_ESCAPE:
            terminate()
        else:
            current_string += chr(inkey)

        display_box(question + ": " + current_string.capitalize())

    return current_string.capitalize() # this is the answer    

def get_key():
    while 1:
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                return event.key
            else:
                pass

def display_box(message):
  "Print a message in a box in the middle of the screen"
  SCREEN.fill(BLACK)
  left = (SCREENWIDTH / 2) - 156
  top = (SCREENHEIGHT / 2) -100
  pygame.draw.rect(SCREEN, DARKGREEN, (left, top, 320, 200)) 
  SCREEN.blit(BASICFONT.render("New High Score!", True, GREEN),(left + 90, top + 35)) 
  SCREEN.blit(BASICFONT.render("Press Enter when done.", True, GREEN),
          (left + 51, top + 160)) 

  pygame.draw.rect(SCREEN, BLACK, (left + 39, top + 110, 240, 20))
  pygame.draw.rect(SCREEN, WHITE, (left + 38, top + 108, 244, 24), 1)

  if len(message) != 0:
      SCREEN.blit(BASICFONT.render(message, True, WHITE), (left+42, top + 111))

  pygame.display.update()

def terminate():
    pygame.quit()
    sys.exit()

if __name__ == '__main__':
    main()
4

2 に答える 2

4

更新:リンクされた質問ドキュメントをより注意深く読んだ後、あなたが望むものを達成するためのより良い方法を見つけたと思います.

KEYDOWNイベントには、追加の属性がありますunicode。ドキュメントの引用:

pygame.KEYDOWN イベントには、追加の属性 unicode と scancode があります。unicode は、入力された完全に翻訳された文字である単一の文字列を表します。これには、シフト キーとコンポジション キーが考慮されます。scancode は、プラットフォーム固有のキー コードを表します。これはキーボードごとに異なる可能性がありますが、マルチメディア キーのような特殊なキーのキー選択に役立ちます。

値ではなくタプルを から返すことをお勧めしますget_key。これにより、2 つの値にアクセスできるようになります。

if event.type == pygame.KEYDOWN:
    return (event.key, event.unicode)

呼び出しコードでは、使用する代わりに値をchr(inkey)使用します。unicode

(inkey, unichr) = get_key()
...
else:
    current_string += unichr

このようにして、すべての詳細 (修飾キー、デッド キーなど) が既に処理された状態で、正しい文字が文字列に追加されます。

PS 使用しないでください。そうしないstring.capitalize()と、文字列が台無しになります。ドキュメントの引用:

最初の文字を大文字にし、残りを小文字にした文字列のコピーを返します。

つまり、文字列は常にこのパターンに従います。最初の文字の場合は大文字、それ以外の場合は小文字です。その他の文字 (大文字と小文字を区別しない) は変更されません。いくつかの例:

>>> "aBcDeF".capitalize()
"Abcdef"
>>> "a123B".capitalize()
"A123b"
>>> "@#$%".capitalize()
"@#$%"
>>> "qq2@3#~`?/|\\".capitalize()
"Qq2@3#~`?/|\\"
于 2012-06-03T02:54:34.960 に答える
1

これが私の最終的な実用的なソリューションです。それが他の人を助けることを願っています。

" This demonstrates how to show an input box on screen and get the player name."
" By Barberic http://web.aanet.com.au/~barberic/"
" with thanks for help from mgibsonbr on stackoverflow.com"

import pygame, sys, os
os.environ['SDL_VIDEO_CENTERED'] = '1'  # centers Pygame SCREEN on desktop

from pygame.locals import *
pygame.font.init()

SCREENWIDTH = 640
SCREENHEIGHT = 480 
SCREEN = pygame.display.set_mode((SCREENWIDTH, SCREENHEIGHT))
BASICFONT = pygame.font.Font('freesansbold.ttf', 18, bold = False, italic=False)
WHITE     = (255, 255, 255)
BLACK     = (  0,   0,   0)
GREEN     = (  0, 255,   0)
DARKGREEN = (  0, 128,   0)

def main():
    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                terminate()
            elif event.type == KEYDOWN:
                if event.key == pygame.K_ESCAPE:
                    terminate()
                elif event.key == pygame.K_n:
                    getname()

        spaceRect = spaceSurf.get_rect()
        spaceRect.midtop = (SCREENWIDTH / 2, SCREENHEIGHT - 30)
        SCREEN.blit(spaceSurf, spaceRect)
        pygame.display.update()

def getname():
    name = ask("Your name")
    SCREEN.fill(BLACK)
    nSurf = BASICFONT.render('Press n to enter name', False, WHITE)
    nRect = nSurf.get_rect()
    nRect.midtop = (SCREENWIDTH / 2, SCREENHEIGHT - 30)
    SCREEN.blit(nSurf, nRect)

    # display the name on screen
    nameSurf = BASICFONT.render('Your name is '+ name, True, WHITE)
    nameRect = nameSurf.get_rect()
    nameRect.midtop = (SCREENWIDTH / 2, SCREENHEIGHT / 2)
    SCREEN.blit(nameSurf, nameRect)

    pygame.display.update()

def ask(question):
    "ask(question) -> answer"
    current_string = ""
    display_box(question + ": " + current_string)
    while 1:
        (inkey, unichr) = get_key()

        if inkey == K_BACKSPACE:  # remove last char
            current_string = current_string[:-1]
        elif inkey == K_RETURN or inkey == K_KP_ENTER:
            break   # break out of the while loop to return current_string
        elif inkey == pygame.K_ESCAPE:
            terminate()
        else:  
           current_string += unichr  # add a new char

        # limit the name length to 12 characters 
        current_string = current_string[:12]
        # show the current name during typing
        display_box(question + ": " + current_string)

    return current_string # this is the answer    

def get_key():
    while 1:
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                return (event.key, event.unicode)

def display_box(message):
  "Print a message in a box in the middle of the screen"
  SCREEN.fill(BLACK)
  left = (SCREENWIDTH / 2) - 156
  top = (SCREENHEIGHT / 2) -100
  pygame.draw.rect(SCREEN, DARKGREEN, (left, top, 320, 200)) 
  SCREEN.blit(BASICFONT.render("New High Score!", True, GREEN),
              (left + 90, top + 35)) 
  SCREEN.blit(BASICFONT.render("Press Enter when done.", True, GREEN),
              (left + 51, top + 160)) 

  pygame.draw.rect(SCREEN, BLACK, (left + 39, top + 110, 240, 20))
  pygame.draw.rect(SCREEN, WHITE, (left + 38, top + 108, 244, 24), 1)

  if len(message) != 0:
    SCREEN.blit(BASICFONT.render(message, True, WHITE), (left+42, top + 111))

  pygame.display.update()

def terminate():
    pygame.quit()
    sys.exit()

if __name__ == '__main__':
    main()
于 2012-06-04T05:47:56.660 に答える