小游戏之还原Egert、Laya雪碧图资源-nodejs

1,436 阅读2分钟

我想搞个小游戏

突然来了兴致想搞个小游戏玩玩。去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切出来的图好像没那么清晰了,不过不耽误我学习。

有了素材资源,我们就能跟上课程学习了...