PIXIJS超级详细教程【从入门到入土-下】

来自GitHub教程 GitHub - Zainking/LearningPixi: ⚡️Pixi教程中文版

PIXIJS教程【从入门到入土-上】地址【https://blog.csdn.net/qq_61672548/article/details/127253760】

5.2 加载纹理贴图集

可以使用Pixi的loader来加载纹理贴图集。如果是用Texture Packer生成的JSON,loader会自动读取数据,并对每一个帧创建纹理。下面就是怎么用loader来加载treasureHunter.json。当它成功加载,setup方法将会执行

loader
  .add("images/treasureHunter.json")
  .load(setup);

现在每一个图像的帧都被加载进Pixi的纹理缓存之中了。你可以使用Texture Packer中定义的他们的名字来取用每一个纹理。

如果你是使用的 loader来加载纹理贴图集, 使用loader的 resources:

let sprite = new Sprite(
  resources["images/treasureHunter.json"].textures["frameId.png"]
);

要创建一个精灵需要输入太多东西了! 所以我建议你给纹理贴图集的textures对象创建一个叫做id的别名,象是这样:

let id = PIXI.loader.resources["images/treasureHunter.json"].textures;

现在你就可以像这样实例化一个精灵了:

let sprite = new Sprite(id["frameId.png"]);

真不错啊~!

六、移动精灵

6.1 移动

现在你知道了如何展示精灵,但是让它们移动呢?很简单:使用Pixi的ticker。这被称为 游戏循环 。任何在游戏循环里的代码都会1秒更新60次。你可以用下面的代码让 cat 精灵以每帧1像素的速率移动。

let icon
function setup() {
    let id = resources["./images/treasureHunter.json"].textures
    icon = new Sprite(id["icon.png"])
    app.stage.addChild(icon)
    //定义游戏循环
    app.ticker.add(animation)
}

function animation() {
    icon.x++
}

你也没必要非得用Pixi的ticker来创建游戏循环。如果你喜欢,也可以用requestAnimationFrame像这样创建:

function gameLoop() {

  //Call this `gameLoop` function on the next screen refresh
  //(which happens 60 times per second)
  requestAnimationFrame(gameLoop);

  //Move the cat
  cat.x += 1;
}

//Start the loop
gameLoop();

(注意 cat 变量需要在setupgameLoop函数之外定义,然后你可以在全局中任何地方都能获取到它们)

你可以让精灵的位置,角度或者大小动起来 - 什么都可以!你会在下面看到更多精灵动画的例子。

6.2 速度属性

为了给你更多的灵活性,这里有两个 速度属性vxvy去控制精灵的运动速度。 vx被用来设置精灵在x轴(水平)的速度和方向。vy被用来设置精灵在y轴(垂直)的速度和方向。 他们可以直接更新速度变量并且给精灵设定这些速度值。这是一个用来让你更方便的更新交互式动画的额外的模块。

第一步是给你的精灵创建vxvy属性,然后给他们初始值。

cat.vx = 0;
cat.vy = 0;

vxvy设置为0表示精灵静止。

接下来,在游戏循环中,更新vxvy为你想让精灵移动的速度值。然后把这些值赋给精灵的xy属性。下面的代码讲明了你如何利用该技术让cat能够每帧向右下方移动一个像素:

function setup() {

  //Create the `cat` sprite
  cat = new Sprite(resources["images/cat.png"].texture);
  cat.y = 96;
  cat.vx = 0;
  cat.vy = 0;
  app.stage.addChild(cat);

  //Start the game loop
  app.ticker.add(gameLoop);
}

function gameLoop(){

  //Update the cat's velocity
  cat.vx = 1;
  cat.vy = 1;

  //Apply the velocity values to the cat's
  //position to make it move
  cat.x += cat.vx;
  cat.y += cat.vy;
}

如果你想让猫往不同的方向移动怎么办?可以把它的 vx 赋值为 -1让猫向左移动。可以把它的 vy 赋值为 -1让猫向上移动。为了让猫移动的更快一点,把值设的更大一点,像3, 5, -2, 或者 -4。

你会在前面看到如何通过利用vxvy的速度值来模块化精灵的速度,它对游戏的键盘和鼠标控制系统很有帮助,而且更容易实现物理模拟。

七、给精灵分组

7.1 Container分组

分组让你能够让你创建游戏场景,并且像一个单一单元那样管理相似的精灵图。Pixi有一个对象叫 Container,它可以帮你做这些工作。让我们弄清楚它是怎么工作的。

想象一下你想展示三个精灵:一只猫,一只刺猬和一只老虎。创建它们,然后设置它们的位置 - 但是不要把它们添加到舞台上

//The cat
let cat = new Sprite(id["cat.png"]);
cat.position.set(16, 16);

//The hedgehog
let hedgehog = new Sprite(id["hedgehog.png"]);
hedgehog.position.set(32, 32);

//The tiger
let tiger = new Sprite(id["tiger.png"]);
tiger.position.set(64, 64);

让后创建一个animals容器像这样去把他们聚合在一起:

let animals = new PIXI.Container();

然后用 addChild 去把精灵图 添加到分组中

animals.addChild(cat);
animals.addChild(hedgehog);
animals.addChild(tiger);

最后把分组添加到舞台上。

app.stage.addChild(animals);

(你知道的,stage对象也是一个Container。它是所有Pixi精灵的根容器。)

这就是上面代码的效果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nFgkW4af-1665574697605)(https://github.com/Zainking/LearningPixi/raw/master/examples/images/screenshots/18.png)]

你是看不到这个包含精灵图的animals分组的。它仅仅是个容器而已。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XVkE8YKn-1665574697606)(https://github.com/Zainking/LearningPixi/raw/master/examples/images/screenshots/19.png)]

不过你现在可以像对待一个单一单元一样对待animals分组。你可以把Container当作是一个特殊类型的不包含任何纹理的精灵。

如果你需要获取animals包含的所有子精灵,你可以用它的children数组获取。

console.log(animals.children)
//Displays: Array [Object, Object, Object]

这告诉你animals有三个子精灵。

因为animals分组跟其他精灵一样,你可以改变它的xy的值,alpha, scale和其他精灵的属性。所有你改变了的父容器的属性值,都会改变它的子精灵的相应属性。所以如果你设置分组的xy的位置,所有的子精灵都会相对于分组的左上角重新定位。如果你设置了 animalsxy的位置为64会发生什么呢?

animals.position.set(64, 64);

整个分组的精灵都会向右和向下移动64像素。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1ccUh7fQ-1665574697607)(https://github.com/Zainking/LearningPixi/raw/master/examples/images/screenshots/20.png)]

animals分组也有它自己的尺寸,它是以包含的精灵所占的区域计算出来的。你可以像这样来获取widthheight的值:

console.log(animals.width);
//Displays: 112

console.log(animals.height);
//Displays: 112

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nqRu3lhU-1665574697608)(https://github.com/Zainking/LearningPixi/raw/master/examples/images/screenshots/21.png)]

如果你改变了分组的宽和高会发生什么呢?

animals.width = 200;
animals.height = 200;

所有的孩子精灵都会缩放到刚才你设定的那个值。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wjxt9EoF-1665574697608)(https://github.com/Zainking/LearningPixi/raw/master/examples/images/screenshots/22.png)]

如果你喜欢,你可以在一个 Container 里嵌套许多其他Container,如果你需要,完全可以创建一个更深的层次。然而,一个 DisplayObject (像 Sprite 或者其他 Container)只能一次属于一个父级。如果你用 addChild 让一个精灵成为其他精灵的孩子。Pixi会自动移除它当前的父级,这是一个不用你操心的有用的管理方式。

7.2 局部位置和全局位置

当你往一个Container添加一个精灵时,它的xy的位置是 相对于分组的左上角 的。这是精灵的局部位置,举个例子,你认为这个猫在这张图的哪个位置?

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C5MDQRit-1665574697610)(https://github.com/Zainking/LearningPixi/raw/master/examples/images/screenshots/20.png)]

让我们看看:

console.log(cat.x);
//Displays: 16

16?是的!这因为猫的只往分组的左上角偏移了16个像素。16是猫的局部位置。

精灵图还有 全局位置 。全局位置是舞台左上角到精灵锚点(通常是精灵的左上角)的距离。你可以通过toGlobal方法的帮助找到精灵图的全局位置:

parentSprite.toGlobal(childSprite.position)

这意味着你能在animals分组里找到猫的全局位置:

console.log(animals.toGlobal(cat.position));
//Displays: Object {x: 80, y: 80...};

上面给你返回了xy的值为80。这正是猫相对于舞台左上角的相对位置,也就是全局位置。

如果你想知道一个精灵的全局位置,但是不知道精灵的父容器怎么办?每个精灵图有一个属性叫parent 能告诉你精灵的父级是什么。在上面的例子中,猫的父级是 animals。这意味着你可以像如下代码一样得到猫的全局位置:

cat.parent.toGlobal(cat.position);

即使你不知道猫的当前父级是谁,上面的代码依然能够正确工作。

这还有一种方式能够计算出全局位置!而且,它实际上最好的方式,所以听好啦!如果你想知道精灵到canvas左上角的距离,但是不知道或者不关心精灵的父亲是谁,用getGlobalPosition方法。这里展示如何用它来找到老虎的全局位置:

tiger.getGlobalPosition().x
tiger.getGlobalPosition().y

它会给你返回xy的值为128。 特别的是,getGlobalPosition是高精度的:当精灵的局部位置改变的同时,它会返回给你精确的全局位置。我曾要求Pixi开发团队添加这个特殊的特性,以便于开发精确的碰撞检测游戏。(谢谢Matt和团队真的把他加上去了!)

如果你想转换全局位置为局部位置怎么办?你可以用toLocal方法。它的工作方式类似,但是通常是这种通用的格式:

sprite.toLocal(sprite.position, anyOtherSprite)

toLocal 找到一个精灵和其他任何一个精灵之间的距离。这段代码告诉你如何获取老虎的相对于猫头鹰的局部位置。

tiger.toLocal(tiger.position, hedgehog).x
tiger.toLocal(tiger.position, hedgehog).y

上面的代码会返回给你一个32的x值和一个32的y值。你可以在例子中看到老虎的左上角和猫头鹰的左上角距离32像素。

7.3 ParticleContainer 分组

Pixi有一个额外的,高性能的方式去分组精灵的方法称作:ParticleContainerPIXI.ParticleContainer)。任何在ParticleContainer 里的精灵都会比在一个普通的Container的渲染速度快2到5倍。这是用于提升游戏性能的一个很棒的方法。

可以像这样创建 ParticleContainer :

let superFastSprites = new PIXI.particles.ParticleContainer();

然后用 addChild 去往里添加精灵,就像往普通的 Container添加一样。

如果你决定用ParticleContainer你必须做出一些妥协。在 ParticleContainer 里的精灵图只有一小部分基本属性:x, y, width, height, scale, pivot, alpha, visible - 就这么多。而且,它包含的精灵不能再继续嵌套自己的孩子精灵。 ParticleContainer 也不能用Pixi的先进的视觉效果像过滤器和混合模式。每个 ParticleContainer 只能用一个纹理(所以如果你想让精灵有不同的表现方式你将不得不更换雪碧图)。但是为了得到巨大的性能提升,这些妥协通常是值得的。你可以在同一个项目中同时用 ContainerParticleContainer,然后微调一下你自己的优化

八、文本

使用一个 Text 对象 (PIXI.Text)在舞台上展示文本。简单来说,你可以这样使用它:

let message = new Text("Hello Pixi!");
app.stage.addChild(message);

这将会在画布上展示文本“Hello, Pixi”。Pixi的文本对象继承自Sprite类,所以它包含了所有相同的属性,像x, y, width, height, alpha, 和 rotation。你可以像处理其他精灵一样在舞台上定位或调整文本。例如,你可以像下面这样使用position.set来设置messagexy位置:

message.position.set(54, 96);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-68Ij0amm-1665574697611)(https://github.com/Zainking/LearningPixi/raw/master/examples/images/screenshots/24.png)]

这样你会得到基础的未加修饰的文本。但是如果你想要更绚丽的文字,使用Pixi的TextStyle函数来自定义文字效果。下面展示如何操作:

let style = new TextStyle({
  fontFamily: "Arial",
  fontSize: 36,
  fill: "white",
  stroke: '#ff3300',
  strokeThickness: 4,
  dropShadow: true,
  dropShadowColor: "#000000",
  dropShadowBlur: 4,
  dropShadowAngle: Math.PI / 6,
  dropShadowDistance: 6,
});

这将创建一个新的包含所有你想用的样式的style对象。所有样式属性,see here

添加style对象作为Text函数的第二个参数来应用样式到文本上,就像这样:

let message = new Text("Hello Pixi!", style);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FKl9zEOQ-1665574697611)(https://github.com/Zainking/LearningPixi/raw/master/examples/images/screenshots/24.5.png)]

如果你想要在你创建文本对象之后改变它的内容,使用text属性。

message.text = "Text changed!";

如果你想要重新定义样式属性,使用style属性。

message.style = {fill: "black", font: "16px PetMe64"};

九、碰撞检测

碰撞检测函数
hitTestRectangle 函数都有些什么呢?它做了什么,还有它是如何工作的?

function hitTestRectangle(r1, r2) {

  //Define the variables we'll need to calculate
  let hit, combinedHalfWidths, combinedHalfHeights, vx, vy;

  //hit will determine whether there's a collision
  hit = false;

  //Find the center points of each sprite
  r1.centerX = r1.x + r1.width / 2;
  r1.centerY = r1.y + r1.height / 2;
  r2.centerX = r2.x + r2.width / 2;
  r2.centerY = r2.y + r2.height / 2;

  //Find the half-widths and half-heights of each sprite
  r1.halfWidth = r1.width / 2;
  r1.halfHeight = r1.height / 2;
  r2.halfWidth = r2.width / 2;
  r2.halfHeight = r2.height / 2;

  //Calculate the distance vector between the sprites
  vx = r1.centerX - r2.centerX;
  vy = r1.centerY - r2.centerY;

  //Figure out the combined half-widths and half-heights
  combinedHalfWidths = r1.halfWidth + r2.halfWidth;
  combinedHalfHeights = r1.halfHeight + r2.halfHeight;

  //Check for a collision on the x axis
  if (Math.abs(vx) < combinedHalfWidths) {

    //A collision might be occuring. Check for a collision on the y axis
    if (Math.abs(vy) < combinedHalfHeights) {

      //There's definitely a collision happening
      hit = true;
    } else {

      //There's no collision on the y axis
      hit = false;
    }
  } else {

    //There's no collision on the x axis
    hit = false;
  }

  //`hit` will be either `true` or `false`
  return hit;
};

现在你知道了如何制造种类繁多的图形对象,但是你能用他们做什么?一个有趣的事情是利用它制作一个简单的 碰撞检测系统 。你可以用一个叫做:hitTestRectangle 的自定义的函数来检测两个矩形精灵是否接触。

hitTestRectangle(spriteOne, spriteTwo)

如果它们重叠, hitTestRectangle 会返回 true。你可以用 hitTestRectangle 结合 if 条件语句去检测两个精灵是否碰撞:

if (hitTestRectangle(cat, box)) {
  //There's a collision
} else {
  //There's no collision
}

正如你所见, hitTestRectangle 是走入游戏设计这片宇宙的大门。

运行在 examples 文件夹的 collisionDetection.html 文件,看看怎么用 hitTestRectangle工作。用方向按键去移动猫,如果猫碰到了盒子,盒子会变成红色,然后 “Hit!” 文字对象会显示出来。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dwYSnQwk-1665574697612)(https://github.com/Zainking/LearningPixi/raw/master/examples/images/screenshots/25.png)]

你已经看到了创建这些所有元素的代码,让猫移动的键盘控制。唯一的新的东西就是 hitTestRectangle 函数被用在 play 函数里检测碰撞。

function play(delta) {

  //use the cat's velocity to make it move
  cat.x += cat.vx;
  cat.y += cat.vy;

  //check for a collision between the cat and the box
  if (hitTestRectangle(cat, box)) {

    //if there's a collision, change the message text
    //and tint the box red
    message.text = "hit!";
    box.tint = 0xff3300;

  } else {

    //if there's no collision, reset the message
    //text and the box's color
    message.text = "No collision...";
    box.tint = 0xccff99;
  }
}

play 函数被每秒调用了60次,每一次这个 if 条件语句都会在猫和盒子之间进行碰撞检测。如果 hitTestRectangletrue,那么文字 message 对象会用 setText 方法去显示 “Hit”:

message.text = "Hit!";

这个盒子的颜色改变的效果是把盒子的 tint 属性改成一个16进制的红色的值实现的。

box.tint = 0xff3300;

如果没有碰撞,消息和盒子会保持它们的原始状态。

message.text = "No collision...";
box.tint = 0xccff99;

代码很简单,但是你已经创造了一个看起来完全活着的互动的世界!它简直跟魔术一样!令人惊讶的是,你大概已经拥有了你需要用Pixi制作游戏的全部技能!

>>> 2022.10.12 19:24 教程已经全部更新完,很大部分都是来自github 原文地址【https://github.com/Zainking/learningPixi】本来我只想做一个文档方便我自己在开发的时候查阅 然后觉得PIXIJS在国内的教程很少 便把此文章放到了CSDN上,能有机会帮助需要的人,因为很多朋友还是很少去国外找教程。PIXIJS还有很多其他很好的教程 【https://pixijs.com/tutorials/】去这里可以查看。

教程原文地址 GitHub - Zainking/LearningPixi: ⚡️Pixi教程中文版

附加

<<< 2022-10-17 21:52 添加一些PixiJS 开发常用API的使用方法,这部分全靠自己看官方文档和实践摸索,难度还是比较大的。官方API文档都是英文的,虽然浏览器带翻译,但是效果并不好,我感觉还不如不翻译,因为如果不是写在代码块的代码也会被翻译,有些变量名或者方法名写在代码块外,然后给翻译成中文,这会让你相当的蒙蔽~ 一些翻译意思也不到位。所以只有中英结合着看~

精灵表

官方教程【小精灵 API 文档 (pixijs.download)

在创建动画精灵中需要用到

实用程序类,用于维护对单个 Sprites 表中的纹理集合的引用。

要从代码访问子画面表,您可以将其JSON数据文件传递给Pixi的加载器:

PIXI.Loader.shared.add("images/spritesheet.json").load(setup);

function setup() {
  let sheet = PIXI.Loader.shared.resources["images/spritesheet.json"].spritesheet;
  ...
}

动画精灵

官方教程【PixiJS API Documentation

1. 创建精灵动画

1.1 创建精灵动画一般方法

注意和创建普通精灵不一样,注意差别 【Loader.shared】

PIXI.Loader.shared.add("./images/down.json").load(setup);

function setup() {
  let sheet = PIXI.Loader.shared.resources["./images/spritesheet.json"].spritesheet;
  let animatedSprite = new PIXI.AnimatedSprite(sheet.animations["down"]);
  ...
}
1.2 创建精灵帧的简单方法
  • 从纹理帧创建AnimatedSprite的简单方法

PIXI.AnimatedSprite.fromFrames (frames)

NameTypeDescription
framesstring[]AnimatedSprite将使用的帧数组id作为它的纹理帧。
  • 从图片创建AnimatedSprite的简单方法

PIXI.AnimatedSprite.fromImages (images)

NameTypeDescription
imagesstring[]AnimatedSprite将使用的图像url数组作为它的纹理帧

2.常用方法

2.1 play()

动画精灵开始运动(图片开始循环)

 animatedSprte.play()
2.2 stop ()

动画精灵停止运动,停止在第一帧

 animatedSprte.stop ()
2.3 update()

我不太清楚这个update是怎么用的,下面是官方的介绍,我没看懂。

Updates the object transform for rendering.

NameTypeDescription
deltaTimenumberTime since last tick.

控制动画精灵帧切换速度可以用 animatedSprte.animationSpeed = 0.1 数字越小越慢

2.4 gotoAndPlay()

gotoAndPlay(frameNumber) void

转到一个特定的帧并开始播放AnimatedSprite。

NameTypeDescription
frameNumbernumber起始帧索引.
2.5 gotoAndStop ()

gotoAndStop (frameNumber) void

停止AnimatedSprite并进入特定帧。

NameTypeDescription
frameNumbernumber帧索引停止在哪帧
2.6 destroy ()

停止AnimatedSprite并销毁它。

2.7 小demo(部分代码)
// 简单方法创建动画精灵
let ss = new PIXI.AnimatedSprite.fromImages(['./images/down1.png', './images/down2.png', './images/down3.png', './images/down4.png'])
//添加到舞台
app.stage.addChild(ss)
//设置精灵位置
ss.y = 220
ss.animationSpeed = 0.1
// ss.play()
//从第一张图片开始
ss.gotoAndPlay(0)
//停在第二张图片
ss.gotoAndStop(1)
//销毁
ss.destroy()
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Simulink是一款强大的仿真工具,用于设计、模拟和分析各种系统的行为。下面是一个从入门入土的Simulink仿真教程。 1. 软件安装:首先需要下载和安装Simulink软件。在MathWorks官方网站上找到适合的版本,并按照指示进行安装。 2. Simulink基础:打开Simulink后,可以看到一个模块化的仿真环境。了解基本的Simulink界面、工具栏和库,这些是使用Simulink进行仿真的基础。 3. 模型建立:使用Simulink可以通过将各种模块组合在一起来建立模型。通过从库中拖拽模块到仿真界面,使用线连接相应的模块,可以构建出一个完整的系统模型。 4. 参数设置:对于每个模块,都可以设置相应的参数。这些参数可根据需要进行调整,以便模型可以更准确地模拟真实系统的行为。 5. 信号输入:创建一个仿真的关键是提供输入信号。可以通过添加信号源模块来生成不同类型的输入信号,如恒定值、正弦波、脉冲等。 6. 仿真运行:配置好模型和输入信号后,可以点击运行按钮开始仿真。仿真结果将在仿真器窗口中显示,此时可以观察系统的行为。 7. 结果分析:Simulink提供了多种工具用于分析仿真结果。可以绘制输出信号的波形图,计算系统的响应时间、频率响应等。 8. 优化改进:根据分析结果,可以调整模型参数以改进系统的性能。这包括调整模块参数、修改模型结构等。 9. 进阶功能:通过进一步学习和实践,还可以掌握更高级的Simulink功能,如使用MATLAB脚本进行仿真、使用状态流图进行建模等。 10. 深入学习:要真正掌握Simulink,需要不断深入学习和实践。可以参考Simulink的官方文档、视频教程和论坛,以及阅读相关书籍。 总之,通过上述步骤,您可以从入门入土地掌握Simulink的基本原理和使用方法,能够进行各种系统模型的建立和仿真。但记住,Simulink只是一个工具,对于真正理解和解决复杂系统问题,还需要深入学习掌握相关的系统理论和建模方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NoBug.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值