파이썬을 이용해 리듬게임을 만들고 있는데 판정이 잘못되어 질문합니다

조회수 348회

제가 놓친게 있는거 같은데 보기엔 문제가 없어 이상합니다. 판정이 잘 되지 않아 판정을 하는 코딩을 고쳐주세요. 부탁드립니다.

import pygame
import random
import time

pygame.init()  # 파이게임 초기화
dis = pygame.display.set_mode((700, 800))  # 화면 크기

perfect_range = 30
left_animes_x = 60
left_animes_y = 0

right_animes_x = 300
right_animes_y = 0

up_animes_x = 520
up_animes_y = 0

# 이미지 불러오기
left_arrow_off = pygame.image.load("left_arrow_off.png")
left_arrow_on = pygame.image.load("left_arrow_on.png")
left_img = left_arrow_off

# 크기 넓이 폭 받기
left_arrow_size = left_img.get_rect().size
left_arrow_width = left_arrow_size[0]
left_arrow_height = left_arrow_size[1]

# 이미지 불러오기
right_arrow_off = pygame.image.load("right_a    rrow_off.png")
right_arrow_on = pygame.image.load("right_arrow_on.png")
right_img = right_arrow_off

# 크기 넓이 폭 받기
right_arrow_size = right_img.get_rect().size
right_arrow_width = right_arrow_size[0]
right_arrow_height = right_arrow_size[1]

# 이미지 불러오기
up_arrow_off = pygame.image.load("up_arrow_off.png")
up_arrow_on = pygame.image.load("up_arrow_on.png")
up_img = up_arrow_off

up_arrow_size = up_img.get_rect().size
up_arrow_width = up_arrow_size[0]
up_arrow_height = up_arrow_size[1]


black = (0, 0, 0)
white = (255, 255, 255)
blue = (0, 0, 255)

# 제목 선정
pygame.display.set_caption('RYTHEM GAME')

game_over = False

while not game_over:  # 만약 게임이 끝나지 않았다면
   for event in pygame.event.get():
       # print(event)

       if event.type == pygame.QUIT:
           game_over = True
       if event.type in [pygame.KEYDOWN]:  # 키를 누르면
           if event.key == pygame.K_a:  # a키를 눌렀으면
               left_img = left_arrow_on


#****************************************
# 화살표가 적 오브젝트에 딱 닿았다면
               if 650 - perfect_range <= left_animes_y <= 650 + left_arrow_height + perfect_range and 650 - perfect_range <= left_animes_y + left_arrow_height <= 650 + left_arrow_height + perfect_range:
                   print("Perfect")
                   left_animes_y = 0
               # 화살표가 적 오브젝트에 위쪽으로 반 닿았다면
               elif left_animes_y <= 650 <= left_animes_y + left_arrow_height:
                   print("Up Good")
                   left_animes_y = 0
               # 화살표가 적 오브젝트에 아래로 반 닿았다면
               elif left_animes_y <= 650 + left_arrow_height <= left_animes_y + left_arrow_height:
                   print("Down Good")
                   left_animes_y = 0
           if event.key == pygame.K_d:  # d키를 누르면
               right_img = right_arrow_on  # 이미지를 right arrow on으로 바꾸기
               # 화살표가 적 오브젝트에 딱 닿았다면
               if 650 - perfect_range <= right_animes_y <= 650 + right_arrow_height + perfect_range and 650 - perfect_range <= right_animes_y
+ right_arrow_height <= 650 + right_arrow_height + perfect_range:
                   print(right_animes_y, "Perfect")
                   # 화살표가 적 오브젝트에 위쪽으로 반 닿았다면
               elif right_animes_y <= 650 <= right_animes_y + right_arrow_height:
                   print(right_animes_y, "Up Good")
                   # 화살표가 적 오브젝트에 아래로 반 닿았다면
               elif right_animes_y <= 650 + right_arrow_height <= right_animes_y + right_arrow_height:
                   print(right_animes_y, "Down Good")
           if event.key == pygame.K_s:  # s키를 누르면
               up_img = up_arrow_on  # 이미지를 up arrow on으로 바꾸기
               # 화살표가 적 오브젝트에 딱 닿았다면
               if 650 - perfect_range <= up_animes_y <= 650
+ up_arrow_height + perfect_range and 650 - perfect_range <= up_animes_y + up_arrow_height <= 650
+ up_arrow_height + perfect_range:
                   print("Perfect")
                   right_animes_y = 0
               # 화살표가 적 오브젝트에 위쪽으로 반 닿았다면
               elif up_animes_y <= 650 <= up_animes_y + up_arrow_height:
                   print("Up Good")
                   right_animes_y = 0
               # 화살표가 적 오브젝트에 아래로 반 닿았다면
               elif up_animes_y <= 650 + up_arrow_height <= up_animes_y
+ up_arrow_height:
                   print("Down Good")
                   right_animes_y=0**
#****************************************

       if event.type in [pygame.KEYUP]:  # 만약 키를 땠으면
           if event.key == pygame.K_a:  # a키를
               left_img = left_arrow_off  # 이미지를 left arrow off로 바꾸기

           if event.key == pygame.K_d:  # d키를
               right_img = right_arrow_off  # 이미지를 right arrow off로 바꾸기

           if event.key == pygame.K_s:  # s키를
               up_img = up_arrow_off  # 이미지를 up arrow off로 바꾸기


   dis.fill(black)  # 화면 색깔
   dis.blit(left_img, (60, 650))  # 왼쪽 화살표 그리기
   dis.blit(up_img, (300, 650))  # 위쪽 화살표 그리기
   dis.blit(right_img, (520, 650))  # 오른쪽 화살표 그리기

   dis.blit(left_arrow_off, (left_animes_x, left_animes_y))  # 왼쪽 적 오브젝트 그리기
   dis.blit(up_arrow_off, (right_animes_x, right_animes_y))# 위쪽 적 오브젝트 그리기
   dis.blit(right_arrow_off, (up_animes_x, up_animes_y))  # 오른쪽 적 오브젝트 그리기

   left_animes_y += 0.5  # 속도
   right_animes_y += 0.5  # 속도
   up_animes_y += 0.5  # 속도

   #아래 벽 넘어가면 다시 위로
   if left_animes_y>800:
       left_animes_y=0

   if right_animes_y>800:
       right_animes_y=0

   if up_animes_y>800:
       up_animes_y=0

   pygame.display.update()  # 화면 업데이트

pygame.quit()  # pygame 끝내기
quit()  # 끝내기

1 답변

  • 당장 딱 눈에 띄는 건 이 부분입니다.

    if 650 - perfect_range <= left_animes_y <= 650 + left_arrow_height + perfect_range and 650 - perfect_range <= left_animes_y + left_arrow_height <= 650 + left_arrow_height + perfect_range:
    

    이런 식의 비교 체이닝은 기대하신 대로 작동하지 않을 거에요. 시험해 보시겠어요?

    import random
    
    perfect_range = random.randint(600, 700)
    left_animes_y = random.randint(600, 700)
    left_arrow_height = random.randint(600, 700)
    
    print('if 650 - ' + str(perfect_range) + ' <= ' + str(left_animes_y) + ' <= 650 + ' + str(left_arrow_height) + ' + ' + str(perfect_range) + ' and 650 - ' + str(perfect_range) + ' <= ' + str(left_animes_y) + ' + ' + str(left_arrow_height) + ' <= 650 + ' + str(left_arrow_height) + ' + ' + str(perfect_range) + ':')
    
    if 650 - perfect_range <= left_animes_y <= 650 + left_arrow_height + perfect_range and 650 - perfect_range <= left_animes_y + left_arrow_height <= 650 + left_arrow_height + perfect_range:
        print('perfect')
    else :
        print('maybe not perfect??')
    

    정신없죠? 이런 코드에서는 버그가 나지 않기가 더 어렵지요. 뭐가 뭔지 모르겠고 들여다보기가 어려우니까요. 지금껏 이 질문에 답변이 안 달린 건 아마 그 때문 같은데요.

    저라면 좀더 쪼개 보겠어요.

    # DDR, 펌프 등과 같은 UI일 것이라고 추정한다.
    # 즉, 화살표의 위쪽 끝이 판정선 + 퍼펙오차범위보다 위에 있지 않고, 아래쪽 끝이 판정선 + 퍼펙오차범위보다 아래에 있지 않으면 퍼펙일 거라고 가정한다.
    # 부등호 방향은 틀렸을 수도 있는데 핵심은 그게 아니고, 2개의 bool 변수를 만든다는 데 있음.
    arrow_top_in_limit = arrow_top < line + perfect_range
    arrow_bottom_in_limit = arrow_bottom > line + perfect_range
    
    # 이제 위에서 미리 얻어둔 2개의 bool을 이용하면 판정 로직 짜기가 좀더 편리하고 깔끔하다.
    if arrow_top_in_limit and arrow_bottom_in_limit :
        print('perfect')
    else if arrow_top_in_limit :
        print('great')
    else :
        print("Hey! Why don't you just get up and dance man?")
    

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)