Kivy Tutorial - PingPong
Kivy Pong Game tutorial
테트리스를 만들 때 사용해야할 요소들을 좀 더 파악해 보기위해서 kivy 홈페이지에 있는 예제인 PongGame - https://kivy.org/docs/tutorials/pong.html을 통해서 공부를 시작했다.
만들어진 게임의 모습은
![]() |
| <최종 완성 모습> |

와 같은데 각각 플레이어별 점수를 나타내는 부분이 있고, 양쪽의 사이드바를 움직여 공을 막아 상대방에게 튕겨내고 막아내지 못하면 상대편에게 점수를 주는 방식이다. 테트리스를 만들 때 필요한 요소인 한 대상의(테트리스에서는 블록, 핑퐁게임에서는 공) 계속적인 움직임 표현, 점수 표현 등을 알아 볼 수 있었다.
예제는 차근차근 필요한 요소들을 채워나가면서 코딩을 실행한다.
처음으로는 우선 kivy를 실행할 수 있도록 파이썬 파일을 만들고 간단하게 채워 놓았다.
| <첫번째 main.py> |
kivy App을 import하고 run할 수 있는 간단한 구조만 만들어 놓았다.
| <첫 번째 pong.kv> |
그리고 <PongGame> 위젯의 모양을 나타내 줄 kv language 파일인데 여기서 부터는 처음 접하기 때문에 조금씩 분석을 하면서 보아야 했다.
3<PongGame>: 4 canvas: 5 Rectangle: 6 pos: self.center_x - 5, 0 7 size: 10, self.height
이 부분은 즉, canvas block은 <PongGame>이라는 widget에 어떤 그래픽이 그려진다는 것을 말한다. 지금은 Rectangle이라는 직사각형 모양을 그리겠다는 것이고, pos을 통해 위치를 표현했는 데 x축을 중앙에서 5픽셀 왼쪽으로 이동했고, y축은 0이다. 그리고 size는 너비를 10픽셀, 높이는 자체 높이와 같게 설정해 준것으로 이렇게 설정해주면 창 모양을 바꿔도 위치나 크기가 유지가 되게된다.
9 Label: 10 font_size: 70 11 center_x: root.width / 4 12 top: root.top - 50 13 text: "0" 14 15 Label: 16 font_size: 70 17 center_x: root.width * 3 / 4 18 top: root.top - 50 19 text: "0"
이제 이 부분 <PongGame> 위젯에 Label widget을 만들어 준다. 언어를 모르고 봐도 직관적으로 이해를 할 수 있는 부분으로 보인다. 글자 크기 x축의 위치, top으로 부터의 거리, 텍스트 내용임을 알 수 있다.
| <첫번째 실행> |
첫 실행시 나타나는 화면이다. 가운데 선이 Rectangle을 통해 만들어 진 것이고, 점수를 나타낼 0이 양쪽에 나타난 것을 볼 수 있다.
다음으로는 이제 공을 추가하는 부분이다.
| <두번째 main.py> |
PongBall 이라는 클래스가 추가되었다. 그리고 NumericProperty(0)으로 변수에 0을 변형해서 집어넣은 부분이 있는데 굳이 이렇게 해야되나? 싶어서 무슨 함수인지 찾아보았다. 찾아보니 자바의 생성자와 비슷한 역할을 하는 것을 알았다. Kivy API를 보니 파이썬의 __init__에서 초기화 시키는 것과 같은 역할을 한다는 것을 알려준다. 즉, 객체 생성시에 저 변수들을 초기화 시켜주기 위해 사용하는 것이었다. 그래서 x축, y축 속도를 설정해 주고, 그 둘 속도를 List화 시켜서 또 속도를 설정해준다. 그리고 move 함수에서 Vector는 말그대로, 벡터 요소를 저장시켜주는 것이다.
| <두번째 pong.kv> |
여기에는 <PongBall>이 추가 되었는데 내용은 굳이 설명 안해도 비슷한 걸 볼 수 있다. 그리고 <PongGame>에 PongBall 요소가 추가되었다.
| <두번째 실행> |
보다시피 공이 중앙에 이제 위치하게 된 것을 볼 수 있다.
이제 다음으로 추가할 부분은 공의 움직임을 추가한다. 여기서는 이제 Clock을 이용한다.
| <세번째 main.py> |
이제 PongGame 클래스에 함수들이 추가된 모습을 볼 수 있다.
| <PongGame Class> |
클래스내에 이제 ball이라는 변수를 만들어서 Object변수로 만들어 놓는다. 그 다음으로는 이제 함수로 serve_ball을 만들어 주었는데, 이름에서도 알 수 있드시 공을 서브할 때 쓰는 함수이다. 첫 줄은 ball의 위치를 center로 옮겨놓고, 다음은 속도를 x축으로는 4로 초기화 하고, y축은 0으로 초기화 한 뒤, 서브를 랜덤하게 보내기 위해, 회전을 시켜주는데 이를 randint를 통해 0~360사이의 값으로 회전시켜서 최종 속도 값을 갖도록 한다.
다음으로 update 함수인데 처음 보면 ball.move()로 PongBall의 move함수를 가져온다. 즉, 공의 위치에 변화를 준다는 뜻이다. 그리고 나서 if문을 통해 ball의 위치가 바닥에 닿거나, 맨 위에 닿으면 속도의 y축 방향을 바꿔서 밖으로 안나가게 한다. 그리고 다음 if문은 왼쪽 끝, 오른쪽 끝에 닿으면 속도의 x축의 방향을 바꾸어 준다.
| <PongApp Class> |
다음으로는 PongApp 클래스가 업데이트를 해준 것을 살펴보자. 이제 PongGame 클래스의 인스턴스를 game으로 생성했고, game.serve_ball을 통해 공의 움직임이 시작되게 한다. 다음으로 이제 Clock의 schedule_interval을 통해서 아까 만들었던 공의 위치의 업데이트를 1/60초 단위로 실행시키게 만들었다.
| <세번째 pong.kv> |
다음으로 kv파일에는 많은 추가가 안되었고, ball 변수를 만들어 pong_ball로 전달했다. 이는, 내부에서 PongBall이라는 부분을 id를 통해서 pong_ball로 전달할 수 있도록 했다. 이 id는 자주쓰는 widget을 편한 변수로 써서 받을 수 있도록 만들어 준다. 이 id로 정해준 값을 사용할 수 있는 범위는 <PongGame>내에서만 가능하다.
| <세번째 실행> |
실행시 계속해서 공이 움직이는 모습을 볼 수 있다.
| <마지막 main.py> |
마지막으로는 이제 마우스를 클릭해서 paddle을 이동시켜서 공을 튀기는 것을 적용시켰다. 여기서는 이제 on_touch_move라는 함수를 이용해서 클릭을 통해서 패들이 이동할 수 있도록 만들어 준다.
score를 먼저 초기화 시켜주고, 공과 패들이 부딪혔는지 확인할 수 있는 bounce_ball 함수를 만들어 준다. offset을 통해서 공이 패들의 어느 부분에 부딪혔는지 확인하고, 속도의 x축의 방향을 바꾸어준 후, 1.1배의 속도를 증가 시킨 것을 볼 수 있다. 이후 offset을 통해 약간의 속도의 방향 조절을 해준다.
player1과 player2를 새롭게 Object로 만들어준다. 각각 패들을 의미하는 값들 이다. 그리고 update 함수에 변경을 해주었다. 플레이어 별로 패들에 부딪힌 것을 확인하고, ball의 위치가 x보다 작은지 즉, 왼쪽 끝으로 나갔는지, 혹은 width보다 큰지, 즉, 오른쪽으로 나갔는지 확인하여 해당 플레이어에게 점수를 추가해준다. 이후에 serve_ball함수를 실행해 다시 시작하도록 세팅한다. 다음에 이제 on_touch_move를 이용해 움직일 수 있도록 하는 부분이 나온다. on_touch_move 함수 자체가 터치로 인해 event가 발생할 수 있도록 만들어 주는 함수이다. 그리고 이 함수 내에서는 터치의 범위를 비교해서 어떤 패들을 움직일지 만들어 놓았다.
| <PongGame Class> |
player1과 player2를 새롭게 Object로 만들어준다. 각각 패들을 의미하는 값들 이다. 그리고 update 함수에 변경을 해주었다. 플레이어 별로 패들에 부딪힌 것을 확인하고, ball의 위치가 x보다 작은지 즉, 왼쪽 끝으로 나갔는지, 혹은 width보다 큰지, 즉, 오른쪽으로 나갔는지 확인하여 해당 플레이어에게 점수를 추가해준다. 이후에 serve_ball함수를 실행해 다시 시작하도록 세팅한다. 다음에 이제 on_touch_move를 이용해 움직일 수 있도록 하는 부분이 나온다. on_touch_move 함수 자체가 터치로 인해 event가 발생할 수 있도록 만들어 주는 함수이다. 그리고 이 함수 내에서는 터치의 범위를 비교해서 어떤 패들을 움직일지 만들어 놓았다.
| <마지막 pong.kv> |
이제 패들을 <PongPaddle>을 통해서 만들어 주었고, 그 패들을 <PongGame>에 만들어 질 수 있도록 추가해 준 모습을 볼 수 있다. player1과 player2는 각각 왼쪽과 오른쪽의 패들로 구분을 해준 모습이다. 그리고 이젠 점수에 변경이 필요하기 때문에 Label내의 text에 score값을 받아 올 수 있도록 설정해준 모습이다.
| <PongGame 완성> |
위의 과정을 차근 차근따라오면서 테트리스 게임을 만드는게 생각보다는 어렵지 않을 것 같다는 것을 느꼈다. 이제 알아야 할 것은 키보드를 통해서 위젯을 움직이는 방법에 대해 알아내면 대충은 알아야할 부분은 안 것 같고, 구성을 하는 방식만 정리하면 될 것 같다.

댓글
댓글 쓰기