Pygame: 등축투영 타일의 좌표
반응형
오늘은 등축 투영(isometric) 타일배치를 위한 좌표계를 구현해봅니다.
직교 좌표계를 등축투영 좌표계로 변환
하향식 게임에서 사용하는 직교좌표계 타일에서 왼쪽 위가 (0, 0) 좌표일 때, 이 타일 좌표계를 그대로 회전시켜 등축투영(isometric) 좌표계로 변환하면 그림처럼 왼쪽 끝이 (0. 0) 좌표계가 됩니다. 하지만 이대로 타일을 배치하면 문제가 발생합니다.
타일을 x가 0인 지점부터 차례대로 채운다고 하면 랜더링 하는 순서로 인해 그림과 같은 문제가 생깁니다. 원점을 꼭대기 부분으로 바꾸지 않으면 계산이 편하긴 하겠지만 랜더링 순서로 인해 맵에 벽이나 언덕 타일이 있는 경우 심각한 문제가 발생합니다.
타일셋 이미지
예제를 작성하기 전에 타일셋 이미지를 프로젝트 디렉토리 내부의 asset/tileset_base.png
에 저장합니다.
코딩: 타일셋 클래스
from itertools import product
from typing import TYPE_CHECKING, List
import pygame
if TYPE_CHECKING:
from pygame import Surface
class Tileset:
"""타일셋 관리 클래스"""
def __init__(self, path: str, size=(64, 64), margin=0, spacing=0):
"""클래스 초기화
Args:
path: 타일셋 이미지 경로
size: 한 타일의 크기
margin: 타일 이미지 여백
spacing: 타일 사이의 간격
"""
self.__tile = [] # 타일 리스트
image = pygame.image.load(path).convert_alpha()
image.set_colorkey((0, 0, 0))
rect = image.get_rect()
x0 = y0 = margin
w, h = rect.size
dx, dy = size[0] + spacing, size[1] + spacing
for y, x in product(range(y0, h, dy), range(x0, w, dx)):
_tile = pygame.Surface(size, pygame.SRCALPHA)
_tile.blit(image, (0, 0), (x, y, *size))
self.__tile.append(_tile)
@property
def tile(self) -> List["Surface"]:
"""타일 목록"""
return self.__tile
Tileset.tile[{타일번호}]
로 타일 이미지를 불러올 수 있습니다. 예시 이미지는 여백도 없고 타일간 경계도 없지만, 에셋 스토어 등에서 타일 이미지를 불러오는 경우 여백이나 타일 경계선이 있는 경우가 간혹 있어서 클래스 초기화에 고려하였습니다.
코딩: 타일맵 클래스
class Tilemap:
"""타일맵 관리 클래스"""
def __init__(self, tileset, grid=(64, 32), size=(5, 5)):
"""클래스 초기화
Args:
tileset: 기본 타일셋
size: 타일을 배치하는 그리드의 크기
size: 타일맵의 크기
"""
self.__grid = grid
self.__tileset = tileset
self.__size = size
def set_tile(self, display: "Surface", pos=(0, 0), idx=0, tileset=None):
"""타일 배치 메서드
Args:
display: 타일을 배치할 표면
pos: 타일 좌표
idx: 배치 타일의 종류
tileset: 배치할 타일셋 (없으면 기본 타일셋)
"""
tileset: Tileset = tileset if tileset != None else self.__tileset
_x, _y = pos
_w, _h = self.__grid
cx = display.get_rect().centerx - (_w * 0.5)
cy = display.get_rect().centery - (_h * self.__size[1] * 0.5)
iso_x = -_x * _w * 0.5 + _y * _w * 0.5
iso_y = _x * _h * 0.5 + _y * _h * 0.5
display.blit(tileset.__tile[idx], (cx + iso_x, cy + iso_y))
타일맵에 타일을 배치하기 위한 클래스입니다.
코딩: 프로그램 작성
import sys
from itertools import product
from typing import TYPE_CHECKING, List
import pygame
from pygame.locals import DOUBLEBUF, QUIT
if TYPE_CHECKING:
from pygame import Surface
if __name__ == "__main__":
"""메인 프로그램
타일을 좌표 순서대로 배치
"""
pygame.init()
display = pygame.display.set_mode((640, 480), DOUBLEBUF)
tileset = Tileset("asset/tileset_base.png")
tilemap = Tilemap(tileset, (64, 32), (7, 7))
clock = pygame.time.Clock()
# 초기 타일 배치
for _pos in product(range(7), range(7)):
tilemap.set_tile(display, _pos, 0)
tile_idx = 0
while True:
tile_idx = (tile_idx + 1) % (len(tileset.__tile) - 1)
for _pos in product(range(7), range(7)):
tilemap.set_tile(display, _pos, tile_idx)
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
pygame.display.flip()
clock.tick(15)
이 스크립트를 실행하면 타일을 좌표 순서대로 변경하는 애니메이션을 실행합니다.
반응형
'프로그래밍 > 파이게임' 카테고리의 다른 글
Pygame: 키보드 조작으로 타일맵 이동 (0) | 2022.01.25 |
---|---|
Pygame: 등축투영 타일맵을 가운데 배치하기 (0) | 2022.01.24 |
Pygame: 타일셋 그리기(3) - 바닥 타일셋 그리기 (0) | 2022.01.21 |
Pygame: 타일셋 그리기(2) - 지형 타일셋 제작 (0) | 2022.01.20 |
Pygame: 타일셋 그리기(1) - 코딩으로 기본 타일셋 생성 (0) | 2022.01.19 |
댓글