티스토리 뷰

2. 마우스 클릭으로 이미지 움직이기

앞 단계에서는 키보드 방향키를 이용하여 우주선 이미지를 움직였다. 이번에는 키보드가 아니라 마우스 클릭 위치를 이용하여 우주선의 위치를 바꾼다. 즉, 사용자가 게임 화면의 어느 지점을 클릭하면 우주선 이미지가 그 위치로 이동한다.

이번 단계에서 필요한 기능

단계 기능
초기화 이미지 불러오기, 이미지 초기 위치 설정
입력 처리 마우스 클릭 감지, 클릭 위치 좌표 가져오기
게임 업데이트 이번 예제에서는 별도 처리 없음
출력 처리 클릭한 위치에 이미지 출력

이번 실습의 핵심은 입력 처리 함수 handle_input()에서 마우스 클릭을 감지하는 것이다.


핵심 개념: 마우스 클릭 이벤트

pygame에서 마우스를 클릭하면 MOUSEBUTTONDOWN 이벤트가 발생한다. 

if event.type == pygame.MOUSEBUTTONDOWN:
이 코드는 “마우스 버튼이 눌렸는가?”를 확인하는 코드이다.마우스를 클릭한 위치는 다음 코드로 가져올 수 있다.
x, y = event.pos
event.pos에는 마우스를 클릭한 위치의 좌표가 들어 있다.예를 들어 사용자가 화면의 오른쪽 아래를 클릭하면 다음과 같은 좌표가 들어올 수 있다.
x = 700
y = 500
이 좌표를 우주선 이미지의 중심 위치로 설정하면, 우주선이 클릭한 위치로 이동한다.
player_rect.center = (x, y)
 

핵심 코드

이번 실습에서 추가되는 핵심 코드는 다음과 같다.

if event.type == pygame.MOUSEBUTTONDOWN:  #ADDED 마우스 클릭 감지
    x, y = event.pos                      #ADDED 클릭한 위치 좌표
    player_rect.center = (x, y)           #ADDED 이미지 중심을 클릭 위치로 이동
이 코드는 다음 순서로 작동한다.
1. 사용자가 마우스를 클릭한다.
2. pygame이 MOUSEBUTTONDOWN 이벤트를 만든다.
3. event.pos에서 클릭한 좌표를 가져온다.
4. player_rect.center를 클릭한 좌표로 바꾼다.
5. render() 함수에서 바뀐 위치에 이미지를 다시 그린다.
 

💻 전체 코드 (ex8_마우스  이동. py)

아래 코드는 마우스 클릭 위치로 우주선 이미지를 이동시키는 전체 예제이다.

import pygame
import sys

# 전역 변수
WIDTH, HEIGHT = 800, 600
screen = None
clock = None
running = True

img1 = None
player_rect = None  # ADDED
speed = 20  # ADDED 한 번 움직일 거리


# 1) 초기화
def init():
    global screen, clock, img1, player_rect
    
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("키 누름 감지하기")
    clock = pygame.time.Clock()
    
    try:
        img1 = pygame.image.load("asset/img1.png").convert_alpha()
    except pygame.error as e:
        print("이미지 로드 실패:", e)
        pygame.quit()
        sys.exit()
        
    # 이미지의 처음 위치 설정
    player_rect = img1.get_rect(center=(WIDTH // 2, HEIGHT * 3 // 4))


# 2) 입력
def handle_input():
    global running, player_rect
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        # ADDED 마우스를 클릭한 위치로 이미지 이동
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # ADDED 왼쪽 마우스 버튼
                x, y = event.pos  # ADDED 마우스를 클릭한 위치
                player_rect.center = (x, y)  # ADDED 이미지의 중심을 클릭 위치로 이동
                
        # ADDED 키를 누른 순간에만 한 번 이동
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                player_rect.x -= speed

            if event.key == pygame.K_RIGHT:
                player_rect.x += speed

            if event.key == pygame.K_UP:
                player_rect.y -= speed
            if event.key == pygame.K_DOWN:
                player_rect.y += speed
                
            #제자리
            if event.key == pygame.K_SPACE:
                player_rect.x = WIDTH//2
                player_rect.y = HEIGHT*3//4
                
            #게임 종료    
            if event.key == pygame.K_ESCAPE:
                running = False

# 3) 업데이트
def update_game():
    global player_rect  # ADDED

    screen_rect = screen.get_rect()      # ADDED
    player_rect.clamp_ip(screen_rect)    # ADDED


# 4) 출력
def render():
    screen.fill((0, 0, 0))
    screen.blit(img1, player_rect)
    pygame.display.flip()


# 5) 실행
def run_game():
    global running
    
    init()
    
    while running:
        handle_input()
        update_game()
        render()
        clock.tick(60)

    pygame.quit()
    sys.exit()


# 시작
run_game()
 

이미지 중심을 클릭 위치로 이동

player_rect.center = (x, y)
이 코드는 우주선 이미지의 중심을 마우스로 클릭한 위치에 맞춘다.여기서 player_rect.center를 사용하는 이유는 이미지의 왼쪽 위 모서리가 아니라 이미지의 중심을 클릭 위치에 맞추기 위해서이다.만약 다음처럼 작성하면,
player_rect.x = x
player_rect.y = y
이미지의 중심이 아니라 이미지의 왼쪽 위 모서리가 클릭 위치로 이동한다.초보자 수업에서는 center를 사용하는 것이 화면에서 더 자연스럽게 보인다.

화면 경계 제한

player_rect.clamp_ip(screen.get_rect())
이 코드는 우주선 이미지가 게임 화면 밖으로 나가지 않도록 제한한다.마우스를 화면 가장자리 근처에서 클릭하면 이미지의 일부가 밖으로 나갈 수 있다.이때 clamp_ip()를 사용하면 이미지 전체가 화면 안에 머물도록 위치를 자동으로 조정한다.

키보드 이동과 마우스 이동의 차이

구분 키보드 방향키 이동 마우스 클릭 이동
입력 장치 키보드 마우스
사용 이벤트 KEYDOWN 또는 get_pressed() MOUSEBUTTONDOWN
이동 방식 좌표를 조금씩 변경 클릭한 위치로 바로 이동
player_rect.x += 5 player_rect.center = event.pos
  • 키보드 이동은 보통 이미지의 좌표를 조금씩 바꾸는 방식이다.
  • 마우스 클릭 이동은 클릭한 위치로 이미지를 바로 옮기는 방식이다.

🎯 핵심 정리
MOUSEBUTTONDOWN
→ 마우스를 누른 순간을 감지한다.

event.pos
→ 마우스를 클릭한 위치 좌표를 가져온다.

player_rect.center = (x, y)
→ 이미지의 중심을 클릭 위치로 이동시킨다.

clamp_ip()
→ 이미지가 화면 밖으로 나가지 않도록 제한한다.
 

마우스 클릭으로 이미지를 움직인다는 것은 클릭한 위치 좌표를 가져와 이미지의 중심 좌표로 설정하는 과정이다.


실습 : 점을 찍고 키보드/마우스로 움직이기

이번 실습은 이미지를 불러오는 대신, 마우스를 클릭한 위치에 작은 점을 그리는 것이 목표이다.
앞 실습에서는 우주선 이미지를 불러와 움직였다면, 이번에는 pygame의 그리기 함수를 이용하여 화면에 직접 점을 표시한다.

단계 기능
초기화 게임 창 만들기
입력 처리 마우스 클릭 위치 감지
게임 업데이트 이번 예제에서는 별도 처리 없음
출력 처리 클릭한 위치에 점 그리기

핵심 개념: 점의 위치 저장하기

pygame의 그리기 함수인 pygame.draw.circle()을 사용한다. 
마우스로 점을 찍으려면 먼저 점의 위치를 저장하여야 한다.

circle_pos = None
circle_pos는 마우스를 클릭한 위치를 저장하는 변수이다.처음에는 아직 클릭한 위치가 없으므로 None으로 둔다.

마우스를 클릭하면 다음 코드로 클릭 위치를 저장한다.

circle_pos = event.pos
event.pos에는 사용자가 클릭한 위치의 (x, y) 좌표가 들어 있다.

📌 핵심 코드

마우스를 클릭한 위치를 저장하는 코드는 다음과 같다.

if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
    circle_pos = event.pos
여기서 event.button == 1은 마우스 왼쪽 버튼을 의미한다.저장된 위치에 점을 그리는 코드는 다음과 같다.
 
if circle_pos is not None:
    pygame.draw.circle(screen, (255, 255, 255), circle_pos, 5)
이 코드는 circle_pos가 비어 있지 않을 때, 즉 사용자가 마우스를 한 번 이상 클릭하였을 때 흰색 원을 그린다.

💻 전체 코드: 마우스 클릭으로 점 찍기(ex09_마우스점찍기.py)

import pygame
import sys

# 전역 변수
WIDTH, HEIGHT = 800, 600
screen = None
clock = None
running = True

img1 = None
player_rect = None  # ADDED
speed = 20  # ADDED 한 번 움직일 거리

circle_pos = None

# 1) 초기화
def init():
    global screen, clock, img1, player_rect
    
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("마우스 클릭으로 점찍기")
    clock = pygame.time.Clock()
    
    try:
        img1 = pygame.image.load("asset/img1.png").convert_alpha()
    except pygame.error as e:
        print("이미지 로드 실패:", e)
        pygame.quit()
        sys.exit()
        
    # 이미지의 처음 위치 설정
    player_rect = img1.get_rect(center=(WIDTH // 2, HEIGHT * 3 // 4))


# 2) 입력
def handle_input():
    global running, player_rect, circle_pos
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        # ADDED 마우스를 클릭한 위치로 이미지 이동
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # ADDED 왼쪽 마우스 버튼
                circle_pos = event.pos  # ADDED 클릭 위치 저장
                
        # ADDED 키를 누른 순간에만 한 번 이동
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                player_rect.x -= speed

            if event.key == pygame.K_RIGHT:
                player_rect.x += speed

            if event.key == pygame.K_UP:
                player_rect.y -= speed
            if event.key == pygame.K_DOWN:
                player_rect.y += speed
                
            #제자리
            if event.key == pygame.K_SPACE:
                player_rect.x = WIDTH//2
                player_rect.y = HEIGHT*3//4
                
            #게임 종료    
            if event.key == pygame.K_ESCAPE:
                running = False

# 3) 업데이트
def update_game():
    global player_rect  # ADDED

    screen_rect = screen.get_rect()      # ADDED
    player_rect.clamp_ip(screen_rect)    # ADDED


# 4) 출력
def render():
    screen.fill((0, 0, 0))
    # ADDED 마우스를 클릭한 적이 있을 때만 점을 그린다.
    if circle_pos is not None:
        pygame.draw.circle(screen, (255,255,255),circle_pos, 10)
    screen.blit(img1, player_rect)
    pygame.display.flip()


# 5) 실행
def run_game():
    global running
    
    init()
    
    while running:
        handle_input()
        update_game()
        render()
        clock.tick(60)

    pygame.quit()
    sys.exit()


# 시작
run_game()
 

🔍 코드 설명

점 위치 변수

circle_pos = None
이 변수는 점을 그릴 위치를 저장한다.마우스를 클릭하기 전에는 점을 그릴 위치가 없으므로 None으로 설정한다.

마우스 클릭 위치 저장

if event.type == pygame.MOUSEBUTTONDOWN:

이 코드는 마우스 버튼을 누르는 순간을 감지한다. 즉, 사용자가 화면에서 마우스를 클릭하면 이 조건문이 실행된다.

        # ADDED 마우스를 클릭한 위치로 이미지 이동
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:  # ADDED 왼쪽 마우스 버튼
                circle_pos = event.pos  # ADDED 클릭 위치 저장

1 왼쪽 마우스 버튼
2 가운데 버튼 또는 휠 버튼
3 오른쪽 마우스 버튼

클릭한 위치에 점 그리기

pygame.draw.circle(screen, (255, 255, 255), circle_pos, 5)
이 코드는 화면에 원을 그리는 함수이다.
코드 의미
screen 점을 그릴 화면
(255, 255, 255) 흰색
circle_pos 점을 그릴 위치
5 반지름 5픽셀

즉, 이 코드는 마우스로 클릭한 위치에 반지름 5인 흰색 원을 그린다는 뜻이다.


💻 확장 실습: 찍은 점을 키보드로 움직이기(ex10_점찍고이동. py)

마우스로 점을 찍은 뒤, 방향키로 점을 움직이도록 확장할 수 있다.

import pygame
import sys

# 전역 변수
WIDTH, HEIGHT = 800, 600
FPS = 60

screen = None
clock = None
running = True

circle_pos = None      # ADDED 클릭한 점의 위치
circle_radius = 10     # ADDED 점의 크기
speed = 20             # ADDED 방향키를 한 번 누를 때 이동할 거리


# 1) 초기화
def init():
    global screen, clock, running
    
    pygame.init()
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("찍은 점을 키보드로 움직이기")
    clock = pygame.time.Clock()
    running = True


# 2) 입력
def handle_input():
    global running, circle_pos
    
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        # ADDED 마우스를 클릭하면 점의 위치를 저장한다.
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                circle_pos = event.pos

        # ADDED 키를 누르면 점을 이동한다.
        if event.type == pygame.KEYDOWN:
            
            # ADDED 점이 찍힌 상태에서만 이동 가능
            if circle_pos is not None:
                x, y = circle_pos

                if event.key == pygame.K_LEFT:
                    x -= speed

                if event.key == pygame.K_RIGHT:
                    x += speed

                if event.key == pygame.K_UP:
                    y -= speed

                if event.key == pygame.K_DOWN:
                    y += speed

                # ADDED 변경된 좌표를 다시 저장한다.
                circle_pos = (x, y)

            # ADDED ESC 키를 누르면 게임 종료
            if event.key == pygame.K_ESCAPE:
                running = False


# 3) 업데이트
def update_game():
    global circle_pos

    # ADDED 점이 화면 밖으로 나가지 않도록 제한한다.
    if circle_pos is not None:
        x, y = circle_pos

        x = max(circle_radius, min(WIDTH - circle_radius, x))
        y = max(circle_radius, min(HEIGHT - circle_radius, y))

        circle_pos = (x, y)


# 4) 출력
def render():
    screen.fill((0, 0, 0))

    # ADDED 점이 있을 때만 화면에 그린다.
    if circle_pos is not None:
        pygame.draw.circle(screen, (255, 255, 255), circle_pos, circle_radius)

    pygame.display.flip()


# 5) 실행
def run_game():
    global running
    
    init()
    
    while running:
        handle_input()
        update_game()
        render()
        clock.tick(FPS)

    pygame.quit()
    sys.exit()


# 시작
run_game()
 

🎯 핵심

이번 실습은 이미지 파일 없이도 게임 화면에 오브젝트를 만들 수 있다는 점을 보여준다.
pygame.draw.circle()을 사용하면 원을 그릴 수 있고, 원의 위치를 변수로 저장하면 그 위치를 변경하여 움직이는 효과를 만들 수 있다. 

마우스 클릭
→ 클릭 위치 좌표 저장
→ 저장된 좌표에 점 그리기
→ 좌표를 변경하면 점이 움직임
 

1. 클릭한 점의 위치 저장

        # ADDED 마우스를 클릭하면 점의 위치를 저장한다.
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                circle_pos = event.pos

2. 방향키로 점 이동

        # ADDED 키를 누르면 점을 이동한다.
        if event.type == pygame.KEYDOWN:
            
            # ADDED 점이 찍힌 상태에서만 이동 가능
            if circle_pos is not None:
                x, y = circle_pos

                if event.key == pygame.K_LEFT:
                    x -= speed

                if event.key == pygame.K_RIGHT:
                    x += speed

                if event.key == pygame.K_UP:
                    y -= speed

                if event.key == pygame.K_DOWN:
                    y += speed

3. 변경된 좌표 다시 저장

                # ADDED 변경된 좌표를 다시 저장한다.
                circle_pos = (x, y)

            # ADDED ESC 키를 누르면 게임 종료
            if event.key == pygame.K_ESCAPE:
                running = False

방향키 입력으로 바뀐 x, y 값을 다시 circle_pos에 저장한다.
이 과정이 있어야 점의 위치가 실제로 바뀐다.

4. 점이 화면 밖으로 나가지 않도록 제한:(

def update_game()
    # ADDED 점이 화면 밖으로 나가지 않도록 제한한다.
    if circle_pos is not None:
        x, y = circle_pos

        x = max(circle_radius, min(WIDTH - circle_radius, x))
        y = max(circle_radius, min(HEIGHT - circle_radius, y))

        circle_pos = (x, y)

점의 중심이 화면 가장자리보다 밖으로 나가면 점이 잘릴 수 있다.
그래서 점의 반지름만큼 안쪽에서만 움직이도록 제한한다. 점은 반지름을 가지고 있으므로, 중심점이 화면 끝까지 가면 점의 일부가 잘릴 수 있다. 그래서 점의 반지름만큼 안쪽에서만 움직이도록 제한한다. 예를 들어 점의 반지름이 10이면, x좌표는 최소 10, 최대 WIDTH - 10까지만 이동할 수 있다.

 

 

 
 
반응형
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/05   »
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
글 보관함