itch.io에서는 다양한 에셋들을 무료 혹은 유료로 구매할 수 있다.
2D 게임에서 장애물을 구현하기 위해 몇 자료를 받아 내가 필요한 형태로 가공하려고 한다.
이를 보면 분할된 여러 이미지가 있어 필요한 부분만 가지고 가공하여 사용할 수 있다.
이를 위해선 tiled라는 프로그램을 사용할 수 있다.
다음과 같이 원하는 픽셀 수를 조절한다.
총 map에 타일을 지정하고 각 타일의 가로 세로 크기를 지정한다.
각 타일의 이미지를 불러와서 원하는 맵으로 만들 수가 있다.
각 부분을 잘 조합하여 원하는 이미지를 쉽게 만들 수 있다.
export as image를 통해
커스텀한 이미지 파일을 사용할 수 있다.
이미지 내부에 서로 다른 두 개의 이미지가 공존하고 있다. 이를 활용하기 위해선 각 부분만을 잘라서 사용해야 한다.
어떻게 해야 할까?
sx, sy는 자를 첫 위치를 표현하고, sw, sh는 해당 정점으로 부터 얼마나 자를지를 표현하는 것 같다.
타입에 따른 x값 위치만 저장하고 y는 고정해 보자.
아까 30개의 타일과 해당 타일들은 가로 세로 16픽셀을 가지도록 만들었다.
이는 이미지의 총너비에 각 타일 비율만큼 곱하여 크기를 표현할 수 있다. 매우 좋은 가독성을 가지는 것 같다.
해당 이미지를 캔버스에 그릴 때 비율을 적절히 조절하면 다음과 같이 원하는 이미지만 잘라서 캔버스에 그릴 수 있다.
이제 해야 할 것은 다음과 같다.
위의 벽과 아래의 벽을 생성해야 하고 이 사이의 값을 랜덤 한 값으로 지정해야 한다.
벽은 오른쪽에서 왼쪽으로 진행해야 하고 랜덤 하게 벽이 등장해야 한다.
캔버스 외부로 나 간경우 배열에서 이를 제거해줘야 한다.
1. 각 벽의 사이 값을 랜덤으로 정의해 준다.
벽 사이는 랜덤 하게 작을 수도 클 수도 있다. 이를 최대 최소값을 통해 랜덤하게 생성하도록 한다.
이를 위해 utils.js에 최대 최소를 가지고 랜덤 한 값을 리턴하는 함수를 정의한다.
이후 gapY 값을 정의한다.
this.gapY = randomNumBetween(App.height * 0.1, App.height * 0.2);
각 벽의 쌍의 Y 값에 대해 고민을 더 해야 한다.
상단 벽의 Y값의 최솟값은 자신의 높이만큼 빼준 값이다. (js에서는 y축이 반대)
최소 : 자신의 높이를 빼준 값.
최대 : 캔버스 높이에서 gapY 만큼을 빼주고 자신의 높이를 빼준 값이 최대 값일 것이다.
최소와 최댓값 사이의 랜덤 한 값이 필요하다.
공통적인 자신의 높이를 빼주고 여기에 0부터 캔버스에서 gapY만큼 빼준 값이 최댓값으로 설정하면 된다.
y2는 y1에서 벽의 높이와 gapY만큼 더해주면 된다.
다만 그림자체에서 한 타일정도의 크기로 여백이 있기 때문에 한 타일의 가로 세로길이가 16px이기에 최소에서는 16을 더해주고 최댓값에서는 16을 빼주는 것으로 약간의 보정을 진행한다.
16도 조금 작은 것 같아 두 배를 적용하는 것으로 변경했다.
이 부분에서 새로운 개념을 알았는데, 첫 번째는 최대한 하나의 변수로 다른 변수를 도출하도록 생각하는 것.
y1에서 y2를 만들면서 복잡성이 줄었다.
그림을 그리는 것도 매우 좋은데, 게임 내부에서 gap이 상단에 생긴 경우는 y1이 최솟값을 가지는 경우다.
gap이 하단에 생기는 경우는 y1이 최대 값을 가지는 경우다.
이를 통해 이해가 조금 더 빨라졌다.
이제 물체를 이동시켜야 한다.
벽은 우측에 존재해야 하기 때문에 x값을 캔버스의 너비로 지정하고 x 값을 조금씩 빼주는 것으로 해보겠다.
get isOut(){
return this.x + this.width < 0;
}
get canGenerateNext(){
return !this.generatedNext && this.x + this.width < App.width * 0.4;
}
update(){
this.x -= 26;
}
//rendering 부분
for( let i = this.walls.length - 1; i >= 0; i-- ){
this.walls[i].update();
this.walls[i].draw();
if (this.walls[i].isOut){
this.walls.splice(i, 1);
continue;
}
if (this.walls[i].canGenerateNext){
this.walls[i].generatedNext = true;
this.walls.push(new Wall({ type: Math.random() > 0.5 ? 'SMALL' : 'BIG'}));
}
}
벽이 화면으로 나간 경우 해당 벽을 배열에서 삭제하고 다음 인덱스로 건너뛴다.
만약 해당 벽이 다음 벽을 생성할 수 있다면 새로운 벽을 만들어 준다.
이때 맵의 크기의 0.4 정도 보다 현재 벽의 최댓값이 더 작은 경우에 만드는데, 이 값을 조절하여 난이도를 조절할 수 있다.
값이 클수록 더 빨리 벽이 생성된다.
'FrontEnd > Canvas' 카테고리의 다른 글
2D 이미지로 입체감을 주는 방법 (0) | 2023.05.08 |
---|
댓글