The Pong Game
- Create the screen
- Create and move a paddle
- Create another paddle
- Create the ball and make it move
- Detect collision with wall and bounce
- Detect collision with paddle
- Detect when paddle misses
- Keep score
Create the screen
Create and move a paddle
1️⃣ paddle 생성
2️⃣ 위, 아래로 움직이게 설정
- 함수를 인자로 넣을 때 괄호 붙이면 안됨
- xcor()와 같은 메서드는 괄호를 필요로 함
⭐️ 괄호가 있으면 그것은 함수나 메서드를 호출하고 반환값
⭐️ 괄호가 없으면 함수나 메서드 자체를 참조
3️⃣ paddle이 자리로 이동하는 애니메이션 제거
- paddle이 만들어 지기 전 tracer(0)으로 화면 끄기
- paddle이 만들어 진 후 화면 계속 업데이트 하도록 while반복문
game_is_on = True
while game_is_on:
screen.update()
Create another paddle
1️⃣ paddle클래스 만들기
한꺼번에 수정하는 방법
2️⃣ 좌우 패들 객체 만들고 터플로 좌표 설정하기
tuple을 쓰는 이유
3️⃣ 좌우 패들 키 설정
Create the ball and make it move
1️⃣ 볼 클래스 생성
2️⃣ 볼 객체 생성, 속도 조정
- 화면을 갱신하기 전에 약간의 지연을 만듦
- 볼은 게임이 진행되는 내내 움직이므로 반복문 안에
Detect collision with wall and bounce
- 상단벽과 하단벽에 부딪혔을 때만 충돌 감지
1️⃣ 움직이는 좌표를 속성으로 설정
- 공의 좌표를 얼마씩 증가시킬지 정의
2️⃣ 튕겨 나가는 기능 메소드 생성
벽에 팅겨 나갈 때 좌표가 +10이었다면 -10으로
-10이면 +10으로 되어야 하므로 곱하기 -1
3️⃣ main.py에 조건문 써주기
Detect collision with paddle
1️⃣ 공과 패들 사이 거리 측정하기
- distance메소드는 공의 중앙에서 패들 중앙 사이의 거리만 측정함
💡패들 100x20, 공 20x20, 패들 위치 (350,0) or (-350,0)
공의 x좌표가 패들안쪽면 x값인 ~~340보다 크고~~(공이 겹쳐서 320으로 수정)
공과 패들 사이의 거리가 50보다 가깝게 설정
2️⃣ x축도 y축과 마찬가지로 팅겨나가는 메소드 만들어주기
def bounce_x(self):
self.x_move *= -1
3️⃣ 조건문 작성
Detect when paddle misses
- 패들은 340에서 360까지 걸쳐 있음
- 370은 공이 20x20이므로 패들과 겹쳐있는 상태임
- 380(혹은 -380)을 지나면 확실히 공을 놓친 것
1️⃣ 공을 원점으로 돌려놓는 메소드 생성
리셋되면 이전 공 방향과 반대로 갈 수 있게 bounce_x메소드 넣어줌
def reset_position(self):
self.goto(0, 0)
self.bounce_x()
2️⃣ 양쪽 패들 공 놓쳤을 때 조건문 따로 써주기
- 점수를 누가 땄는지 확인하기 위해서
Keep score
1️⃣ Scoreboard 클래스 생성 후 main.py에 객체 생성
- 속성값 넣어주기
2️⃣ 점수 올리는 메소드 생성
- 점수 쓰는 코드를 따로 메소드 생성
- 점수 갱신되기 전에 clear() 넣어주기
공 스피드 증가시키기
1️⃣ Ball클래스의 속성값 추가
2️⃣ 공을 팅겼을 때 메소드에 스피드 증가 코드 넣어주기
3️⃣ 리셋시 속도 되돌리기
Final code for paddle.py
from turtle import Turtle
class Paddle(Turtle):
def __init__(self, position):
super().__init__()
self.shape("square")
self.color("white")
self.shapesize(stretch_wid=5, stretch_len=1)
self.penup()
self.goto(position)
def go_up(self):
new_y = self.ycor() + 20
self.goto(self.xcor(), new_y)
def go_down(self):
new_y = self.ycor() - 20
self.goto(self.xcor(), new_y)
Final code for ball.py
from turtle import Turtle
class Ball(Turtle):
def __init__(self):
super().__init__()
self.color("white")
self.shape("circle")
self.penup()
self.x_move = 10
self.y_move = 10
self.move_speed = 0.1
def move(self):
new_x = self.xcor() + self.x_move
new_y = self.ycor() + self.y_move
self.goto(new_x, new_y)
def bounce_y(self):
self.y_move *= -1
def bounce_x(self):
self.x_move *= -1
self.move_speed *= 0.9
def reset_position(self):
self.goto(0, 0)
self.move_speed = 0.1
self.bounce_x()
Final code for scoreboard.py
from turtle import Turtle
class Scoreboard(Turtle):
def __init__(self):
super().__init__()
self.color("white")
self.penup()
self.hideturtle()
self.l_score = 0
self.r_score = 0
self.update_scoreboard()
def update_scoreboard(self):
self.clear()
self.goto(-100, 200)
self.write(self.l_score, align="center", font=("Courier", 80, "normal"))
self.goto(100, 200)
self.write(self.r_score, align="center", font=("Courier", 80, "normal"))
def l_point(self):
self.l_score += 1
self.update_scoreboard()
def r_point(self):
self.r_score += 1
self.update_scoreboard()
Final code for main.py
from turtle import Screen, Turtle
from paddle import Paddle
from ball import Ball
from scoreboard import Scoreboard
import time
screen = Screen()
screen.bgcolor("black")
screen.setup(width=800, height=600)
screen.title("Pong")
screen.tracer(0)
r_paddle = Paddle((350, 0))
l_paddle = Paddle((-350, 0))
ball = Ball()
scoreboard = Scoreboard()
screen.listen()
screen.onkey(r_paddle.go_up, "Up")
screen.onkey(r_paddle.go_down, "Down")
screen.onkey(l_paddle.go_up, "w")
screen.onkey(l_paddle.go_down, "s")
game_is_on = True
while game_is_on:
time.sleep(ball.move_speed)
screen.update()
ball.move()
if ball.ycor() > 280 or ball.ycor() < -280:
ball.bounce_y()
if ball.distance(r_paddle) < 50 and ball.xcor() > 320 or ball.distance(l_paddle) < 50 and ball.xcor() < -320:
ball.bounce_x()
if ball.xcor() > 380:
ball.reset_position()
scoreboard.l_point()
if ball.xcor() < -380:
ball.reset_position()
scoreboard.r_point()
screen.exitonclick()