如何使用动画实现纸张推车

How to implement paper-dolling with animations?

本文关键字:张推车 实现 动画 何使用      更新时间:2023-09-26

对于2D自上而下的游戏(想想塞尔达+一个RPG)使用Canvas&Javascript,在允许动画的同时,实现纸张推车的最佳方式是什么?

使用精灵表制作动画已经足够简单了,但在混合中添加纸块(即,能够"装备"物品和盔甲,并在角色上显示这些物品的视觉表示)似乎并不容易,或者至少是一项非重复性任务。

例如,想象为一个挥舞剑的角色设置动画。一个简单的带有动画的精灵表就可以了。但是,如果你想让动画中的实际剑在装备不同的剑时发生变化,该怎么办?你会用不同的剑重复相同的动画来创建额外的精灵吗?每一件物品呢?每个NPC呢?(假设我也想要NPC的纸团,而不仅仅是角色)

一个可以做到这一点,只需将可穿戴项目的数量保持在最低限度,以限制所需的精灵动画帧的数量。

我认为可以将角色动画分开,然后在角色动画的顶部/下方添加剑/物品动画。这样,不同的角色可以重用相同的项目动画,并将其与角色动画相匹配。但你仍然会有很多精灵为每个项目。人物必须相似。

有什么想法或建议吗?

(如果重要的话,我想我计划做的是让NPC不需要任何纸张,玩家可以为每种物品制作角色动画+动画。对于盔甲,它将与玩家的身材和尺寸相匹配。)

我想,对于每一套可穿戴的物品,你都会有一系列可以放在播放器上的物品,例如:

var AwesomeDragonProofDiamondArmour =
{
    head: 'awesome-diamond-helmet.png',
    chest: 'awesome-diamond-chest.png',
    legs: 'awesome-diamond-legs.png',
    boots: 'awesome-diamond-boots.png'
};

然后在你的玩家设置中,你会有相同的数组;当然,在许多RPG游戏中,你并不是从一整套令人敬畏的钻石盔甲开始的,而是从皮革开始的,也许还有一种不错的胸甲。

var RubbishLeatherArmour =
{
    head:   'rubbish-leather-helmet.png',
    chest:  'rubbish-leather-chest.png',
    legs:   'rubbish-leather-legs.png',
    boots:  'rubbish-leather-boots.png'
};
var SortOfGoodSteelArmour =
{
    head:   'sort-of-good-steel-helmet.png',
    chest:  'sort-of-good-steel-chest.png',
    legs:   'sort-of-good-steel-legs.png',
    boots:  'sort-of-good-steel-boots.png'
};
var Player =
{
    head:   RubbishLeatherArmour.head,
    chest:  SortOfGoodSteelArmour.chest,
    legs:   RubbishLeatherArmour.legs,
    boots:  RubbishLeatherArmour.boots
}

这些PNG将是透明的,其想法是将它们与基本的玩家图形合成,最终得到一个纸团角色。为了减少开销,明智的做法是将这些图形放在一个单独的精灵表中,并存储每个项目的X、Y、宽度和高度,如下所示:

var RobustMetalArmour = 
{
    head: [120, 120, 20, 20],
    chest: [140, 120, 20, 20],
    legs: [160, 120, 20, 30],
    boots: [180, 120, 20, 10]
}

其中数组为[x,y,width,height]。这有一个缺点,那就是只有一个尺寸,所以除非你的角色都是相同的尺寸(实际上在基于瓦片的RPG中很可能),否则为每个尺寸的角色生成所有图形可能会很耗时。

另一种方法是使用画布绘制功能绘制图形,其中可以为头盔指定x/y/width/height,然后根据需要绘制任意大小的头盔。类似这样的东西:

function drawPlus(ctx, x, y, size, colour)
{
    ctx.lineWidth = 1;
    ctx.strokeStyle = colour;
    ctx.beginPath();
    ctx.moveTo(x + 0.5, y + 0.5 - size);
    ctx.lineTo(x + 0.5, 0.5 + y);
    ctx.lineTo(x + 0.5 + size, 0.5 + y);
    ctx.moveTo(x + 0.5 - size, y + 0.5);
    ctx.lineTo(x + 0.5, 0.5 + y);
    ctx.lineTo(x + 0.5, 0.5 + y + size);
    ctx.stroke();
    ctx.closePath();
}

上述函数在屏幕上绘制一个+。对于宽度为奇数的线条,0.5是必需的-请参阅本线程。

无论哪种方式,这都会很耗时,具体取决于您希望在每个角色上显示的项目数量。