본문 바로가기
게임 데이터 분석

[게임 데이터 분석 #8] opencv를 활용해 비행기 이동 경로, 낙하 경로 등 출력하기

by DongGoo 2023. 7. 6.

Python을 기반으로 개발을 진행하였습니다.
 
1.  비행 경로 및 낙하 경로 추출
지난 [게임 데이터 분석 #7]에서 isGame안에 있는 정보를 통해 자기장의 단계를 찾을 수 있었습니다.
이번에도 isGame를 사용하여 비행 경로와 낙하 경로를 추출해 보겠습니다.
[게임 데이터 분석 #7]에 대한 내용은 아래의 링크에 접속하시면 됩니다.
https://big-data97.tistory.com/67

 

[게임 데이터 분석 #7] DB데이터 사용 및 지도에 자지장 그리기

Python을 기반으로 개발을 진행하였습니다. 1. 자기장 데이터 가져오기 자기장을 맵위에 그리기 위해서는 자기장의 반지름 정보와 중심이 되는 점(x,y)의 위치를 알아야 합니다. 자기장의 반지름의

big-data97.tistory.com

 
우선 isGame데이터를 다시 확인 해보겠습니다.

isGame = 0 -> Before lift off
isGame = 0.1 -> On airplane
isGame = 0.5 -> When there’s no ‘zone’ on map(before game starts)
isGame = 1.0 -> First safezone and bluezone appear
isGame = 1.5 -> First bluezone shrinks
isGame = 2.0 -> Second bluezone appears
isGame = 2.5 -> Second bluezone shrinks
...

isGame이 0.1일 경우 on airplane라고 명시 되어있습니다. 이는 isGame이 0.1인 수들만 추출하면 비행기 경로를 추출 할 수 있다는 뜻입니다.
하지만 isGame이 0.1인 데이터들을 추출 하게 되면 다음 그림과 같이 나타납니다.

비행기 경로인 곧은 직선과 바로 이어져 나오는 낙하 경로가 나타나게 됩니다.
해당 이미지의 문제점은 두 가지가 있습니다.

  1. 비행기 경로가 중간에 끊기는점
  2. 낙하한 경로만 출력할 수 없는점

우선적으로 1번의 문제를 해결해 보겠습니다.
 
2. 비행기 경로 출력하기
비행기의 경로를 끊기지 않고 출력하기 위해서는 수학 공식인 y = ax + b, 일차 함수가 필요합니다.
(x1,y1)과(x2,y2)를 알고 있다면 기울기와 상수를 통해 비행기 경로를 끊김없이 출력할 수 있습니다.
2-1 기울기를 통해 무한한 직선 그리기
(x1,y1),(x2,y2)의 값이 주어졌을 때 a,b값을 구하는 식은 다음과 같습니다.

a = (y2 - y1) / (x2 - x1)
b = (x2y1 - x1*y2) / (x2 - x1)

 
아래의 코드와 같이 isGame가 0.1이하 인 x,y 좌표를 추출해서 location_x,location_y에 할당합니다.

if event["_T"] in ("LogPlayerPosition", "LogParachuteLanding"):
    if event["character"]["name"] == username:
            if event['common']['isGame'] > 0 and  event['common']['isGame'] <= 0.1:
                sub_positions.append({
                    "player_name": event["character"]["name"],
                    "location_x": event["character"]["location"]["x"],
                    "location_y": event["character"]["location"]["y"],
                })

 
낙하산 경로와 비행기에서의 경로가 같이 나타나기 때문에 sub_positions리스트에 좌표를 넣은 후 각각의 x1,y1,x2,y2,에 좌표를 입력해줍니다.
여기서 각각 입력하는 이유는 비행기의 경로는 처음 등장하는 xy,두번째로 등장하는 xy의 값만 알고 있다면 기울기를 구해 무한한 직선을 그려 비행기 경로를 출력 할 수 있기 때문입니다.
낙하산의 경로는 비행기 경로를 그린 후에 추가로 설명하도록 하겠습니다.

for position_index in range(len(sub_positions) - 1):
    # 비행기 경로 추출
    lin_function_x1 = int(sub_positions[0]["location_x"] * scale_factor)
    lin_function_y1 = int(sub_positions[0]["location_y"] * scale_factor)
    lin_function_x2 = int(sub_positions[1]["location_x"] * scale_factor)
    lin_function_y2 = int(sub_positions[1]["location_y"] * scale_factor)
    # 낙하산 경로 추출
    x = int(sub_positions[position_index]["location_x"] * scale_factor)
    y = int(sub_positions[position_index]["location_y"] * scale_factor)
    x1 = int(sub_positions[position_index + 1]["location_x"] * scale_factor)
    y1 = int(sub_positions[position_index + 1]["location_y"] * scale_factor)

    cv2.line(map_image, (x, y), (x1, y1), (0, 125, 250), 20) # 낙하산 경로
a = (lin_function_y2 - lin_function_y1) / (lin_function_x2 - lin_function_x1) # 기울기
b = (lin_function_x2*lin_function_y1 - lin_function_x1*lin_function_y2) / (lin_function_x2 - lin_function_x1)
        
cv2.line(map_image, (0,int(b)), (int(map_image.shape[1]), int(a*map_image.shape[1] + b)), (0, 0, 250), 80,cv2.LINE_4) # 비행기 경로

위의 코드를 통해 lin_function_x1,lin_function_y1에 첫번째 좌표를 lin_function_x2,lin_function_y2에 두번째 좌표를 대입해 줍니다. 
그리고 a와b를 구한 뒤 구한 값을 통해 그림을 그리게 되면 경로에 해당하는 무한한 직선이 그려집니다.
 
다음은 낙하산 경로 입니다.
낙하산 경로 역시 따로 좌표를 나타나는것이 아니기 때문에 비행기 경로와 분리하기 어렵습니다.
하지만 낙하산 경로 의에 비행기 경로를 그리게 되면 겹치는 비행기 경로를 제외한 부분이 낙하산의 경로라고 볼 수 있기 때문에 따로 분리하는 작업을 거치지 않고 두가지 선을 동시에 그려줍니다.
결과는 다음과 같습니다.

빨간색이 비행기 경로, 주황색이 낙하산 경로, 민트색이 지상에서의 이동경로 입니다.