🤖

본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.

⚠️

본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.

이미지 로딩 중...

레벨 디자인과 타일맵 완벽 가이드 - 슬라이드 1/7
A

AI Generated

2025. 12. 4. · 18 Views

레벨 디자인과 타일맵 완벽 가이드

플랫포머 게임의 레벨을 타일맵으로 구현하는 방법을 배웁니다. 타일셋 준비부터 충돌 영역 설정, 배경과 장식까지 완성도 높은 게임 스테이지를 만드는 과정을 다룹니다.


목차

  1. 플랫포머용 타일셋
  2. 지형 레이어 만들기
  3. 플랫폼 배치
  4. 충돌 영역 설정
  5. 배경 레이어
  6. 장식 오브젝트 배치

1. 플랫포머용 타일셋

김개발 씨는 드디어 자신만의 플랫포머 게임을 만들기로 결심했습니다. 캐릭터는 만들었는데, 막상 캐릭터가 뛰어다닐 맵을 어떻게 만들어야 할지 막막했습니다.

한 칸 한 칸 이미지를 배치하자니 너무 비효율적인 것 같았습니다.

타일셋은 게임 맵을 구성하는 작은 이미지 조각들의 모음입니다. 마치 레고 블록처럼, 동일한 크기의 타일들을 조합하여 다양한 지형을 만들어낼 수 있습니다.

이 방식을 사용하면 메모리도 절약하고, 맵 수정도 훨씬 간편해집니다.

다음 코드를 살펴봅시다.

// Phaser 씬에서 타일셋 로드하기
function preload() {
    // 타일셋 이미지 로드 (32x32 픽셀 크기의 타일들)
    this.load.image('tiles', 'assets/tilesets/platformer_tiles.png');

    // Tiled에서 만든 JSON 맵 파일 로드
    this.load.tilemapTiledJSON('level1', 'assets/maps/level1.json');
}

function create() {
    // 타일맵 생성
    const map = this.make.tilemap({ key: 'level1' });

    // 타일셋을 맵에 연결 (Tiled에서 지정한 이름과 일치해야 함)
    const tileset = map.addTilesetImage('platformer_tiles', 'tiles');

    console.log('타일셋 로드 완료:', tileset.name);
}

김개발 씨는 입사 3개월 차 주니어 개발자입니다. 회사에서 간단한 플랫포머 게임 프로토타입을 만들라는 과제를 받았습니다.

캐릭터 스프라이트는 어찌저찌 만들었는데, 맵을 어떻게 구성해야 할지 고민이었습니다. "혹시 맵 전체를 하나의 큰 이미지로 그려야 하나요?" 김개발 씨가 선배 박시니어 씨에게 물었습니다.

박시니어 씨가 웃으며 대답했습니다. "그러면 스테이지마다 거대한 이미지를 만들어야 하잖아요.

게임 업계에서는 타일셋이라는 방식을 사용합니다." 타일셋이란 정확히 무엇일까요? 쉽게 비유하자면, 타일셋은 마치 욕실 바닥에 까는 타일과 같습니다.

동일한 크기의 작은 타일 조각들을 규칙적으로 배열하면 넓은 바닥을 덮을 수 있습니다. 게임에서도 마찬가지입니다.

32x32 픽셀 크기의 작은 이미지 조각들을 격자 형태로 배치하여 맵 전체를 구성합니다. 타일셋이 없던 시절에는 어땠을까요?

초창기 게임 개발자들은 스테이지마다 전체 배경을 하나의 이미지로 그렸습니다. 메모리 용량이 기하급수적으로 늘어났고, 맵을 조금만 수정하려 해도 전체 이미지를 다시 작업해야 했습니다.

특히 긴 스테이지를 가진 게임에서는 이런 방식이 불가능에 가까웠습니다. 바로 이런 문제를 해결하기 위해 타일맵 시스템이 등장했습니다.

하나의 타일셋 이미지만 있으면 수백 개의 스테이지를 만들 수 있습니다. 타일의 배치 정보만 바꾸면 되기 때문입니다.

메모리 사용량은 획기적으로 줄어들고, 맵 수정은 훨씬 간편해집니다. 위의 코드를 살펴보겠습니다.

먼저 preload 함수에서 두 가지를 로드합니다. 첫째는 타일셋 이미지 자체이고, 둘째는 타일 배치 정보가 담긴 JSON 파일입니다.

이 JSON 파일은 보통 Tiled라는 무료 맵 에디터에서 만듭니다. create 함수에서는 로드한 데이터를 실제 타일맵 객체로 변환합니다.

addTilesetImage 메서드의 첫 번째 인자는 Tiled에서 지정한 타일셋 이름이고, 두 번째 인자는 Phaser에서 로드할 때 사용한 키입니다. 이 두 가지가 올바르게 연결되어야 타일이 제대로 표시됩니다.

실제 현업에서는 어떻게 활용할까요? 대부분의 2D 게임 스튜디오에서는 Tiled, Aseprite, TexturePacker 같은 도구를 함께 사용합니다.

아티스트가 타일셋을 그리면, 레벨 디자이너가 Tiled에서 맵을 제작하고, 개발자가 Phaser로 불러와 게임에 적용합니다. 역할이 분리되어 협업이 수월해집니다.

박시니어 씨의 설명을 들은 김개발 씨는 고개를 끄덕였습니다. "레고 블록이라고 생각하니까 이해가 되네요!"

실전 팁

💡 - 타일 크기는 16x16, 32x32, 64x64 등 2의 거듭제곱을 사용하세요

  • Tiled 맵 에디터는 무료이며 Phaser와 호환이 뛰어납니다

2. 지형 레이어 만들기

김개발 씨가 타일셋을 로드하는 데 성공했습니다. 그런데 막상 맵을 보니 땅, 플랫폼, 배경이 모두 한 레이어에 뒤섞여 있었습니다.

박시니어 씨가 "레이어를 분리해야 한다"고 조언했지만, 왜 그래야 하는지 잘 이해가 되지 않았습니다.

레이어는 투명한 필름을 겹쳐 놓은 것과 같습니다. 배경, 지형, 장식물을 각각 다른 레이어에 배치하면 관리가 쉬워지고, 레이어별로 다른 속성을 부여할 수 있습니다.

특히 충돌 처리나 시차 스크롤 효과를 구현할 때 레이어 분리는 필수입니다.

다음 코드를 살펴봅시다.

function create() {
    const map = this.make.tilemap({ key: 'level1' });
    const tileset = map.addTilesetImage('platformer_tiles', 'tiles');

    // 배경 레이어 생성 (가장 뒤에 그려짐)
    const backgroundLayer = map.createLayer('Background', tileset, 0, 0);

    // 지형 레이어 생성 (플레이어가 밟는 땅)
    const groundLayer = map.createLayer('Ground', tileset, 0, 0);

    // 장식 레이어 생성 (가장 앞에 그려짐)
    const decorationLayer = map.createLayer('Decoration', tileset, 0, 0);

    // 레이어 깊이 설정으로 그리기 순서 명시
    backgroundLayer.setDepth(0);
    groundLayer.setDepth(1);
    decorationLayer.setDepth(2);
}

김개발 씨가 만든 첫 번째 맵은 엉망이었습니다. 배경 구름과 땅바닥이 같은 레이어에 있어서, 충돌 처리를 하려니 캐릭터가 구름에도 부딪혔습니다.

당연히 게임이 제대로 동작할 리 없었습니다. "레이어를 나눠야 해요." 박시니어 씨가 말했습니다.

"포토샵에서 레이어 작업하는 것처럼요." 레이어란 정확히 무엇일까요? 쉽게 비유하자면, 레이어는 마치 애니메이션 셀화와 같습니다.

옛날 애니메이터들은 배경을 한 장의 셀에 그리고, 캐릭터를 다른 셀에 그려서 겹쳤습니다. 배경은 그대로 두고 캐릭터 셀만 바꾸면 움직이는 것처럼 보였습니다.

게임의 레이어도 이와 같은 원리입니다. 레이어를 분리하지 않으면 어떤 문제가 생길까요?

첫째, 충돌 판정이 복잡해집니다. 배경의 장식용 타일에도 충돌이 발생하면 플레이어가 이상한 곳에서 막히게 됩니다.

둘째, 타일을 수정할 때 실수로 다른 요소를 건드리기 쉽습니다. 셋째, 시차 스크롤처럼 레이어별로 다른 속도로 움직이는 효과를 구현할 수 없습니다.

위의 코드에서 createLayer 메서드를 세 번 호출합니다. 첫 번째 인자는 Tiled에서 만든 레이어의 이름입니다.

Tiled에서 'Background', 'Ground', 'Decoration'이라는 이름으로 레이어를 만들었다면, 정확히 같은 이름을 사용해야 합니다. 대소문자도 일치해야 합니다.

setDepth 메서드는 레이어의 그리기 순서를 결정합니다. 숫자가 작을수록 뒤에, 클수록 앞에 그려집니다.

배경은 0, 지형은 1, 장식은 2로 설정하면 의도한 대로 겹쳐서 표시됩니다. 실제 게임에서는 더 많은 레이어를 사용하기도 합니다.

먼 배경, 중간 배경, 가까운 배경, 지형, 플랫폼, 전경 장식, UI 등 용도에 따라 세분화합니다. 레이어가 많아질수록 표현력은 풍부해지지만, 관리해야 할 것도 늘어납니다.

김개발 씨는 Tiled를 열어 레이어를 세 개로 나눴습니다. 배경 레이어에는 하늘과 구름을, 지형 레이어에는 땅과 플랫폼을, 장식 레이어에는 나무와 풀을 배치했습니다.

다시 게임을 실행하니 캐릭터가 지형만 밟고, 구름은 배경에서 자연스럽게 떠 있었습니다.

실전 팁

💡 - Tiled에서 레이어 이름을 지을 때 영문으로 일관되게 작성하세요

  • 레이어 순서는 Tiled와 Phaser에서 동일하게 유지하는 것이 헷갈리지 않습니다

3. 플랫폼 배치

지형 레이어까지 만든 김개발 씨는 이제 공중에 떠 있는 플랫폼을 추가하고 싶었습니다. 슈퍼 마리오처럼 점프해서 올라갈 수 있는 발판들 말입니다.

그런데 플랫폼도 지형 레이어에 넣어야 할지, 따로 분리해야 할지 고민이 되었습니다.

플랫폼은 플레이어가 점프하여 착지할 수 있는 공중 발판입니다. 지형과 같은 레이어에 배치할 수도 있지만, 움직이는 플랫폼이나 특수 효과가 있는 플랫폼은 별도로 관리하는 것이 좋습니다.

타일맵의 특정 영역만 플랫폼으로 지정하여 게임 플레이를 풍성하게 만들 수 있습니다.

다음 코드를 살펴봅시다.

function create() {
    const map = this.make.tilemap({ key: 'level1' });
    const tileset = map.addTilesetImage('platformer_tiles', 'tiles');

    // 고정 플랫폼 레이어
    const platformLayer = map.createLayer('Platforms', tileset, 0, 0);

    // 플랫폼 레이어에 충돌 설정
    platformLayer.setCollisionByProperty({ collides: true });

    // 플레이어 생성
    this.player = this.physics.add.sprite(100, 300, 'player');
    this.player.setGravityY(800);

    // 플레이어와 플랫폼 간 충돌 설정
    this.physics.add.collider(this.player, platformLayer);

    // 월드 경계를 맵 크기에 맞춤
    this.physics.world.setBounds(0, 0, map.widthInPixels, map.heightInPixels);
}

김개발 씨는 평평한 땅만 있는 맵이 심심하다고 느꼈습니다. 마리오 게임처럼 공중에 발판을 두고 점프해서 올라가는 재미를 추가하고 싶었습니다.

문제는 어떻게 구현해야 하는지였습니다. 박시니어 씨가 힌트를 줬습니다.

"플랫폼도 결국 타일이에요. 다만 충돌 속성이 있는 타일이죠." 플랫폼 배치의 핵심은 무엇일까요?

쉽게 비유하자면, 플랫폼은 마치 징검다리와 같습니다. 물 위에 놓인 돌처럼, 허공에 떠 있지만 밟으면 건널 수 있습니다.

게임에서도 마찬가지입니다. 플랫폼 타일에 충돌 속성을 부여하면, 물리 엔진이 플레이어가 닿았을 때 멈추게 합니다.

Tiled에서 플랫폼을 만드는 방법은 두 가지입니다. 첫 번째는 타일에 커스텀 속성을 추가하는 방법입니다.

Tiled의 타일셋 에디터에서 플랫폼으로 쓸 타일을 선택하고, collides라는 속성을 true로 설정합니다. 그러면 Phaser에서 setCollisionByProperty 메서드로 해당 타일들만 충돌 처리할 수 있습니다.

두 번째는 레이어 전체에 충돌을 설정하는 방법입니다. setCollisionByExclusion이나 setCollision 메서드를 사용하면 특정 타일 인덱스에 충돌을 부여할 수 있습니다.

단순한 맵에서는 이 방법이 더 빠릅니다. 위의 코드에서 **setGravityY(800)**은 플레이어에게 중력을 적용합니다.

이 값이 있어야 플레이어가 점프 후 아래로 떨어집니다. 그리고 this.physics.add.collider가 플레이어와 플랫폼 사이의 충돌을 처리합니다.

실제 게임에서는 플랫폼의 종류가 다양합니다. 한 방향으로만 통과 가능한 원웨이 플랫폼, 시간이 지나면 무너지는 플랫폼, 좌우로 움직이는 플랫폼 등이 있습니다.

이런 특수 플랫폼은 타일맵보다는 별도의 스프라이트로 만드는 것이 제어하기 쉽습니다. 김개발 씨는 Tiled에서 Platforms라는 레이어를 새로 만들고, 나무 발판 타일을 공중 여기저기에 배치했습니다.

collides 속성을 true로 설정하고 게임을 실행했더니, 캐릭터가 점프해서 발판 위에 착지하는 것을 확인할 수 있었습니다.

실전 팁

💡 - 플랫폼 간격은 캐릭터의 점프력을 고려해서 조절하세요

  • 원웨이 플랫폼은 Arcade Physics의 checkCollision.down = false로 구현할 수 있습니다

4. 충돌 영역 설정

플랫폼까지 배치한 김개발 씨에게 새로운 문제가 생겼습니다. 캐릭터가 발판 모서리에서 이상하게 걸리거나, 타일 일부만 밟아도 전체가 충돌로 인식되었습니다.

좀 더 정교한 충돌 처리가 필요했습니다.

충돌 영역은 물리 엔진이 충돌을 감지하는 보이지 않는 경계입니다. 기본적으로 타일 전체가 충돌 영역이 되지만, 경사면이나 복잡한 형태의 지형에서는 타일별로 커스텀 충돌 영역을 설정해야 자연스러운 움직임이 가능합니다.

다음 코드를 살펴봅시다.

function create() {
    const map = this.make.tilemap({ key: 'level1' });
    const tileset = map.addTilesetImage('platformer_tiles', 'tiles');

    const groundLayer = map.createLayer('Ground', tileset, 0, 0);

    // 타일 인덱스로 충돌 설정 (1번부터 50번 타일까지)
    groundLayer.setCollision([1, 2, 3, 4, 5, 10, 11, 12, 13, 14]);

    // 또는 범위로 설정
    groundLayer.setCollisionBetween(1, 50);

    // 특정 타일 제외하고 모두 충돌 (-1은 빈 타일)
    groundLayer.setCollisionByExclusion([-1]);

    // 디버그 모드로 충돌 영역 시각화
    const debugGraphics = this.add.graphics().setAlpha(0.5);
    groundLayer.renderDebug(debugGraphics, {
        tileColor: null,
        collidingTileColor: new Phaser.Display.Color(243, 134, 48, 255),
        faceColor: new Phaser.Display.Color(40, 39, 37, 255)
    });
}

김개발 씨의 캐릭터가 경사면에서 허공에 떠 있었습니다. 타일은 사각형인데 경사면 그래픽이 들어 있어서, 실제 충돌 영역과 시각적 영역이 맞지 않았기 때문입니다.

"충돌 디버깅부터 해봐요." 박시니어 씨가 조언했습니다. 충돌 영역이란 정확히 무엇일까요?

쉽게 비유하자면, 충돌 영역은 마치 보이지 않는 벽과 같습니다. 우리 눈에는 그림만 보이지만, 물리 엔진은 별도의 경계선을 기준으로 충돌을 판단합니다.

이 경계선이 그림과 일치하지 않으면 캐릭터가 벽에 박혀 있는 것처럼 보이거나, 허공에 떠 있는 것처럼 보입니다. Phaser에서 충돌을 설정하는 방법은 여러 가지입니다.

setCollision은 특정 타일 인덱스에 충돌을 부여합니다. 타일셋에서 몇 번째 타일인지 알아야 합니다.

setCollisionBetween은 범위로 지정할 때 유용합니다. 1번부터 50번까지 모든 지형 타일에 충돌을 주고 싶다면 이 메서드가 편합니다.

setCollisionByExclusion은 반대로 접근합니다. 빈 타일(-1)만 제외하고 나머지 모든 타일에 충돌을 설정합니다.

단순한 맵에서는 이 방법이 가장 빠릅니다. 디버그 모드는 개발 과정에서 필수입니다.

renderDebug 메서드를 사용하면 충돌 영역이 색깔로 표시됩니다. 주황색으로 표시된 부분이 실제로 충돌이 발생하는 영역입니다.

이걸 보면서 타일이 제대로 설정되었는지 확인할 수 있습니다. 경사면이나 곡선 지형은 어떻게 처리할까요?

Tiled의 충돌 에디터를 사용하면 타일별로 다각형 충돌 영역을 그릴 수 있습니다. 다만 Arcade Physics는 사각형만 지원하므로, 복잡한 충돌 영역이 필요하다면 Matter.js 물리 엔진을 고려해야 합니다.

김개발 씨는 디버그 모드를 켜고 맵을 살펴봤습니다. 충돌이 없어야 할 배경 타일에 주황색이 표시되어 있었습니다.

해당 타일의 충돌 설정을 제거하니 캐릭터가 정상적으로 움직였습니다.

실전 팁

💡 - 개발 중에는 항상 충돌 디버그 모드를 켜두세요

  • 배포 전에는 디버그 그래픽스를 비활성화하는 것을 잊지 마세요

5. 배경 레이어

기능적인 부분은 완성되었지만, 김개발 씨의 게임은 밋밋해 보였습니다. 하늘이 단색이고, 깊이감이 전혀 없었습니다.

선배가 추천해준 다른 게임을 보니 배경이 여러 겹으로 되어 있고, 캐릭터가 움직일 때 배경도 다른 속도로 움직이고 있었습니다.

배경 레이어는 게임 월드에 깊이감과 분위기를 더해줍니다. 단순히 정적인 이미지를 깔 수도 있지만, 시차 스크롤 효과를 적용하면 먼 배경은 천천히, 가까운 배경은 빠르게 움직여 입체감을 연출할 수 있습니다.

다음 코드를 살펴봅시다.

function create() {
    // 가장 먼 배경 (하늘) - 고정
    this.add.image(400, 300, 'sky').setScrollFactor(0);

    // 먼 산 배경 - 느리게 스크롤
    this.mountains = this.add.tileSprite(400, 300, 800, 600, 'mountains');
    this.mountains.setScrollFactor(0);

    // 중간 숲 배경 - 중간 속도로 스크롤
    this.trees = this.add.tileSprite(400, 450, 800, 300, 'trees');
    this.trees.setScrollFactor(0);

    // 맵과 플레이어 설정
    const map = this.make.tilemap({ key: 'level1' });
    // ... 타일맵 설정

    // 카메라가 플레이어 따라가도록 설정
    this.cameras.main.startFollow(this.player);
}

function update() {
    // 시차 스크롤 효과 - 카메라 위치에 따라 배경 이동
    this.mountains.tilePositionX = this.cameras.main.scrollX * 0.1;
    this.trees.tilePositionX = this.cameras.main.scrollX * 0.3;
}

김개발 씨는 유명한 플랫포머 게임들을 분석하기 시작했습니다. 할로우 나이트, 오리와 눈먼 숲 같은 게임들은 배경만 봐도 감탄이 나왔습니다.

단순한 그림이 아니라 여러 겹의 레이어가 서로 다른 속도로 움직이며 깊이감을 만들어냈습니다. "이건 시차 스크롤이라고 해요." 박시니어 씨가 설명했습니다.

시차 스크롤이란 무엇일까요? 쉽게 비유하자면, 기차 창밖을 보는 것과 같습니다.

기차가 달릴 때 가까운 전봇대는 휙휙 지나가지만, 멀리 있는 산은 천천히 움직이는 것처럼 보입니다. 이것이 시차 효과입니다.

게임에서도 이 원리를 적용하면 평면적인 2D 화면에 깊이감을 줄 수 있습니다. setScrollFactor는 카메라 움직임에 따라 객체가 얼마나 따라 움직일지 결정합니다.

0이면 카메라가 움직여도 객체는 제자리에 있고, 1이면 카메라와 동일한 속도로 움직입니다. 0.5면 카메라의 절반 속도로 움직입니다.

그런데 위 코드에서는 배경에 setScrollFactor(0)을 주고, update 함수에서 직접 위치를 조절합니다. 왜 이렇게 할까요?

tileSprite는 반복되는 패턴 이미지입니다. 끝없이 이어지는 배경을 만들 때 유용합니다.

tilePositionX를 변경하면 패턴이 스크롤되는 것처럼 보입니다. 카메라 scrollX에 작은 계수를 곱해서 느린 스크롤 효과를 만듭니다.

배경 레이어를 구성할 때는 보통 3~5개의 레이어를 사용합니다. 가장 뒤의 하늘은 완전히 고정하고, 먼 산은 0.1, 중간 숲은 0.3, 가까운 풀은 0.6 정도의 계수를 줍니다.

숫자는 게임의 스케일과 원하는 느낌에 따라 조절합니다. 김개발 씨는 무료 게임 에셋 사이트에서 시차 배경 이미지를 다운받았습니다.

하늘, 먼 산, 숲, 안개 레이어를 각각 다른 속도로 설정했더니, 게임이 훨씬 풍성해 보였습니다.

실전 팁

💡 - 배경 레이어는 3~5개가 적당하며, 너무 많으면 성능에 영향을 줍니다

  • 시차 계수는 0.1에서 0.5 사이가 자연스럽습니다

6. 장식 오브젝트 배치

배경까지 완성한 김개발 씨의 게임이 점점 그럴듯해지고 있었습니다. 하지만 뭔가 허전했습니다.

맵이 너무 깔끔하고 정돈되어 있어서 살아있는 느낌이 들지 않았습니다. 실제 게임들은 곳곳에 작은 장식물들이 배치되어 있었습니다.

장식 오브젝트는 게임플레이에 직접 영향을 주지 않지만, 맵에 생동감과 완성도를 더해주는 요소입니다. 풀, 돌, 버섯, 나비, 빛 효과 등을 적절히 배치하면 밋밋한 맵이 풍성한 세계로 변합니다.

충돌이 없으므로 자유롭게 배치할 수 있습니다.

다음 코드를 살펴봅시다.

function create() {
    const map = this.make.tilemap({ key: 'level1' });
    const tileset = map.addTilesetImage('platformer_tiles', 'tiles');

    // 지형 레이어
    const groundLayer = map.createLayer('Ground', tileset, 0, 0);
    groundLayer.setCollisionByExclusion([-1]);

    // 전경 장식 레이어 (플레이어 앞에 그려짐)
    const foregroundDecor = map.createLayer('ForegroundDecor', tileset, 0, 0);
    foregroundDecor.setDepth(10);  // 플레이어보다 높은 depth

    // 후경 장식 레이어 (플레이어 뒤에 그려짐)
    const backgroundDecor = map.createLayer('BackgroundDecor', tileset, 0, 0);
    backgroundDecor.setDepth(0);  // 플레이어보다 낮은 depth

    // 플레이어
    this.player = this.physics.add.sprite(100, 300, 'player');
    this.player.setDepth(5);  // 장식 레이어들 사이에 위치

    // 애니메이션이 있는 장식 (예: 반딧불)
    const particles = this.add.particles(0, 0, 'firefly', {
        x: { min: 0, max: map.widthInPixels },
        y: { min: 0, max: 200 },
        lifespan: 4000,
        speedX: { min: -20, max: 20 },
        speedY: { min: -10, max: 10 },
        alpha: { start: 0.8, end: 0 },
        quantity: 1,
        frequency: 500
    });
}

김개발 씨는 완성된 맵을 선배에게 보여줬습니다. "깔끔하긴 한데, 좀 심심하네요." 박시니어 씨의 평가였습니다.

"장식을 추가해보세요." 장식이란 무엇일까요? 쉽게 비유하자면, 장식은 마치 인테리어 소품과 같습니다.

방의 기능에는 침대와 책상만 있으면 되지만, 화분, 액자, 조명 같은 소품이 있어야 사람 사는 공간처럼 느껴집니다. 게임 맵도 마찬가지입니다.

플랫폼만 있는 맵은 기능적이지만 무미건조합니다. 장식 오브젝트는 크게 두 종류로 나눕니다.

첫째는 후경 장식입니다. 플레이어 뒤에 그려지는 요소들입니다.

배경과 지형 사이에 배치되어 공간감을 더해줍니다. 멀리 보이는 나무, 안개, 폐허 등이 여기에 속합니다.

둘째는 전경 장식입니다. 플레이어 앞에 그려져서 화면을 가립니다.

가까운 풀, 덩굴, 빛줄기 등이 여기에 속합니다. 이런 요소들은 플레이어가 세계 안에 있다는 느낌을 강화합니다.

depth 값으로 그리기 순서를 제어합니다. 낮은 값이 먼저 그려지고, 높은 값이 나중에 그려집니다.

플레이어의 depth를 5로 설정하고, 후경 장식은 0, 전경 장식은 10으로 설정하면 플레이어가 장식들 사이에 자연스럽게 위치합니다. 파티클 시스템은 동적인 장식에 유용합니다.

반딧불, 낙엽, 먼지, 빗방울 같은 효과를 쉽게 만들 수 있습니다. 위 코드에서는 반딧불이 맵 상단에서 천천히 떠다니도록 설정했습니다.

장식 배치에도 원칙이 있습니다. 플레이어의 시선이 가는 곳, 주요 경로 주변, 랜드마크가 될 만한 장소에 집중적으로 배치합니다.

모든 곳에 균일하게 배치하면 오히려 밋밋해 보입니다. 김개발 씨는 풀, 버섯, 돌멩이를 지형 위에 듬성듬성 배치했습니다.

일부 큰 나무 잎사귀는 전경 레이어에 넣어서 캐릭터가 그 뒤로 지나가는 것처럼 보이게 했습니다. 게임을 실행하니 마치 숲 속을 탐험하는 것 같은 분위기가 났습니다.

"이제 정말 게임 같아졌네요!" 김개발 씨가 뿌듯해하며 말했습니다.

실전 팁

💡 - 전경 장식은 플레이어를 너무 많이 가리지 않도록 반투명하게 설정하세요

  • 장식은 규칙적으로 배치하지 말고 자연스럽게 흩어 놓는 것이 좋습니다

이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!

#Phaser#Tilemap#LevelDesign#Platformer#GameDevelopment#Game

댓글 (0)

댓글을 작성하려면 로그인이 필요합니다.