文本未动态显示,pygame

text not showing up dynamically, pygame

下面的代码应该创建一个显示乐谱文本的绿色按钮。不幸的是,按钮什么都不做,我设法让它工作的唯一方法是将对 makeText 的函数调用放在 while 循环中而不是放在 clickButton 函数中,但如果我这样做,它就不再是动态的。有人可以解释为什么当我按下按钮并修复我的代码以使其显示时文本没有显示吗?

import pygame
import sys
#game stuff
pygame.init()
screen = pygame.display.set_mode((640, 480),0,32)
clock = pygame.time.Clock()

#functions
def makeText(title,text,posx,posy):
    font=pygame.font.Font(None,30)
    scoretext=font.render(str(title)+ ": " +str(text), 1,(0,0,0))
    screen.blit(scoretext, (posx, posy))
def clickButton(name,x,y,width,height):
    if x + width > cur[0] > x and y + height > cur[1] > y:
        if click == (1,0,0):
            makeText("score",300,100,10)
#objects
button1 = pygame.Rect((0,0), (32,32))

while True:
    screen.fill((255,255,255))
    screen.fill((55,155,0), button1)
#update display
    pygame.display.update()
    clock.tick(60)
#event handling
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            cur = event.pos
            click = pygame.mouse.get_pressed()
            clickButton("button1",button1.left,button1.top,button1.width,button1.height)

您正在检查 clickButton 函数中 "click" 的值,但我没有看到 click 在 clickButton 可以访问它的任何地方定义。 也许您应该将 click 作为参数传递给 clickButton 函数,这可能会使 if 条件为真?

问题在于,一旦您创建了文本,您的主循环就会继续运行并调用 screen.fill,甚至在调用 pygame.display.update() 之前就透支了文本。


您可以将其更改为:

...
def clickButton(name,x,y,width,height):
    print x + width > cur[0] > x and y + height > cur[1] > y
    if x + width > cur[0] > x and y + height > cur[1] > y:
        if click == (1,0,0):
            makeText("score",300,100,10)
#objects
button1 = pygame.Rect((0,0), (32,32))

while True:
    screen.fill((255,255,255))
    screen.fill((55,155,0), button1)

#event handling
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()
        elif event.type == pygame.MOUSEBUTTONDOWN:
            cur = event.pos
            click = pygame.mouse.get_pressed()
            clickButton("button1",button1.left,button1.top,button1.width,button1.height)
...

所以文本是在用背景颜色填充屏幕之后和调用 pygame.display.update() 之前创建的,但这并没有解决 [=15= 的下一次迭代再次填充屏幕的问题]循环。


所以解决方案是跟踪按钮被按下的事实,a.k.a。跟踪 状态 .

这是一个不同方法的示例,对按钮使用 类,对全局状态使用 dict(因此您不需要全局变量,这应该避免大多数时间,因为如果您的游戏开始变得更加复杂,它会很快变得非常混乱。

点击第一个按钮显示或隐藏分数,点击第二个按钮更改背景颜色并获得 100 分。

看看创建新按钮变得多么容易;它只是添加了一个简单的功能。

import pygame
import sys
import random

pygame.init()
screen = pygame.display.set_mode((640, 480),0,32)
clock = pygame.time.Clock()

# create font only once
font = pygame.font.Font(None,30)

# it's always a good idea to cache all text surfaces, since calling 'Font.render' is
# an expensive function. You'll start to notice once your game becomes more complex
# and uses more text. Also, use python naming conventions
text_cache = {}
def make_text(title, text):
    key = "{title}: {text}".format(title=title, text=text)
    if not key in text_cache:
        text = font.render(key, 1,(0,0,0))
        text_cache[key] = text
        return text
    else:
        return text_cache[key]

# we use the 'Sprite' class because that makes drawing easy
class Button(pygame.sprite.Sprite):
    def __init__(self, rect, color, on_click):
        pygame.sprite.Sprite.__init__(self)
        self.rect = rect
        self.image = pygame.Surface((rect.w, rect.h))
        self.image.fill(color)
        self.on_click = on_click

# this happens when the first button is pressed
def toggle_score_handler(state):
    state['show_score'] = not state['show_score']

# this happens when the second button is pressed
def toggle_backcolor_handler(state):
    state['backcolor'] = random.choice(pygame.color.THECOLORS.values())
    state['score'] += 100

# here we create the buttons and keep them in a 'Group'
buttons = pygame.sprite.Group(Button(pygame.Rect(30, 30, 32, 32), (55, 155 ,0), toggle_score_handler),
                              Button(pygame.Rect(250, 250, 32, 32), (155, 0, 55), toggle_backcolor_handler))

# here's our game state. In a real 
# game you probably have a custom class
state = {'show_score': False,
         'score': 0,
         'backcolor': pygame.color.Color('White')}

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            quit()
        # you can check for the first mouse button with 'event.button == 1'
        elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
            # to check if the mouse is inside the button, you 
            # can simple use the 'Rect.collidepoint' function
            for button in (b for b in buttons if b.rect.collidepoint(event.pos)):
                button.on_click(state)

    screen.fill(state['backcolor'])
    # draw all buttons by simple calling 'Group.draw'
    buttons.draw(screen)

    if state['show_score']:
        screen.blit(make_text("score", state['score']), (100, 30))

    pygame.display.update()
    clock.tick(60)