ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [내배캠] Python으로 오락실 게임만들기 ft.나도코딩, pygame
    내일배움캠프/과제 2022. 8. 9. 23:18

    제가 사용한 이미지들입니다.

    기존 강의인 공 부쉬기 게임에 이미지와 약간의 기능을 추가하였습니다.

    images.zip
    0.63MB

     

    변경 사항 및 추가 기능

    - 이미지 변경

    - 점프 기능 

    - 방향에 따른 이미지 변경

    - 필살기, 횟수 설정

    - 필살기 횟수 표시

    import pygame 
    import os
    ######################################################################
    pygame.init() # 반드시 필요 초기화 작업
    # screen size
    screen_width = 640
    screen_height = 480
    screen = pygame.display.set_mode((screen_width,screen_height))
    #title
    pygame.display.set_caption('Save the earth Son')
    #FPS
    clock = pygame.time.Clock()
    #####################################################################
    
    # 1. 사용자 게임 초기화 (배경화면, 게임 이미지, 케릭터 좌표, FPS속도, 폰트 등)
    current_path = os.path.dirname(__file__)
    image_path = os.path.join(current_path, "images")
    background = pygame.image.load(os.path.join(image_path, 'background.png'))
    
    # character create
    character = pygame.image.load(os.path.join(image_path, 'character.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
     
    # 얼마나 움직일지 변수 설정
    x_to = 0
    y_to = 0
    foot = 5
    
    #무기 생성
    weapon = pygame.image.load(os.path.join(image_path, 'weapon.png'))
    weapon_size = weapon.get_rect().size
    weapon_width = weapon_size[0]
    
    # 여러개의 무기가 들어올 것이기에 리스트로 무기 각각의 위치를 받을 예정
    weapons = []
    weapon_speed = 10
    
    #원기옥 필살기 유무와 횟수, 속도
    one_exis = False
    one_cnt = 1
    one_speed = 20
    #원기옥 생성
    one = pygame.image.load(os.path.join(image_path, 'one2.png'))
    one_size = weapon.get_rect().size
    one_width = one_size[0]
    one_height = one_size[1]
    
    
    
    #볼 이미지
    ball_images = [
        pygame.image.load(os.path.join(image_path, 'ball1.png')),
        pygame.image.load(os.path.join(image_path, 'ball2.png')),
        pygame.image.load(os.path.join(image_path, 'ball3.png')),
        pygame.image.load(os.path.join(image_path, 'ball4.png'))
    ]
    #볼 크기에 따른 속도
    ball_speed_y = [-18, -15, -12, -9]
    
    #여러개의 볼이 들어올 것
    balls = []
    
    #초기 공 1개 삽입 
    balls.append({
        "pos_x" : 50, 
        "pos_y" : 50,
        "img_idx"  : 0,
        "to_x" : 3,
        "to_y" : -6,
        "init_spd_y" : ball_speed_y[0]
    })
    
    # 공과 무기의 충돌시 인덱스 초기값 -1
    weapon_to_remove = -1
    ball_to_remove = -1
    
    # 게임 폰트
    game_font = pygame.font.Font(None, 40)
    #게임시간 설정과 현재 틱(시간)
    total_time = 100
    start_ticks = pygame.time.get_ticks()
    
    # 게임 결과 (실패, 완료, 타임오버)
    game_result = 'Game Over'
    
    
    running = True
    while running:
        dt = clock.tick(60)
    
        # 2. 이벤트 처리 (키보드, 마우스 등)
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
    
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    character = pygame.image.load(os.path.join(image_path, 'character.png'))
                    x_to -= foot
                if event.key == pygame.K_RIGHT:
                    character = pygame.image.load(os.path.join(image_path, 'character2.png'))
                    x_to += foot
                if event.key == pygame.K_SPACE:    
                    weapon_x_pos = character_x_pos + character_width//2 - weapon_width//2
                    weapon_y_pos = character_y_pos
                    #쏠 때마다 무기의 위치 값 삽입
                    weapons.append([weapon_x_pos,weapon_y_pos])
                
                if event.key == pygame.K_UP:
                    #바닥에서 50내의 위치에선 점프 가능하게 설정
                    if character_y_pos > screen_height - character_height - 50 :
                        y_to = 10
                #필살기의 횟수 존재 시 사용가능하게 설정
                if event.key == pygame.K_DOWN:
                    if one_cnt > 0:
    
                        one_exis = True
                        character = pygame.image.load(os.path.join(image_path, 'character3.png'))
                        one_cnt -= 1
                        one_x_pos = character_x_pos + character_width//2 - one_width//2
                        one_y_pos = 0
    
                    
            if event.type == pygame.KEYUP:
                if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                    x_to = 0
                    
                
        # 3. 캐리터 위치 정의
        character_x_pos += x_to
        character_y_pos -= y_to
        
        if character_y_pos < screen_height - character_height * 4:
            y_to = -3
        
        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 > screen_height - character_height:
            character_y_pos = screen_height - character_height
        
        weapons = [[w[0], w[1] - weapon_speed ] for w in weapons]
    
        weapons = [[w[0], w[1]] for w in weapons if w[1] > 0 ]
    
        
        #공이 볼 리스트에 있으면 반복문을 돌것(초기에 큰 공 하나 삽입함)
        for ball_idx, ball_val in enumerate(balls):
            #현재 공의 위치
            ball_pos_x = ball_val["pos_x"]
            ball_pos_y = ball_val["pos_y"]
            #이미지에 따라 크기가 달라지므로 구해줘야함
            ball_img_idx = ball_val["img_idx"]
            ball_size = ball_images[ball_img_idx].get_rect().size
            ball_width = ball_size[0]
            ball_height = ball_size[1]
            #이미지가 벽에 닿으면 방향을 바꿔줌
            if ball_pos_x < 0 or ball_pos_x > screen_width - ball_width:
                ball_val['to_x'] *= -1
            #공이 바닥에 닿으면 해당공의 속도로 변경
            if ball_pos_y > screen_height-ball_height:
                ball_val["to_y"] = ball_val["init_spd_y"]
            else:
                ball_val['to_y'] += 0.5
    
            ball_val["pos_x"] += ball_val["to_x"]
            ball_val["pos_y"] += ball_val["to_y"]
    
    
        # 4. 충돌 처리
        
        character_rect = character.get_rect()
        character_rect.left = character_x_pos
        character_rect.top = character_y_pos
    
        for ball_idx, ball_val in enumerate(balls):
            ball_pos_x = ball_val["pos_x"]
            ball_pos_y = ball_val["pos_y"]
            ball_img_idx = ball_val["img_idx"]
    
            ball_rect = ball_images[ball_img_idx].get_rect()
            ball_rect.left = ball_pos_x
            ball_rect.top = ball_pos_y
    
            if character_rect.colliderect(ball_rect):
                running = False
                break
            if one_exis:
                one_rect = one.get_rect()
                one_rect.left = one_x_pos
                one_rect.top = one_y_pos
    
                if one_rect.colliderect(ball_rect):
                    ball_to_remove = ball_idx
                    if ball_img_idx < 3:
                        ball_width = ball_rect.size[0]
                        ball_height = ball_rect.size[1]
    
                        small_ball_rect = ball_images[ball_img_idx + 1].get_rect()
                        small_ball_width = small_ball_rect.size[0]
                        small_ball_height = small_ball_rect.size[1]
    
    
                        balls.append({
                            "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2), 
                            "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                            "img_idx"  : ball_img_idx + 1,
                            "to_x" : -3,
                            "to_y" : -6,
                            "init_spd_y" : ball_speed_y[ball_img_idx + 1]
                        })
                        balls.append({
                            "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2), 
                            "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                            "img_idx"  : ball_img_idx + 1,
                            "to_x" : 3  ,     
                            "to_y" : -6,
                            "init_spd_y" : ball_speed_y[ball_img_idx + 1]
                        })
                        break
    
            for weapon_idx, weapon_val in enumerate(weapons):
                weapon_pos_x = weapon_val[0]
                weapon_pos_y = weapon_val[1]
    
                weapon_rect = weapon.get_rect()
                weapon_rect.left = weapon_pos_x
                weapon_rect.top = weapon_pos_y
    
                if weapon_rect.colliderect(ball_rect):
                    weapon_to_remove = weapon_idx
                    ball_to_remove = ball_idx
    
                    if ball_img_idx < 3:
                        ball_width = ball_rect.size[0]
                        ball_height = ball_rect.size[1]
    
                        small_ball_rect = ball_images[ball_img_idx + 1].get_rect()
                        small_ball_width = small_ball_rect.size[0]
                        small_ball_height = small_ball_rect.size[1]
    
    
                        balls.append({
                            "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2), 
                            "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                            "img_idx"  : ball_img_idx + 1,
                            "to_x" : -3,
                            "to_y" : -6,
                            "init_spd_y" : ball_speed_y[ball_img_idx + 1]
                        })
                        balls.append({
                            "pos_x" : ball_pos_x + (ball_width/2) - (small_ball_width/2), 
                            "pos_y" : ball_pos_y + (ball_height/2) - (small_ball_height/2),
                            "img_idx"  : ball_img_idx + 1,
                            "to_x" : 3  ,     
                            "to_y" : -6,
                            "init_spd_y" : ball_speed_y[ball_img_idx + 1]
                        })
                    break
            else:
                continue
            break
    
        if ball_to_remove > -1:
            del balls[ball_to_remove]
            ball_to_remove = -1
            
        if weapon_to_remove > -1:
            del weapons[weapon_to_remove]
            weapon_to_remove = -1
            
    
        if len(balls) == 0:
            game_result = 'Mission Complete'
            running = False
    
    
    
    
        # 5. 화면에 그리기
        screen.blit(background, (0,0))
    
        for weapon_x_pos, weapon_y_pos in weapons:
            screen.blit(weapon, (weapon_x_pos, weapon_y_pos))
        if one_exis:
            screen.blit(one, (one_x_pos, one_y_pos))
            one_x_pos -= 5
            one_y_pos += 5
    
        for idx, val in enumerate(balls):
            ball_pos_x = val['pos_x']
            ball_pos_y = val['pos_y']
            ball_img_idx = val['img_idx']
            screen.blit(ball_images[ball_img_idx], (ball_pos_x, ball_pos_y))
    
    
        screen.blit(character, (character_x_pos, character_y_pos))
    
    
        elapsed_time = (pygame.time.get_ticks() - start_ticks)/1000
        timer = game_font.render("Time : {}".format(int(total_time - elapsed_time)), True, (255,255,255 ))
        chance = game_font.render("Chance : {}".format(one_cnt), True, (255,255,255 ))
        screen.blit(timer, (10,10))
        screen.blit(chance, (10,60))
    
        if total_time - elapsed_time< 0:
            game_result = 'Time Over'
            running = False
    
        pygame.display.update()
    
    msg = game_font.render(game_result, True, (255,255,0))
    msg_rect = msg.get_rect(center = (int(screen_height / 2) , int(screen_height / 2)))
    screen.blit(msg, msg_rect)
    pygame.display.update() # redraw screen
    
    pygame.time.delay(2000)
    
    pygame.quit()

     

    출처.

    https://www.youtube.com/watch?v=Dkx8Pl6QKW0 

     

    댓글

Designed by Tistory.