iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 27
1
自我挑戰組

GAME30天系列 第 27

創建 (Game物件

  • 分享至 

  • xImage
  •  

今天來實作計分功能

計算分數的分數有上千百種
筆者選擇了一個簡單的計分方式
兩位玩家互相等待的時間越短, 分數越高
所以我們需要額外得到互相等待的時間
原本的等待是這麼寫

Game.prototype.waitOtherPlayer = function() {
  if ( this.isPlayerOneReady ) {
    this.isPlayerTwoReady = true
  }else {
    this.isPlayerOneReady = true
  }

  return new Promise( (resolve, reject) => {
    if ( this.waitingTimer === null ) {
      this.waitingTimer = setInterval(() => {
        console.log('keep waiting')
        console.log('playerA: ' + this.isPlayerOneReady)
        console.log('playerB: ' + this.isPlayerTwoReady)
        
        if ( this.isPlayerOneReady && this.isPlayerTwoReady ) {
          clearInterval(this.waitingTimer)
          this.waitingTimer = null
          this.isPlayerOneReady = this.isPlayerTwoReady = false 
          resolve(true)
        }
      }, 200)
    }else {
      resolve(false)
    }
  })
}

我們要新增一個回傳參數, 回傳等待的總毫秒

Game.prototype.waitOtherPlayer = function() {
  if ( this.isPlayerOneReady ) {
    this.isPlayerTwoReady = true
  }else {
    this.isPlayerOneReady = true
  }

  return new Promise( (resolve, reject) => {
    if ( this.waitingTimer === null ) {
      let delay = 200;
      let times = 0;
      let totalWaitingMs = 0;
      this.waitingTimer = setInterval(() => {
        times += 1
        totalWaitingMs = delay * times
        console.log('keep waiting, time goes: ' + totalWaitingMs)
        console.log('playerA: ' + this.isPlayerOneReady)
        console.log('playerB: ' + this.isPlayerTwoReady)
        
        if ( this.isPlayerOneReady && this.isPlayerTwoReady ) {
          clearInterval(this.waitingTimer)
          this.waitingTimer = null
          this.isPlayerOneReady = this.isPlayerTwoReady = false 
          resolve(true, totalWaitingMs)
        }
      }, delay)
    }else {
      resolve(false)
    }
  })
}

在接收玩家答案的地方計算並存入分數

answer (data) {
  ...
  ...
  GAME.waitOtherPlayer().then((isAllReady, time) => {
    
    ...
    //等待結束後, 把等待時間傳入getScore計算分數
    if (isAllReady) {
      let score = GAME.getScore(time);
      GAME.countScore(score)
      GAME.questionStep += 1
    }
  })
} 

GAME.getScore

Game.prototype.getScore = function(time) {
  // max time is 3000
  return Math.floor(10000 / Math.sqrt(time))
}

GAME.countScore

Game.prototype.countScore = function(newScore = 0) {
  let answerHis = this.answerList[this.questionStep];
  let answer = Object.keys(answerHis).map(player => answerHis[player].anser)
  
  if(answer[0] !== 'C' && answer[1] !== 'C') {
    this.score = this.score + newScore
  }   //else 沒有分數
}

最後, 我們應該在 Game over 時回傳分數

getQuestion (data) {
  try {
    ...
    ...

    let res = {
      id : data.id
    };
    if ( question ) {
      res.type = 'question'
      ...
      ...
    }else {
      res.type = 'gameOver'
      res.score = GAME.score
      console.log(`GAME.score:${GAME.score}`)
    }
    connection.send(JSON.stringify(res))

  } catch (error) {
    connection.close()
    throw error
  }
}

現在的GAME物件

//Game建構式,  遊戲房間
function Game( connection, id ) {
  this.connection = connection; //以各變數紀錄遊戲中各種狀態
  this.id = id;
  this.type = null; // 1. wait 2. play 3. over
  this.playerA = '';
  this.playerB = '';
  this.score = 0;
  this.isOver = false;
  this.isPlayerOneReady = false;
  this.isPlayerTwoReady = false;
  this.waitingTimer = null;
  this.questionStep = 0;
  this.questionList = [];
  this.answerList = [];
  setTimeout(() => {
    (this.type !== 'play') && delete Manager[this.id]
  }, 10000);  //GAME物件建立後, 一段時間沒開始遊戲就自我毀滅, 減少記憶體消耗

  return this;
}
// 加入遊戲
Game.prototype.join = function ( userName ) {
  return new Promise( (resolve, reject) => {
    let timer = null;

    if ( this.playerA !== '' ) {
      this.playerB = userName
    }else {
      this.playerA = userName
    }

    timer = setInterval(() => {
      if ( this.playerA !== '' && this.playerB !== '' ) {
        this.questionList = generateQuestionList()
        clearInterval(timer)
        resolve({
          id : this.id,
          playerA : this.playerA,
          playerB : this.playerB
        })
      }
    }, 1000)
  })
}
// 獲得題目
Game.prototype.getQuestion = function() {
  return this.questionList[this.questionStep]
}
// 儲存玩家回答
Game.prototype.setAnswerHistory = function( answer ) {
  let data = {
    questionId : answer.questionId,
    questionStep : answer.questionStep
  }
  data[answer.userName] = {
    userName : answer.userName,
    answer : answer.answer
  }
  if ( this.answerList.length !== answer.questionStep + 1 ) {
    this.answerList.push(data)
  }else {
    this.answerList[answer.questionStep][answer.userName] = {
      userName : answer.userName,
      answer : answer.answer
    }
  }
}
//等待另一位玩家
// 這個應該是GAME物件中最重要的方法
// socket連線中會有需要兩位玩家同步的時候都會用到此方法
// 例如 同時開始計時,同時公布答案
Game.prototype.waitOtherPlayer = function() {
  if ( this.isPlayerOneReady ) {
    this.isPlayerTwoReady = true
  }else {
    this.isPlayerOneReady = true
  }

  return new Promise( (resolve, reject) => {
    if ( this.waitingTimer === null ) {
      let delay = 200;
      let times = 0;
      let totalWaitingMs = 0;
      this.waitingTimer = setInterval(() => {
        times += 1
        totalWaitingMs = delay * times
        console.log('keep waiting, time goes: ' + totalWaitingMs)
        console.log('playerA: ' + this.isPlayerOneReady)
        console.log('playerB: ' + this.isPlayerTwoReady)
        
        if ( this.isPlayerOneReady && this.isPlayerTwoReady ) {
          clearInterval(this.waitingTimer)
          this.waitingTimer = null
          this.isPlayerOneReady = this.isPlayerTwoReady = false 
          resolve({
            isAllReady: true, 
            time: totalWaitingMs
          })
        }
      }, delay)
    }else {
      resolve({
        isAllReady: false
      })
    }
  })
}
//計算分數
Game.prototype.getScore = function(time) {
  // max time is 3000
  return Math.floor(10000 / Math.sqrt(time))
}

Game.prototype.countScore = function(newScore = 0) {
  let answerHis = this.answerList[this.questionStep];
  
  console.log(this.answerList);
  
  let answers = Object.keys(answerHis).map(player => answerHis[player].anser)
  
  if(answers[0] !== 'C' && answers[1] !== 'C') {
    this.score = this.score + newScore
  }   //else 沒有分數
}

上一篇
創建 (Game Manager
下一篇
創建 (排行榜
系列文
GAME30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言