파이썬을 이용해 리듬게임을 만들고 있는데 판정이 잘못되어 질문합니다
조회수 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?")
댓글 입력