2017-12-11 22 views
1

편집 : 더 긴 예제 코드를 추가했습니다.파이썬 파이 게임 - 우발적 인 연속 클릭을 피하십시오.

파이 게임에서 버튼 코딩에 문제가 있습니다. 저는 파이 게임 모듈의 초보자입니다.

기본적으로 목표는 포인트 앤 클릭으로 말하기 게임을 만드는 것입니다. 플레이어는 각 게임 루프의 두 가지 선택 사항, 즉 "왼쪽으로 이동"또는 "오른쪽으로 이동"과 함께 표시됩니다. 따라서 각 gameloop에 두 개의 버튼이 있으며, 모두 동일한 좌표에 있습니다. 내가 부주의 버튼을 클릭하면

import pygame 
import os 
import time 

pygame.init() 

display_width= 1280 
display_height = 720 

gameDisplay = pygame.display.set_mode((display_width, display_height)) 
clock = pygame.time.Clock() 

def button(msg,x, y, w, h, ic, ac, action=None): #message, x y location, width, height, inactive and active colour 
    if action ==None: 
     pygame.display.update() 
     clock.tick(15) 
    mouse = pygame.mouse.get_pos() 
    click = pygame.mouse.get_pressed() 
    if x+w > mouse[0] > x and y+h > mouse[1] > y: 
     pygame.draw.rect(gameDisplay, ac,(x,y,w,h)) 
     for event in pygame.event.get(): 
      if event.type == pygame.MOUSEBUTTONDOWN: 
       pygame.display.update() 
       clock.tick(15) 
       if action == "left1": 
        game_loop("loop1-1.png",0,0,"left2","left2","","") 
    else: 
     pygame.draw.rect(gameDisplay, ic,(x,y,w,h)) 

    smallText = pygame.font.SysFont('timesnewroman',20) 
    textSurf, textRect = text_objects(msg, smallText, silver) 
    textRect.center = ((x+(w/2)), (y+(h/2))) 
    gameDisplay.blit(textSurf, textRect) 

def game_loop(pic,width,heigth,act1,act2,left,right): 
    intro = True 
    while intro: 
     for event in pygame.event.get(): 
      print(event) 
      if event.type == pygame.QUIT: 
       pygame.quit() 
       quit() 

     gameDisplay.fill(white) 
     gameDisplay.blit(get_image(pic), (0, 0)) #MAIN MENU PIC 

     button(left,440,450,width,heigth, dark_gray, gray, action=act1)#start nupp 
     button(right,740,450,width,heigth, dark_gray, gray, action=act2)#exit nupp 

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

문제는 내가 할 수있는 나는 의도적으로 빠르게 마우스 왼쪽 버튼을 클릭하지 않으면 의미가 발생 : 여기

는 기능입니다. 일단 game_loop1이 호출되고 좀 더 길게 클릭하면 프로그램은이 game_loop1에서 첫 번째 클릭을 다시 읽고 다음 game_loop을 실행 한 다음 다음을 실행합니다. 이는 플레이어가 실수로 gameloops를 건너 뛸 수 있음을 의미합니다.

첫 번째 클릭 후 프로그램을 지연시키는 방법이 있습니까? 또는 함수에 keyup을 포함하는 방법 일 수 있습니다. 따라서 다음 gameloop에서 클릭 수가 계산되지 않습니다.

감사합니다.

+0

안녕하세요! 코드를 [최소의 실행 가능한 예제] (https://stackoverflow.com/help/mcve)로 바꿀 수 있습니까? 그러면 코드가 어떻게 작동하는지, 문제가있는 곳을 파악하고 문제를 해결하는 방법에 대한 정보를 쉽게 얻을 수 있습니다. – skrx

+2

주된 문제는'pygame.mouse.get_pressed()'입니다. 마우스 버튼을 누르고 있는지 확인하지만 버튼이 한 번 클릭되었는지 만 알고 싶습니다. 즉, pygame.event.get()에서 이벤트에 대한 이벤트 루프'를 사용하고'if event.type == pygame.MOUSEBUTTONDOWN'을 확인해야합니다. 나는 최소한의 예를 준비하려고 노력할 것이다. 편집 : 나는 최근 몇 가지 예제를 게시했습니다 [여기] (https://stackoverflow.com/a/47664205/6220679). – skrx

+0

그런데 어디에서 그 코드를 찾았습니까? [링크 된 질문] (https://stackoverflow.com/q/47639826/6220679)과 거의 같습니다. 아마이 질문을 복제물로 표시해야합니다. – skrx

답변

0

원래 코드는 너무 복잡하여 문제를 해결할 수 없다고 생각하며 원하는대로 할 수있는 좋은 방법을 보여줄 것입니다. 서로 다른 주/장면간에 전환하려면 finite-state machine이 필요합니다. functions as scenes here으로 간단한 예제를 찾을 수 있습니다.

장면의 논리가 거의 같은 경우 장면의 데이터 (예 : 배경 이미지)를 바꿀 수도 있습니다. 각 상태/장면은 전환 할 수있는 새 상태를 알아야하므로 사전의 사전에 데이터를 저장합니다. 중첩 된 딕트는 장면의 배경 이미지와 연결된 왼쪽 및 오른쪽 장면을 포함합니다. 사용자가 버튼/rect를 누르면 왼쪽 또는 오른쪽 버튼인지 확인한 다음 states 사전의 해당 장면 (하위)으로 전환합니다.

import pygame 


pygame.init() 

display_width= 1280 
display_height = 720 

gameDisplay = pygame.display.set_mode((display_width, display_height)) 
clock = pygame.time.Clock() 

# Use uppercase names for constants that should never be changed. 
DARK_GRAY = pygame.Color('gray13') 
BACKGROUND1 = pygame.Surface((display_width, display_height)) 
BACKGROUND1.fill((30, 150, 90)) 
BACKGROUND2 = pygame.Surface((display_width, display_height)) 
BACKGROUND2.fill((140, 50, 0)) 
BACKGROUND3 = pygame.Surface((display_width, display_height)) 
BACKGROUND3.fill((0, 80, 170)) 

states = { 
    'scene1': {'background': BACKGROUND1, 'left_scene': 'scene2', 'right_scene': 'scene3'}, 
    'scene2': {'background': BACKGROUND2, 'left_scene': 'scene1', 'right_scene': 'scene3'}, 
    'scene3': {'background': BACKGROUND3, 'left_scene': 'scene1', 'right_scene': 'scene2'}, 
    } 

def game_loop(): 
    # The buttons are just pygame.Rects. 
    left_button = pygame.Rect(440, 450, 60, 40) 
    right_button = pygame.Rect(740, 450, 60, 40) 
    # The current_scene is a dictionary with the relevant data. 
    current_scene = states['scene1'] 

    while True: 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       return 
      elif event.type == pygame.MOUSEBUTTONDOWN: 
       # If the left button is clicked we switch to the 'left_scene' 
       # in the `current_scene` dictionary. 
       if left_button.collidepoint(event.pos): 
        current_scene = states[current_scene['left_scene']] 
        print(current_scene) 
       # If the right button is clicked we switch to the 'right_scene'. 
       elif right_button.collidepoint(event.pos): 
        current_scene = states[current_scene['right_scene']] 
        print(current_scene) 

     # Blit the current background. 
     gameDisplay.blit(current_scene['background'], (0, 0)) 
     # Always draw the button rects. 
     pygame.draw.rect(gameDisplay, DARK_GRAY, left_button) 
     pygame.draw.rect(gameDisplay, DARK_GRAY, right_button) 
     pygame.display.update() 
     clock.tick(30) # 30 FPS feels more responsive. 


game_loop() 
pygame.quit() 
+0

추가 설명이 필요한지 물어보십시오. – skrx

+0

게시물 주셔서 감사합니다! 당신의 방법은 절대적으로 나아졌지만, 시간 제약 때문에 나는 그것을 끝내기 위해 길고 멍청한 방법을 사용했습니다. 내 문제에 대한 해답을 찾았고 귀하의 게시물에 동의하는 것으로 보입니다 - 나는 방금 프레임 속도를 올릴 필요가있었습니다! 그러나 나는 그것을 위해 60 fps로 변경했습니다. – Tuts

+0

'button' 함수의 주된 문제는'pygame.mouse.get_pressed()'를 사용했다는 것입니다. 왜냐하면 마우스 버튼이 현재 눌러져 있는지 확인하기 때문입니다. 대신에 이벤트 루프에서'pygame.MOUSEBUTTONDOWN' 이벤트를 사용하면, 사용자가 한 번 클릭했는지 확인할 수 있습니다. 마우스 클릭 한 번에 하나의'MOUSEBUTTONDOWN' 이벤트 만 이벤트 대기열에 추가됩니다. – skrx