스테이지에 따라 아이템이 생성, 아이템 획득 시 점수 획득, 아이템 별 획득 점수 구분 3가지의 기능을 구현하였습니다. 정말 막상해보면 작성한걸 보면 간단한 코드들이였는데 생각하고 또 생각하고 멍떄리면서 생각하는 시간이 너무 오래걸렸습니다. 젠장..
일단 스테이지에 따라 아이템이 생성은 클라이언트 먼저 만져 주었습니다.
아이템이 생성되는 시점을 찾아보면서 생성하는 함수를 발견! 수정해 주었습니다.
ItemController.js파일의 createItem 함수 였습니다.
createItem(currentStage) {
const unlockInfo = this.itemUnlock.find((unlockInfo) => unlockInfo.stage_id === currentStage);
const index = this.getRandomNumber(
unlockInfo.item_id[0] - 1,
unlockInfo.item_id[unlockInfo.item_id.length - 1] - 1,
);
const itemInfo = this.itemImages[index];
const x = this.canvas.width * 1.5;
const y = this.getRandomNumber(10, this.canvas.height - itemInfo.height);
// 본격 아이템 생성
const item = new Item(this.ctx, itemInfo.id, x, y, itemInfo.width, itemInfo.height, itemInfo.image);
this.items.push(item);
}
먼저 itemUnlock의 게임데이터가 담긴 변수를 이용해서 스테이지마다 생성할 아이템 id를 찾습니다. 그리고 getRandomNumber(min, max) 라는 함수를 이용해서 랜덤으로 생성할 id를 찾아 생성하게 하였습니다.
{
"name": "item_unlock",
"version": "1.0.0",
"data": [
{ "id": 101, "stage_id": 1000, "item_id": [1] },
{ "id": 201, "stage_id": 1001, "item_id": [1, 2] },
{ "id": 301, "stage_id": 1002, "item_id": [2, 3] },
{ "id": 401, "stage_id": 1003, "item_id": [2, 3, 4] },
{ "id": 501, "stage_id": 1004, "item_id": [3, 4] },
{ "id": 601, "stage_id": 1005, "item_id": [3, 4, 5] },
{ "id": 701, "stage_id": 1006, "item_id": [4, 5, 6] }
]
}
이것 또한 아이템획득시 점수 획득 또 프론트엔드에서 찾아보았습니다. 발견!
Score.js에서 getItem이라는 함수를 찾았습니다. 프론트에서 아이템을 얻을때 실행되는 함수 입니다. 또 수정해 주었습니다.
getItem(itemId) {
const item = itemAssetData.data.find((item) => item.id === itemId); // 해당 아이템 점수 찾기
sendEvent(12, { item: itemId, itemScore: item.score, currentStage: this.currentStageId });
this.score += item.score; // 해당 아이템 점수 획득
}
해당하는 아이템의 정보가 담긴 itemAssetData에서 해당 데이터를 찾고 item변수에 할당해주었습니다.
{
"name": "item",
"version": "1.0.0",
"data": [
{ "id": 1, "score": 2, "width": 50, "height": 50, "image": "images/items/pokeball_red.png" },
{ "id": 2, "score": 5, "width": 50, "height": 50, "image": "images/items/pokeball_yellow.png" },
{ "id": 3, "score": 7, "width": 50, "height": 50, "image": "images/items/pokeball_purple.png" },
{ "id": 4, "score": 8, "width": 50, "height": 50, "image": "images/items/pokeball_cyan.png" },
{ "id": 5, "score": 9, "width": 50, "height": 50, "image": "images/items/pokeball_orange.png" },
{ "id": 6, "score": 10, "width": 50, "height": 50, "image": "images/items/pokeball_pink.png" }
]
}
지금까지는 클라이언트의 점수만 건드렸다면 서버에서도 아이템을 획득할때 저장을 해야합니다. 저번에 스테이지 정보를 저장한 것처럼 아이템을 저장할 모델링을 새로 만들어 줍니다.
item.model.js을 만들어 주었습니다.
// 유저마다 획득한 아이템을 담을 객체
const items = {};
// 시작시 해당유저 아이템 박스 초기화
export const createItem = (uuid) => {
items[uuid] = [];
};
// 현재 플레이가 획득한 아이템을 불러오는 함수
export const getItems = (uuid) => {
return items[uuid];
};
// 아이템 획득시 등록하는 함수
// timestamp는 획득한 시간을 저장한다
export const addItem = (uuid, itemId, timestamp) => {
const isItem = items[uuid].find((item) => item.itemId === itemId);
if (isItem) {
isItem.timestamp = timestamp; // 이게 바로되네 배열이라 주소를 참조해서 되는건가보네
isItem.count += 1;
} else {
items[uuid].push({ itemId, timestamp, count: 1 });
}
};
그후 이제는 저번에 스테이지 넘어가는 구간에 점수를 점검하는 부분을 수정해 주어야 합니다.
기존에는 스테이지의 점수만을 더해주어 비교했다면 지금은 획득한 아이템의 점수도 함산하여 비교해 주어야 합니다.
그래서 저번에 만든 score.validation.js 파일의 scoreValidation함수를 수정해 주었습니다.
import { getGameAssets } from '../init/assets.js';
export const scoreValidation = (serverTime, userStages, targetStageId, userItems) => {
const errorScope = 3; // 오차 범위
const { stages, items } = getGameAssets();
let totalScore = 0;
// 점수검증에서 1스테이지 점수 와 2스테이지 점수 + 3스테이지 점수 등을 나누어 더해주었을때 오차 범위가 5인 약간 이러한 형태로 가야될것같다
// 현재로는 일단 1스테이지 점수는 현재 플레이어의 총 스테이지만큼 반복문을 돌고 각 스테이지의 점수를 더해서 총 점수를 가져오고 그점수를 오차범위에 들어오는지 비교하여 확인하기
for (let i = 0; i < userStages.length; i++) {
// 각 스테이지 구간에서 점수를 구한다.
const stageEndTime = i === userStages.length - 1 ? serverTime : userStages[i + 1].timestamp; // 마지막 인덱스와 일치하면 즉 현재 스테이지면 현재 시간 serverTime을 할당 그외에는 바로 다음 스테이지 시작시간 즉 해당스테이지의 EndTime
const elapsedTime = (stageEndTime - userStages[i].timestamp) / 1000; // 각 스테이지 마다의 경과한 시간을 구합니다.
// console.log('--------elapsedTime--------', elapsedTime);
const stageScore = elapsedTime * stages.data[i].scorePerSecond; // 경과한 시간에 데이터 테이블의 초당 점수를 곱해줍니다.
// console.log('-------stageScore---------', stageScore);
totalScore += stageScore;
}
// 획득한 아이템 점수를 더해 주기
for (let i = 0; i < userItems.length; i++) {
const itemId = userItems[i].itemId;
const userItemInfo = userItems.find((item) => item.itemId === itemId);
const itemInfo = items.data.find((item) => item.id === itemId);
const itemTotalScore = itemInfo.score * userItemInfo.count;
totalScore += itemTotalScore;
}
// console.log('-------totalScore---------', totalScore);
const targetStage = stages.data.find((stage) => stage.id === targetStageId);
const itemInfo = items.data.find((item) => item.id === userItems[userItems.length - 1].itemId); // 가장 최고점의 아이템 점수 가져와서 오차범위 더해주기
const errorScopeResult = Math.abs(targetStage.score - totalScore);
if (errorScopeResult > errorScope + itemInfo.score) return false;
else return true;
};
// 획득한 아이템 점수를 더해 주기
for (let i = 0; i < userItems.length; i++) {
const itemId = userItems[i].itemId;
const userItemInfo = userItems.find((item) => item.itemId === itemId);
const itemInfo = items.data.find((item) => item.id === itemId);
const itemTotalScore = itemInfo.score * userItemInfo.count;
totalScore += itemTotalScore;
}
// console.log('-------totalScore---------', totalScore);
const targetStage = stages.data.find((stage) => stage.id === targetStageId);
const itemInfo = items.data.find((item) => item.id === userItems[userItems.length - 1].itemId); // 가장 최고점의 아이템 점수 가져와서 오차범위 더해주기
const errorScopeResult = Math.abs(targetStage.score - totalScore);
if (errorScopeResult > errorScope + itemInfo.score) return false;
else return true;
해당 아이템의 점수들을 합산하여 마지막에 오차범위를 비교하여 점수를 검정하는 로직으로 작성하였습니다. 여기서 오차범위 이상의 아이템 점수를 획득하여 값을 비교할 수 없을때가 있을 수 있어 아이템 점수 중 가장 높은 점수를 더 해주어 작성해 주었습니다.
그러고 현재 잘 작동되는 것을 보실 수 있습니다.
제공해준 코드의 흐름이 어느정도 파악이 되고 나서는 무엇을 작성하고 어떻게 동작하는지 예상이 되면서 코드 작성이 좀 더 편해졌던거 같습니다. 코드 하나하나 보는 것도 좋지만 큰틀로 보고 예상한 값이 맞는지를 console.log로 막 찍어 보면서 값을 직접 확인해 보는 방법으로 좀 더 빠르게 흐름이 이해가 되더라구요. 좋았습니다.
그리고 요즘 감기 기운도 좀 생기면서 집중이 잘 안되더라구요. 컨디션이 공부할때 영향을 많이 미칠줄 잘 몰랐는데 요즘들어 공부는 체력전인 것 같더라구요. 하핫 그런의미에서 운동도 다시 시작해야겠다는 다짐을 하면서 오늘은 여기까지 작성해 보겠습니다.
그럼 오늘도 화이팅!