[python] pygame 움직이는 오브젝트 - 중력 적용
이전 포스트에서 pygame에서 움직이는 오브젝트 생성을 다루었습니다. 이번엔 오브젝트에 중력 효과를 더해 보고자 합니다. 각 오브젝트가 가진 속도 벡터와 중력 벡터를 더하여 최종 벡터를 생성합니다. 두 벡터를 더하는 공식을 유도하는데 사용된 개념을 표현하는 그림입니다.
두개의 2차원 벡터를 더하여 하나의 벡터를 출력하는 기능은 소스코드 상에서 addVectors() 함수로 정의되어 있으니 참고 바랍니다.
중력과 더불어, 오브젝트들이 무한정 움직이지 않게 하기 위해 마찰과 탄성 개념을 추가하였으며, 소스코드 상에서 drag, elasticity 상수로 정의되어 있습니다.
아래는 소스코드입니다.
import pygame
import random
import math
# 윈도우 타이틀
pygame.display.set_caption('Gravity Test')
# 배경화면 색상
background_color = (255,255,255)
# 윈도우 사이즈
(width, height) = (400, 400)
screen = pygame.display.set_mode((width, height))
# 항력
drag = 0.999
# 탄성
elasticity = 0.75
# 중력
gravity = (math.pi, 0.002)
# FPS 설정
clock = pygame.time.Clock()
# 파티클 생성
number_of_particles = 10
my_particles = []
def addVectors(v1, v2):
angle1, length1 = v1
angle2, length2 = v2
x = math.sin(angle1) * length1 + math.sin(angle2) * length2
y = math.cos(angle1) * length1 + math.cos(angle2) * length2
angle = 0.5 * math.pi - math.atan2(y, x)
length = math.hypot(x, y)
return (angle, length)
class Particle():
def __init__(self, position, size):
self.x, self.y = position
self.size = size
self.colour = (0, 0, 255)
self.thickness = 1
self.speed = 0
self.angle = 0
def display(self):
pygame.draw.circle(screen, self.colour, (int(self.x), int(self.y)), self.size, self.thickness)
def move(self, df):
# 중력 적용
self.angle, self.speed = addVectors((self.angle, self.speed), gravity)
# df : 초당 프레임 수 (FPS에 따른 위치 보정)
self.x += math.sin(self.angle) * self.speed * df
self.y -= math.cos(self.angle) * self.speed * df
# 항력 적용
self.speed *= drag
def bounce(self):
if self.x > width - self.size:
self.x = 2*(width - self.size) - self.x
self.angle = - self.angle
self.speed *= elasticity
elif self.x < self.size:
self.x = 2*self.size - self.x
self.angle = - self.angle
self.speed *= elasticity
if self.y > height - self.size:
self.y = 2*(height - self.size) - self.y
self.angle = math.pi - self.angle
self.speed *= elasticity
elif self.y < self.size:
self.y = 2*self.size - self.y
self.angle = math.pi - self.angle
self.speed *= elasticity
for n in range(number_of_particles):
size = random.randint(10, 20)
x = random.randint(size, width-size)
y = random.randint(size, height-size)
particle = Particle((x, y), size)
particle.speed = random.random()
particle.angle = random.uniform(0, math.pi*2)
my_particles.append(particle)
running = True
while running:
df = clock.tick(60)
for event in pygame.event.get():
# 닫기 버튼 감지
if event.type == pygame.QUIT:
running = False
screen.fill(background_color)
for particle in my_particles:
particle.move(df)
particle.bounce()
particle.display()
pygame.display.flip()
아래는 결과화면입니다.
끝.
댓글
댓글 쓰기