想要做网页游戏怎么办 ?PixiJs 篇(一)

举报
空城机 发表于 2021/08/09 10:27:45 2021/08/09
【摘要】 一款制作web游戏的js库,pixi非常的简易并且体量小,使用起来非常方便

在这里插入图片描述

作为一个不太正经的前端开发人员,为了生存一定得想办法提升自己的能力呀!!!

想学习一些与前端能搭的上边的新知识,想做一个能在 web 上运行的小游戏练练手︿( ̄︶ ̄)︿,就算不提高能力也得提高自己的眼界吧,虽然技术饭可能吃不到老,开发人的痛 o(╥﹏╥)o


时代变了

实际上空城机本人,下文中可能也会这样称呼)之前就已经在学习与之相关的一些知识了。当前如果想要在 web 端网页上做一些小游戏,现在基本上也就是 HTML 游戏了吧,毕竟 flash 已经在逐步退出了,时代变了。在当初网页上面很多小游戏都是以 flash 为主开发的,比如鼎鼎有名的半瓶神仙醋这位开发人员就是开发了不少的 flash 小游戏。

只要是接触过互联网的人,无论年龄,对 Flash 都不陌生,比如早期在线视频、Flash 动画以及网页版小游戏等都离不开它的支持。直到今天,很多网站上的内容仍需通过 Flash 插件才能显示,之前有个火车系统网站应为 flash 停用的事件还是挺火的(大连车务段昼夜攻关恢复查看列车运行图),不过其不安全、泄露隐私、进程服务无法彻底终止等特性也始终让人诟病。

当初的 4399 之类的小游戏网站也在不断的转型,从 flash 的时代中走出来,还是挺怀念以前的《死神 VS 火影》之类的小游戏的。

flash 的消失:Adobe 正式公布了 2020 年 12 月 31 日,终止支持 Flash。这个日期后,Adobe 将不会发布 Flash 的任何更新与安全补丁。此外,Adobe 还将从官方网站中删除 Flash Player 早期版本的所有存档,并阻止基于 Flash 的内容运行。

学习的选择

一般学习流程步骤如下了解相关游戏背景知识与专业术语(理解场景(页面),sprite(控件) ,时间轴(timer,定时器)等)了解具体语言以及 ide,以及游戏引擎比如 dom,cocos 等

事实上在目前一些前端游戏的开发上,选择无非就是那么几样。对于空城机这种业余的,刚开始入门还是从简单的 js 库进行入手吧。之后再学习一下Cocos creator这个工具。在 HTML 上,入门的 js 库也许就那几个选择吧,虽然空城机之前已经拜过three.js的山头了,但是 pixi.js 的山头空城机也准备拜一下,毕竟 3D 的门总是看起来比 2D 更加高大。

之前写过 three.js 的学习记录,读者们有兴趣的话阔以去瞧瞧空城机的这一个系列。

《Three.Js 杂记(一)——起步》

《Three.js 杂记(十一)—— 精灵与粒子(绘制中国地图)》

因为不是学生了、白天要上班的原因,直接上班学习过于嚣张啦,所以先从文档开始慢慢学起来吧!

网上找的建议:

如果你不用游戏引擎。那就写原生html,js,css,或者使用canvas/svg。

如果使用游戏引擎,又想用前端的技术栈,那就用cocos creator。
一次开发,多端打包。整个引擎非常的像Unity3d,可以理解为是2d版本的unity。使用的是js作为脚本语言。
cocos creator暂时只能做2d游戏。

如果你想做3d游戏。那就直接开搞Unity3d吧。
不过虽然Unity3d也支持js作为脚本语言,但实际上大部分公司和团队选择的是C#,
大部分教程也是以C#作为脚本语言,所以如果要上手Unity3d,那就需要学习C#



正文开始

前面废话水了一大堆的字呢┗( T﹏T )┛

image.png

接下来才是有关于 pixi 的正菜…



什么是 Pixi.JS?

官方说明:
The aim of this project is to provide a fast lightweight 2D library that works across all devices. The PixiJS renderer allows everyone to enjoy the power of hardware acceleration without prior knowledge of WebGL. Also, it’s fast. Really fast.

译文:这个项目的目标是提供一个快速轻量级的 2D 库,它可以跨所有设备工作。PixiJS 渲染器让每个人都可以享受硬件加速的强大功能,而无需事先了解 WebGL。而且,速度很快。真的很快。

好了,从上面这一段 pixi 开发者的说明中,空城机了解到了 pixi.js 是一个轻量级的 2D 库,能够用于 HTML 的动作渲染,并且由于和 webgl 对接,所以我们无需担心 pixi.js 的渲染性能问题, pixi.js 非常快。

接下来看另一份有关 pixi 比较全面的介绍(下面这段当然是抄的):


Pixi是一个非常快的2D sprite渲染引擎。这是什么意思?这意味着它可以帮助你显示、动画和管理交互式图形,这样你就可以轻松地使用JavaScript和其他HTML5技术制作游戏和应用程序。它有一个合理的,整洁的API,并包括许多有用的功能,如支持纹理地图集和提供一个精简的系统,为动画精灵(交互式图像)。它还为您提供了一个完整的场景图,这样您就可以创建嵌套精灵(精灵中的精灵)的层次结构,并允许您将鼠标和触摸事件直接附加到精灵上。而且,最重要的是,Pixi可以让您自由的使用,使其适应您的个人编码风格,并与其它框架无缝集成。

Pixi的API实际上是Macromedia / Adob​​e Flash率先使用的,并且经过反复考验和改进,所以Flash开发人员极易上手。 当前使用类似的API的渲染框架包括:CreateJS,Starling,Sparrow和Apple的SpriteKit。 Pixi API的优势在于它具有通用性:它不是游戏引擎。 这样对使用者来说很棒,因为您可以完全自由地使用它制作自己喜欢的东西,甚至是创建自己的游戏引擎。


在此介绍两个对于 Pixi.Js 学习很有用的网站:

PixiJS API Document

Pixi.js中文网

其中的中文网对于我们学习很便利,但是有个缺点,时代变了呀,中文网中讲述的一些 pixi 的方法可能已经改变了,如果下载的是最新版本的 pixi.js 那我们就可能使用不了这些方法了(就和空城机当初学 three.js 一样)

所以另一个 API 网站就显得尤为重要了,虽然 API 网站是英文的,对于我这种英文不好的学习者来说非常非常不友好,但是里面能够找到最新的方法。所以英文的瑕疵我阔以接受了,生活就像…,你不能反抗,那就只能接受了。

在这里插入图片描述

怎么开始干活?

找到参考教程后,那我们就阔以按照教程来慢慢学习起来了。

First

首先,第一步,我们先把 pixi.js 下载下来并安装好吧。

在中文网的教程当中,提供了 GitHub 仓库地址:https://github.com/pixijs/pixi.js/releases

可以通过仓库来获取 pixi.js 文件,并且使用 script 标签进行导入文件

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

但是由于本人创建了一个 vue cli 项目,所以我选择使用 npm 进行下载。下载的语句也很简单,注意需要在 pixi 后面加.js。 使用语句下载完 pixi.js 后,本人并没有在 package.json 中找到下载的 pixi,实际上已经被下载好了啦。

npm install pixi.js

我们阔以使用以下代码进行测试,来试一下到底是否已经导入 pixi.js。

vue 项目中,写在 main.js 中进行测试即可。


import * as PIXI from 'pixi.js'
Vue.use(PIXI)
/*********** 如果使用script标签,不需要上面两句 ***************/
// 测试pixi是否安装完成
let type = "WebGL"
if(!PIXI.utils.isWebGLSupported()){
  type = "canvas"
}
PIXI.utils.sayHello(type)

出现啦,F12 打开页面的控制台,会发现 PixiJS 能够成功的进行使用,并且还会告诉你当前 PixiJS 的版本。 中文网的教程使用的版本是 PixiJS 4.4.5。
在这里插入图片描述

Second

导入了 pixi.js 工具,那么赶紧搭建舞台吧,有了舞台,人物们才能够粉墨登场呀
在这里插入图片描述

pixi.js 搭建出的场景也是在<canvas>上面的,这一点想必大家也都见怪不怪了

创建一个环境:

使用 Pixi 上的 Application 对象创建一个矩形显示区域。 它会自动生成一个 HTML < canvas >元素,然后在 canvas 画布上显示图像。PIXI.Application 会自动选择使用 Canvas 或者是 WebGL 来渲染图形,这取决于您的浏览器支持情况。PIXI.Application有一个options对象。在本例中,它的width和height属性用来设置 Canvas 画布的宽度和高度(以像素为单位)。您可以在这个 options 对象中设置更多的可选属性;下面是如何使用它来设置反锯齿,透明度和分辨率。

<template>
  <div id="pixi1"></div>
</template>

<script>
    // var pixi = require('pixi');  
    import * as pixi from 'pixi.js'

    export default {
        name: "pixi1",
        props: {},
        data() {
            return {};
        },
        mounted() {
            this.initState();
        },
        methods: {
            initState() {
                //Create a Pixi Application   创建一个pixi应用
                let app = new pixi.Application({
                    width: 300,         // default: 300 宽度
                    height: 300,        // default: 300 高度
                    antialias: true,    // default: false 反锯齿
                    transparent: true, // default: false 透明度
                    resolution: 1 ,      // default: 1 分辨率
                    backgroundAlpha: 0,   // 设置背景颜色透明度   0是透明
                    //因为WebGL非常快,所以Pixi的renderer对象将默认为WebGL。如果您想使用canvas绘图API,可以将forceCanvas选项设置为true
                    forceCanvas: false
                });
                console.log(app)
                // 将创建好的canvas添加到元素当中去
                document.getElementById('pixi1').appendChild(app.view)
            }
        }
    };
</script>
<style scoped>
</style>

生成了一个透明的 canvas 标签,宽高为 300 像素
在这里插入图片描述

生成的 pixi:
在这里插入图片描述

当然为了看的清楚一些,将背景设置成有色的吧,renderer.backgroundColor

let app = new pixi.Application({
  width: 300,         // default: 800 宽度
  height: 300,        // default: 600 高度
  antialias: true,    // default: false 反锯齿
  transparent: false, // default: false 透明度
  resolution: 1,       // default: 1 分辨率
  backgroundAlpha: 0   // 设置背景颜色透明度   0是透明
});
app.renderer.backgroundColor = 0x8b968d;  // 设置canvas背景颜色

效果:
在这里插入图片描述

如果需要将舞台铺满全屏,接下来阔以设置 canvas 的大小以及监听形变

initState() {
  //Create a Pixi Application   创建一个pixi应用
  let app = new pixi.Application({
    width: 300,         // default: 800 宽度
    height: 300,        // default: 600 高度
    antialias: true,    // default: false 反锯齿
    transparent: false, // default: false 透明度
    resolution: 1,       // default: 1 分辨率
    backgroundAlpha: 0   // 设置背景颜色透明度   0是透明
  });
  console.log(app)
  app.renderer.backgroundColor = 0x8b968d;  // 设置画布背景颜色
  // app.view是canvas画布  生成一个256像素×256像素的黑色canvas元素
  document.getElementById('pixi1').appendChild(app.view)
  app.renderer.view.style.position = "absolute";
  app.renderer.view.style.display = "block";
  app.renderer.autoResize = true;  //为了确保画布的大小调整到与分辨率匹配
  app.renderer.resize(window.innerWidth, window.innerHeight);    //改变舞台大小
  window.onresize = function () {
    app.renderer.resize(window.innerWidth, window.innerHeight);
  } 
  // stage是舞台  stage(舞台)是Pixi的Container(容器)对象
  console.log(app.stage)
}

效果:
在这里插入图片描述

关于 pixi.js 创建的属性其实还有很多,这里就不一一列举了,需要使用了赶紧去查看api文档

Third

有了舞台,那么人物也要出场啦!

image.png

任何你想要在渲染器中可见的东西都必须添加到一个特殊的 Pixi 对象中,这个对象叫做stage(舞台)。就是上面的 app.stage 可以打印出来看看。

stage(舞台)是 Pixi 的Container(容器)对象。你可以把一个Container(容器)想象成一种空盒子,它会把你放进去的东西组合在一起并储存起来。stage(舞台)对象是场景中所有可见事物的根容器。你在stage(舞台)里放的任何东西都会在 canvas 画面上渲染出来。现在stage(舞台)是空的,但很快我们就会开始把东西放进去。

而舞台之上的表演者,也就是人物被称之为 sprite(精灵)。这一种的特殊图像对象。您可以控制它们的位置、大小和其他属性。

创建方法有三种:

  • 通过单个图像文件。

  • 通过雪碧图。

  • 通过纹理贴图。

本人有一篇文章中也有提及纹理贴图怎么制作:纹理打包器 TexturePacker

这里因为我困了,就简要写一发一下代码了。

这是由我之前通过 TexturePacker 生成的纹理贴图集,baokemeng1.json。

生成的 json 主要说明了是由三张图片构成的,具体素材我扔到网盘了,有兴趣可以下载一下:https://pan.baidu.com/s/1A-BsG_5hqCXhgKXnJ-lM2w

提取码:gjhi

json 中说明了位置信息,也是之后使用时判断和裁剪人物与场景的判断依据

"anim.png":
{
	"frame": {"x":212,"y":1,"w":50,"h":88},
	"rotated": false,
	"trimmed": true,
	"spriteSourceSize": {"x":0,"y":2,"w":50,"h":88},
	"sourceSize": {"w":50,"h":90}
},
"changjing.png":
{
	"frame": {"x":1,"y":1,"w":209,"h":214},
	"rotated": false,
	"trimmed": false,
	"spriteSourceSize": {"x":0,"y":0,"w":209,"h":214},
	"sourceSize": {"w":209,"h":214}
},
"damu2.png":
{
	"frame": {"x":212,"y":91,"w":56,"h":87},
	"rotated": false,
	"trimmed": true,
	"spriteSourceSize": {"x":0,"y":0,"w":56,"h":87},
	"sourceSize": {"w":60,"h":90}
}},

废话不多说,赶紧看看效果吧

就决定是你了,代码兽,赶紧上吧

<template>
    <div id="pixi4"></div>
</template>

<script>
import * as pixi from 'pixi.js'

function keyboard(value) {
  let key = {};
  key.value = value;
  key.isDown = false;
  key.isUp = true;
  key.press = undefined;
  key.release = undefined;
  //The `downHandler`
  key.downHandler = event => {
    if (event.key === key.value) {
      if (key.isUp && key.press) key.press();
      key.isDown = true;
      key.isUp = false;
      event.preventDefault();
    }
  };

  //The `upHandler`
  key.upHandler = event => {
    if (event.key === key.value) {
      if (key.isDown && key.release) key.release();
      key.isDown = false;
      key.isUp = true;
      event.preventDefault();
    }
  };

  //Attach event listeners
  const downListener = key.downHandler.bind(key);
  const upListener = key.upHandler.bind(key);
  
  window.addEventListener(
    "keydown", downListener, false
  );
  window.addEventListener(
    "keyup", upListener, false
  );
  
  // Detach event listeners
  key.unsubscribe = () => {
    window.removeEventListener("keydown", downListener);
    window.removeEventListener("keyup", upListener);
  };
  
  return key;
}

export default {
    name: "pixi4",
    components: {},
    props: {},
    data() {
        return {
            loader: null
        };
    },
    created() {},
    mounted() {
        this.initState();
    },
    watch: {},
    computed: {},
    methods: {
        initState() {
            this.loader = new pixi.Loader();
            let Rectangle = pixi.Rectangle; 
            //Create a Pixi Application   创建一个pixi应用
            let app = new pixi.Application({
                width: window.innerWidth,         // default: 800 宽度
                height: window.innerHeight,        // default: 600 高度
                antialias: true,    // default: false 反锯齿
                // transparent: true, // default: false 透明度
                resolution: 1 ,      // default: 1 分辨率
                backgroundAlpha: 0   // 设置背景颜色透明度   0是透明
            });

            document.getElementById('pixi4').appendChild(app.view)
            app.renderer.view.style.display = "block";
            app.renderer.autoResize = true;  
            window.onresize = function () {
                app.renderer.resize(window.innerWidth, window.innerHeight);
            }
            // 加载纹理贴图,创造精灵,并将精灵添加到stage舞台上
            let src2 = "./img/baokemeng1.json";
            this.loader.add([{name:'huo',url: src}, {name:'damu',url: src2}]).load(()=>{
                let textures = this.loader.resources.damu.textures; 
                // 场景           
                let changjingsprite = this.setTexture(textures["changjing.png"])
                app.stage.addChild(changjingsprite);
                // 裁剪人物
                let rectangle = new Rectangle(229, 1, 16.7, 22);
                let texture = textures["anim.png"];
                texture.frame = rectangle;
                let damu = this.setTexture(texture)
                app.stage.addChild(damu);
                // 场景大小和位置
                changjingsprite.scale.set(2, 2);
                changjingsprite.x = 100
                // 大木在场景大小、位置
                damu.width = 33;
                damu.height = 44;
                damu.x = 220;
                damu.y = 180;
                damu.vx = 0;
                damu.vy = 0;
                
                // 大木移动
                app.ticker.add(()=> this.gameLoop(damu));
                this.keyMove(damu);
            })
            
            // 监听src加载事件
            this.loader.onProgress.add((loader, resource) => {
                // console.log("当前进度:", loader.progress, "%"); 
                // console.log(resource.url)
            });
            this.loader.onError.add(() => {
                console.log("载入图片或json失败了")
            });
    
        },
        keyMove(person) {
            let left = keyboard('a'), up = keyboard('w'), right = keyboard('d'), down = keyboard('s');
            left.press = () => {
                person.vx = -1;
                person.vy = 0;
            };
            left.release = () => {
                person.vx = 0;
                person.vy = 0;
            };
            right.press = () => {
                person.vx = 1;
                person.vy = 0;
            };
            right.release = () => {
                person.vx = 0;
                person.vy = 0;
            };
            up.press = () => {
                person.vx = 0;
                person.vy = -2;
            };
            up.release = () => {
                person.vx = 0;
                person.vy = 0;
            };
            down.press = () => {
                person.vx = 0;
                person.vy = 2;
            };
            down.release = () => {
                person.vx = 0;
                person.vy = 0;
            };
        },
        gameLoop(person){
            //Move the cat 1 pixel 
            person.x += person.vx;
            person.y += person.vy;
        },
        setTexture (texture) {
            // console.log(texture)
            let sprite = new pixi.Sprite(texture);
            return sprite;
        },
    },
};
</script>
<style scoped>
</style>

效果:

在这里插入图片描述

呼,结束了!

哈哈哈,终于完成了 pixi.js 学习记录第一篇

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。