Yeppyshiba Blog

About
coding

phaser3 에 패럴랙스 스크롤링 (parallax scrolling) 구현하기

5/31/2022

devcodingphaserweb gameparallax scroll

패럴랙스 스크롤링 (parallax scrolling) 이란?

패럴랙스 스크롤링(parallax scrolling)은 원거리에 있는 배경 이미지는 느리게 움직이게 하고, 근거리에 있는 사물 이미지는 빠르게 움직이도록 함으로써 2D 기반에서 입체감을 느낄 수 있게 만든 기법입니다. 하나의 이미지를 여러 개의 레이어(layer)로 분리한 후 스크롤에 반응하는 속도를 다르게 조정하는 방식으로 구현하게 됩니다. 1930년대부터 애니메이션 분야에 사용되던 기법이었으나, 최근에는 웹 디자인에서도 손쉽게 볼 수 있습니다.

phaser3 코드를 작성해보자!

데모를 위해서 백그라운드 이미지가 필요합니다. 여기에서 저희는 이 스프라이트들을 쓰겠습니다.

서로 다른 배경 이미지를 서로 다른 속도로 반복해서 보여줌으로써 입체감을 느끼게 하는게 목표입니다!

먼저 데모용 스크립트를 작성해보겠습니다.

typescript
1import Phaser from 'phaser';
2
3class MyGame extends Phaser.Scene {
4 preload() {
5 // 백그라운드 이미지 로딩
6 }
7
8 create() {
9 // 백그라운드 설정
10 }
11
12 update() {}
13}
14
15new Phaser.Game({
16 type: Phaser.AUTO,
17 backgroundColor: '#000000',
18 pixelArt: true,
19 antialias: false,
20 roundPixels: false,
21 scale: {
22 mode: Phaser.Scale.NONE,
23 parent: 'Phaser-Example',
24 width: 640,
25 height: 480,
26 },
27 scene: MyGame,
28});

실제 구현을 위해서, 사용할 레이어들의 이미지들을 호출해보도록 하겠습니다.

foreground
foreground
back
back
far
far

총 위의 3가지 이미지를 사용할 예정입니다.

typescript
1 preload() {
2 this.load.image("foreground", Foreground);
3 this.load.image("back", Back);
4 this.load.image("far", Far);
5 }

가장 뒷 배경 레이어를 추가해보자!

도시 야경에서 가장 뒷 배경이 되는 이미지를 여기에서 등록해보도록 하겠습니다.

far
far
Phaser 의 TileSprite Object 를 사용해볼 것 인데요.

텍스쳐를 반복 그리는데 최적화된 Object 입니다.

TileSprite 자체적으로 텍스쳐를 스크롤과 크기를 조정할 수 있습니다. 자동으로 래핑되며 매끄러운 텍스처를 소스로 사용하여 게임 배경을 만들 수 있도록 설계되었습니다.

다만, 실제 캔버스 크기보다 더 큰 TileSprite를 생성해서는 안 됩니다. 게임의 전체 맵을 스크롤하는 큰 반복 배경을 만들려면 캔버스 크기에 맞는 TileSprite를 만든 다음 tilePosition 속성을 사용하여 플레이어가 이동할 때 텍스처를 스크롤합니다. 만약 엄청 큰 픽셀의 사이즈를 만든다면 엄청나게 메모리를 소모하며 퍼포먼스 이슈를 발생시킨다고 하네요. 😭😭😭

❗️ tilePosition을 사용하여 텍스처를 스크롤하고 tileScale을 사용하여 텍스처의 크기를 조정하세요. 스프라이트 자체의 크기를 조정하거나 필요 이상으로 크게 만들지 마세요.

phaser 의 해상도를 가져와서 가득찬 크기의 TileSprite Object 를 생성해봅니다.

typescript
1 create() {
2 const { width, height } = this.scale;
3
4 this.add
5 .tileSprite(0, 0, width, height, 'far')
6 .setOrigin(0.0, 0.0);
7 }

❗️ setOrigin 명령어는 object 의 배피를 중앙이 아닌 좌측, 상단을 기준으로 위치를 정의하고 싶을 수 있습니다. 이 경우는 setOrigin() 매서드를 사용합니다. 자세한 내용은 api 문서 참조하세요.

TileSprite
TileSprite

다음과 같이 반복되는 텍스쳐를 확인할 수 있겠습니다. 나중에 구름같은 배경에 쓸때 유용할 수 있겠는데요. 저희는 반복시키지 않을 것이라, setTileScaled 메소드를 활용해서 한화면 가득차도록 크게 키우도록 하겠습니다.

typescript
1 create() {
2 const { width, height } = this.scale;
3 const scaledWidth = width / 256;
4 const scaledHeight = height / 192;
5 const scaled = Math.max(scaledWidth, scaledHeight);
6
7 this.add
8 .tileSprite(0, 0, width, height, 'far')
9 .setTileScale(scaled)
10 .setOrigin(0.0, 0.0);
11 }

texture 의 가로 세로 크기를 가지고 scale 된 사이즈를 구하고, 가장 낮은 사이즈 기준으로 scale 을 조정하였습니다.

Scaled TileSprite
Scaled TileSprite

남은 모두 레이어를 추가해보자!

그럼 화면 가득찬 배경을 확인할 수 있겠습니다. 이제 순서대로 나머지 두가지 레이어도 동일하게 추가할 것인데, 반복될 작업을 줄이기 위해서 TileSprite 등록하는 부분을 함수로 빼두겠습니다.

typescript
1const addScaledBackground = (scene: Phaser.Scene, asset: string, textureWidth: number, textureHeight: number) => {
2 const { width, height } = scene.scale;
3 const scaledWidth = width / textureWidth;
4 const scaledHeight = height / textureHeight;
5 const scaled = Math.max(scaledWidth, scaledHeight);
6
7 return scene.add.tileSprite(0, 0, width, height, asset).setTileScale(scaled).setOrigin(0.0, 0.0);
8};

위 함수들을 이용해서 tileSprite 들을 등록해봅시다.

typescript
1 create() {
2 addScaledBackground(this, 'far', 256, 192);
3 addScaledBackground(this, 'back', 256, 192);
4 addScaledBackground(this, 'foreground', 352, 192);
5 }
Mixed TileSprite
Mixed TileSprite

제법 그럴듯 해졌습니다! 이제 움직여 보겠습니다! 그럴려면 update 매쏘드에서 등록된 tileSprite 를 움직이도록 해볼껍니다.

이제 움직여보자!

typescript
1 create() {
2 this.far = addScaledBackground(this, 'far', 256, 192);
3 this.back = addScaledBackground(this, 'back', 256, 192);
4 this.foreground = addScaledBackground(this, 'foreground', 352, 192);
5 }
6
7 update() {
8 if (this.far) this.far.tilePositionX += 0.1;
9 if (this.back) this.back.tilePositionX += 0.3;
10 if (this.foreground) this.foreground.tilePositionX += 0.5;
11 }
결과!

총평

update 메소드를 보시면 각 스피드를 다르게 지정하는게 키포인트입니다. camera 를 움직이는것도 가능하나, 다만 아까전에 공유드렸던 내용대로 tileSprite 를 무한히 키울 수 없어 게임 자체적인 크기를 유한한게 아니라면 tilePositionX / tilePositionY 를 통해서 스크롤을 구현하여야 합니다.

출처 및 참고

Relate
Stories

gatsby 블로그에 조회수 추가하기

gatsby 블로그에 조회수 추가하기

coding
2 years ago, 434 Views

gatsby 는 정적 사이트 생성기로써, 훌륭한 블로그 툴입니다. 다만 조회수등 여러가지 다이나믹한 기능들은 (바로) 지원하지 않는데요...

Read more
아키타견

아키타견

review
2 years ago, 70 Views

아키타견은 일본의 대표적인 견종 중 하나로써, 일본 아키타현 지방의 개의 품종입니다. 의외로 역사는 짧은편에 속하는 견종으로 16세기 아키타 마타기라고 불리는 사냥을 위해 길러진 토착견이 기원입니다.

© 2022-2024 Yeppyshiba Blog. All rights reserved.

Akita inu icons created by tulpahn - Flaticon