在画布中翻转精灵

Posted

技术标签:

【中文标题】在画布中翻转精灵【英文标题】:Flip a sprite in canvas 【发布时间】:2011-12-16 15:45:03 【问题描述】:

我正在使用画布来显示一些精灵,我需要水平翻转一个(使其面向左侧或右侧)。但是,我看不到任何使用 drawImage 的方法。

这是我的相关代码:

this.idleSprite = new Image();
this.idleSprite.src = "/game/images/idleSprite.png";
this.idleSprite.frameWidth = 28;
this.idleSprite.frameHeight = 40;
this.idleSprite.frames = 12;
this.idleSprite.frameCount = 0;

this.draw = function() 
        if(this.state == "idle") 
            c.drawImage(this.idleSprite, this.idleSprite.frameWidth * this.idleSprite.frameCount, 0, this.idleSprite.frameWidth, this.idleSprite.frameHeight, this.xpos, this.ypos, this.idleSprite.frameWidth, this.idleSprite.frameHeight);
            if(this.idleSprite.frameCount < this.idleSprite.frames - 1)  this.idleSprite.frameCount++;  else  this.idleSprite.frameCount = 0; 
         else if(this.state == "running") 
            c.drawImage(this.runningSprite, this.runningSprite.frameWidth * this.runningSprite.frameCount, 0, this.runningSprite.frameWidth, this.runningSprite.frameHeight, this.xpos, this.ypos, this.runningSprite.frameWidth, this.runningSprite.frameHeight);
            if(this.runningSprite.frameCount < this.runningSprite.frames - 1)  this.runningSprite.frameCount++;  else  this.runningSprite.frameCount = 0; 
        
    

如您所见,我使用drawImage 方法将我的精灵绘制到画布上。翻转我能看到的精灵的唯一方法是翻转/旋转整个画布,这不是我想要做的。

有没有办法做到这一点?或者我需要制作一个面向另一个方向的新精灵并使用它吗?

【问题讨论】:

【参考方案1】:

您可以在不翻转整个画布的情况下转换画布绘图上下文。

c.save();
c.scale(-1, 1);

将反映上下文。绘制你的图像,然后

c.restore();

你又可以正常画了。欲了解更多信息,请参阅https://developer.mozilla.org/en-US/docs/Web/Guide/html/Canvas_tutorial/Transformations

【讨论】:

谢谢!但是由于西蒙的回答,我将使用他的技术。尽管它正在回答我的问题,但我会将您的答案标记为已接受的答案:)【参考方案2】:

虽然 Gaurav 展示了在画布中翻转精灵的技术方法...

不要为您的游戏这样做。

改为制作第二张图片(或使您当前的图片更大),它是恶意表单的翻转版本。 “翻转上下文并绘制图像”与“仅绘制图像”之间的性能差异可能很大。在 Opera 和 Safari 中,翻转画布会导致绘制速度慢十倍,而在 Chrome 中则慢两倍。示例见this jsPerf。

预先计算翻转的精灵总是更快,在游戏中画布性能真的很重要。

【讨论】:

谢谢。我最终做的是向我现有的精灵(在它下方)添加另一个精灵,而我的角色以另一种方式运行,并添加了一些代码以根据方向使用该组精灵。像这样:i.imgur.com/uIPvF.png 看起来不错!虽然我会重新排列新行:垂直排列每个翻转版本,所以翻转时唯一需要更改的是 y 坐标。 Gaurav 的答案实际上只是由于 ctx.save/restore 而导致性能成本高昂。事实上,如果你每次都简单地调用 ctx.scale(...),有趣的是翻转版本的绘制速度更快:jsperf.com/ctx-flip-performance/3。 (如果您为翻转的情况调用 ctx.scale(-1) 并为非翻转的情况调用任何内容,它会更快:jsperf.com/ctx-flip-performance/4)。 杰夫你提出了一个很好的观点,saverestore 不是必需的,但你的结果是侥幸,现在看看结果。您可能在浏览器完成加载页面或 Java(用于计时器)之前就已经开始了测试。我认为/4 的测试不准确,因为翻转所需的工作还必须包括将转换恢复到正常状态的工作。这意味着至少要再次调用ctx.scale(-1,1)。这是一个“公平”的测试,在每个被测试的浏览器和移动设备中翻转速度都比较慢,有时甚至非常慢:jsperf.com/ctx-flip-performance/5 我曾认为 .scale() 设置变换比例而不是相乘。乘法是 w3.org 文档 (dev.w3.org/html5/2dcontext/#dom-context-2d-scale) 中隐含的内容,这确实会使测试 /4 无效。 (它使用了有点含糊的术语“添加”)。然而,这似乎不是它正在做的事情,至少在 chrome 上:jsperf.com/ctx-flip-performance/8.【参考方案3】:

使用它来翻转你的精灵表 http://flipapicture.com/

【讨论】:

不幸的是,这不支持 PNG :(

以上是关于在画布中翻转精灵的主要内容,如果未能解决你的问题,请参考以下文章

敌人的精灵不会向左翻转

在画布中同时渲染精灵表中的多个部分?

画布精灵表错误

为啥精灵套件中的坐标系会翻转,我可以全局更改吗?

无法使用移动输入翻转精灵

具有不间断反射的精灵图像