🏃♂️달리기
Last updated
Last updated
const STATE_INIT = 3000;
const STATE_READY = 3001;
const STATE_PLAYING = 3002;
const STATE_JUDGE = 3004;
const STATE_END = 3005;
const STATE_INTRO = 3006;
let _players = App.players;
let _state = STATE_INIT;
let _start = false;
let _stateTimer = 0;
let _countDown = 10;
let _finishCountDown = false;
let _finishCount = 30;
let _finishTimer = 0;
let _delayTimer = 0;
let _playerBaseSpeed = 120;
let _rank = 1;
let _rankList = [];
//모든 플레이어가 결승점을 통과한 경우 처리
function finishCheck(){
let allPlayer = 0;
let finishedPlayer = 0;
for(let p of _players){
if(!p)
continue;
if(p.tag.isNotPlayer)
continue;
if(p.tag.isFinish)
finishedPlayer++;
allPlayer++;
}
if(finishedPlayer == allPlayer)
return true
return false;
}
//달리기 맵 설정이 정상적으로 되어있는 지 확인하고, 아닌 경우 에러메세지를 리턴한다.
function checkSetting(){
let warningMsg = '';
if (!Map.hasLocation("race_start_point")) {
warningMsg = 'race_start_point';
}
if (!Map.hasLocation("race_end_point")) {
warningMsg = 'race_end_point';
}
if (!Map.hasLocation("race_finish_point")) {
warningMsg = 'race_finish_point';
}
return warningMsg;
}
function startState(state){
_state = state;
_stateTimer = 0;
switch (state) {
case STATE_INIT:
for(let p of _players){
//달리기 앱을 실행한 유저를 확인한다.
if(p.id == App.creatorID){
if(p.isMobile)
//유저의 환경이 모바일인 경우의 위젯
p.tag.widget = p.showWidget("setting.html", "bottom", 440, 340);
else
//유저의 환경이 pc인 경우의 위젯
p.tag.widget = p.showWidget("setting.html", "middle", 440, 340);
p.tag.widget.sendMessage({
str_title : 'Run',
str_title_text1 : "A race to see who reaches the finish line the fastest",
str_title_text2 : 'Click the Start Running button to start the game',
str_title_start : "Start",
str_title_how : "How to set up a map"
});
p.tag.widget.onMessage.Add(function (sender, msg) {
//게임을 취소하는 경우, 나타난 위젯을 제거한다
if (msg.type == "cancle") {
if(p.tag.widget_warning){
p.tag.widget_warning.destroy();
p.tag.widget_warning = null;
}
if(p.tag.widget){
p.tag.widget.destroy();
p.tag.widget = null;
}
} else {
// 맵에 필요한 설정 체크
let warning = checkSetting();
if(warning !== ''){
if(p.tag.widget_warning){
p.tag.widget_warning.destroy();
p.tag.widget_warning = null;
}
if(p.isMobile)
p.tag.widget_warning = App.showWidget("warning.html", "top", 440, 60);
else
p.tag.widget_warning = App.showWidget("warning.html", "bottom", 440, 250);
p.tag.widget_warning.sendMessage({
str_warningText : 'Race track needs to be setup',
str_warningText2 : ' needed)',
str_warningText3 : 'Run',
warningMsg: warning,
})
} else {
if(p.tag.widget){
p.tag.widget.destroy();
p.tag.widget = null;
}
startState(STATE_INTRO);
_start = true;
}
}
})
}
}
break;
case STATE_INTRO:
App.showCenterLabel("\n minigame - RUN \n\n", 0xffffff, 0x000000, 120); ;
break;
case STATE_READY:
for(let p of _players){
if(p.tag.start)
continue;
//모든 플레이어가 "race_start_point" 로케이션으로 이동한다
p.spawnAtLocation("race_start_point");
p.moveSpeed = 0;
p.sendUpdated();
}
break;
case STATE_PLAYING:
App.showCenterLabel("Start!!", 0xffffff, 0x000000, 120); ;
for(let p of _players){
if(p.tag.start)
continue;
p.moveSpeed = _playerBaseSpeed;
p.sendUpdated();
}
break
// 게임 결과 처리
case STATE_JUDGE:
for(let i =0 ; i <_rankList.length; i++){
let rank = '';
if(i == 0)
rank = '1st';
else if(i == 1)
rank = '2nd';
else if(i == 2)
rank = '3rd';
else
rank = `${i + 1}th`;
//게임종료 후 등수 표시
App.sayToAll(`${rank} : ${_rankList[i].name} !`);
}
for(let p of _players){
p.moveSpeed = 80;
p.sendUpdated();
}
_start = false;
break
// 게임 종료 처리
case STATE_END:
for(let p of _players){
//게임이 종료되면 모든 플레이어는 "race_end_point" 로케이션으로 이동한다
p.spawnAtLocation("race_end_point");
if(p.tag.isNotPlayer)
p.tag.isNotPlayer = false;
}
_start = false;
break
}
}
App.onLeavePlayer.add(function(p){
_players = App.players;
p.moveSpeed = 80;
p.sendUpdated();
})
// 플레이어가 해당 맵에 들어왔을 때 처리
App.onJoinPlayer.Add(function (p) {
p.tag = {};
//게임시작 후 들어온 플레이어 처리
if (_start) {
p.tag.isNotPlayer = true;
} else {
p.tag.isNotPlayer = false;
p.tag.speedTimer = 0;
p.tag.isFinish = false;
p.tag.speedChnage = false;
p.sendUpdated();
}
//게임이 시작된 후 들어온 플레이어는 'race_end_point' 로케이션으로 이동시킨다
if(p.tag.isNotPlayer)
p.spawnAtLocation("race_end_point");
_players = App.players;
});
App.onStart.Add(function(){
startState(_state);
//"speed_set_40", "speed_set_60", "speed_set_140", "speed_set_160" 으로 지정한 로케이션을 밟으면
//2초간 해당 로케이션 이름의 숫자와 같이 플레이어의 속도가 변한다. (2초 후 플레이어의 속도는 _playerBaseSpeed 가 된다 )
//ex) "speed_set_40"를 밟으면 속도가 40으로 변함
let speed = [40,60,140,160];
for(let i =0; i<speed.length; i++){
App.addOnLocationTouched(`speed_set_${speed[i]}`, function(p){
if(_state !== STATE_PLAYING)
return;
p.moveSpeed = speed[i];
p.tag.speedTimer = 0;
p.tag.speedChnage = true;
//로케이션에 설정된 속도에 따라 "속도가 빨라졌습니다", "속도가 느려졌습니다" 등의 라벨이 해당 플레이어에게 띄워진다
let str = '';
if(i == 0)
str = 'Speed greatly reduced';
else if(i == 1)
str = 'Speed reduced';
else if(i == 2)
str = 'Speed increased';
else
str = 'Speed greatly increased';
p.showCenterLabel(`${str}`, 0xffffff, 0x000000, 120);
p.sendUpdated();
})
}
//"speed_set_random" 로케이션을 밟는 경우 플레이어의 속도가 40, 60, 140, 160 중 하나의 속도로 2초간 바뀐다 (2초 후 플레이어의 속도는 _playerBaseSpeed 가 된다 )
App.addOnLocationTouched(`speed_set_random`, function(p){
if(_state !== STATE_PLAYING)
return;
p.moveSpeed = speed[Math.floor(Math.random() * 4)];
//로케이션에 설정된 속도에 따라 "속도가 빨라졌습니다", "속도가 느려졌습니다" 등의 라벨이 해당 플레이어에게 띄워진다
let str = '';
if(p.moveSpeed == 40)
str = 'Speed greatly reduced';
else if(p.moveSpeed == 60)
str = 'Speed reduced';
else if(p.moveSpeed == 140)
str = 'Speed increased';
else
str = 'Speed greatly increased';
p.showCenterLabel(`${str}`, 0xffffff, 0x000000, 120);
p.tag.speedTimer = 0;
p.tag.speedChnage = true;
p.sendUpdated();
})
//플레이어가 결승선을 통과하는 경우
App.addOnLocationTouched("race_finish_point", function(p){
if(p.tag.isFinish)
return;
if(p.tag.isNotPlayer)
return;
_delayTimer = 0;
// 처음으로 플레이어가 결승선을 통과하는 경우 레이스 종료 카운트 다운을 시작한다(디폴트 30초)
if(!_finishCountDown)
_finishCountDown = true;
// 플레이어가 결승선을 최초에 통과한 경우를 체크한다
p.tag.isFinish = true;
_rankList.push(p);
_rank++;
})
});
App.onUpdate.Add(function(dt){
_stateTimer += dt;
if(_start){
for(let p of _players){
if(p.tag.isNotPlayer)
p.showCenterLabel("game is in progress, please wait..",0xffffff, 0x000000, 120);
}
}
switch (_state) {
case STATE_INIT:
break;
case STATE_INTRO:
if(_stateTimer >= 3){
startState(STATE_READY);
}
break;
case STATE_READY:
//출발선에서 _countDown 초(디폴트 10초) 간 레이스 카운트 다운을 시작한다
App.showCenterLabel(`${_countDown} seconds later the race will start. `,0xffffff, 0x000000, 120);
if(_stateTimer >= 1){
_stateTimer = 0;
_countDown --;
}
//카운트가 종료되면 (_countDown 가 0이 되면) 레이스가 시작된다
if(_countDown <= 0)
startState(STATE_PLAYING);
break;
case STATE_PLAYING:
for(let p of _players){
if(finishCheck() && _rankList.length == 0){
p.showCenterLabel("There is no winner",0xffffff, 0x000000, 120);
p.spawnAtLocation("race_end_point");
startState(STATE_END);
}
// else if(finishCheck())
// startState(STATE_JUDGE);
if(p.tag.isNotPlayer)
continue;
if(p.tag.speedChnage)
p.tag.speedTimer += dt;
//어떤 속도 지정 타일을 밟아도 2초 후 기본 속도(_playerBaseSpeed)로 돌아온다
if(p.tag.speedTimer >= 2 && p.tag.speedChnage){
p.moveSpeed = _playerBaseSpeed;
p.tag.speedChnage = false;
p.sendUpdated();
}
}
if(_finishCountDown)
{
_delayTimer += dt;
//플레이어가 결승선을 통과하면 1.5초간 플레이어의 이름과 레이스 카운트다운을 라벨로 나타낸다
if(_delayTimer <=1.5)
App.showCenterLabel(`${_rankList[_rankList.length -1].name} ${_rank - 1} place ! \n\n ${_finishCount} seconds later the race will end`,0xffffff, 0x000000, 120);
else
App.showCenterLabel(`${_finishCount} seconds later the race will end`,0xffffff, 0x000000, 120);
_finishTimer += dt;
if(_finishTimer >= 1){
_finishCount--;
_finishTimer = 0;
}
// 레이스 카운트다운이 종료(0초)되었거나, 모든 플레이어가 결승선을 통과한 경우, 다음 단계로 넘어간다
if(_finishCount == 0 || finishCheck()){
startState(STATE_JUDGE);
}
}
break;
case STATE_JUDGE:
//5초간 우승자(1등)의 이름을 라벨로 나타낸다
if(_stateTimer <= 5){
App.showCenterLabel(`- Winner - \n\n ${_rankList[0].name}`,0xffffff, 0x000000, 120);
}
//5초간 "잠시 후 대기실로 이동합니다"라는 라벨을 띄웁다
else if(_stateTimer > 5 && _stateTimer <= 10 ){
App.showCenterLabel("You will soon be transported to the waiting room",0xffffff, 0x000000, 120);
}
else {
startState(STATE_END);
}
break;
case STATE_END:
break;
}
});