오늘 본격적으로 구현을 시작해 보았습니다. 일단 먼저 제공해준 게임이랑 저희가 기획한 게임의 흐름을 알아보았습니다.
먼저 랜덤 디펜스 게임으로 타워의 위치값도 랜덤이고, 몬스터도 랜덤으로 생성됩니다. 그리고 몬스터 처치시에 골드와 점수가 오르면서 해당 점수가 오를때 목표 점수에 도달시 웨이브 레벨이 상승합니다. 대략 이런 느낌인것 같습니다.
저는 여기서 필요한 맥락이 "몬스터 처치시에 점수가 오르면 목표 점수에 도달시 웨이브 레벨 상승" 인 것 같습니다. 그래서 이 기반으로 코드를 작성해 보았습니다.
유저의 현재 웨이브레벨 상승 구현
// waveHandler.js
import { getGameAssets } from '../init/assets.js';
import { setWaveLevel, getWaveLevel } from '../models/waveLevelModel.js';
import { scoreValidation } from '../utils/scoreValidation.js';
/**
*
* @param {string} uuid 해당 유저의 uuid
* @param {JSON} payload 클라이언트에서 받은 데이터
* @returns
*/
export const waveLevelIncrease = async (uuid, payload) => {
// paload는 : score, currentLevel, nextLevel
// 유저의 현재 wave 정보 불러오기
const currentWave = await getWaveLevel(uuid);
// 해당 유저의 wave 정보가 없다
if (!currentWave) {
return { status: 'fail', type: 'waveLevelIncrease', message: 'No waves found for user' };
}
// 서버 vs 클라이언트 현재 같은 waveLevel이 맞는지 체크
if (+currentWave !== payload.currentLevel) {
return { status: 'fail', type: 'waveLevelIncrease', message: 'Current wave mismatch' };
}
// nextLevel 대한 검증 <- 게임에셋에 존재하는가? 넘어갈 웨이브 정보가 없다면
const { waveLevel } = getGameAssets();
if (!waveLevel.data.some((wave) => wave.id === payload.nextLevel)) {
return { status: 'fail', type: 'waveLevelIncrease', message: 'Next wave not found' };
}
// 점수 검증
if (!(await scoreValidation(uuid, payload))) {
return { status: 'fail', type: 'waveLevelIncrease', message: 'Invalid elapsed time' };
}
// 다음 웨이브 id 추가
await setWaveLevel(uuid, payload.nextLevel);
return {
status: 'success',
type: 'waveLevelIncrease',
message: 'wave level is increment successfully',
waveLevel: payload.nextLevel,
handlerId: 31,
};
};
서버에선 여러 검증을 통해 웨이브레벨을 올려줍니다. 검증 순서에 맞게 정리해 보겠습니다.
먼저 현재 게임 웨이브 레벨을 체크합니다.
서버에서 저장된 웨이브 레벨 정보와 클라이언트의 웨이브 레벨가 일치한지를 체크합니다.
게임 데이터 테이블(게임 에셋 데이터)에 다음 웨이브 레벨 정보가 있는지 체크합니다.
서버에서 계산한 점수와 클라이언트에선 넘겨 받은 점수와 동일한지 체크합니다.
그 다음 최종적으로 서버에서 다음 웨이브 레벨 정보를 저장 후 클라이언트에게 성공 메세지와 함계 다음 웨이브 레벨 정보를 보내줍니다.
여기서 scoreValidation
함수를 이용하여 점수 검증을 진행하였습니다.
이것도 한번 같이 보겠습니다.
export const scoreValidation = async (uuid, payload) => {
const { waveLevel, monsters } = getGameAssets();
const userMonsters = await getMonsters(uuid);
let totalScore = 0;
// console.log(uuid);
// console.log('----userMonsters----', userMonsters);
// 획득한 아이템 점수를 더해 주기
for (let i = 0; i < userMonsters.length; i++) {
const monsterId = userMonsters[i].monsterId;
const monsterWaveLevel = userMonsters[i].waveLevelData;
// 게임 에셋에 있는 몬스터 정보를 가져오기
const monsterInfo = monsters.data.find((monster) => monster.id === monsterId);
totalScore += monsterInfo.score * monsterWaveLevel;
}
// 클라이언트 점수와 서버에서 계산한 점수와 동일한지 체크
// 게임데이터 wave 목표점수보다 높은지 확인
const nextWaveLevel = waveLevel.data.find((wave) => wave.id === payload.nextLevel);
if (payload.score !== totalScore || payload.score < nextWaveLevel.score) return false;
else return true;
};
이런식으로 여러 검증이 다 통과하면 클라이언트에게 다음 웨이브 레벨 데이터를 돌려주어 클라이언트는 받은 웨이브 레벨 데이터로 해당 웨이브 레벨을 적용시켜 동기화 시켜줍니다.
뭔가 클라에서 -> 서버로 가고 -> 다시 클라로 돌아오고 저번 과제할때도 그랬지만 뭔가 복잡은 한데 막상 구현하고 테스트 해보면 은근히 쉬운 기능이였던거 같습니다. 이제 추가로 팀원들과 병합을 하면서 무엇을 해야 할지 팀원분들과 상의를 해보아야겠습니다. 굿
오늘도 화이팅!