小遊戲之還原Egert、Laya雪碧圖資源-nodejs

minh8023發表於2020-04-07

我想搞個小遊戲

突然來了興致想搞個小遊戲玩玩。去B站學習如何做個小遊戲。UP主說:讓我們把準備好的資源拷貝到資料夾裡....B站視訊戳這裡

???準備好的資源在哪裡???

不可細說

我們只是拿素材同步B站的學習。如何解包網上有大把的教程了,解包後拿到素材資源。一般都是合併後的圖。前端叫做雪碧圖,幾個遊戲引擎叫法都不一樣,不過不影響我們學習。

分析雪碧圖資源

解壓素材資源後一般都是一張雪碧圖對應一個json的檔案,json檔案內包含了這個雪碧圖詳細的資源。

laya的圖集會對應一個.atlas的檔案資源,cocos creatoregert對應的直接就是json檔案。在這裡,可能是我見的包比較少,暫時分析是這樣的。

// 大致類似這種
"loading_z1":{"x":1,"y":94,"w":310,"h":62,"offX":0,"offY":0,"sourceW":310,"sourceH":62}
// 還有這種
"FRIENDS.png": {
  "frame": { "h": 36, "idx": 0, "w": 156, "x": 1181, "y": 1356 },
  "sourceSize": { "h": 36, "w": 156 },
  "spriteSourceSize": { "x": 0, "y": 0 }
}
// cocos creator 做的比較好...不像給人類看的
複製程式碼

NodeJs真是個神奇的寶寶

我拿到合併素材的後就找認識的設計師。來給我切開...設計師:???這啥。

還是找最可靠的寶寶吧,切個圖而已nodejs寶寶都會的。常用的圖片處理的的庫就有GMIM。實際上可用的庫,看你網路吧。我是滿腦子已經騷操作了,然後這兩個庫一個裝不上,404了。後選擇了node-images,擼起袖子就是幹程式碼。

/*
 * @description CropSprite
 * @author minh8023 <https://github.com/minh8023>
 */
const images = require("images") // 用的node-images庫
const stripJsonComments = require('strip-json-comments')
const fs = require('fs')
const filePath = './src', outPath = './dist'
function getJson(name) {
  let pagesJson = {}
  console.time(`讀取【${name}】耗時`)
  try {
    // Egert
    pagesJson = JSON.parse(stripJsonComments(fs.readFileSync(`${filePath}/${name}.json`, 'utf8')))
  } catch (error) {
    // laya
    pagesJson = JSON.parse(stripJsonComments(fs.readFileSync(`${filePath}/${name}.atlas`, 'utf8')))
  }
  const key = Object.keys(pagesJson.frames)
  const values =  Object.values(pagesJson.frames)
  return Array.from(key, (item, index)=> {
    return {
      name: item,
      ...values[index]
    }
  })
}
/**
 * 裁剪圖片
 */
function cropSprite(arr, name) {
  const img = images(`${filePath}/${name}.png`)
  console.timeEnd(`讀取【${name}】耗時`)
  const path = `${outPath}/${name}`
  if (!fs.existsSync(outPath)) fs.mkdirSync(outPath)
  if (!fs.existsSync(path)) fs.mkdirSync(`${outPath}/${name}`)
  console.time(`裁剪【${name}】耗時`)
  arr.map((item) => {
    if (item.spriteSourceSize) {
      cropLaya(img, item, name)
    } else {
      cropEgert(img, item, name)
    }
  })
  console.timeEnd(`裁剪【${name}】耗時`)
}
/**
 * 裁剪laya的圖
 */
function cropLaya (img, ele, name) {
  const res = images(img, ele.frame.x, ele.frame.y, ele.frame.w, ele.frame.h)
  images(ele.sourceSize.w, ele.sourceSize.h)
  .draw(res, ele.spriteSourceSize.x, ele.spriteSourceSize.y)
  .save(`${outPath}/${name}/${ele.name}`)
}
/**
 * 裁剪Egert的圖
 */
function cropEgert (img, ele, name) {
  const res = images(img, ele.x, ele.y, ele.w, ele.h) // 先剪裁出來
  images(ele.sourceW, ele.sourceH) // 新建實際大小空白圖
  .draw(res, ele.offX, ele.offY) // 把剪裁出來的圖畫上去
  .save(`${outPath}/${name}/${ele.name}.png`) // 存圖
}
const argv = process.argv.slice(2)
argv.map((name) => {
  cropSprite(getJson(name), name)
})
// node index.js loading_res ui
// 讀取【loading_res】耗時: 2.075ms
// 裁剪【loading_res】耗時: 16.134ms
// 讀取【ui】耗時: 22.990ms
// 裁剪【ui】耗時: 244.103ms
複製程式碼

大致寫了這麼一個js來處理,這裡沒寫cocos的,其實差不多,不過cocos的資源名稱沒那麼好找...

整體程式碼放到git上了,可以戳這裡

這裡還有個插曲node-images有個bug,還有點不知道咋描述了...參考issues修復

寫在最後

可能是我的錯覺?node-images切出來的圖好像沒那麼清晰了,不過不耽誤我學習。

有了素材資源,我們就能跟上課程學習了...

相關文章