`
haiyupeter
  • 浏览: 418169 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

PIXI 创建 Sprite的几种方法-PIXI文档翻译(3)

阅读更多
1、通过spritesheets图创建sprite

你现在知道如何从单个图像文件制作精灵。但是,作为游戏设计师,你通常会使用tilesets(也称为spritesheets)来制作 sprite。Pixi有一些方便的内置方法来帮助你做到这一点。tileset是包含子图像的单个图像文件。子图像表示您要在游戏中使用的所有图形。这里是一个包含游戏角色和游戏对象作为子图像的tileset图像的示例。





整个图块集为192×192像素。每个图像都在一个自己的32 x 32像素的网格单元。存储和访问所有的游戏图形在一个tileset是一个非常处理器和内存高效的方式来处理图形,而Pixi是为他们优化。

您可以通过定义与要提取的子图像大小和位置相同的矩形区域,从图块集中捕获子图像。这里是从tileset中提取的火箭子图像的例子




让我们看看这样做的代码。首先,tileset.png使用Pixi的加载图像loader,就像你在前面的例子中做的一样。

loader
  .add("images/tileset.png")
  .load(setup);


接下来,当图像加载时,使用tileset的矩形子部分创建sprite的图像。这里是提取子图像,创建火箭精灵,并定位和显示在画布上的代码。

function setup() {

  //Create the `tileset` sprite from the texture
  var texture = TextureCache["images/tileset.png"];

  //Create a rectangle object that defines the position and
  //size of the sub-image you want to extract from the texture
  var rectangle = new Rectangle(192, 128, 64, 64);

  //Tell the texture to use that rectangular section
  texture.frame = rectangle;

  //Create the sprite from the texture
  var rocket = new Sprite(texture);

  //Position the rocket sprite on the canvas
  rocket.x = 32;
  rocket.y = 32;

  //Add the rocket to the stage
  stage.addChild(rocket);

  //Render the stage   
  renderer.render(stage);
}


这个怎么用?

Pixi有一个内置Rectangle对象(PIXI.Rectangle),它是一个用于定义矩形形状的通用对象。它需要四个参数。前两个参数定义了矩形x和y位置。最后两个定义它width和height。以下是定义新Rectangle对象的格式。

var rectangle = new PIXI.Rectangle(x, y, width, height);


矩形对象只是一个数据对象 ; 它由你决定如何使用它。在我们的示例中,我们使用它来定义要提取的图块上的子图像的位置和面积。Pixi纹理有一个有用的属性frame,可以设置为任何Rectangle对象。的frame作物的纹理的尺寸Rectangle。这里是如何使用frame 来裁剪纹理到火箭的大小和位置。

var rectangle = new Rectangle(192, 128, 64, 64);
texture.frame = rectangle;


然后,您可以使用裁剪的纹理创建精灵:

var rocket = new Sprite(texture);


这就是它的工作原理!

因为制作sprite纹理从一个瓷砖是你会做的很多频率,Pixi有一个更方便的方式来帮助你这样做 - 让我们来看看下一步是什么。

2、使用纹理图集

如果你在一个大型,复杂的游戏,你会想要一个快速,有效的方式来创建精灵从tilesets。这是 纹理地图集真正有用的地方。纹理地图集是一个JSON数据文件,其中包含匹配图块集PNG图像上的子图像的位置和大小。如果你使用纹理地图集,你需要知道你想要显示的子图像是它的名字。您可以按任何顺序排列tileset图像,JSON文件将跟踪其大小和位置。这真的很方便,因为它意味着tileset图像的大小和位置没有硬编码到您的游戏程序。如果您对图块集进行更改,例如添加图片,调整图片大小或删除图片,只需重新发布JSON文件,游戏就会使用该数据显示正确的图片。您不必对您的游戏代码进行任何更改。

Pixi与标准JSON纹理地图集格式兼容,该格式由一个名为Texture Packer的流行软件工具输出。Texture Packer的“Essential”许可证是免费的。让我们来了解如何使用它来制作纹理图集,并将图集加载到Pixi中。(你不必使用Texture Packer。类似的工具,像Shoebox或spritesheet.js,以与Pixi兼容的标准格式输出PNG和JSON文件。)

首先,从您要在游戏中使用的单个图像文件的集合开始。





(本节的所有图像都是由Lanea Zimmerman创建的。你可以在这里找到更多她的作品 ,谢谢你,Lanea!)

接下来,打开Texture Packer并选择JSON Hash作为框架类型。将图像拖动到Texture Packer的工作区中。(您也可以将Texture Packer指向包含图像的任何文件夹。)它将自动在单个tileset图像上排列图像,并为它们指定与其原始图像名称匹配的名称。




(如果您使用的是免费版的Texture Packer,请设置Algorithm为Basic,设置Trim模式为 None,设置Size约束,Any size然后将PNG Opt Level向左滑动,0这些是基本设置,版本的Texture Packer来创建您的文件,没有任何警告或错误。)

完成后,点击发布按钮。选择文件名和位置,并保存已发布的文件。你最终会得到2个文件:一个PNG文件和一个JSON文件。在这个例子中,我的文件名是 treasureHunter.json和treasureHunter.png。为了让你的生活更轻松,只需将这两个文件保存在项目的images文件夹中。(您可以将JSON文件视为图像文件的额外元数据,因此将这两个文件保存在同一文件夹中是有意义的。)JSON文件描述了图块中每个子图像的名称,大小和位置。这里是一个描述blob怪物子图像的片段。

"blob.png":
{
    "frame": {"x":55,"y":2,"w":32,"h":24},
    "rotated": false,
    "trimmed": false,
    "spriteSourceSize": {"x":0,"y":0,"w":32,"h":24},
    "sourceSize": {"w":32,"h":24},
    "pivot": {"x":0.5,"y":0.5}
},


该treasureHunter.json文件还包含具有相似数据的“dungeon.png”,“door.png”,“exit.png”和“explorer.png”属性。这些子图像中的每一个被称为帧。拥有这些数据是非常有帮助的,因为现在你不需要知道每个子图像在tileset中的大小和位置。所有你需要知道的是sprite的帧id。框架id只是原始图像文件的名称,如“blob.png”或“explorer.png”。

使用纹理地图集的许多优点是,您可以轻松地在每个图像周围添加2像素的填充(Texture Packer默认情况下会这样做。)这对于防止纹理流失的可能性很重要 。纹理流失是当图块上的相邻图像的边缘出现在子图形旁边时发生的效果。这是因为您的计算机的GPU(图形处理单元)决定如何舍入小数像素值。应该把它们向上还是向下?这对于每个GPU将是不同的。在图像间留下1或2个像素间距,使所有图像一致显示。

(注意:如果你有一个图形周围有两个像素填充,并且你仍然注意到一个奇怪的“关闭一个像素”毛刺的方式Pixi显示它,尝试改变纹理的缩放模式算法,这里的方法:texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST;。这些毛刺有时会因为GPU浮点舍入错误而发生。)

现在你知道如何创建纹理地图集,让我们了解如何将它加载到你的游戏代码。

3、加载纹理图集
要获取纹理地图集到Pixi,使用Pixi的加载 loader。如果JSON文件是用Texture Packer制作的,那么 loader它将解释数据并自动从tileset的每个框架创建一个纹理。以下是如何使用loader加载treasureHunter.json 文件。当它加载时,setup函数将运行。

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


tileset上的每个图像现在都是Pixi缓存中的单独纹理。您可以使用与Texture Packer中相同的名称(“blob.png”,“dungeon.png”,“explorer.png”等)访问缓存中的每个纹理。

4、从加载的纹理图集创建精灵

Pixi给你三个一般的方法来创建一个精灵从纹理图集:

使用TextureCache:
var texture = TextureCache["frameId.png"],
    sprite = new Sprite(texture);


如果你使用Pixi的loader加载纹理地图集,使用加载器的resources:
var sprite = new Sprite(
  resources["images/treasureHunter.json"].textures["frameId.png"]
);


这是太多的输入只是为了创建一个sprite!所以我建议你创建一个别名id,指向纹理的altas的textures对象,像这样:
var id = PIXI.loader.resources["images/treasureHunter.json"].textures; 


然后你可以创建每个新的sprite像这样:
let sprite = new Sprite(id["frameId.png"]);


好多了!

这里是你如何可以在使用这三种不同的精灵创作技法setup函数来创建和显示 dungeon,explorer以及treasure精灵。

//Define variables that might be used in more 
//than one function
var dungeon, explorer, treasure, door, id;

function setup() {

  //There are 3 ways to make sprites from textures atlas frames

  //1. Access the `TextureCache` directly
  var dungeonTexture = TextureCache["dungeon.png"];
  dungeon = new Sprite(dungeonTexture);
  stage.addChild(dungeon);

  //2. Access the texture using the loader's `resources`:
  explorer = new Sprite(
    resources["images/treasureHunter.json"].textures["explorer.png"]
  );
  explorer.x = 68;

  //Center the explorer vertically
  explorer.y = stage.height / 2 - explorer.height / 2;
  stage.addChild(explorer);

  //3. Create an optional alias called `id` for all the texture atlas 
  //frame id textures.
  id = PIXI.loader.resources["images/treasureHunter.json"].textures; 

  //Make the treasure box using the alias
  treasure = new Sprite(id["treasure.png"]);
  stage.addChild(treasure);

  //Position the treasure next to the right edge of the canvas
  treasure.x = stage.width - treasure.width - 48;
  treasure.y = stage.height / 2 - treasure.height / 2;
  stage.addChild(treasure);


  //Render the stage
  renderer.render(stage);
}


以下是此代码显示的内容:





阶段维度为512 x 512像素,您可以在上面的代码中看到stage.height和stage.width属性用于对齐精灵。这里是如何explorer的y位置垂直居中:

explorer.y = stage.height / 2 - explorer.height / 2;


学习使用纹理地图集创建和显示精灵是一个重要的基准。所以在我们继续之前,让我们来看看你可以写的代码来添加剩余的精灵:门blob和exit门,这样你可以产生一个如下所示的场景:




这里是完成所有这一切的整个代码。我还包括HTML代码,所以你可以看到一切在其正确的上下文。(你会在这个库中的examples/spriteFromTextureAtlas.html文件中找到这个工作代码 。)请注意,blobsprite被创建并在循环中添加到舞台中,并分配随机位置。

<!doctype html>
<meta charset="utf-8">
<title>Make a sprite from a texture atlas</title>
<body>
<script src="../pixi.js/bin/pixi.js"></script>
<script>

//Aliases
var Container = PIXI.Container,
    autoDetectRenderer = PIXI.autoDetectRenderer,
    loader = PIXI.loader,
    resources = PIXI.loader.resources,
    TextureCache = PIXI.utils.TextureCache,
    Texture = PIXI.Texture,
    Sprite = PIXI.Sprite;

//Create a Pixi stage and renderer and add the 
//renderer.view to the DOM
var stage = new Container(),
    renderer = autoDetectRenderer(512, 512);
document.body.appendChild(renderer.view);

//load a JSON file and run the `setup` function when it's done
loader
  .add("images/treasureHunter.json")
  .load(setup);

//Define variables that might be used in more 
//than one function
var dungeon, explorer, treasure, door, id;

function setup() {

  //There are 3 ways to make sprites from textures atlas frames

  //1. Access the `TextureCache` directly
  var dungeonTexture = TextureCache["dungeon.png"];
  dungeon = new Sprite(dungeonTexture);
  stage.addChild(dungeon);

  //2. Access the texture using throuhg the loader's `resources`:
  explorer = new Sprite(
    resources["images/treasureHunter.json"].textures["explorer.png"]
  );
  explorer.x = 68;

  //Center the explorer vertically
  explorer.y = stage.height / 2 - explorer.height / 2;
  stage.addChild(explorer);

  //3. Create an optional alias called `id` for all the texture atlas 
  //frame id textures.
  id = PIXI.loader.resources["images/treasureHunter.json"].textures; 

  //Make the treasure box using the alias
  treasure = new Sprite(id["treasure.png"]);
  stage.addChild(treasure);

  //Position the treasure next to the right edge of the canvas
  treasure.x = stage.width - treasure.width - 48;
  treasure.y = stage.height / 2 - treasure.height / 2;
  stage.addChild(treasure);

  //Make the exit door
  door = new Sprite(id["door.png"]); 
  door.position.set(32, 0);
  stage.addChild(door);

  //Make the blobs
  var numberOfBlobs = 6,
      spacing = 48,
      xOffset = 150;

  //Make as many blobs as there are `numberOfBlobs`
  for (var i = 0; i < numberOfBlobs; i++) {

    //Make a blob
    var blob = new Sprite(id["blob.png"]);

    //Space each blob horizontally according to the `spacing` value.
    //`xOffset` determines the point from the left of the screen
    //at which the first blob should be added.
    var x = spacing * i + xOffset;

    //Give the blob a random y position
    //(`randomInt` is a custom function - see below)
    var y = randomInt(0, stage.height - blob.height);

    //Set the blob's position
    blob.x = x;
    blob.y = y;

    //Add the blob sprite to the stage
    stage.addChild(blob);
  }

  //Render the stage   
  renderer.render(stage);
}

//The `randomInt` helper function
function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

</script>
</body>


你可以在上面的代码中看到,所有的blob都是使用for循环创建的 。每个blob沿x轴都是均匀分布的,如下所示:

var x = spacing * i + xOffset;
blob.x = x;


spacing具有值48,并且xOffset具有值150.这意味着第一blob将具有x150 的位置。这从舞台的左侧偏移150像素。每个后续blob都将有一个x值比blob循环的上一次迭代中创建的值大48像素。这将创建一个均匀间隔的blob怪物线,从左到右,沿着地下城楼。

每个blob也给出随机y位置。这里是这样做的代码:

var y = randomInt(0, stage.height - blob.height);
blob.y = y;


所述blob的y位置可以分配0和512之间的任何随机数,这是的值stage.height。这在一个自定义函数的帮助下工作randomInt。randomInt返回一个在您提供的任意两个数字之间的范围内的随机数。

randomInt(lowestNumber, highestNumber)


这意味着如果你想要1和10之间的随机数,你可以得到一个这样:

var randomNumber = randomInt(1, 10);


这里是执行randomInt所有这些工作的函数定义:
function randomInt(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

randomInt 是一个伟大的小功能,保持在你的背部口袋里制作游戏 - 我一直使用它。
  • 大小: 38.4 KB
  • 大小: 75.1 KB
  • 大小: 13.2 KB
  • 大小: 121.9 KB
  • 大小: 9.1 KB
  • 大小: 10.5 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics