python으로 게임 만들기/도넛 먹기 게임

[도넛 먹기 게임] 점수가 이상했던 원인 파악 & 해결

bay07 2024. 2. 25. 19:40

 

▶ 문제 상황

맨 처음에는, 강아지가 도넛과 충돌했을 때, 도넛을 배경색으로 바꾸었다. 

(눈에는 안보이지만 존재하는 투명도넛의 상태)

그렇게 되니까 while문을 계속 돌면서 도넛 점수가 계속 올라가게 되는 현상이 발생했다. 

특히 도넛의 속도가 느린 경우 점수가 더 많이 올라가고 (캐릭터와 닿아있는 시간이 길어지기 때문에)

빠른 경우 점수가 적게 올라가는 문제가 발생했다. 

# 도넛 먹었을 때 대체할 배경 
rep = pygame.image.load("C:/Users/Soyoung/Desktop/pygame/replace0.png")

	# 도넛 개수가 10개 
    for i in range(10):
    	# 도넛과 충돌했을 때
        if character_rect.colliderect(donut_rect[i]):
            # 점수 증가 
            score_now += 1
            # 도넛 이미지를 배경 이미지로 바꿈
            donut[i] = rep

 

▶ 해결 방안 

이것을 해결하기 위해서, 아예 투명도넛을 없애버리고

그냥 도넛이 캐릭터와 충돌했을 때, 도넛을 화면 아래로 내려버렸다. 

그러면 캐릭터와 더 닿을 일이 없기 때문에 점수가 갑자기 증가하거나 하지 않게 된다. 

    # 도넛 10개
    for i in range(10):
    	# 강아지가 도넛과 충돌하면
        if character_rect.colliderect(donut_rect[i]):
            # 점수 1 증가
            score_now += 1
            # 도넛의 위치를 스크린 아래로 두기.
            # 그러면 while문을 돌았을 때 다시 (x,0) 좌표에 랜덤으로 생성됨 
            donut_y_pos[i] = screen_height+1

▷ 시연 영상 

영상을 보면, 코드가 우리가 원하는 대로 잘 작동하는 것을 알 수 있다. 

 


▷ 전체코드 ver4

더보기
# 도넛 먹기 게임 ver4
# 점수 문제 해결 

import pygame
import random

pygame.init()

screen_width = 480 
screen_height = 640 
screen = pygame.display.set_mode((screen_width, screen_height))

pygame.display.set_caption("Enjoy Donut Game")

# FPS
clock = pygame.time.Clock()

background = pygame.image.load("C:/Users/Soyoung/Desktop/pygame/background3.png")

# 캐릭터 만들기
character = pygame.image.load("C:/Users/Soyoung/Desktop/pygame/bichon02.png")
character_size = character.get_rect().size
character_width = character_size[0]
character_height = character_size[1]
character_x_pos = (screen_width / 2) - (character_width / 2)
character_y_pos = screen_height - character_height

# 이동 위치
to_x = 0
to_y = 0 
character_speed = 10

# 폰트 지정
game_font = pygame.font.Font(None, 35)

# 총 시간
total_time = 40

# 총 점수
score_now = 0 

# 시작시간 정보
# 시작 tick을 받아옴
start_ticks = pygame.time.get_ticks()

# 도넛 만들기
# 도넛 사이즈는 픽셀로 30*30으로 고정하자.
donut = ['']*10
for i in range(10):
    temp = pygame.image.load(f"C:/Users/Soyoung/Desktop/pygame/donut{i}.jpg")
    donut[i] = temp

donut_size = donut[0].get_rect().size
donut_width = donut_size[0]
donut_height = donut_size[1]

# 독약 만들기
doc = ['']*3
for i in range(3):
    temp = pygame.image.load(f"C:/Users/Soyoung/Desktop/pygame/doc{i}.png")
    doc[i] = temp

doc_size = doc[0].get_rect().size
doc_width = doc_size[0]
doc_height = doc_size[1]

# 도넛 먹었을 때 대체할 배경 
# rep = pygame.image.load("C:/Users/Soyoung/Desktop/pygame/replace0.png")

# 도넛의 위치는 랜덤하게 정하기
donut_x_pos = [0]*10
donut_y_pos = [0]*10
donut_speed = [0]*10
for i in range(10):
    donut_x_pos[i] = random.randint(0, screen_width - donut_width)
    donut_y_pos[i] = 0
    donut_speed[i] = 3*i + 3

# 독약의 위치는 랜덤하게 정하기
doc_x_pos = [0]*3
doc_y_pos = [0]*3
doc_speed = [0]*3
for i in range(3):
    doc_x_pos[i] = random.randint(0, screen_width - doc_width)
    doc_y_pos[i] = 0
    doc_speed[i] = 3*i + 5


running = True
while running:
    dt = clock.tick(30)
    
    # 이벤트 처리
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False 

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                to_x -= character_speed
            elif event.key == pygame.K_RIGHT:
                to_x += character_speed
            
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                to_x = 0

    # 게임 캐릭터 위치 정의
    character_x_pos += to_x
    character_y_pos += to_y
    
    if character_x_pos < 0:
        character_x_pos = 0
    elif character_x_pos > screen_width - character_width:
        character_x_pos = screen_width - character_width
    if character_y_pos < 0:
        character_y_pos = 0    
    elif character_y_pos > screen_height - character_height:
        character_y_pos = screen_height - character_height    
    
    # 도넛은 그냥 스피드만큼 y 좌표가 움직인다고 하면 됨
    for i in range(10):
        donut_y_pos[i] += donut_speed[i]
        if donut_y_pos[i] > screen_height:
            donut_y_pos[i] = 0
            donut_x_pos[i] = random.randint(0, screen_width - donut_width)
            donut[i] = pygame.image.load(f"C:/Users/Soyoung/Desktop/pygame/donut{i}.jpg")
  
    # 독약은 그냥 스피드만큼 y 좌표가 움직인다고 하면 됨
    for i in range(3):
        doc_y_pos[i] += doc_speed[i] 
        if doc_y_pos[i]  > screen_height:
            doc_y_pos[i]  = 0
            doc_x_pos[i]  = random.randint(0, screen_width - doc_width)   
        
    # 충돌 처리
    # 캐릭터 정보 가져오기
    character_rect = character.get_rect()
    character_rect.left = character_x_pos
    character_rect.top = character_y_pos
    
    # 도넛 정보 가져오기
    donut_rect = ['']*10
    for i in range(10):
        donut_rect[i] = donut[i].get_rect()
        donut_rect[i].left = donut_x_pos[i]
        donut_rect[i].top = donut_y_pos[i]
    
    # 독약 정보 가져오기
    doc_rect = ['']*3
    for i in range(3):
        doc_rect[i] = doc[i].get_rect()
        doc_rect[i].left = doc_x_pos[i]
        doc_rect[i].top = doc_y_pos[i]
    
    # 도넛과 충돌하면 점수가 올라가게 
    for i in range(10):
        if character_rect.colliderect(donut_rect[i]):
            score_now += 1
            donut_y_pos[i] = screen_height+1
            #donut[i] = rep
        
    # 독약과 충돌하면 멈추게
    for i in range(3):
        if character_rect.colliderect(doc_rect[i]):
            print("충돌")
            pygame.time.delay(1000)
            running = False
        
    # 화면에 그리기
    screen.blit(background, (0, 0))
    screen.blit(character, (character_x_pos, character_y_pos))
    for i in range(10):
        screen.blit(donut[i], (donut_x_pos[i], donut_y_pos[i]))
    screen.blit(character, (character_x_pos, character_y_pos)) 
    for i in range(3):
        screen.blit(doc[i], (doc_x_pos[i], doc_y_pos[i]))
    screen.blit(character, (character_x_pos, character_y_pos))
    
    # 타이머 & 스코어
    elapsed_time = (pygame.time.get_ticks() - start_ticks)/1000
    timer = game_font.render(" Time   "+str(int(total_time - elapsed_time)), True, (255,51,102))
    score_temp = game_font.render("Score  "+str(int(score_now)), True, (255,51,102))
    screen.blit(timer, (320,20))
    screen.blit(score_temp, (320,55))
    pygame.display.update()   
    
    if total_time - elapsed_time <= 0:
        print("Time out")
        running = False

# gama finish 화면 
screen.blit(background, (0,0))
pygame.display.update()
end_message = game_font.render("Game Finished !", True, (102,0,153))
screen.blit(end_message, (140,200))
pygame.display.update()
# 게임이 꺼지기 전에 4초정도 대기하기
pygame.time.delay(4000)

pygame.quit()

dreaming2.mp4
3.92MB
pygame_image1.zip
0.26MB

 

 

 

▷ 참고 자료