당구 시뮬레이션

Jeuk Oh·2021년 9월 10일
4

ㅋㅅㅋ

목록 보기
2/10

개요

다음 주 월요일에 포켓볼 최적해를 구하는 시험이 있습니다.
공의 위치만 인풋으로 받고 수구에게 줄 방향과 힘만 아웃풋으로 주는 과제인데요,

아쉽게도 당구 시뮬레이션을 시험 중에만 열어줘서 제 알고리즘을 테스트해보기 위해 직접 테스트 환경을 만들어보았습니다.

물리 환경을 대충 구현하고 틱 당 matplotlib로 그림을 그려서 모은 뒤에 애니메이션화 하는 것인데 단점은 랜더링이 너무 오래 걸리네요. 멀티 프로세스를 이용해서 연산과 드로잉을 분리하면 조금 빠를 것 같은데, 점점 배보다 배꼽이 커지는 것 같아서 포기!

어차피 목적은 목적구를 테이블 모서리와 변 중앙에 있는 6개의 홀에 넣는 것이기 때문에, 혼자 알고리즘을 테스트할때는 시작과 결과, 공들의 로그만 찍어서 확인해볼 듯 합니다.

그래도 만들고 나니 뿌듯해서 이렇게 올려봅니다. 헤헤


물리 구현

구글링으로 당구를 구현한 프로그램들을 찾아보고 대충 감을 잡고 따라했습니다. Ball은 객체로써 position과 velocity 값을 가지고, 정지해있습니다.

Board는 Ball의 집합을 가지고, check 함수들과 play 메서드를 가지고 있습니다.

    def play(self,F):
        self.balls[0].getforce(F)
        cnt = 0
        while self.checkrestballs():
            cnt += 1
            col_group = self.checkcollisionballs()


            for b1, b2 in col_group:
                b1.vel, b2.vel = elastic_collision(b1,b2)

            for ball in self.balls:
                ball.update()
                isout(ball)
                # print(ball.vel, ball.pos)

play는 [Fx,Fy] 힘을 인자로 받아 수구에게 힘을 전달해주고, 이후 모든 볼의 속도가 0이 될 때까지 업데이트와 충돌체크를 반복합니다.

ball은 업데이트되면서 마찰력에 의해 속력이 감소하고, 충돌한 공들이 있는지 확인하고 있다면 두 공의 충돌값을 계산하여 속도를 변환시켜줍니다. 공이 테이블 바깥으로 나가거나 접촉하면 속도를 반전시켜서 나가지 않게해줍니다.


너무 비효율적으로 시각화를 하여 저 영상 하나 만드는데, 5분 가까이 걸린다는 건 비밀.. 일단은 배보다 배꼽이 커지면 안되니 여기까지 하고 수구에게 줄 적절한 힘 값을 계산하는 알고리즘을 짜보겠습니다.

profile
개발을 재밌게 하고싶습니다.

1개의 댓글

comment-user-thumbnail
2021년 9월 10일

ㅁㅊㄷㅁㅊㅇ
자소서 끝나고 해보겠습니다,,ㅋㅋ

답글 달기