使用 Pixi.js 插件实现探险者小游戏(一)

什么是 Pixi

Pixi 是一个非常快的 2D sprite 渲染引擎。使用它你可以轻松的利用 JavaScript 和其他 HTML5 技术制作游戏和应用程序。
Pixi 的官网地址:https://pixijs.com/
本游戏使用的是 Pixi 的 V4.5.5 版本,官网最新版本更新到了 V8.x,两个版本 API 相差很大,建议大家学习最新版本。从 github 官网上下载 V4.5.5 版本:https://github.com/pixijs/pixijs/releases

安装 Pixi

Pixi.js V4.x 不支持 npm 安装,我们从 github 上下载下来后直接通过 script 标签引入。

<script src="./public/pixi.4.5.5.min.js"></script>

创建应用和舞台 stage

首先,我们使用 Pixi 的 Application 对象创建一个矩形显示区域,它会自动生成一个 HTML <canvas> 元素;接着,我们把应用的视图插入到 DOM 中。初始化应用时可以设置很多属性,在这里我们只配置展示区域大小和背景色。

// 创建PIXI应用
const app = new PIXI.Application({
  width: 600,
  height: 600,
  forceWebGL: true, // 强制使用WebGL,默认是false,设置为true,强制使用WebGL
  backgroundColor: 0x1099bb, // 背景颜色,默认是0x000000,设置为0x1099bb,背景颜色为蓝色
})

// 把应用视图插入到DOM中。
document.getElementById('app').appendChild(app.view)

由于 PIXI 的方法和属性调用太深了,使用时不太方便,我们可以使用别名来简化方法和属性调用。后面代码中我们见到的以下划线开头的变量都是重新定义的。

const _Application = PIXI.Application
const _Sprite = PIXI.Sprite
const _Texture = PIXI.Texture
const _TextureCache = PIXI.utils.TextureCache
const _loader = PIXI.loader
const _utils = PIXI.utils
const _resources = PIXI.loader.resources
const _Rectangle = PIXI.Rectangle
const _Text = PIXI.Text

我们可以通过应用实例访问舞台对象,const _stage = app.stage,stage(舞台)是 Pixi 中一个特殊的根容器,所有要展示在<canvas>上的元素(图片、文字)都要装进 stage 里才能展示。调用 _stage.addChild 方法添加元素。

创建 sprite 精灵与纹理缓存

在 PIXI 中,图像被称为 sprite(精灵),它是一种特殊的图像对象。我们可以控制它们的位置、大小和其他属性,制作和控制 sprite 是我们进入游戏开发的最重要一步。
Pixi 使用 WebGL 在 GPU 上渲染图像,图像需要转换为 GPU 可以处理的东西,这个东西被称为texture(纹理)。为保证快速高效,Pixi 使用 texture cache(纹理缓存)来存储和引用你的精灵需要的所有图像。

1. 加载图像到纹理缓存

Pixi 强大的 loader(加载器)对象可以加载任何类型的图像,我们使用 loader 加载器来加载图像,加载的图像会缓存到纹理缓存中。loader 还可以加载 JSON 文件,后面我们会讲到 纹理贴图集,它就是一个 JSON 文件。

// 我们可以链式加载图像,并给加载的每个图像指定别名
_loader
      .add('wallImg', 'images/1.png') // 加载的图片1是砖块,我们指定别名为wallImg
      .add('catImg', 'images/2.png')
      .add('devilImg', 'images/3.png')
      .add('treasureImg', 'images/4.png')
      .load(intLoad) // intLoad是一个回调函数,表示图像加载完成后要进行的操作

// 也可以把图片放到一个数组中进行加载
_loader.add(['images/1.png', 'images/2.png', 'images/3.png', 'images/4.png']).load(intLoad)

注意:加载图像要使用 anywhere 或者 http-server 起一个本地服务,否则会提示加载图像跨域。

2. 从纹理缓存中获取纹理并创建精灵

图片加载完后我们就可以从纹理缓存中获取图像对应的纹理,根据PIXI.Sprite创建精灵对象,然后把精灵对象放入舞台 stage 中就可以展示了。这些操作要在加载图片完成后的回调函数中进行。我们可以对精灵对象设置大小、坐标位置、缩放比例、旋转角度、透明度等属性。
精灵默然展示在可视区的左上角,水平向右为 X 轴正方向,垂直向下为 Y 轴的正方向。

_loader
      .add('wallImg', 'images/1.png') // 加载的图片1是砖块,我们指定别名为wallImg
      .add('catImg', 'images/2.png')
      .add('devilImg', 'images/3.png')
      .add('treasureImg', 'images/4.png')
      .load(intLoad) // intLoad是一个回调函数,表示图像加载完成后要进行的操作

function intLoad(){
  let texture = _TextureCache['wallImg'] // 从纹理缓存中获取图像对应的纹理
  let sprite = new _Sprite(texture) // 根据纹理生成一个精灵对象
  _stage.addChild(sprite) // 把精灵对象放入舞台容器
  // 控制精灵坐标位置,可以使用x、y属性,也可以使用position设置
  // sprite.x = 100
  // sprite.y = 100
  sprite.position.set(100, 100)
  // 设置精灵的大小
  sprite.width = 40
  sprite.height = 40
  // 设置精灵的缩放比例,可以单个轴方向上缩放,也可以同时缩放
  // sprite.scale.x = 0.5
  // sprite.scale.y = 0.5
  sprite.scale.set(1)
  // 精灵旋转,旋转点为精灵的左上角。顺时针为正,逆时针为负
  sprite.rotation = Math.PI / 4 // 顺时针旋转90度。
  // 精灵透明度设置
  sprite.alpha = 0.5
  // 隐藏精灵
  sprite.visible = false
  // 更换精灵,会有同一个精灵有不同纹理的场景。飞机正常状态切换到爆炸状态
  sprite.texture = _TextureCache['catImg']
  
}

创建游戏中涉及到的所有精灵,代码如下:

      _loader
        .add('wallImg', 'images/1.png')
        .add('catImg', 'images/2.png')
        .add('devilIMg', 'images/3.png')
        .add('treasureImg', 'images/4.png')
        .load(intLoad)
      function intLoad() {
        // 创建砖块精灵
        const wallSprite = new _Sprite(_TextureCache['wallImg'])
        wallSprite.width = 40
        wallSprite.height = 40
        _stage.addChild(wallSprite)
        // 创建猫精灵
        const catSprite = new _Sprite(_TextureCache['catImg'])
        catSprite.width = 40
        catSprite.height = 40
        catSprite.position.set(40, 0)
        _stage.addChild(catSprite)
        // 创建恶魔精灵
        const devilSprite = new _Sprite(_TextureCache['devilIMg'])
        devilSprite.width = 40
        devilSprite.height = 40
        devilSprite.position.set(80, 0)
        _stage.addChild(devilSprite)
        // 创建宝物精灵
        const treasureSprite = new _Sprite(_TextureCache['treasureImg'])
        treasureSprite.width = 40
        treasureSprite.height = 40
        treasureSprite.position.set(120, 0)
        _stage.addChild(treasureSprite)
      }

页面展示如下图所示,这节我们主要学习如何创建精灵图,下一节就要让这些精灵图动起来了。

当我们要开发一款大型复杂的游戏时,有很多精灵元素需要创建,这时候创建雪碧图就很有必要了,我们可以根据雪碧图来创建精灵。我们可以使用纹理打包器 Texture Packer工具来生成雪碧图。Texture Packer除了能生成雪碧图外,还能生成纹理贴图集,它是一个 JSON 文件,里面包含了雪碧图中各个子图的位置及大小等信息,纹理贴图集的 JSON 数据结构如下:

{
  "frames": {
    "1.png": {
      "frame": { "x": 0, "y": 0, "w": 100, "h": 100 },
      "rotated": false,
      "trimmed": false,
      "spriteSourceSize": { "x": 0, "y": 0, "w": 100, "h": 100 },
      "sourceSize": { "w": 100, "h": 100 }
    },
    "2.png": {
      "frame": { "x": 100, "y": 0, "w": 100, "h": 100 },
      "rotated": false,
      "trimmed": false,
      "spriteSourceSize": { "x": 0, "y": 0, "w": 100, "h": 100 },
      "sourceSize": { "w": 100, "h": 100 }
    },
    "3.png": {
      "frame": { "x": 200, "y": 0, "w": 100, "h": 100 },
      "rotated": false,
      "trimmed": false,
      "spriteSourceSize": { "x": 0, "y": 0, "w": 100, "h": 100 },
      "sourceSize": { "w": 100, "h": 100 }
    },
    "4.png": {
      "frame": { "x": 300, "y": 0, "w": 100, "h": 100 },
      "rotated": false,
      "trimmed": false,
      "spriteSourceSize": { "x": 0, "y": 0, "w": 100, "h": 100 },
      "sourceSize": { "w": 100, "h": 100 }
    }
  }
}

我们可以加载纹理贴图集,然后获取里面的精灵。

loader
  .add("images/textureMap.json")
  .load(intLoad)

function intLoad() {
        const textures = _loader.resources['images/textureMap.json'].textures
        // 使用纹理缓存TextureCache创建砖块精灵
        const wallSprite = new _Sprite(_TextureCache['1.png'])
        wallSprite.width = 40
        wallSprite.height = 40
        _stage.addChild(wallSprite)
        // 使用loader的resource来创建创建猫精灵
        const catSprite = new _Sprite(textures['2.png'])
        catSprite.width = 40
        catSprite.height = 40
        catSprite.position.set(40, 0)
        _stage.addChild(catSprite)
        // 创建恶魔精灵
        const devilSprite = new _Sprite(textures['3.png'])
        devilSprite.width = 40
        devilSprite.height = 40
        devilSprite.position.set(80, 0)
        _stage.addChild(devilSprite)
        // 创建宝物精灵
        const treasureSprite = new _Sprite(textures['4.png'])
        treasureSprite.width = 40
        treasureSprite.height = 40
        treasureSprite.position.set(120, 0)
        _stage.addChild(treasureSprite)
      }


游戏全部资源已放到 github 上,请下载演示。

posted @ 2025-03-11 13:07  老甄Home  阅读(322)  评论(0)    收藏  举报