변경해야 몇 가지가 있습니다. 이벤트가 발생할 때마다 (예 : 마우스가 움직이는 경우) button
함수를 호출합니다.
button
기능이 너무 많이 수행 중입니다. 텍스트 표면을 만들고 블리트하고, 직사각형을 그리고, 충돌을 확인하고 click
메서드를 호출합니다.
pygame.mouse.get_pressed()
을 사용하지 말고 대신 이벤트 루프에서 MOUSEBUTTONDOWN
이벤트를 처리해야합니다. mouse.get_pressed
은 마우스 버튼이 눌려져 있는지 확인하고 단 한 번의 클릭이 발생하지 않았는지 확인합니다.
여기서는 버튼이없는 기능과 버튼이없는 간단한 솔루션 만 보여 드리겠습니다. 충돌을 처리하고 이벤트 루프에서 번호를 업데이트합니다. 여러 단추를 만들려면 개체 지향 방식으로 다시 작성하는 것이 좋습니다 (원하는 경우 예제를 보여줄 수 있음).
import pygame
pygame.init()
width, height = (200,300)
screen = pygame.display.set_mode((width, height))
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
GRAY = (30, 30, 30)
FONT = pygame.font.Font("freesansbold.ttf", 50)
def loop():
clock = pygame.time.Clock()
number = 0
# The button is just a rect.
button = pygame.Rect(0, 100, 200, 200)
done = False
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# This block is executed once for each MOUSEBUTTONDOWN event.
elif event.type == pygame.MOUSEBUTTONDOWN:
# 1 is the left mouse button, 2 is middle, 3 is right.
if event.button == 1:
# `event.pos` is the mouse position.
if button.collidepoint(event.pos):
# Increment the number.
number += 1
screen.fill(WHITE)
pygame.draw.rect(screen, GRAY, button)
text_surf = FONT.render(str(number), True, BLACK)
# You can pass the center directly to the `get_rect` method.
text_rect = text_surf.get_rect(center=(width/2, 30))
screen.blit(text_surf, text_rect)
pygame.display.update()
clock.tick(30)
loop()
pygame.quit()
부록 : 나는 pygame.sprite.Sprite
의 서브 클래스이며, 스프라이트 그룹에 추가 할 수있는 Button
클래스와 객체 지향 솔루션을 사용하는 것이 좋습니다. 자신의 이미지를 Button
클래스에 전달하거나 기본 이미지를 사용할 수 있습니다. 또한 게임 클래스의 특정 특성을 업데이트하기 위해 handle_event
메서드에서 호출 될 각 단추 인스턴스에 콜백 함수 또는 메서드를 전달해야합니다. 여기에는 게임을 종료하는 카운터와 다른 메서드를 증가시키는 메서드가 있습니다.
import pygame as pg
pg.init()
screen = pg.display.set_mode((800, 600))
FONT = pg.font.SysFont('Comic Sans MS', 32)
# Default button images/pygame.Surfaces.
IMAGE_NORMAL = pg.Surface((100, 32))
IMAGE_NORMAL.fill(pg.Color('dodgerblue1'))
IMAGE_HOVER = pg.Surface((100, 32))
IMAGE_HOVER.fill(pg.Color('lightskyblue'))
IMAGE_DOWN = pg.Surface((100, 32))
IMAGE_DOWN.fill(pg.Color('aquamarine1'))
# Button is a sprite subclass, that means it can be added to a sprite group.
# You can draw and update all sprites in a group by
# calling `group.update()` and `group.draw(screen)`.
class Button(pg.sprite.Sprite):
def __init__(self, x, y, width, height, callback,
font=FONT, text='', text_color=(0, 0, 0),
image_normal=IMAGE_NORMAL, image_hover=IMAGE_HOVER,
image_down=IMAGE_DOWN):
super().__init__()
# Scale the images to the desired size (doesn't modify the originals).
self.image_normal = pg.transform.scale(image_normal, (width, height))
self.image_hover = pg.transform.scale(image_hover, (width, height))
self.image_down = pg.transform.scale(image_down, (width, height))
self.image = self.image_normal # The currently active image.
self.rect = self.image.get_rect(topleft=(x, y))
# To center the text rect.
image_center = self.image.get_rect().center
text_surf = font.render(text, True, text_color)
text_rect = text_surf.get_rect(center=image_center)
# Blit the text onto the images.
for image in (self.image_normal, self.image_hover, self.image_down):
image.blit(text_surf, text_rect)
# This function will be called when the button gets pressed.
self.callback = callback
self.button_down = False
def handle_event(self, event):
if event.type == pg.MOUSEBUTTONDOWN:
if self.rect.collidepoint(event.pos):
self.image = self.image_down
self.button_down = True
elif event.type == pg.MOUSEBUTTONUP:
# If the rect collides with the mouse pos.
if self.rect.collidepoint(event.pos) and self.button_down:
self.callback() # Call the function.
self.image = self.image_hover
self.button_down = False
elif event.type == pg.MOUSEMOTION:
collided = self.rect.collidepoint(event.pos)
if collided and not self.button_down:
self.image = self.image_hover
elif not collided:
self.image = self.image_normal
class Game:
def __init__(self, screen):
self.done = False
self.clock = pg.time.Clock()
self.screen = screen
# Contains all sprites. Also put the button sprites into a
# separate group in your own game.
self.all_sprites = pg.sprite.Group()
self.number = 0
# Create the button instances. You can pass your own images here.
self.start_button = Button(
320, 70, 170, 65, self.increment_number,
FONT, 'Increment', (255, 255, 255),
IMAGE_NORMAL, IMAGE_HOVER, IMAGE_DOWN)
# If you don't pass images, the default images will be used.
self.quit_button = Button(
320, 240, 170, 65, self.quit_game,
FONT, 'Quit', (255, 255, 255))
# Add the button sprites to the sprite group.
self.all_sprites.add(self.start_button, self.quit_button)
def quit_game(self):
"""Callback method to quit the game."""
self.done = True
def increment_number(self):
"""Callback method to increment the number."""
self.number += 1
print(self.number)
def run(self):
while not self.done:
self.dt = self.clock.tick(30)/1000
self.handle_events()
self.run_logic()
self.draw()
def handle_events(self):
for event in pg.event.get():
if event.type == pg.QUIT:
self.done = True
for button in self.all_sprites:
button.handle_event(event)
def run_logic(self):
self.all_sprites.update(self.dt)
def draw(self):
self.screen.fill((30, 30, 30))
self.all_sprites.draw(self.screen)
pg.display.flip()
if __name__ == '__main__':
pg.init()
Game(screen).run()
pg.quit()
부록 2 : 사전으로 단추와 중간 용액. 또한 목록을 사용할 수도 있지만 사전은 읽기 쉽습니다.
import pygame
pygame.init()
WHITE = (255, 255, 255)
ACTIVE_COLOR = pygame.Color('dodgerblue1')
INACTIVE_COLOR = pygame.Color('dodgerblue4')
FONT = pygame.font.Font(None, 50)
def draw_button(button, screen):
"""Draw the button rect and the text surface."""
pygame.draw.rect(screen, button['color'], button['rect'])
screen.blit(button['text'], button['text rect'])
def create_button(x, y, w, h, text, callback):
"""A button is a dictionary that contains the relevant data.
Consists of a rect, text surface and text rect, color and a
callback function.
"""
# The button is a dictionary consisting of the rect, text,
# text rect, color and the callback function.
text_surf = FONT.render(text, True, WHITE)
button_rect = pygame.Rect(x, y, w, h)
text_rect = text_surf.get_rect(center=button_rect.center)
button = {
'rect': button_rect,
'text': text_surf,
'text rect': text_rect,
'color': INACTIVE_COLOR,
'callback': callback,
}
return button
def main():
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
done = False
number = 0
def increment_number(): # A callback function for the button.
"""Increment the `number` in the enclosing scope."""
nonlocal number
number += 1
print(number)
def quit_game(): # A callback function for the button.
nonlocal done
done = True
button1 = create_button(100, 100, 250, 80, 'Click me!', increment_number)
button2 = create_button(100, 200, 250, 80, 'Me too!', quit_game)
# A list that contains all buttons.
button_list = [button1, button2]
while not done:
for event in pygame.event.get():
if event.type == pygame.QUIT:
done = True
# This block is executed once for each MOUSEBUTTONDOWN event.
elif event.type == pygame.MOUSEBUTTONDOWN:
# 1 is the left mouse button, 2 is middle, 3 is right.
if event.button == 1:
for button in button_list:
# `event.pos` is the mouse position.
if button['rect'].collidepoint(event.pos):
# Increment the number by calling the callback
# function in the button list.
button['callback']()
elif event.type == pygame.MOUSEMOTION:
# When the mouse gets moved, change the color of the
# buttons if they collide with the mouse.
for button in button_list:
if button['rect'].collidepoint(event.pos):
button['color'] = ACTIVE_COLOR
else:
button['color'] = INACTIVE_COLOR
screen.fill(WHITE)
for button in button_list:
draw_button(button, screen)
pygame.display.update()
clock.tick(30)
main()
pygame.quit()
사용중인 코드를 제공 할 수 있습니까? – serge1peshcoff
버튼 변수 ie에 추가해야합니다. 버튼에 할당 된 기능을 실행하기 전에 그것을 기억하고 확인하기 위해'clicked = True'를 사용하십시오. 마우스 버튼을 놓으면 클리어합니다. – furas
BTW :'event.type == MOUSEBUTTONDOWN' 또는'pygame.mouse.get_pressed()'를 사용합니까? 'MOUSEBUTTONDOWN'을 사용하면 마우스 버튼이'누르지 않음 '상태로 바뀔 때만 이벤트가 생성되기 때문에이 문제는 발생하지 않아야합니다. 그러나 마우스 버튼을 계속 누르고 있으면 이벤트가 생성되지 않습니다. 'get_pressed()'는 마우스 버튼을 계속 누르고 있으면 True를 반환합니다. – furas