欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何利用nodejs實現命令行游戲

 更新時間:2020年11月24日 09:24:26   作者:YuClyc  
這篇文章主要給大家介紹了關于如何利用nodejs實現命令行游戲的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

本文以貪吃蛇為例, 一步一步地分析如何實現一個命令行游戲.

實現原理

命令行輸入

  • 通過 process.stdin 監(jiān)聽命令行輸入的按鍵, 改變小蛇的前進的方向

畫面渲染

  • 通過 ANSI 轉義序列 擦除之前的輸出
  • 通過 process.stdout 每隔一段時間將畫面幀輸出到命令行

源碼解析

監(jiān)聽按鍵事件

使用過 yarn upgrade-interactive 命令更新 npm 依賴, 或者使用過 vue-cli 等腳手架創(chuàng)建過新項目的同學應該都見過: 這些工具會在命令行輸出很多選項, 通過上下按鍵可以移動焦點, 通過空格鍵可以選擇

那么這些操作是如何實現的呢? 下面通過 readline 和 process.stdin 來實現命令行監(jiān)聽按鍵事件:

process.stdin 是一個可讀流, 通過 readline.emitKeypressEvents 可以給可讀流注冊 keypress 事件, 通過 keypress 事件就能獲取到按鍵的值

readline.emitKeypressEvents(process.stdin) // 注冊 keypress 事件

process.stdin.setRawMode(true) // 開啟原始模式, 使輸入的每個字符帶上各種詳細屬性

process.stdin.on('keypress', (...args) => {
 console.log(args)
 // 按下方向鍵會輸出
 // [
 //  undefined,
 //  {
 //   sequence: '\u001b[A',
 //   name: 'up',
 //   ctrl: false,
 //   meta: false,
 //   shift: false,
 //   code: '[A'
 //  }
 // ]
})

注意: setRawMode 會使命令行按下 ctrl + c 不再發(fā)送終止信號, 可能需要自行處理退出邏輯

繪制幀畫面

輸出到命令行的游戲畫面默認為 30 行 x 50 列, 將其劃分為一個二維數組, 每隔一段時間將二維數組的值打印出來并擦除之前打印的值, 即完成一次幀畫面的渲染

process.stdout 是一個可寫流, 調用 process.stdout.write 可以向命令行寫入數據, nodejs 中 console.log 其實就是將數據寫入到 process.stdout 并換行

通過向命令行寫入開頭為 ANSI 轉義序列 的字符串可以 光標移動/滾動屏幕/擦除顯示/顏色文本 等等功能, 想要深入了解可以自行搜索關鍵字學習, 本文使用 ansi-escapes npm 包實現擦除功能

const ansiEscapes = require('ansi-escapes')

function clear(lines) {
 process.stdout.write(ansiEscapes.eraseLines(lines)) // 可以擦除指定行數的輸出
}

根據游戲畫面的寬高定義一個二維數組, 小蛇的頭和身體視為畫面中的點, 值為非空值, 空白畫面則為空字符串

let dots = []
for (let col = 0; col < wall.height; col++) {
 dots[col] = new Array(wall.width).fill(' ')
}

在每一幀中, 小蛇的頭會向前進的方向前進一個, 頭接著的第一節(jié)身體則會移動到上一幀頭所在的位置, 以此類推每一節(jié)身體都會移動到前一節(jié)身體的位置上, 所以需要定義一個數據記錄之前的頭和身體的位置

const SNAKE_HEAD = '@' // 頭的符號
const SNAKE_BODY = '○' // 身體的符號

function drawFrame() {
 let dots = []
 for (let col = 0; col < wall.height; col++) {
  dots[col] = new Array(wall.width).fill(' ')
 }

 let nextBody = []
 let head = next(snake.body[0]) // next 方法傳入當前點的 x, y 坐標, 返回向前進方向前進一個的 x, y 坐標
 nextBody.push(head)
 dots[head.y][head.x] = SNAKE_HEAD
 for (let i = 1; i < snake.length; i++) {
  let body = snake.body[i - 1]
  dots[body.y][body.x] = SNAKE_BODY
  nextBody.push(body)
 }
 
 screen.draw(dots) // 將二維數組中的點輸出到命令行中
 
 // 更新蛇的狀態(tài)
 snake.body = nextBody
 snake.head = snake.body[0]
}

蛇吃鳥蛋邏輯

小蛇每吃到一個鳥蛋, 身體會長一節(jié), 并在畫面中隨機生成另一個鳥蛋. 到了這一步其實就很簡單了, 隨機生成一個點作為鳥蛋的位置, 插入到之前的二維數組中.

function layAEgg() {
 let x = ~~(wall.width * Math.random())
 let y = ~~(wall.height * Math.random())
 return { x, y }
}

當小蛇的頭的位置與鳥蛋的位置相同時, 則視為蛇吃到鳥蛋, 蛇的長度加一, 并在尾部增加一節(jié)上一幀蛇尾的節(jié)點位置

const SNAKE_HEAD = '@'
const SNAKE_BODY = '○'
const BIRD_EGG = '●'

function drawFrame() {
 let dots = []
 for (let col = 0; col < wall.height; col++) {
  dots[col] = new Array(wall.width).fill(' ')
 }

 let nextBody = []
 let head = next(snake.body[0])
 nextBody.push(head)
 dots[head.y][head.x] = SNAKE_HEAD
 for (let i = 1; i < snake.length; i++) {
  let body = snake.body[i - 1]
  dots[body.y][body.x] = SNAKE_BODY
  nextBody.push(body)
 }

 // 判斷蛇頭位置在上一幀中是否為鳥蛋位置, 為真視為蛇吃到鳥蛋
 if (prevDots && prevDots[head.y][head.x] === BIRD_EGG) {
  let body = snake.body[snake.length - 1]
  dots[body.y][body.x] = SNAKE_BODY
  nextBody.push(body)
  snake.length += 1
  egg = null
  prevDots = null
 }

 if (!egg) {
  egg = layAEgg()
  while (dots[egg.y][egg.x] !== ' ') {
   egg = layAEgg()
  }
 }
 dots[egg.y][egg.x] = BIRD_EGG

 prevDots = dots // 保存上一幀的數據, 用于下次繪制時判斷邏輯

 screen.draw(dots)
 snake.body = nextBody
 snake.head = snake.body[0]
}

總結

至此, 命令行貪吃蛇游戲基本邏輯都已實現, 剩下的就是使用定時器每隔一段時間繪制一次幀畫面. 其實幾乎任何像素游戲(如俄羅斯方塊/吃豆人等)都可以按照這個流程實現, 不同的只是幀畫面的處理邏輯而已. 如果感興趣的話, 可以去我的 github 查看該 貪吃蛇游戲源碼

到此這篇關于如何利用nodejs實現命令行游戲的文章就介紹到這了,更多相關nodejs實現命令行游戲內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • node的process以及child_process模塊學習筆記

    node的process以及child_process模塊學習筆記

    這篇文章主要介紹了node的process以及child_process模塊學習筆記,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Nodejs+Socket.io實現通訊實例代碼

    Nodejs+Socket.io實現通訊實例代碼

    本篇文章主要介紹了Nodejs+Socket.io實現通訊實例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-02-02
  • nodejs個人博客開發(fā)第六步 數據分頁

    nodejs個人博客開發(fā)第六步 數據分頁

    這篇文章主要為大家詳細介紹了nodejs個人博客開發(fā)的數據分頁,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • node.js如何根據URL返回指定的圖片詳解

    node.js如何根據URL返回指定的圖片詳解

    這篇文章主要介紹了NODE.JS如何根據URL返回指定的圖片詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-10-10
  • 前端面試之輸入npm?run后執(zhí)行原理

    前端面試之輸入npm?run后執(zhí)行原理

    這篇文章主要為大家介紹了前端面試之輸入npm?run后發(fā)生了什么及執(zhí)行原理解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • docker中編譯nodejs并使用nginx啟動

    docker中編譯nodejs并使用nginx啟動

    這篇文章主要介紹了docker中編譯nodejs并使用nginx啟動的相關資料,需要的朋友可以參考下
    2017-06-06
  • nodejs微信開發(fā)之授權登錄+獲取用戶信息

    nodejs微信開發(fā)之授權登錄+獲取用戶信息

    這篇文章主要介紹了nodejs微信開發(fā)之授權登錄+獲取用戶信息,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03
  • Node.js中.pfx后綴文件的處理方法

    Node.js中.pfx后綴文件的處理方法

    這篇文章主要介紹了Node.js中.pfx后綴文件的處理方法,文中介紹的很詳細,對大家具有一定的參考價值,需要的朋友們下面來一起看看吧。
    2017-03-03
  • gulp加批處理(.bat)實現ng多應用一鍵自動化構建

    gulp加批處理(.bat)實現ng多應用一鍵自動化構建

    這篇文章主要給大家介紹了利用gulp加上批處理(.bat)實現ng多應用一鍵自動化構建的相關資料,文中介紹的很詳細,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-02-02
  • 提高NodeJS中SSL服務的性能

    提高NodeJS中SSL服務的性能

    盡管OpenSSL露出驚天漏洞,但是基于SSL的加密協(xié)議還是應用得最廣泛的,這只是OpenSSL這個開源軟件本身的問題(詳情: OpenSSL是坑貨寫的),下面這篇文章提供了一些如何在NodeJS中,提高HTTPS性能方面的技巧
    2014-07-07

最新評論