我在一个月前开始使用Pygame,让我的第一个游戏运行良好,并有一个高分表和玩家名称输入框。我的问题是当玩家输入他们的名字时让shift键工作。 而不是弄乱我的游戏,我创建了一个小测试程序。每当我点击任何修改键或键盘时,我都会收到错误“文件”C:\ PythonProjects \ NameBox \ namebox.py“,第61行,在ask current_string + = chr(inkey)中 ValueError:chr()arg不在范围(256)“
中任何人都可以帮我解决这个问题。我已经尝试了很多我在网上找到的建议,但无法让它们起作用。也许有更好的方法可以做到这一点,但至少这给了我一个名字(全部只是小写)并将其与得分和日期一起输入正确位置的高分表。
这是我的测试计划。希望我正确输入代码。
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()
答案 0 :(得分:4)
更新:仔细阅读the linked question和the docs之后,我想我找到了更好的方法来实现您的目标。
KEYDOWN
事件有一个附加属性unicode
。引用文档:
pygame.KEYDOWN事件有一个额外的属性unicode和scancode。 unicode表示单个字符串,它是输入的完全翻译字符。这考虑了移位和组合键。 scancode表示平台特定的密钥代码。这可能与键盘不同,但对于像多媒体键这样的奇怪键的键选择很有用。
我建议您从get_key
返回一个值而不是一个元组,这样您就可以访问这两个值:
if event.type == pygame.KEYDOWN:
return (event.key, event.unicode)
在您的通话代码中,不要使用chr(inkey)
而是使用unicode
值:
(inkey, unichr) = get_key()
...
else:
current_string += unichr
这样,正确的字符将附加到字符串中,并且已经处理了所有小细节(修饰键,死键等)。
P.S。不要使用string.capitalize()
,否则会弄乱你的字符串。引用the docs:
返回字符串的副本,其第一个字符为大写,其余字符为小写。
这意味着任何字母都是你的字符串总是遵循这种模式:如果是第一个字符则为大写,否则为小写。其他字符(没有案例)将保持不变。一些例子:
>>> "aBcDeF".capitalize()
"Abcdef"
>>> "a123B".capitalize()
"A123b"
>>> "@#$%".capitalize()
"@#$%"
>>> "qq2@3#~`?/|\\".capitalize()
"Qq2@3#~`?/|\\"
答案 1 :(得分: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()