Flappy Bird와 마찬가지로 Jetty Cat은 탭하거나 클릭하여 조작하는 고양이가 제트 팩을 사용하여 무한한 장애물을 피하는 게임입니다. 먼저 메인 게임 로직을 구현 한 다음 UI를 구현합니다. 그 후 멋진 전환, 파티클 시스템 및 미묘한 효과를 추가하여 게임을 다듬을 것입니다.
그것이 우리가 할 일입니다 :
::: warn 보시다시피, 이것은 "Hello world"예제가 아니라 전체 게임을 처음부터 만드는 가이드입니다. 완료 할 시간을 충분히 주세요! :::
Creating the project and importing assets
ct.js를 열고 프로젝트 이름을 쓰고 "만들기"버튼을 클릭하여 새 프로젝트를 만듭니다. 프로젝트를 저장할 위치를 ct.js에 알려줍니다. "내 문서"와 같은 폴더를 선택하는 것이 좋습니다.
ct.js 창 상단에 있는 "텍스처"탭을 클릭합니다. 그런 다음 파일 탐색기를 열고 ct.js 폴더에서 examples/JettyCat_assets 폴더를 찾으십시오. 내부에는 우리가 사용할 자산이 있습니다. 파일 뷰어에서 ct.js로 에셋을 드래그 하면 ct가 이를 프로젝트로 빠르게 가져옵니다.
이러한 텍스처를 준비해야 합니다. 배경을 적절하게 표시하고 게임 내의 복사본이 서로 정확하게 상호 작용하도록 충돌 모양을 설정해야 합니다. 먼저 프로젝트의 배경을 열어 보겠습니다. BG_Ground 카드를 클릭합니다.
여기에서 "배경으로 사용 하시겠습니까?"확인란을 클릭해야 합니다. 이는 ct.js에게 이 텍스처를 다르게 패킹 하도록 지시하고 레벨에서 반복 할 수 있도록 합니다.
왼쪽 하단에서 "저장"을 누르십시오. 이제 BG_Sky 텍스처로 똑같이 하십시오.
배경이 준비되었습니다! 스프라이트의 충돌 모양을 설정할 시간입니다. 어디에나 설정할 필요는 없지만, 서로 충돌하는 오브젝트와 게임 중에 클릭하는 오브젝트에 대해서는 설정해야 합니다. Jetty_Cat, OhNo 및 Pause와 같은 헤더는 대화식이 아니며 장식 일뿐 아니라 PressHint는 정보 역할을 하며 클릭을 직접 수신하지도 않습니다. 그러나 고양이와 튜브는 충돌 할 것이고 별들은 고양이가 그것들과 겹치는 시기를 알아야 합니다.
PotatoCat을 열어 보자! 가장 먼저 해야 할 일은 텍스처의 축을 이동하는 것입니다. 기본적으로 왼쪽 상단에 사각형 축으로 표시됩니다. 축은 사본이 축척 되고 회전하는 지점입니다. 축을 고양이 몸의 중심에 놓습니다. 그런 다음 충돌 모양을 정의하겠습니다. 고양이는 원형이나 직사각형처럼 보이지 않으므로 충돌 모양을 왼쪽 열에 다각형으로 설정합니다. 오각형이 나타납니다. 고양이의 실루엣을 더 잘 표현하기 위해 노란색 선을 클릭하여 모서리를 드래그하고 새 점을 추가 할 수 있습니다. 15 점이면 충분합니다.
팁
꼬리와 귀의 윤곽을 그리지 않는 것이 좋습니다. 꼬리가 튜브에 부딪쳐서 플레이어가 지면 불공평하다고 생각할 수 있습니다. 어쨌든 꼬리는 너무 유연해서 치명적인 충돌을 일으킬 수 없습니다 ?
모양을 정의한 후 "저장"버튼을 클릭하여 자산 목록으로 돌아갑니다. 우리는 Star뿐만 아니라 같은 방식으로 PotatoCat_Stunned 텍스처를 조정해야 합니다.
파이프의 경우 약간 다른 것을 사용합니다. 첫 번째 Tube_01을 열고 해당 축을 거의 스프라이트 하단에 배치합니다. 축은 회전 뿐만 아니라 크기 조정에도 영향을 미친다는 것을 기억하십니까? 화면 상단에서 매달린 파이프와 하단에서 자라는 파이프 모두에 동일한 텍스처를 재사용 합니다. 위쪽이 작동하도록 하려면 아래쪽 축을 기준으로 음의 크기를 조정하여 끝을 아래로 뒤집습니다. 나중에 회전 할 수도 있으며,베이스가 제자리에 고정 된 상태에서 멋지게 흔들릴 것입니다.
4 개의 튜브 텍스처 모두에 대해 이 작업을 수행해야 합니다. 그런 다음 레벨 생성 및 코딩 운동을 시작할 수 있습니다!
메인 룸 만들기 및 고양이 이동
모든 재미가 일어날 방을 만들어 봅시다! 방은 종종 레벨이라고 합니다. 모든 리소스가 결합되고 서로 상호 작용할 수 있는 곳입니다. ct.js 창 상단에 있는 "Rooms"탭을 열고 새로 만듭니다.
이 정확한 방에 대한 방 편집기가 나타납니다. 방을 InGame이라고 부르십시오. 나중에 코드에서 이 특정 이름을 사용할 것입니다. 그러나 이름을 지정하는 데 규칙은 없습니다. 나중에 메뉴를 코딩하는 동안 기억할 수 있는 것이 필요합니다 ?
그런 다음 기어 아이콘이 있는 속성 탭에서 방의 크기를 설정해야 합니다. 1080x1920 픽셀로 설정합니다.
이제 배경을 추가하겠습니다. "배경"탭을 클릭 한 다음 하늘과 지면의 두 가지를 추가하십시오. 하늘은 그대로 보이지만 지면을 조정해야 합니다. 왼쪽 열에서 배경 텍스처 옆에 있는 톱니 바퀴를 클릭하고 드롭 다운 "반복"을 찾습니다. "반복 -x"로 설정 : X가 수평 축 (Y는 수직 축)이므로 배경 타일을 수평으로 만 만듭니다. 그런 다음 Shift Y 필드를 변경하여 지면을 방의 프레임 하단으로 오른쪽으로 이동해야 합니다.
힌트:
방을 마우스로 끌고 마우스 휠로 확대하거나 왼쪽 오른쪽 모서리에 있는 "확대 / 축소"버튼을 사용하여 방을 탐색 할 수 있습니다.
또한 제대로 정렬되도록 두 배경의 깊이를 설정합니다. Depth는 ct.js에게 객체를 정렬하는 방법을 알려주는 3 차원으로 하늘이 실수로 다른 모든 것과 겹치지 않도록 합니다. 양수 값은 물건을 카메라에 더 가깝게 가져 오므로 양의 깊이를 가진 물체는 음의 물체와 겹칩니다.
하늘의 깊이 값을 -20으로, 땅의 깊이를 -10으로 설정합니다. 이것이 ct.js가 이러한 구성을 이해하는 방법입니다.
고양이 유형
텍스처는 대부분의 게임에 필수적이지만 자체적으로는 아무것도 하지 않습니다. 우리는 이미 배경을 사용했으며 순전히 장식적인 질감을 위한 것입니다. 반면 유형은 게임 플레이 로직을 포함 할 수 있으며 복사본을 만드는 데 사용됩니다. 복사본은 우리가 방에 추가하는 것이며, 이러한 복사본은 화면에서 서로 상호 작용하는 엔티티입니다.
우리 고양이의 유형을 만들어 봅시다! ct.js 창 상단의 "유형"탭을 열고 "만들기"버튼을 누릅니다. 이름을 PotatoCat으로 지정하고 "스프라이트 변경"사각형을 클릭하고 고양이의 텍스처를 선택하여 텍스처를 설정합니다.
이제 고양이를 방에 추가 할 수 있습니다! "방"탭으로 다시 전환하고 유일한 방을 열어 탐색하십시오. 우리 고양이는 "사본"탭의 왼쪽 열에 나타납니다. 그것을 클릭 한 다음 레벨에서 사본을 표시 할 위치를 다시 한 번 클릭하십시오. 지금은 고양이 한 마리만 있으면 됩니다.
지금 "Play 버튼"을 클릭하면 디버거가 실행되고 배경과 고양이가 있는 정적 화면이 표시됩니다. 고양이는 아직 움직이지 않습니다. 그것이 우리가 지금 바꿀 것입니다!
"유형"탭을 다시 열고 고양이 유형을 엽니다. 여기에 코드를 위한 4 개의 탭이 있습니다.
그것이 우리가 할 일입니다 :
On Create 탭에 다음 코드를 입력합니다.
this.speed = 10;
this.direction = 0;
this.speed = 10; 각 프레임에서 고양이를 10 픽셀 씩 움직여야 함을 의미합니다. 초당 60FPS를 사용하면 초당 600 픽셀이 됩니다. 이는 우리 방의 약 절반입니다.
this.direction = 0; 0도에서 주어진 방향으로 고양이를 움직인다는 뜻입니다. 0 도는 오른쪽으로 90도 (위쪽으로 180도) 왼쪽으로 270도 아래쪽으로 이동 함을 의미합니다.
이제 플레이어가 화면을 누를 때마다 고양이를 움직여 봅시다. 마우스 및 모바일 터치 이벤트를 모두 지원해야 하므로 이를 지원하는 모듈을 활성화해야 합니다. 하지만 간단합니다. ct.js 창의 상단에 있는 "Project"탭을 연 다음 왼쪽에 있는 "Catmods"를 엽니다. 사용 가능한 모듈이 있는 섹션에서 모듈 터치를 찾으십시오. 활성화하려면 클릭하십시오. 주위에 작은 회전 원이 있는 녹색 확인란이 있습니다.
터치 모듈에는 코드를 깔끔하게 유지하는 데 도움이 되는 옵션이 있습니다. 활성화 된 모듈에 대한 설정은 "Catmods '설정"헤더 아래 왼쪽에 나타납니다. 터치 탭을 클릭 한 다음 "마우스 이벤트를 터치 이벤트로 감지"옵션을 선택하십시오. 이 옵션을 사용하면 터치 이벤트에 대해서만 코드를 작성할 수 있으며 마우스에서도 자동으로 작동합니다.
이제 ct.js에서 입력 방법은 Actions로 그룹화됩니다. 이 프로젝트에서는 화면 터치라는 하나의 입력 방법 만 사용합니다. 화면 상단의 "프로젝트"탭에서 왼쪽의 "작업 및 입력 방법"탭을 누릅니다.
첫 번째 작업을 추가하고 이름을 Poof로 지정합니다. 네. 그런 다음 오른쪽에서 "입력 방법 추가"를 클릭하고 터치 제목 아래에서 "모든 터치"방법을 찾습니다. 검색을 사용하여 결과를 빠르게 필터링 할 수 있습니다.
작업이 완료되면 저장하고 고양이에게로 돌아갈 수 있습니다.
행위? 왜?
노련한 개발자의 경우 작업은 여기에서 불필요한 단계로 보일 수 있지만 다양한 입력 방법을 지원해야 할 때 빛납니다. 키보드와 게임 패드를 모두 지원하는 게임을 만들고 키보드가 WASD 이동과 화살표 이동을 지원한다고 가정 해 보겠습니다. 하나의 작업은 세 가지 방법을 모두 지원하며 나중에 새 입력 방법을 추가하더라도 코드가 슬림하게 유지됩니다. 그 외에도 모두 동일한 코드로 사용할 수 있습니다!
여기에서 작업에 대한 자세한 내용을 읽을 수 있습니다.
다음 코드를 cat의 On Step 이벤트에 추가합니다.
if (ct.actions.Poof.down) {
this.gravity = 2;
this.addSpeed(ct.delta * 4, 90);
}
(ct.actions.Poof.down)은 플레이어가 화면을 누를 때만 작동합니다. 작동한다면 고양이를 아래로 당기는 중력을 정의하고 고양이를 위로 당기는 속도를 추가합니다. 추가 된 속도에 ct.delta를 곱하여 모든 경우에 원활하게 실행되도록해야합니다.
ct.delta
ct.delta는 대부분 1과 같지만이 승수를 간과해서는 안됩니다. 플레이어의 프레임 속도가 떨어지거나 어떤 이유로 게임이 지연되는 경우 ct.delta는 이러한 프레임 드롭 및 지연을 보상하기 위해 더 큰 값이 됩니다. 예를 들어 프레임 속도가 초당 60 프레임에서 30 프레임으로 떨어지면 ct.delta는 일시적으로 2가 됩니다. 그 외에도 ct.delta는 게임 내 시간 확장을 지원하고 슬로우 모션 효과와 게임 일시 중지를 만들 수 있습니다. (그리고 우리는 이러한 기능을 구현할 것입니다!)
팁
플레이어가 화면을 누르기 시작하고 멈출 때 true를 반환하는 ct.actions.Poof.pressed 및 ct.actions.Poof.released도 있습니다.
On Step에서 정의되는 중력이 이상해 보이죠? 실제로 On Create 이벤트에 더 잘 배치되어 처음부터 한 번 설정되고 변경되지 않는 상수입니다. 그러나 입력 확인과 함께 절 안에 배치하면 약간의 트릭이 추가됩니다. 고양이는 플레이어가 게임과 상호 작용 한 후에 만 떨어지기 시작합니다! 따라서 고양이가 그렇지 않으면 빨리 땅에 부딪힐 것이기 때문에 그들은 즉시 잃지 않을 것입니다.
이제 기본 행이 있는지 확인하십시오. this.move (); On Step 탭에서. 이 줄은 복사본의 위치를 처리합니다. On Step 코드의 마지막 줄이어야 합니다.
지금 프로젝트를 실행하면 고양이가 왼쪽에서 오른쪽으로 이동 한 다음 클릭에 반응하여 날고 떨어지기 시작하는 것을 볼 수 있습니다. 하지만 뷰포트에서 빠르게 날아갑니다. 세트의 변경!
카메라 이동
Ct.js에는 화면에 항목을 표시하는 역할을 하는 엔티티 ct.camera가 있습니다. 그것은 많은 기능을 가지고 있으며 그중 하나는 사본을 따르고 있습니다.
고양이의 "On Create"탭을 열고 다음 코드를 추가합니다.
ct.camera.follow = this;
ct.camera.followY = false;
ct.camera.shiftX = 250;
ct.camera.follow 링크를 따라야 하는 사본에 대한 링크를 지정하고 이를 이 값으로 설정하여 고양이를 따르도록 지시합니다. 이것은 코드를 실행하는 사본을 나타냅니다. 객실에는 이벤트와 이 키워드도 있습니다.
ct.camera.followY = 거짓; 카메라를 수직 (Y 축)으로 움직일 필요가 없음을 나타냅니다. 오른쪽으로 만 슬라이드 합니다.
ct.camera.shiftX = 250; 카메라가 고양이를 기준으로 오른쪽으로 250 픽셀을 유지하도록 합니다. 기본적으로 고양이가 뷰포트의 중앙에 있도록 초점을 맞춥니 다.
지금 게임을 실행하면 카메라가 고양이를 잘 따라갈 것입니다. 예이!
충돌 코드 작성
실제 게임 플레이를 구현하기에 좋은 시기 입니다. 튜브에 대한 유형을 추가하고, 일부를 레벨에 배치하고, 파이프와 지면 모두에 대한 충돌을 코딩합니다. 그런 다음 파이프의 텍스처를 무작위화하여 높이를 변경합니다.
파이프 추가
새 유형을 만들고 튜브라고 합니다. 우리 컬렉션에서 비교적 긴 파이프 중 하나로 텍스처를 선택하십시오. 그런 다음 충돌 모양을 "장애물"로 설정합니다.
그런 다음 방을 열고 바닥에 파이프를 추가하여 충돌을 확인할 수 있습니다. InGame 룸을 열고 왼쪽 열에서 튜브를 선택한 다음 스폰 하려는 레벨 뷰를 클릭하여 추가합니다. 테스트를 위해 많은 것이 필요하지 않습니다.
그런 다음 고양이 유형을 열고 On Step 탭을 선택합니다. 다음을 수행합니다.
이것이 충돌을 확인하는 코드입니다. 플레이어의 입력을 확인하는 코드 뒤에 배치하지만 this.move (); 선:
// If the cat bumped into something solid and the game is not over
if (!this.gameover && ct.place.occupied(this, 'Obstacle')) {
// Change the texture
this.tex = 'PotatoCat_Stunned';
// Set a flag that we will use to stop other logic
this.gameover = true;
// Jump to the left
this.speed = 25;
this.direction = 135;
// Stop camera movement
ct.camera.follow = false;
}
ct.place.occupied는 특정 충돌 그룹과 주어진 복사본의 충돌을 확인합니다. 이 메소드는 ct.place 모듈에서 제공하며 "Catmods"탭에서 다른 메소드에 대한 참조를 찾을 수 있습니다.
On Step 이벤트가 시작될 때 바로 이 코드 블록이 필요합니다.
if (this.gameover) {
this.gravity = 2;
this.move();
return;
// No code below will be executed if "return" was executed.
}
this.gravity = 2; 플레이어가 아직 게임과 상호 작용하지 않은 경우에도 고양이에게 중력이 설정되어 있는지 확인합니다 (상호 작용이 없어 패배 한 경우). 반환; 더 이상 실행을 중지하고 그 위에 this.move ()를 배치합니다. 맨 아래에 있는 동일한 줄이 실행되지 않기 때문입니다.
테스트 할 시간입니다! 충돌 중에 고양이가 급격히 갑작스럽게 움직이면 충돌 모양과 축이 시작 텍스처와 동일한 방식으로 설정되어 있는지 확인합니다.
고양이가 땅이나 화면의 상단 가장자리에 닿으면 잃게 만듭니다.
어떤 이유로 바닥, 심지어 하늘까지도 펄럭이는 새 같은 게임의 튜브만큼 치명적입니다. 이제 지상에는 유형이 없으며 ct.place 및 sky와 함께 작동하지 않습니다. 게임의 엔티티가 전혀 아닙니다. 그러나 그것들은 평평하고 수평 적이며 우리는 공간에서 고양이의 위치를 확인하는 규칙으로 충돌 논리를 강화할 수 있습니다.
이제 방을 열고 레벨 위로 마우스를 이동하면 왼쪽 하단 모서리에 현재 좌표가 표시됩니다. 초기 뷰 프레임의 상단은 Y 축에서 항상 0 픽셀이고 지면의 상단 가장자리는 1750 픽셀입니다. 사본의 위치는 this.x 및 this.y에 의해 정의되며 이를 읽고 다른 값과 비교할 수 있습니다.
고양이의 충돌 논리를 다음과 같이 수정하여 고양이가 땅과 하늘에 부딪혀 기절 할 수 있도록 합니다. 새로운 비교와 나누기 위해 ct.place.occupied 주위에 괄호를 추가했습니다.
// If the game is not over, the cat bumped into something solid, or
if (!this.gameover && (ct.place.occupied(this, 'Obstacle') ||
// the cat is below the ground minus its approximate height, or
this.y > 1750 - 200) ||
// the cat flew off the upper boundary,
this.y < 0
) {
// Change the texture
this.tex = 'PotatoCat_Stunned';
// Set a flag that we will use to stop other logic
this.gameover = true;
// Jump to the left
this.speed = 25;
this.direction = 135;
// Stop camera movement
ct.camera.follow = false;
}
텍스쳐를 변경하여 파이프의 높이 무작위화
이전에 this.tex = 'NewTextureName';으로 고양이의 질감을 변경했습니다. 파이프에 대해 네 가지 다른 텍스처가 있으므로 높이를 무작위로 지정하기 위해 파이프로 동일한 작업을 수행 할 수 있습니다.
Ct.js에는 임의 값을 생성하는 데 도움이 되는 ct.random이라는 내장 모듈이 있습니다. 상단의 Catmods 탭에서 찾아서 활성화하십시오. 그런 다음 튜브의 OnCreate 코드를 열고 다음 스니펫을 추가합니다.
this.tex = ct.random.dice(
'Tube_01',
'Tube_02',
'Tube_03',
'Tube_04'
);
ct.random.dice는 임의의 수의 인수를 받아들이고 호출 될 때마다 그 중 하나를 무작위로 반환하는 함수입니다.
테스트 할 시간입니다! 파이프가 잘못 정렬 된 경우 네 가지 텍스처 모두에 대해 충돌 모양을 설정하고 해당 축을 파이프 바닥에 배치했는지 확인합니다.
시간을 통해 파이프 생성
유형으로서 룸은 자체 로직을 가질 수도 있습니다. 룸 편집기의 "룸 이벤트"버튼 아래에 숨겨져 있습니다. 네 가지 이벤트도 있습니다.
시간이 지남에 따라 새 파이프를 생성하기 위해 다음을 수행합니다.
유일한 방 InGame을 엽니다. Control 키를 누른 상태에서 마우스를 드래그 하거나 이러한 복사본을 마우스 오른쪽 버튼으로 클릭하고 상황에 맞는 메뉴를 사용하여 기존 튜브를 제거합니다. 그런 다음 왼쪽 열에서 "회의실 이벤트"버튼을 클릭합니다.
OnCreate 코드에 다음 줄을 넣으십시오.
this.spawnTimer = ct.speed * 5;
여기서 ct.speed는 초당 프레임 수이므로 첫 번째 튜브를 생성하기 전에 정확히 5 초 동안 기다립니다.
On Step에 다음 코드를 입력합니다.
// Substract elapsed time from the timer
this.spawnTimer -= ct.delta;
// If the timer is up…
if (this.spawnTimer <= 0) {
// Wind it again
this.spawnTimer += ct.speed * 2;
// Create two tubes
var tube1 = ct.types.copy('Tube', ct.camera.right + 250, ct.camera.bottom - 130); // At the bottom of the camera
var tube2 = ct.types.copy('Tube', ct.camera.right + 250, ct.camera.top - 70); // At the top
// Change second tube's texture depending on which texture is used in the first tube
if (tube1.tex === 'Tube_01') { // Shortest tube will result in the longest tube
tube2.tex = 'Tube_04';
} else if (tube1.tex === 'Tube_02') {
tube2.tex = 'Tube_03';
} else if (tube1.tex === 'Tube_03') {
tube2.tex = 'Tube_02';
} else if (tube1.tex === 'Tube_04') { // Longest will result in the shortest one
tube2.tex = 'Tube_01';
}
// Thus we will always get gaps of the same size, but with random tubes.
// Now, flip the upper (second) tube
tube2.scale.y = -1;
}
많은 코드가 있습니다!
this.spawnTimer는 각 프레임에서 감소하고 결국 0 또는 더 작은 값으로 바뀝니다. 그런 일이 발생하면 나중에 다시 실행되도록 값을 다시 양수로 설정합니다. 여기에 2 초를 더합니다. (ct.speed는 1 초당 프레임 수입니다.)
ct.types.copy (typeName, xPosition, yPosition)을 사용하여 두 개의 복사본을 만들고 변수 tube1 및 tube2에 대한 참조를 저장합니다. 처음에는 ct.random.dice가있는 On Create 코드가 생성 직후에 실행되므로 높이는 완전히 정상입니다. 이것은 두 튜브가 모두 긴 것으로 판명 된 경우의 좋은 부분에서 차단 된 경로를 초래할 것입니다. 이를 수정하기 위해 tube1.tex로 첫 번째 tube1의 텍스처 이름을 읽고 추출 된 값에 따라 두 번째 tube2의 텍스처를 설정합니다.
ct.camera.right, ct.camera.left, ct.camera.top, ct.camera.bottom은 게임 좌표에서 뷰 경계의 좌표를 나타냅니다. 여기서 우리는 뷰포트가 끝나는 오른쪽과 뷰포트의 아래쪽과 위쪽 가장자리 위에 화면 밖에서 튜브를 만드는 데 사용합니다.
마지막으로 tube2.scale.y = -1을 실행하여 두 번째 튜브를 뒤집습니다. 그래픽 편집기에서 이미지를 수직으로 뒤집을 때와 똑같은 작업입니다. 참고로 수평 스케일을 설정하는 tube2.scale.x도 있습니다.
지금 프로젝트를 실행하면 튜브 사이에 작은 간격을 두고 날아가는 멋지게 생성 된 튜브를 볼 수 있습니다. 그러나 잠깐, 고양이는 너무 커서 날아갈 수 없습니다! 아니,이 튜토리얼을 "뚱뚱한 고양이"라고 불러야 했는데…
걱정 마세요, 해결책이 있습니다 ✨ 우리는 고양이를 조금 더 작게 만들기 위해 동일한 스케일링을 사용할 것입니다. 축척 값은 1과 -1뿐만 아니라 그 사이에 있는 어떤 것도 개체를 더 작게 만들거나 1보다 크게 만들 수 있습니다.
고양이의 크기를 조정하는 방법에는 두 가지가 있습니다.
쓸모없는 사본 청소
시간이 지남에 따라 복사본을 생성하면 그 수가 계속 증가합니다. 우리가 아무것도 하지 않으면 게임이 천천히 PC의 메모리를 많이 먹어 결국 충돌합니다. 이를 방지하기 위해 카메라 왼쪽을 지난 복사본을 삭제합니다.
다음 코드를 튜브의 On Step 이벤트에 추가합니다.
if (this.x < ct.camera.left - 150) {
this.kill = true;
}
여기서 우리는 복사본의 수평 좌표를 카메라의 왼쪽과 비교합니다. 또한 튜브가 제거되기 전에 뷰포트에서 완전히 벗어날 수 있도록 왼쪽으로 150 픽셀을 관찰합니다.
별 추가
수집 할 때 점수가 증가하는 별 보너스 유형을 추가해 보겠습니다. 다음을 수행합니다.
이제 InGame 룸의 이벤트를 열고 this.score = 0; 줄을 추가합니다. 이렇게 하면 다른 복사본에서 편집하고 읽을 수 있는 변수가 생성됩니다.
새 유형을 만들고 별이라고 부릅니다. 텍스처를 설정하십시오.
On Step 코드에 다음 스크립트를 넣으십시오.
if (ct.place.meet(this, 'PotatoCat')) {
this.kill = true;
ct.room.score += 1;
}
ct.place.meet은 충돌 그룹이 아니라 특정 유형에 대해 확인하지만 ct.place.occupied와 같습니다. 여기서 우리는 별이 우리 고양이와 충돌하는지 확인합니다. 그렇다면 this.kill = true는 별을 제거해야 함을 나타냅니다. ct.room.score + = 1; 룸의 "On Create"코드에서 이전에 생성 된 점수 변수를 증가 시킵니다.
팁
ct.room은 항상 현재 방을 가리킵니다. 중첩 된 방이 있는 경우 ct.room은 항상 기본 방을 가리킵니다.
또한 메모리 누수를 방지하고 수집 되지 않은 별을 제거하려면 이 코드가 필요합니다.
if (this.x < ct.camera.left - 150) {
this.kill = true;
}
산란 별
방의 On Step 코드에서 다음 두 튜브 사이 어딘가에 30 % 확률로 별을 추가 할 몇 줄 (강조 표시된 줄)을 추가합니다. ct.random 모듈의 메소드를 사용합니다.
// Substract elapsed time from the timer
this.spawnTimer -= ct.delta;
// If the timer is up…
if (this.spawnTimer <= 0) {
// Wind it again
this.spawnTimer += ct.speed * 2;
// Create two tubes
var tube1 = ct.types.copy('Tube', ct.camera.right + 250, ct.camera.bottom - 130); // At the bottom of the camera
var tube2 = ct.types.copy('Tube', ct.camera.right + 250, ct.camera.top - 70); // At the top
// Change second tube's texture depending on which texture is used in the first tube
if (tube1.tex === 'Tube_01') { // Shortest tube will result in the longest tube
tube2.tex = 'Tube_04';
} else if (tube1.tex === 'Tube_02') {
tube2.tex = 'Tube_03';
} else if (tube1.tex === 'Tube_03') {
tube2.tex = 'Tube_02';
} else if (tube1.tex === 'Tube_04') { // Longest will result in the shortest one
tube2.tex = 'Tube_01';
}
// Thus we will always get gaps of the same size, but with random tubes.
// Now, flip the upper (second) tube
tube2.scale.y = -1;
// Create a star bonus with 30% chance somewhere in between top and bottom edge, with 300px padding.
if (ct.random.chance(30)) {
ct.types.copy('Star', ct.camera.right + 250 + 500, ct.random.range(ct.camera.top + 300, ct.camera.bottom - 300));
}
}
ct.random.chance (30)은 100 개 중 30 번 true를 반환하고 그렇지 않으면 false를 반환합니다. 별이 다소 자주 나타나도록 숫자를 조정할 수 있습니다.
ct.random.range (a, b)는 주어진 범위 사이에서 임의의 값을 선택합니다. 우리의 경우에는 별이 지면이나 상단 가장자리 근처에서 생성되지 않도록 카메라에 상대적으로 두 좌표를 계산합니다.
카운터가 있는 UI 요소 만들기
ct.js에서 v1.3부터 UI 요소는 일반적으로 별도의 공간에 생성 된 다음 다른 공간에 삽입됩니다. 이러한 내포 된 룸은 종종 "레이어"라고도 합니다.
ct.js 창 상단의 UI 탭으로 이동하여 새 텍스트 스타일을 만듭니다. 오렌지라고 부르세요. 여기에서는 점수와 다른 텍스트 줄을 표시하는 데 사용할 텍스트 스타일을 만듭니다.
첫 번째 탭인 "Font"에서 글꼴 크기를 80으로 설정하고 두께를 900으로 설정합니다. 그런 다음 가운데에 맞춥니다. 이렇게 하면 텍스트가 더 굵고 커집니다.
"채우기"탭으로 전환하고 활성화하십시오. 수직 그라데이션 채우기를 만들어 보겠습니다. 옅은 노란색과 주황색을 사용합니다.
그런 다음 "Stroke"탭으로 전환하고 활성화합니다. 획의 색상을 진한 갈색으로 설정하고 가중치를 10으로 설정합니다.
이제 스타일을 저장할 수 있습니다. 그 후에 별 아이콘과 점수 카운터를 표시하는 새로운 유형이 필요합니다.
새 유형을 만들고 이름을 StarCounter라고 합니다. 텍스처로 Star 텍스처를 재사용 합니다. On Create 코드에 다음 스니펫을 넣으십시오.
this.label = new PIXI.Text('0', ct.styles.get('Orange'));
this.label.x = 130;
this.label.y = -60;
this.addChild(this.label);
이 코드는 Pixi.js의 API로 만든 마법입니다. Pixi.js는 ct.js가 기반으로 하는 그래픽 프레임 워크이며 복사본과 배경 이외의 것을 표시해야 할 때 API를 사용합니다. 여기서 new PIXI.Text는 새 텍스트 레이블을 생성합니다. 첫 번째 인수는 표시 될 문자열입니다. 방 시작시 점수가 0 점이므로 초기 텍스트로 '0'을 씁니다. 두 번째 인수는 텍스트 스타일입니다. 생성 된 스타일 'Orange'에서 로드 합니다.
this.label = new Pixi.Text (…)를 작성하면 생성 된 레이블에 대한 참조를 즉시 기억하고 복사본의 매개 변수 this.label로 저장합니다. 그런 다음 this.label.x = 130; 그리고 this.label.y = -60이지만 우리는 사본을 기준으로 하고 있습니다. StarCounter 사본 자체는 여전히 아이콘을 표시하지만 텍스트를 표시하는 데 사용하는 컨테이너에 가깝습니다. this.addChild (this.label) 행은 마지막으로 작성된 텍스트 레이블을 사본에 넣습니다.
각 프레임에서 텍스트 레이블을 업데이트해야 합니다. On Draw 이벤트에서 this.label.text = ct.room.score; 줄을 입력합니다.
마지막으로 이 카운터를 위한 공간을 만들고 이 공간을 메인 공간에 넣습니다. 새 방을 만들고 이름을 UI_InGame이라고 합니다. 그런 다음 메인 룸의 뷰포트와 일치하도록 뷰 크기를 1080x1920으로 설정하고 카운터의 사본을 왼쪽 상단 모서리에 배치합니다.
그런 다음 InGame 방을 열고 OnCreate 코드 하단에 다음 코드를 추가합니다.
ct.rooms.append('UI_InGame', {
isUi: true
});
그 후 레벨에 별이 생성되고, 해당 증가 점수가 뷰포트의 왼쪽 상단 모서리에 표시됩니다.
메뉴 만들기
이제 게임이 완성 된 느낌이 들도록 일반 메뉴가 있는 방을 더 추가합니다.
메인 메뉴
Jetty_Cat 텍스처를 열고 축이 중심에 있는지 확인합니다. 그런 다음 새 유형을 만듭니다. 순전히 장식용이므로 여기에 코드를 작성하지 않습니다.
그런 다음 "Button_Play"텍스처를 열고 축이 중심에 있고 충돌 모양이 원형인지 확인합니다.
그런 다음이 텍스처로 새 유형을 만듭니다. On Step 코드에 다음을 입력하십시오.
if (ct.touch.collideUi(this)) {
ct.rooms.switch('InGame');
}
뭔가 새로운 것이 있습니다! ct.touch.collideUi (this)는 주어진 사본이 터치 되었는지 여부를 확인합니다. UI 레이어와 함께 작동합니다. 향후 프로젝트에서 게임 플레이 요소에 필요할 경우 ct.touch.collide (copy)도 있습니다. 다른 라인에서 ct.touch.collideUi는 플레이어가 버튼을 눌렀는지 확인하고 버튼을 눌렀다면 메인 룸으로 전환합니다.
새 방을 만들고 MainMenu라고 합니다. 배경을 추가하고 최근에 생성 된 복사본을 다음과 같이 레이아웃 합니다.
정확하게 사본을 배치하려면 키보드의 Alt 버튼을 누르고 있습니다.
복사본이 사라지거나 배치되지 않는 것 같으면 배경 깊이를 -20 및 -10으로 설정했는지 확인하십시오. 요소가 겹칠 수 있습니다!
이제 게임을 실행해도 메인 룸에서 시작됩니다. 이를 변경하려면 룸 탭을 열고 MainMenu 룸을 마우스 오른쪽 버튼으로 클릭합니다. 컨텍스트 메뉴에서 "시작 방으로 설정"을 선택합니다.
일시 중지 메뉴
일시 중지 메뉴의 경우 몇 개의 새 버튼과 메인 룸과 UI 위에 오버레이 될 새 룸이 필요합니다.
Button_Pause 텍스처에 대한 유형을 만듭니다. Button_Pause 텍스처의 축이 중앙에 있고 전체 텍스처를 덮는 적절한 직사각형 모양인지 확인하십시오.
Button_Pause 유형은 On Step 이벤트에 다음 코드를 포함합니다.
// If the button was pressed,
if (ct.touch.collideUi(this)) {
// Check if we don't have any rooms called 'UI_Paused'
if (ct.rooms.list['UI_Paused'].length === 0) {
// Create a room UI_Paused, put it above the current one (append it),
// and specify that it is a UI layer (isUi: true)
ct.rooms.append('UI_Paused', {
isUi: true
});
// Turns ct.delta into 0, effectively stopping the game
ct.pixiApp.ticker.speed = 0;
}
}
UI_Paused라는 이름을 기억하십시오. 나중에 이 이름으로 방을 만들어야 합니다.
ct.pixiApp.ticker.speed는 ct.delta가 계산되는 방식에 영향을 미치는 멀티 플레이어입니다. 0으로 설정하면 모든 사람의 ct.delta가 0으로 바뀌기 때문에 효과적으로 게임을 일시 중지합니다. 우리의 고양이와 타이머는 ct.delta에 의존합니다.
방 UI_InGame을 열고 생성 된 유형을 오른쪽 상단에 배치합니다.
그 후 MainMenu에 대해 생성 된 것과 유사한 두 가지 새로운 유형을 생성합니다. Button_Play 및 Pause 텍스처를 사용합니다. 하지만 버튼은 Button_Continue라고 해야 합니다.
이 버튼은 On Step 이벤트에 다음 코드를 포함합니다.
if (ct.touch.collideUi(this)) {
ct.rooms.remove(this.getRoom());
ct.pixiApp.ticker.speed = 1;
}
ct.rooms.remove (룸); 이전에 추가 된 공간을 제거합니다. 기본 항목은 제거 할 수 없지만 중첩 된 항목을 제거하기 위해 만들어집니다. this.getRoom ()은 현재 복사본을 소유 한 방을 찾습니다. ct.pixiApp.ticker.speed = 1; ct.delta를 정상 동작으로 되돌리고 게임을 일시 중지합니다.
마지막 단계는 일시 중지 해제 버튼과 장식 헤더가 있는 이 중첩 된 공간을 만드는 것입니다. UI_Paused라는 방을 만들고 Button_Continue 복사본과 "Paused"헤더를 배치합니다. 뷰포트 크기도 1080x1920으로 설정해야 합니다!
점수 화면
마지막 단계는 플레이어가 패배 한 후 표시되는 점수 화면을 만드는 것입니다. 최종 점수를 표시 할 헤더와 유형이 하나 더 필요합니다. 게임을 재생하는 버튼의 경우 Button_Play 유형을 재사용 합니다.
OhNo 텍스처로 유형을 만듭니다. 논리가 없습니다.
다른 하나 인 EndGame_ScoreCounter에는 텍스처가 전혀 없습니다. 대신 코드를 통해 텍스트 레이블을 표시합니다. 또한 플레이어의 최고 점수를 기억하고 표시합니다. 이 코드를 On Create 이벤트에 넣으십시오.
if (!('JettyCat_HighScore' in localStorage)) {
localStorage['JettyCat_HighScore'] = ct.room.score;
} else if (localStorage['JettyCat_HighScore'] < ct.room.score) {
localStorage['JettyCat_HighScore'] = ct.room.score;
}
var scoreText = 'Your score: ' + ct.room.score + '\nHighscore: ' + localStorage['JettyCat_HighScore'];
this.label = new PIXI.Text(scoreText, ct.styles.get('Orange'));
this.label.anchor.x = this.label.anchor.y = 0.5;
this.addChild(this.label);
localStorage는 브라우저에 텍스트 데이터를 저장할 수 있는 내장 객체입니다. 여기에서 자세한 내용과 진행 상황을 확인할 수 있습니다.
if (! ( 'JettyCat_HighScore'in localStorage))는 속성 JettyCat_HighScore가 localStorage 개체 내에 존재하는지 확인합니다. 저장된 데이터가 있는지 확인하는 좋은 방법입니다. 그건 그렇고, 사본, 방 및 기타 개체에서도 작동합니다.
브라우저에 이러한 레코드가 없으면 localStorage [ 'JettyCat_HighScore'] = ct.room.score; 스토리지에 기록합니다. 그렇지 않으면 다른 검사를 수행합니다. localStorage [ 'JettyCat_HighScore'] <ct.room.score는 저장된 결과가 현재 결과보다 작은 지 확인합니다. 그렇다면 만세! 플레이어는 방금 기록을 깼습니다. 레코드가 다시 업데이트 됩니다.
var scoreText = 'Your score: ' + ct.room.score + '\nHighscore: ' + localStorage['JettyCat_HighScore'];
문자열을 임시 변수에 저장합니다. var 키워드로 정의 된 모든 것은 하나의 프레임과 하나의 이벤트에 존재합니다. 그다지 목적은 없지만 더 깨끗한 코드를 작성하고 임시 변수를 재사용 할 수 있습니다. \ n 조합은 거기에 줄 바꿈이 있음을 나타냅니다. + 연산자를 사용하여 현재 점수 및 저장된 점수와 문자열을 결합합니다. 마지막으로 새 텍스트 레이블을 만들고 해당 텍스트를 생성 된 변수의 값으로 설정합니다 (new PIXI.Text (scoreText, ct.styles.get ( 'Orange'));에서 인수로 사용).
이제 생성 된 유형으로 UI_OhNo라는 방을 생성합니다.
마지막으로 필요한 것은 고양이가 장애물에 부딪 힐 때이 방을 만드는 것입니다. PotatoCat 유형을 열고 On Step 이벤트에서 표면 또는 장애물과의 충돌을 감지하는 위치를 찾으십시오. ct.camera.follow = false; 줄 바로 뒤에 다음 코드를 추가합니다.
// Wait for 1000 milliseconds (for one second)
ct.u.wait(1000)
.then(() => {
// Add a layer with "Lose" UI
ct.rooms.append('UI_OhNo', {
isUi: true
});
});
A-a-and… 따다! 훌륭해! 이 게임은 모든 기능을 갖추고 있으며 플레이 할 수 있습니다!
팁
ct.u.wait (1000)은 1 초 동안 기다린 다음 .then (() => {…}) 부분에서 주어진 코드를 실행하는 비동기 메서드입니다. "비동기"는 코드가 On Step 이벤트 외부에서 실행되고 게임에서 나중에 발생 함을 의미합니다. 비동기 작업으로 작업하는 동안 항상 구조 method (). then (() => {…})을 찾을 수 있습니다. 자바 스크립트 세계에서는 이러한 작업을 "Promise"라고도 합니다. 하지만 사용할 필요가 없는 경우 .then (() => {…})으로 부분을 생략 할 수 있습니다.
그게 다야!
전환, 파티클 효과 및 기타 멋진 기능에 대해서는 게임을 다듬는 이 튜토리얼의 두 번째 부분을 참조하십시오.
코딩에 익숙해 지도록 다음 항목을 변경해보십시오.
등록된 댓글이 없습니다.