패럴랙스 스크롤링 (parallax scrolling) 이란?
패럴랙스 스크롤링(parallax scrolling)은 원거리에 있는 배경 이미지는 느리게 움직이게 하고, 근거리에 있는 사물 이미지는 빠르게 움직이도록 함으로써 2D 기반에서 입체감을 느낄 수 있게 만든 기법입니다. 하나의 이미지를 여러 개의 레이어(layer)로 분리한 후 스크롤에 반응하는 속도를 다르게 조정하는 방식으로 구현하게 됩니다. 1930년대부터 애니메이션 분야에 사용되던 기법이었으나, 최근에는 웹 디자인에서도 손쉽게 볼 수 있습니다.
phaser3 코드를 작성해보자!
서로 다른 배경 이미지를 서로 다른 속도로 반복해서 보여줌으로써 입체감을 느끼게 하는게 목표입니다!
먼저 데모용 스크립트를 작성해보겠습니다.
typescript1import Phaser from 'phaser';23class MyGame extends Phaser.Scene {4 preload() {5 // 백그라운드 이미지 로딩6 }78 create() {9 // 백그라운드 설정10 }1112 update() {}13}1415new 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});
실제 구현을 위해서, 사용할 레이어들의 이미지들을 호출해보도록 하겠습니다.
총 위의 3가지 이미지를 사용할 예정입니다.
typescript1 preload() {2 this.load.image("foreground", Foreground);3 this.load.image("back", Back);4 this.load.image("far", Far);5 }
가장 뒷 배경 레이어를 추가해보자!
도시 야경에서 가장 뒷 배경이 되는 이미지를 여기에서 등록해보도록 하겠습니다.
텍스쳐를 반복 그리는데 최적화된 Object 입니다.
TileSprite 자체적으로 텍스쳐를 스크롤과 크기를 조정할 수 있습니다. 자동으로 래핑되며 매끄러운 텍스처를 소스로 사용하여 게임 배경을 만들 수 있도록 설계되었습니다.
다만, 실제 캔버스 크기보다 더 큰 TileSprite를 생성해서는 안 됩니다. 게임의 전체 맵을 스크롤하는 큰 반복 배경을 만들려면 캔버스 크기에 맞는 TileSprite를 만든 다음 tilePosition 속성을 사용하여 플레이어가 이동할 때 텍스처를 스크롤합니다. 만약 엄청 큰 픽셀의 사이즈를 만든다면 엄청나게 메모리를 소모하며 퍼포먼스 이슈를 발생시킨다고 하네요. 😭😭😭
❗️ tilePosition을 사용하여 텍스처를 스크롤하고 tileScale을 사용하여 텍스처의 크기를 조정하세요. 스프라이트 자체의 크기를 조정하거나 필요 이상으로 크게 만들지 마세요.
phaser 의 해상도를 가져와서 가득찬 크기의 TileSprite Object 를 생성해봅니다.
typescript1 create() {2 const { width, height } = this.scale;34 this.add5 .tileSprite(0, 0, width, height, 'far')6 .setOrigin(0.0, 0.0);7 }
❗️ setOrigin 명령어는 object 의 배피를 중앙이 아닌 좌측, 상단을 기준으로 위치를 정의하고 싶을 수 있습니다. 이 경우는 setOrigin() 매서드를 사용합니다. 자세한 내용은 api 문서 참조하세요.
다음과 같이 반복되는 텍스쳐를 확인할 수 있겠습니다. 나중에 구름같은 배경에 쓸때 유용할 수 있겠는데요. 저희는 반복시키지 않을 것이라, setTileScaled 메소드를 활용해서 한화면 가득차도록 크게 키우도록 하겠습니다.
typescript1 create() {2 const { width, height } = this.scale;3 const scaledWidth = width / 256;4 const scaledHeight = height / 192;5 const scaled = Math.max(scaledWidth, scaledHeight);67 this.add8 .tileSprite(0, 0, width, height, 'far')9 .setTileScale(scaled)10 .setOrigin(0.0, 0.0);11 }
texture 의 가로 세로 크기를 가지고 scale 된 사이즈를 구하고, 가장 낮은 사이즈 기준으로 scale 을 조정하였습니다.
남은 모두 레이어를 추가해보자!
그럼 화면 가득찬 배경을 확인할 수 있겠습니다. 이제 순서대로 나머지 두가지 레이어도 동일하게 추가할 것인데, 반복될 작업을 줄이기 위해서 TileSprite 등록하는 부분을 함수로 빼두겠습니다.
typescript1const 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);67 return scene.add.tileSprite(0, 0, width, height, asset).setTileScale(scaled).setOrigin(0.0, 0.0);8};
위 함수들을 이용해서 tileSprite 들을 등록해봅시다.
typescript1 create() {2 addScaledBackground(this, 'far', 256, 192);3 addScaledBackground(this, 'back', 256, 192);4 addScaledBackground(this, 'foreground', 352, 192);5 }
제법 그럴듯 해졌습니다! 이제 움직여 보겠습니다! 그럴려면 update 매쏘드에서 등록된 tileSprite 를 움직이도록 해볼껍니다.
이제 움직여보자!
typescript1 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 }67 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 블로그에 조회수 추가하기
codinggatsby 는 정적 사이트 생성기로써, 훌륭한 블로그 툴입니다. 다만 조회수등 여러가지 다이나믹한 기능들은 (바로) 지원하지 않는데요...