스테이지 구분의 경우 스켈레톤 코드에 데이터 테이블은 구현이 되어있고, 게임 진행 시 스테이지 전환 관련해서는 구현되어 있지 않다. 일단은 스켈레톤 코드를 거의 건들이지 않고 연동 먼저 하고 손을 댈 생각이다.
export const moveStageHandler = (userId, payload) => {
let currentStage = getStage(userId);
if (!currentStage.length) {
return { status: "fail", message: "No stages found for user" };
}
currentStage.sort((a, b) => a.id - b.id);
const currentStageId = currentStage[currentStage.length - 1].id;
if (currentStageId !== payload.currentStage)
return { status: "fail", message: "current stage mismatch" };
// 점수 검증
const serverTime = Date.now();
const elapsedTime =
(serverTime - currentStage[currentStage.length - 1].timestamp) / 1000;
console.log(currentStage.timestamp);
console.log(elapsedTime);
// 여기부터 바뀔 부분
// 1스테이지 -> 2스테이지로 넘어가는 가정
if (elapsedTime < 100 || elapsedTime > 105) {
return { status: "fail", message: "Invalid elapsed time" };
}
const { stage } = getGameAssets();
if (!stage.data.some((stage) => stage.id === payload.targetStage))
return { status: "fail", message: "Target stage not found" };
setStage(userId, payload.targetStage, serverTime);
return { status: "success" };
};
현재 스켈레톤 코드에서는 1스테이지에서 2스테이지 넘어갈때만 점수검증을 통해 처리해주고 있다는 것을 알 수 있다.
여기에 데이터 테이블을 참고하여 각 스테이지마다 필요로 하는 점수를 확인하고 검증할 수 있는 과정을 추가하면 되겠다.
// 기존 스테이지 점수를 구함
const curStage = stage.data.find((stage) => stage.id === currentStageId);
// 다음 타켓 스테이지의 점수를 구함.
const targetStage = stage.data.find(
(stage) => stage.id === payload.targetStage
);
if (!targetStage)
return { status: "fail", message: "Target stage not found" };
// 타겟 스테이지 점수와 기존 스테이지 점수의 차이를 구함.
const intervalScore = targetStage.score - curStage.score;
// 타겟 스테이지 점수 네트워크 시간 오차범위
if (elapsedTime < intervalScore - 0.5 || elapsedTime > intervalScore + 0.5) {
return { status: "fail", message: "Invalid elapsed time" };
}
setStage(userId, payload.targetStage, serverTime);
return { status: "success", message: "Move to target stage" };
update(deltaTime) {
this.score += deltaTime * 0.001;
// 점수가 100점 이상이 될 시 서버에 메세지 전송
if (Math.floor(this.score) === 100 && this.stageChange) {
this.stageChange = false;
sendEvent(11, { currentStage: 1000, targetStage: 1001 });
}
}
현재는 하드코딩으로 100점 이상이 되었을 경우 다음 스테이지 넘어가게 이벤트를 보내고 있다. 데이터 테이블에서 정보를 받아서
각 점수마다 이벤트를 송출하도록 바꾸면 될 것 같다.
update(deltaTime) {
this.score += deltaTime * 0.001;
// 등록된 스테이지 데이터 테이블 점수 내에서만 구동
if (Math.floor(this.score) <= stageScore[stageScore.length - 1].score) {
// 다음 스테이지 조건 점수와 현재 점수가 같으면서 stageChance가 true일 때 스테이지 변경 시도
if (
Math.floor(this.score) === stageScore[this.stage + 1].score &&
this.stageChange
) {
// 프레임단위 호출이기 때문에 여러번 호출되는 것을 방지
this.stageChange = false;
// 현재 스테이지 아이디와 타겟 스테이지 아이디를 서버로 전송함
sendEvent(11, {
currentStage: stageScore[this.stage].id,
targetStage: stageScore[this.stage + 1].id,
});
// 해당 점수가 지나갈 때 stageChange가 true로 바뀌게 1초 setTimeOut 설정
setTimeout(() => {
this.stage++;
this.stageChange = true;
}, 1000);
}
}
}
파일, CDN, DB 의 방법이 있지만 서버에서 api로 fetch 하는 방향으로 설정하였다. 작업하다보면 바뀔 수 있지만 지금 당장은 fetch로...
app.get("/api/getAssets", (req, res) => {
const data = getGameAssets();
if (!data) return res.status(404).json({ message: "Not found assets" });
return res.json(data);
});
let stageScore;
async function fetchData() {
try {
const res = await fetch("/api/getAssets");
const data = await res.json();
stageScore = data.stage.data;
} catch (error) {
console.error("Error fetch:", error);
}
}
fetchData();
현재 위에서 스테이지를 변경하는 방법은 시간초에 따른 점수 획득으로 서버에 저장된 시간과 비교하여 변경되고 있다. 만약 스테이지에 따라 1초당 얻는 점수를 변경하려면 계산하는 과정과 데이터 테이블에 컬럼을 추가적으로 넣어주어야 할 것 같다.
데이터 테이블에 perSecond를 추가해주고 클라이언트 측 초당 올라가는 점수를 perSecond만큼 곱해주고, 서버측은 나눠주면 될 것 같다.
const intervalScore =
(targetStage.score - curStage.score) / curStage.perSecond;
update(deltaTime) {
this.score += deltaTime * this.perSecond * 0.001;
// 등록된 스테이지 데이터 테이블 점수 내에서만 구동
if (Math.floor(this.score) <= stageScore[stageScore.length - 1].score) {
// 다음 스테이지 조건 점수와 현재 점수가 같으면서 stageChance가 true일 때 스테이지 변경 시도
if (
Math.floor(this.score) === stageScore[this.stage + 1].score &&
this.stageChange
) {
// 프레임단위 호출이기 때문에 여러번 호출되는 것을 방지
this.stageChange = false;
// 현재 스테이지 아이디와 타겟 스테이지 아이디를 서버로 전송함
sendEvent(11, {
currentStage: stageScore[this.stage].id,
targetStage: stageScore[this.stage + 1].id,
});
// 해당 점수가 지나갈 때 stageChange가 true로 바뀌게 1초 setTimeOut 설정
setTimeout(() => {
this.stage++;
// 스테이지 증가와 동시에 초당 점수 변경
this.perSecond = stageScore[this.stage].perSecond;
this.stageChange = true;
}, 1000);
}
}
}