게임 일시정지 온오프 버튼과 사운드 음소거 온오프 버튼을 만든다.
버튼은 누를 때마다 2장의 스프라이트를 번갈아서 교체하는 Toggle 형식으로 만든다.
오른쪽 상단에 버튼 두 개를 만들어준다.
버튼의 스프라이트 교체는 버튼 컴포넌트의 Transition 속성으로 구현할 수도 있다.
기본 트랜지션 상태는 보다시피 4 종류밖에 제공하지 않는데, 버튼을 누를 때마다 스프라이트를 교체하는 건 이 상태들로 구현할 수 없다.
그래서 트랜지션은 NONE으로 두고서 스크립트로 조작을 한다.
@property(cc.Sprite)
pauseGameButton:cc.Sprite = null;
@property(cc.Sprite)
pauseSoundButton:cc.Sprite = null;
pauseGameSprite:cc.SpriteFrame = null;
playGameSprite:cc.SpriteFrame = null;
pauseSoundSprite:cc.SpriteFrame = null;
playSoundSprite:cc.SpriteFrame = null;
먼저 위에서 만든 버튼 두 개를 GameScene 스크립트에 링크시킨다.
스프라이트 프레임을 교체할 때마다 새로 불러오는 작업은 리소스 관리 측면에서 깔끔하지 않기 때문에
미리 4 종류의 버튼 스프라이트 프레임들을 캐싱해놓을 것이다.
스프라이트와 스프라이트 프레임은 엄연히 다른 것이다. 스프라이트는 이미지 컴포넌트의 한 종류고,
스프라이트 프레임은 스프라이트 컴포넌트에 포함되는 이미지 파일(.png) 그 자체다.
start() {
this.InitFishPool();
this.InitStatus();
this.InitRestartButton();
this.LoadResources();
AudioManager.Instance.PlayBgmSound("Bgm", true, true);
}
LoadResources()
{
var target = this;
cc.resources.load('Images/PauseGameIcon', cc.SpriteFrame, function (err:Error, spriteFrame:cc.SpriteFrame) {
cc.log(err);
if (!err)
target.pauseGameSprite = spriteFrame;
});
cc.resources.load('Images/PlayGameIcon', cc.SpriteFrame, function (err:Error, spriteFrame:cc.SpriteFrame) {
cc.log(err);
if (!err)
target.playGameSprite = spriteFrame;
});
cc.resources.load('Images/PauseSoundIcon', cc.SpriteFrame, function (err:Error, spriteFrame:cc.SpriteFrame) {
cc.log(err);
if (!err)
target.pauseSoundSprite = spriteFrame;
});
cc.resources.load('Images/PlaySoundIcon', cc.SpriteFrame, function (err:Error, spriteFrame:cc.SpriteFrame) {
cc.log(err);
if (!err)
target.playSoundSprite = spriteFrame;
});
}
onLoad 또는 start 함수에 LoadResources 함수를 추가한다.
cc.resources.load 함수를 통해 이미지 파일을 로드해서 4 종류의 버튼 스프라이트 프레임을 초기화한다.
리소스 로드 함수도 target 지정을 꼭 해줘야한다.
그냥 this.puaseGameSprite로 접근하면 이때의 this는 GameScene이 아닌 다른 무언가다.
이미지를 로드하고, 로드한 이미지를 어떤 변수에 초기화하는 작업은 순차적으로 실행될 것 같지만
전혀 그렇지 않기 때문에 코코스 크리에이터에서는 리소스 로드 함수가 콜백 함수 형식으로 구현돼있다.
자바스크립트에서 콜백 함수는 해당 함수를 호출하는 인스턴스(target)가 필요하다.
콜백 함수가 파라미터로 들어가는 코코스 API 함수들은 함수의 마지막 파라미터에 selectorTarget이 들어가거나
위 코드처럼 명시적으로 target을 지정해줘야 한다.
const {ccclass, property} = cc._decorator;
@ccclass
export default class Utility {
static LoadSpriteFrame(path:string, callback:CallableFunction)
{
cc.resources.load(path, cc.SpriteFrame, function (err:Error, spriteFrame:cc.SpriteFrame) {
cc.log(err);
if (!err)
callback(spriteFrame);
});
}
}
cc.resources.load 함수를 사용하는 반복 코드는 static 함수로 매핑시켰다.
객체를 전달받지 않고서 함수 내에서 파라미터의 value 값을 초기화하는건 자바스크립트에서 불가능하고,
콜백 함수가 리턴하는 값을 받아서 단순하게 변수에 대입하는건 undefined 에러가 발생한다.
그래서 Callback 대입 패턴을 사용했다. 이 외에 Promise 패턴도 있다고 한다.
(자세한건 https://stackoverflow.com/questions/58517713/return-value-from-callback-in-typescript 참고)
LoadResources()
{
var target = this;
Utility.LoadSpriteFrame('Images/PauseGameIcon', (frame) => { target.pauseGameSprite = frame; });
Utility.LoadSpriteFrame('Images/PlayGameIcon', (frame) => { target.playGameSprite = frame; });
Utility.LoadSpriteFrame('Images/PauseSoundIcon', (frame) => { target.pauseSoundSprite = frame; });
Utility.LoadSpriteFrame('Images/PlaySoundIcon', (frame) => { target.playSoundSprite = frame; });
}
위에서 매핑한 함수는 이렇게 사용했다. 중복되는 코드를 간소화시킬 수 있다.
pauseGame:boolean = false;
pauseSound:boolean = false;
PauseGame(on:boolean)
{
this.pauseGame = on;
this.gameOverPanel.active = this.pauseGame;
this.pauseGameButton.spriteFrame = this.pauseGame ? this.playGameSprite : this.pauseGameSprite;
this.pauseGame ? cc.director.pause() : cc.director.resume();
}
PauseSound(on:boolean)
{
this.pauseSound = on;
this.pauseSoundButton.spriteFrame = this.pauseSound ? this.playSoundSprite : this.pauseSoundSprite;
AudioManager.Instance.SetMute(this.pauseSound);
}
초기화된 4 종류의 버튼 스프라이트 프레임을 활용하는 코드다.
게임을 일시 정지하거나 해제하는 PauseGame 함수, 사운드를 음소거하거나 해제하는 PauseSound 함수다.
그리고 현재 일시정지 상태와 음소거 상태를 저장하는 boolean 변수들도 만들어준다.
PauseGameEvent()
{
this.PauseGame(!this.pauseGame);
}
PauseSoundEvent()
{
this.PauseSound(!this.pauseSound);
}
PauseGame, PauseSound 함수는 파라미터로 boolean이 들어가기 때문에
Properties 뷰에서 버튼들의 이벤트 리스트에 추가할 수 없다. 때문에 파라미터가 없는 함수들을 만들어서 대체한다.
버튼 클릭으로 실행하는 PauseGame은 오로지 상태 반전(true → false, false ← true)을 위한 함수이므로
현재 일시정지 상태, 음소거 상태를 저장하는 변수가 필요했던 것이다.
DropFish()
{
this.life--;
this.lifeLabel.string = "X" + this.life;
if(this.life == 0)
{
//this.gameOverPanel.active = true;
if (cc.sys.localStorage.getItem("best_score") < this.score)
cc.sys.localStorage.setItem("best_score", this.score);
//cc.director.pause();
this.PauseGame(true);
}
}
RestartGame()
{
this.InitStatus();
//this.gameOverPanel.active = false;
this.PauseGame(false);
this.fishPool.forEach(pool => {
pool.forEach(fish => {
if (fish.active)
fish.getComponent(Fish).RemoveFish(true);
});
});
}
PauseGame 함수를 재활용하기 위해 기존에 일시정지, 일시정지 해제하는 코드를 수정한다.
'Cocos Creator' 카테고리의 다른 글
getChildByName (0) | 2021.06.11 |
---|---|
cc.tween (0) | 2021.06.09 |
[예제 게임] GameScene #4 (오디오 매니저) (0) | 2021.06.04 |
[예제 게임] GameScene #3 (게임 일시 정지) (0) | 2021.06.03 |
[예제 게임] GameScene #2 (UI 배치, 클릭 이벤트, 스코어 갱신) (0) | 2021.06.01 |