diff --git a/src/pages/games/SnackGame/game/screen/BizGameScreen.ts b/src/pages/games/SnackGame/game/screen/BizGameScreen.ts index 4e1d2af..09e61c5 100644 --- a/src/pages/games/SnackGame/game/screen/BizGameScreen.ts +++ b/src/pages/games/SnackGame/game/screen/BizGameScreen.ts @@ -14,6 +14,7 @@ import { SettingsPopup } from '../popup/SettingPopup'; import { Snack } from '../snackGame/Snack'; import { SnackGame, SnackGameOnPopData } from '../snackGame/SnackGame'; import { + SNACK_TYPE, SnackGameMode, Streak, snackGameGetConfig, @@ -95,7 +96,7 @@ export class BizGameScreen extends Container implements AppScreen { let isGolden = false; const streak = data.reduce((acc: Streak, snack) => { - if (snack.type === 2) isGolden = true; + if (snack.type === SNACK_TYPE.GOLDEN) isGolden = true; const { row: y, column: x } = snack.getGridPosition(); acc.push({ x, y }); diff --git a/src/pages/games/SnackGame/game/screen/GameScreen.ts b/src/pages/games/SnackGame/game/screen/GameScreen.ts index 90c0f24..60816d3 100644 --- a/src/pages/games/SnackGame/game/screen/GameScreen.ts +++ b/src/pages/games/SnackGame/game/screen/GameScreen.ts @@ -12,6 +12,7 @@ import { SettingsPopup } from '../popup/SettingPopup'; import { Snack } from '../snackGame/Snack'; import { SnackGame, SnackGameOnPopData } from '../snackGame/SnackGame'; import { + SNACK_TYPE, SnackGameMode, SnackGamePosition, Streak, @@ -100,7 +101,7 @@ export class GameScreen extends Container implements AppScreen { const occurredAt = new Date().toISOString(); const streak = data.reduce((acc: Streak, snack) => { - if (snack.type === 2) isGolden = true; + if (snack.type === SNACK_TYPE.GOLDEN) isGolden = true; const { row: y, column: x } = snack.getGridPosition(); acc.push({ x, y }); @@ -118,7 +119,7 @@ export class GameScreen extends Container implements AppScreen { let isGolden = false; data.forEach((snack) => { - if (snack.type === 2) isGolden = true; + if (snack.type === SNACK_TYPE.GOLDEN) isGolden = true; }); return this.itemHandlers.bomb(position, isGolden); diff --git a/src/pages/games/SnackGame/game/snackGame/Snack.ts b/src/pages/games/SnackGame/game/snackGame/Snack.ts index 7e98ae6..1ed5575 100644 --- a/src/pages/games/SnackGame/game/snackGame/Snack.ts +++ b/src/pages/games/SnackGame/game/snackGame/Snack.ts @@ -1,7 +1,7 @@ import gsap from 'gsap'; import { Container, Sprite, Texture } from 'pixi.js'; -import { SnackGamePosition } from './SnackGameUtil'; +import { SNACK_TYPE, SnackGamePosition, SnackType } from './SnackGameUtil'; import { Label } from '../ui/Label'; import { resolveAndKillTweens, @@ -14,7 +14,7 @@ const defaultSnackOptions = { /** 텍스처 선택을 위한 스낵 이름 */ name: '', /** 그리드 내부의 스낵 타입 */ - type: 0, + type: SNACK_TYPE.EMPTY as SnackType, /** 넓이와 높이 사이즈 */ size: 50, /** 스낵 숫자 */ @@ -42,7 +42,7 @@ export class Snack extends Container { /** 스낵의 열 인덱스 */ public column = 0; /** 그리드 내부의 스낵 타입 */ - public type = 0; + public type: SnackType = SNACK_TYPE.EMPTY; /** 텍스처 선택을 위한 스낵 이름 */ public name = ''; /** 스낵이 가진 숫자 */ diff --git a/src/pages/games/SnackGame/game/snackGame/SnackGameAction.ts b/src/pages/games/SnackGame/game/snackGame/SnackGameAction.ts index 060c353..8e42ded 100644 --- a/src/pages/games/SnackGame/game/snackGame/SnackGameAction.ts +++ b/src/pages/games/SnackGame/game/snackGame/SnackGameAction.ts @@ -1,7 +1,7 @@ import { ItemType } from '@utils/types/item.type'; import { SnackGame } from './SnackGame'; -import { SnackGamePosition } from './SnackGameUtil'; +import { SNACK_TYPE, SnackGamePosition } from './SnackGameUtil'; import { sfx } from '../util/audio'; import { HapticFeedback } from '../util/hapticFeedback'; @@ -46,7 +46,7 @@ export class SnackGameActions { if ( this.snackGame.board .getSelectedSnacks() - .some((snack) => snack.type === 2) + .some((snack) => snack.type === SNACK_TYPE.GOLDEN) ) { this.snackGame.board.reset(); this.snackGame.board.setup(this.snackGame.config, session!.board); @@ -77,7 +77,9 @@ export class SnackGameActions { const session = await this.snackGame.board.popAllSelectedSnacks(position); if ( - this.snackGame.board.getSelectedSnacks().some((snack) => snack.type === 2) + this.snackGame.board + .getSelectedSnacks() + .some((snack) => snack.type === SNACK_TYPE.GOLDEN) ) { this.snackGame.board.reset(); this.snackGame.board.setup(this.snackGame.config, session!.board); diff --git a/src/pages/games/SnackGame/game/snackGame/SnackGameBoard.ts b/src/pages/games/SnackGame/game/snackGame/SnackGameBoard.ts index 1638714..945fd9d 100644 --- a/src/pages/games/SnackGame/game/snackGame/SnackGameBoard.ts +++ b/src/pages/games/SnackGame/game/snackGame/SnackGameBoard.ts @@ -8,9 +8,9 @@ import { SnackGame } from './SnackGame'; import { SnackGamePosition, SnackGameConfig, - snackGameGetSnack, SnackGameGrid, - SnackType, + SNACK_TYPE, + getSnackAssets, snackGameGetSnackType, snackGameSetPieceType, snackGameCreateGrid, @@ -36,10 +36,8 @@ export class SnackGameBoard { public columns = 0; /** 각 보드 슬롯의 크기 (너비 및 높이) */ public tileSize = 0; - /** 게임에 사용 가능한 일반 유형 목록 */ - public commonTypes: SnackType[] = []; /** 스낵 유형을 스낵 이름에 매핑 */ - public typesMap!: Record; + public typesMap: Record | null = null; /** 선택된 Snack 스택 */ public selectedSnacks: Snack[] = []; @@ -71,19 +69,9 @@ export class SnackGameBoard { this.snacksMask.height = this.getHeight(); this.snacksContainer.visible = true; - // 게임에서 사용될 스낵 타입 배열 - const snacks = snackGameGetSnack(config.mode); - - if (!this.commonTypes.length) { - this.typesMap = {}; - - for (let i = 0; i < snacks.length; i++) { - const name = snacks[i]; - const type = i + 1; - - this.commonTypes.push(type); - this.typesMap[type] = name; - } + // 게임 모드에 맞는 스낵 타입-에셋 매핑 설정 + if (!this.typesMap) { + this.typesMap = getSnackAssets(config.mode); } // 초기 격자 상태 생성 @@ -115,8 +103,8 @@ export class SnackGameBoard { * @param snackType 새 스낵의 유형 */ public createSnack(position: SnackGamePosition, snackInfo: SnackResponse) { - const type = snackInfo.golden ? 2 : 1; - const name = this.typesMap[type]; + const type = snackInfo.golden ? SNACK_TYPE.GOLDEN : SNACK_TYPE.NORMAL; + const name = this.typesMap![type]; const snack = pool.get(Snack); const viewPosition = this.getViewPositionByGridPosition(position); snack.onTap = (position) => this.snackGame.actions.actionTap(position); @@ -162,7 +150,7 @@ export class SnackGameBoard { // const combo = this.snackGame.process.getProcessRound(); // 그리드의 해당 위치에 있는 스낵을 0으로 설정하고 보드에서 팝 - snackGameSetPieceType(this.grid, position, 0); + snackGameSetPieceType(this.grid, position, SNACK_TYPE.EMPTY); const popData = { snack, type }; this.snackGame.stats.registerPop(popData); this.snackGame.onPop?.(popData); diff --git a/src/pages/games/SnackGame/game/snackGame/SnackGameUtil.ts b/src/pages/games/SnackGame/game/snackGame/SnackGameUtil.ts index 0ee464d..b9112ed 100644 --- a/src/pages/games/SnackGame/game/snackGame/SnackGameUtil.ts +++ b/src/pages/games/SnackGame/game/snackGame/SnackGameUtil.ts @@ -1,7 +1,12 @@ import { SnackResponse } from '../game.type'; -/** 각 그리드 내부 스낵 타입 */ -export type SnackType = number; // TODO: 타입 안정성과 가독성을 위해 새로운 타입으로 정의 +/** 각 그리드 내부 스낵 타입 상수 */ +export const SNACK_TYPE = { + EMPTY: 0, + NORMAL: 1, + GOLDEN: 2, +} as const; +export type SnackType = (typeof SNACK_TYPE)[keyof typeof SNACK_TYPE]; /** 스낵게임 board를 표현하는 2차원 배열 타입 */ export type SnackGameGrid = SnackType[][]; @@ -23,14 +28,22 @@ export const snackGameModes = ['default', 'inf'] as const; /** 게임 모드 타입 */ export type SnackGameMode = (typeof snackGameModes)[number]; -/** 각 게임 모드에 사용되는 snack 타입 배열 */ -const snacks: Record = { - /** 기본 모드 */ - default: ['snack', 'golden_snack'], - /** 무한 모드 */ - inf: ['snack'], +/** 각 게임 모드에 사용되는 스낵 타입-에셋 매핑 */ +const snackAssetsByMode: Record>> = { + default: { + [SNACK_TYPE.NORMAL]: 'snack', + [SNACK_TYPE.GOLDEN]: 'golden_snack', + }, + inf: { + [SNACK_TYPE.NORMAL]: 'snack', + }, }; +/** 게임 모드별 스낵 타입-에셋 매핑을 반환 */ +export function getSnackAssets(mode: SnackGameMode): Record { + return snackAssetsByMode[mode] as Record; +} + /** 스낵게임 기본 설정 */ export const defaultConfig = { /** 게임의 row 개수 */ @@ -55,11 +68,6 @@ export function snackGameGetConfig( return { ...defaultConfig, ...customConfig }; } -/** 스낵게임에 필요한 스낵들을 모드 기준으로 구별해 반환합니다. */ -export function snackGameGetSnack(mode: SnackGameMode): string[] { - return [...snacks[mode]]; -} - /** * 주어진 스낵 타입을 바탕으로 2차원 배열 그리드를 생성합니다. * 기믹을 가진 요소는 초기 실행 시 생성될 랜덤한 index를 초기화 합니다. @@ -76,10 +84,12 @@ export function snackGameCreateGrid( const grid: SnackGameGrid = []; for (let r = 0; r < rows; r++) { - const types = []; + const types: SnackType[] = []; for (let c = 0; c < columns; c++) { - const currentType = board[r][c].golden ? 2 : 1; + const currentType = board[r][c].golden + ? SNACK_TYPE.GOLDEN + : SNACK_TYPE.NORMAL; types.push(currentType); } @@ -127,7 +137,7 @@ export function snackGameGetSnackType( export function snackGameSetPieceType( grid: SnackGameGrid, position: SnackGamePosition, - type: number, + type: SnackType, ) { grid[position.row][position.column] = type; }