티스토리 뷰
게임 만들기 기초: 게임 업데이트

1. 게임 업데이트의 의미
게임은 단순히 화면에 그림을 출력하는 프로그램이 아니다. 사용자의 입력을 받고, 입력에 따라 게임 상태를 바꾸며, 바뀐 결과를 다시 화면에 보여주는 프로그램이다. 이때 게임 업데이트(Game Update)는 게임 안의 상태를 계산하고 변화시키는 단계이다.
예를 들어 마우스로 점을 찍으면 점이 생성된다. 그다음 점이 아래로 떨어지도록 위치를 계속 바꾸면 자유낙하처럼 보인다.
이처럼 점의 위치, 속도, 충돌, 점수, 시간 변화 등을 계산하는 부분이 게임 업데이트이다.
2. 게임의 기본 흐름
입력 처리는 사용자가 무엇을 하였는지 확인하는 단계이다. 업데이트는 그 입력 결과를 바탕으로 게임 상태를 바꾸는 단계이다.
출력 처리는 바뀐 상태를 화면에 그리는 단계이다.
3. 점 자유낙하 예시
1. 시작위치: 마우스로 점을 찍으면 점의 좌표가 만들어진다. 즉, event.pos 값이 circle_pos값이 되겠지?
circle_pos = (x, y)
2.중력 적용: 점이 아래로 떨어지려면 y좌표를 계속 증가시키면 된다.
x, y = circle_pos
y = y + fall_speed
circle_pos = (x, y)
4. update_game() 함수의 역할
def update_game():
global circle_pos
if circle_pos is not None:
x, y = circle_pos
y = y + fall_speed
circle_pos = (x, y)
circle_pos is not None은 현재 화면에 점이 있는지 확인하는 조건이다. 점이 아직 생성되지 않았다면 떨어뜨릴 대상이 없으므로 업데이트하지 않는다.
핵심 정리
| 입력 처리 | 사용자의 행동을 받는 단계 | 마우스 클릭, 키보드 입력 |
| 게임 업데이트 | 게임 상태를 바꾸는 단계 | 점 이동, 자유낙하, 충돌 검사 |
| 출력 처리 | 바뀐 결과를 화면에 그리는 단계 | 점 그리기, 배경 출력 |

| 구분 | 설명 | 예시 |
| 오브젝트 상태 갱신(Object State Update) | 게임 속 물체의 상태를 바꿈 | 캐릭터 위치 변경, 적 이동 |
| 시간 기반 처리(Time-based Update) | 시간이 지나면서 상태가 바뀜 | 1초마다 점수 증가, 5초 뒤 적 등장 |
| 물리 연산(Physics Calculation) | 움직임을 계산함 | 자유낙하, 포물선 운동 |
| 충돌 처리(Collision Detection) | 물체가 서로 닿았는지 판단함 | 공과 벽돌 충돌, 캐릭터와 적 충돌 |
| 게임 규칙(Game Logic) | 게임의 규칙을 적용함 | 적을 잡으면 점수 증가, 생명 0이면 종료 |
| 게임 상태 전환(State Change) | 게임의 진행 상태를 바꿈 | PLAY → PAUSE, PLAY → GAME OVER |
0. 게임 기본 골격 (ex_basic.py)
import pygame
import sys
# 전역 변수
WIDTH, HEIGHT = 800, 600
screen = None
clock = None
running = True
#색상(Added)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
# 1. 게임 초기화
def init():
global screen, clock
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("기본 게임 뼈대")
clock = pygame.time.Clock()
# 2. 입력 처리
def handle_input():
global running
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
# 3. 게임 업데이트
def update_game():
pass # ADDED (현재 변화 없음)
# 4. 출력 처리
def render():
screen.fill(BLACK)
pygame.display.flip()
# 5. 게임 실행
def run_game():
init()
# 게임 메인 루프
while running:
handle_input()
update_game()
render()
clock.tick(60)
# 게임 종료
pygame.quit()
sys.exit()
run_game()

1. 자유 낙하
기본코드 - 마우스 클릭으로 점 찍기


01. 기본 코드 ― 마우스 클릭으로 점 찍기(ex_dot.py )
마우스를 클릭한 위치에 반지름이 5인 흰색 원을 그리는 프로그램을 작성한다. 이 실습은 이후에 배울 자유낙하, 포물선 운동, 충돌 처리, 이미지 자동 이동 실습의 기본 코드로 사용된다.
단계별 핵심 코드
이 구조에서 자유낙하를 구현할 때는 전역변수 → 업데이트 → 출력 → 충돌 처리 순서로 추가하면 이해하기 쉽다.
1단계. 공에 필요한 전역변수 추가하기
circle_pos = None # ADDED 마우스로 클릭한 점의 위치
circle_radius = 5 # ADDED 원의 반지름
- circle_pos는 마우스로 클릭한 위치를 저장하는 변수이다.
- 처음에는 아직 마우스를 클릭하지 않았으므로 None으로 둔다.
2단계. 게임 제목 수정하기
- init() 함수에서 게임 창 제목을 바꾼다.
3단계. 입력 처리 함수에서 circle_pos 사용 선언하고, 마우스 왼쪽 클릭 확인하기
- 마우스를 클릭하면 circle_pos 값을 바꾸어야 한다. 따라서 handle_input() 함수에서 global에 circle_pos를 추가한다.
def handle_input():
global running, circle_pos # ADDED circle_pos 사용
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: # ADDED 마우스 왼쪽 클릭 확인
circle_pos = event.pos # ADDED 클릭한 위치 저장
- 마우스 버튼과 왼쪽 버튼을 눌렀는지 2가기를 확인해서, 이 때의 event.pos 값을 circle.pos로 저장한다.
버튼 번호
보통 pygame에서 많이 쓰는 버튼 번호는 다음과 같다.
| 버튼 | 값 |
| 왼쪽 버튼 | 1 |
| 가운데 버튼(휠 클릭) | 2 |
| 오른쪽 버튼 | 3 |
예를 들어 화면의 가운데 근처를 클릭하면 다음과 같은 값이 저장될 수 있다.
4단계. 출력- 점 위치가 있을 때만 원 그리기
# 4. 출력 처리
def render():
screen.fill(BLACK)
if circle_pos is not None: # ADDED 점 위치가 있을 때만 원 그리기
pygame.draw.circle(screen, WHITE, circle_pos, circle_radius) # ADDED
pygame.display.flip()
- 마우스를 클릭하기 전에는 circle_pos가 None이다. 따라서 점 위치가 있을 때만 원을 그리도록 조건문을 사용한다.
- 클릭한 위치에 흰색 원을 그린다.
screen : 어느 화면에 그릴 것인가
WHITE : 어떤 색으로 그릴 것인가
circle_pos : 어디에 그릴 것인가
circle_radius : 얼마나 크게 그릴 것인가

import pygame
import sys
# 전역 변수
WIDTH, HEIGHT = 800, 600
screen = None
clock = None
running = True
#색상(Added)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
#dot 그리기
circle_pos = None # ADDED 마우스로 클릭한 점의 위치
circle_radius = 5 # ADDED 원의 반지름
# 1. 게임 초기화
def init():
global screen, clock
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("마우스 클릭으로 점 찍기")
clock = pygame.time.Clock()
# 2. 입력 처리
def handle_input():
global running, circle_pos # ADDED circle_pos 사용
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: # ADDED 마우스 왼쪽 클릭 확인
circle_pos = event.pos # ADDED 클릭한 위치 저장
# 3. 게임 업데이트
def update_game():
pass # ADDED (현재 변화 없음)
# 4. 출력 처리
def render():
screen.fill(BLACK)
if circle_pos is not None: # ADDED 점 위치가 있을 때만 원 그리기
pygame.draw.circle(screen, WHITE, circle_pos, circle_radius) # ADDED
pygame.display.flip()
# 5. 게임 실행
def run_game():
init()
# 게임 메인 루프
while running:
handle_input()
update_game()
render()
clock.tick(60)
# 게임 종료
pygame.quit()
sys.exit()
run_game()
2. 찍은 점을 자유 낙하하는 프롬프트를 작성하라.
이 실습은 이전에 만든 마우스 클릭으로 점 찍기 코드에 자유낙하 기능을 추가하는 예제이다.
마우스를 클릭하면 점이 생성되고, 생성된 점은 중력의 영향을 받아 화면 아래쪽으로 떨어진다.
마우스 클릭
→ 점의 시작 위치 저장
→ 속도 초기화
→ 중력으로 속도 증가
→ 속도만큼 y좌표 이동
→ 이동 궤적 저장
→ 바닥에 닿으면 정지

📝 프롬프트
마우스로 찍은 점이 중력가속도 9.8로 자유낙하하도록 수정해줘, 공의 궤적은 노란색으로 표시해줘
1. 자유낙하의 핵심 원리: 중력 → 속도 증가 → 위치 변화
자유낙하는 물체가 중력의 영향을 받아 아래로 떨어지는 운동이다. 게임 화면에서는 실제 물리 법칙을 간단히 흉내 내어 구현한다.
- 중력이 속도를 바꾼다. 중력 때문에 공의 아래 방향 속도가 점점 커진다.
ball_vel_y += GRAVITY
- 속도가 위치를 바꾼다
ball_y += ball_vel_y
속도 = 속도 + 중력가속도
위치 = 위치 + 속도
📌 단계별 핵심 코드
마우스 클릭
→ 점의 시작 위치 저장
→ 속도 초기화
→ 중력으로 속도 증가
→ 속도만큼 y좌표 이동
→ 이동 궤적 저장
→ 바닥에 닿으면 정지
1단계. 전역 변수 및 초기값 추가
WIDTH, HEIGHT = 800, 600
FPS = 60 # ADDED
screen = None
clock = None
running = True
- FPS = 60은 1초에 60번 화면을 갱신한다는 뜻이다.
자유낙하에서는 시간 계산이 필요하므로 FPS 값을 변수로 두는 것이 좋다. - 색상 추가: 기본 색상 외에 궤적을 표시할 색상을 추가한다.
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0) # ADDED 궤적 색상
GREEN = (0, 255, 0) # ADDED 속도 표시 색상
- 점과 자유낙하 변수 추가: 마우스로 클릭한 점이 아래로 떨어지도록 하기 위해 다음 변수를 추가한다.
circle_pos = None # ADDED 점의 위치
circle_radius = 5 # ADDED 점의 반지름
circle_vel = 0.0 # ADDED 점의 y방향 속도
G = 9.8 # ADDED 중력가속도
PIXELS_PER_METER = 100 # ADDED 1m를 100픽셀로 표현
trail = [] # ADDED 점의 이동 궤적
- circle_pos는 점의 위치이다. 처음에는 클릭한 점이 없으므로 None으로 둔다.
- circle_vel은 점의 세로 방향 속도이다. 처음에는 정지 상태이므로 0.0이다.
- G = 9.8은 중력가속도이다. 현실의 중력값을 화면에서 표현하기 위해 PIXELS_PER_METER를 함께 사용한다.
- trail은 점이 지나간 위치를 저장하는 리스트이다.
# 전역 변수
WIDTH, HEIGHT = 800, 600
FPS = 60 # ADDED
screen = None
clock = None
running = True
# 색상
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0) # ADDED 궤적 색상
GREEN = (0, 255, 0) # ADDED 속도 표시 색상
circle_pos = None # ADDED 점의 위치
circle_radius = 5 # ADDED 점의 반지름
circle_vel = 0.0 # ADDED 점의 y방향 속도
G = 9.8 # ADDED 중력가속도
PIXELS_PER_METER = 100 # ADDED 1m를 100픽셀로 표현
trail = []
2단계. 초기화 init() - 제목만 변경하자.
pygame.display.set_caption("자유낙하")
3단계. 입력 handle_input()
- 중요한 부분은 다음이다.
circle_pos = [x, y]
- 기존 점 찍기에서는 클릭 위치를 튜플(tuple)로 저장하여도 되었다.
circle_pos = event.pos
- 그러나 자유낙하에서는 y좌표가 계속 변해야 한다. 따라서 값을 수정할 수 있는 리스트(list)로 저장한다
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
x, y = event.pos
circle_pos = [x, y] # ADDED 좌표를 수정할 수 있도록 리스트로 저장
circle_vel = 0.0 # ADDED 속도 초기화
trail = [] # ADDED 궤적 초기화
4단계. update_game() 함수의 역할
자유낙하의 핵심은 update_game() 함수에 있다. 이 함수는 매 프레임마다 점의 속도와 위치를 바꾼다.
# 3. 게임 업데이트
def update_game():
global circle_pos, circle_vel, trail
if circle_pos is not None:
dt = 1 / 60 # ADDED 1프레임 시간
circle_vel += G * PIXELS_PER_METER * dt # ADDED 속도 증가
circle_pos[1] += circle_vel * dt # ADDED y좌표 증가
trail.append((int(circle_pos[0]), int(circle_pos[1]))) # ADDED 궤적 저장
if circle_pos[1] >= HEIGHT - circle_radius:
circle_pos[1] = HEIGHT - circle_radius
circle_vel = 0.0
이 예제에서 update_game()은 다음 일을 한다.
| 역할 | 설명 |
| 시간 계산 | 한 번 움직일 때 사용할 시간값을 정한다 |
| 속도 증가 | 중력 때문에 점의 속도가 점점 빨라지게 한다 |
| 위치 변경 | 증가한 속도만큼 점의 y좌표를 아래로 이동시킨다 |
| 궤적 저장 | 점이 지나간 위치를 저장한다 |
| 바닥 처리 | 점이 화면 아래에 닿으면 멈추게 한다 |
이 함수는 점의 속도와 위치를 계속 바꾸는 역할을 한다.
| 코드 | 의미 |
| dt = 1 / 60 | dt는 한 번 업데이트될 때 흐르는 시간이다. 게임은 1초에 60번 반복된다. FPS가 60이면 한 프레임은 1/60초이다. |
| circle_vel += G * dt * PIXELS_PER_METER | 중력 때문에 아래 방향 속도가 점점 커지는 부분 |
| circle_pos[1] += circle_vel * dt | 증가한 속도만큼 점의 y좌표를 아래로 이동시키는 코드 |
| trail.append((int(circle_pos[0]), int(circle_pos[1]))) | 점이 움직일 때마다 현재 위치가 계속 저장된다. 나중에 render() 함수에서 이 위치들을 노란색 점으로 그리면 공의 궤적이 보인다. int()를 사용하는 이유는 화면에 그림을 그릴 때 좌표를 정수로 맞추기 위해서이다. |
| circle_vel = 0 | 속도 초기화 |
여기서 circle_pos[1]은 점의 y좌표이다.
circle_pos = [x, y]
| circle_pos[0] | x좌표 |
| circle_pos[1] | y좌표 |
바닥에 닿았는지 확인하고 바닥에 고정
if circle_pos[1] >= HEIGHT - circle_radius:
circle_pos[1] = HEIGHT - circle_radius
circle_vel = 0.0
- 현재 화면 높이는 600이다. 하지만 원의 중심이 600까지 내려가면 원의 일부가 화면 밖으로 나간다.
그래서 원의 반지름만큼 빼준다. 즉, 반지름이 5이면 점의 중심은 최대 595까지만 내려가야 한다. - 점이 바닥보다 더 아래로 내려가지 않도록 위치를 고정한다. 이 코드가 없으면 점이 화면 아래로 계속 사라질 수 있다.
- circle_vel = 0.0 : 점이 바닥에 닿으면 더 이상 떨어지지 않아야 한다. 그래서 속도를 0으로 만든다.
5단계. 출력 - render()
배경 지우기
→ 점이 있는지 확인
→ 궤적 그리기
→ 현재 점 그리기
→ 화면 업데이트
- 점이 있는지 확인한다
if circle_pos is not None:
- 궤적을 먼저 그린다.
trail에는 점이 지나간 위치들이 저장되어 있다. 이 위치들을 작은 노란색 점으로 그리면 궤적처럼 보인다.
for pos in trail:
pygame.draw.circle(screen, YELLOW, pos, 2)
- 현재 점을 나중에 그린다.
현재 점은 궤적보다 나중에 그리는 것이 좋다. 그래야 흰색 점이 노란색 궤적 위에 선명하게 보인다.
pygame.draw.circle(
screen,
WHITE,
(int(circle_pos[0]), int(circle_pos[1])),
circle_radius
)
# 4. 출력 처리
def render():
screen.fill(BLACK)
if circle_pos is not None:
# ADDED 궤적 출력
for pos in trail:
pygame.draw.circle(screen, YELLOW, pos, 2)
# ADDED 현재 점 출력
pygame.draw.circle(
screen,
WHITE,
(int(circle_pos[0]), int(circle_pos[1])),
circle_radius
)
pygame.display.flip()
전체 코드 (ex01_gravity.py)
import pygame
import sys
# 전역 변수
WIDTH, HEIGHT = 800, 600
FPS = 60 # ADDED
screen = None
clock = None
running = True
# 색상
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
YELLOW = (255, 255, 0) # ADDED 궤적 색상
GREEN = (0, 255, 0) # ADDED 속도 표시 색상
circle_pos = None # ADDED 점의 위치
circle_radius = 5 # ADDED 점의 반지름
circle_vel = 0.0 # ADDED 점의 y방향 속도
G = 9.8 # ADDED 중력가속도
PIXELS_PER_METER = 100 # ADDED 1m를 100픽셀로 표현
trail = [] # ADDED 점의 이동 궤적
# 1. 게임 초기화
def init():
global screen, clock
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("자유낙하")
clock = pygame.time.Clock()
# 2. 입력 처리
def handle_input():
global running, circle_pos, circle_vel, trail
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
x, y = event.pos
circle_pos = [x, y] # ADDED 좌표를 수정할 수 있도록 리스트로 저장
circle_vel = 0.0 # ADDED 속도 초기화
trail = [] # ADDED 궤적 초기화
# 3. 게임 업데이트
def update_game():
global circle_pos, circle_vel, trail
if circle_pos is not None:
dt = 1 / 60 # ADDED 1프레임 시간
circle_vel += G * PIXELS_PER_METER * dt # ADDED 속도 증가
circle_pos[1] += circle_vel * dt # ADDED y좌표 증가
trail.append((int(circle_pos[0]), int(circle_pos[1]))) # ADDED 궤적 저장
if circle_pos[1] >= HEIGHT - circle_radius:
circle_pos[1] = HEIGHT - circle_radius
circle_vel = 0.0
# 4. 출력 처리
# 4. 출력 처리
def render():
screen.fill(BLACK)
if circle_pos is not None:
# ADDED 궤적 출력
for pos in trail:
pygame.draw.circle(screen, YELLOW, pos, 2)
# ADDED 현재 점 출력
pygame.draw.circle(
screen,
WHITE,
(int(circle_pos[0]), int(circle_pos[1])),
circle_radius
)
pygame.display.flip()
# 5. 게임 실행
def run_game():
init()
while running:
handle_input()
update_game()
render()
clock.tick(60)
pygame.quit()
sys.exit()
run_game()
- 마우스 클릭 → 점 생성
- 게임 업데이트 → 점의 속도 증가
- 게임 업데이트 → 점의 y좌표 증가
- 출력 처리 → 이동한 점과 궤적 출력
1-1 실습: 중력 가속도 변경하기


1. 실습 문제
이번 실습에서는 자유낙하 코드에서 중력 가속도 값을 변경하여 점이 떨어지는 속도가 어떻게 달라지는지 확인한다. 기존 자유낙하 코드에서는 중력 가속도를 다음과 같이 설정하였다.
- G 값이 커지면 점이 더 빠르게 떨어지고, G 값이 작아지면 점이 더 천천히 떨어진다.
G = 9.8
- 이번 실습에서는 이 값을 더 작게 변경한다.
G = 4.5 # ADDED 중력 가속도 값을 작게 변경
2. 핵심 개념
중력 가속도 G는 점이 아래로 떨어질 때 속도가 얼마나 빠르게 증가하는지를 결정하는 값이다.
circle_vel += G * dt * PIXELS_PER_METER
이 코드에서 G 값이 크면 속도가 빠르게 증가한다.반대로 G 값이 작으면 속도가 천천히 증가한다.따라서 G = 9.8일 때보다 G = 4.5일 때 점은 더 천천히 떨어진다.
| G = 9.8 | 점이 빠르게 아래로 떨어짐 |
| G = 4.5 | 점이 더 천천히 아래로 떨어짐 |
| G = 1.0 | 점이 매우 천천히 떨어짐 |
| G = 20.0 | 점이 매우 빠르게 떨어짐 |
G 값 증가 → 속도 증가가 빨라짐 → 점이 빠르게 떨어짐
G 값 감소 → 속도 증가가 느려짐 → 점이 천천히 떨어짐

- Total
- Today
- Yesterday
- HIG
- 스마트기술
- 텍스트 마이닝
- 라이브러리
- Text Mining
- 안드로이드
- HCI
- 피그마
- 초보자를 위한 텍스트마이닝
- 데이타R지
- 4차산업혁명
- 프로토타입
- python
- 챗봇
- 파이썬기초
- 데이터R지
- Idle
- 챗GPT
- matplotlib
- UI
- 파이썬
- 휴리스틱평가
- 컴퓨팅사고력
- figma
- 자바스크립트
- 파이썬 기초
- pygame
- 텍스트마이닝
- 관계자분석
- UX
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |