2012-07-05 56 views
21

我正在制作一款自上而下的射击游戏,它依赖于始终朝着鼠标指针旋转的头像。我实现旋转这样的:为什么在上下文旋转后图像会丢失质量?

//Rendering. 
context.save(); //Save the context state, we're about to change it a lot. 

context.translate(position[0] + picture.width/2, position[1] + picture.height/2); //Translate the context to the center of the image. 
context.rotate(phi); //Rotate the context by the object's phi. 
context.drawImage(picture.image, -picture.width/2, -picture.height/2); //Draw the image at the appropriate position (center of the image = [0, 0]). 

context.restore(); //Get the state back. 

phi为零时,图像被在其正常质量渲染,具有尖锐边缘和可检测的像素。但是,当我设置phi为非零值(实际上,当它不是0Pi/2PiPi+Pi/22Pi),图像失去它的清晰度和单个像素不能再看到的,因为他们是模糊的。

下面是截图(约截图的总体质量差抱歉,但我觉得差比明显更多):

enter image description here

这是,嗯,有点难以接受。我不能让图像一直模糊不清! 为什么会发生这种情况,我可以解决它吗?

+3

想想原始像素需要如何与图像的旋转版本对齐..它们不会匹配像素网格 - 那么应该怎么做..? – Randy 2012-07-05 20:59:14

+0

为什么在非HTML5游戏中不会发生这种情况?这天晚些时候我正在玩Dragon Fly,并且它没有旋转小龙的问题! – corazza 2012-07-05 21:00:09

+5

Flash有点不同.. – Daedalus 2012-07-05 21:00:46

回答

14

你可以尝试

context.imageSmoothingEnabled = false; 

docs

context.imageSmoothingEnabled [=值]

返回模式是否填充和的drawImage()方法时将尝试平滑图像他们不得不重新调整它们(而不是仅仅用“大像素”渲染图像)。

可以设置,以改变图像是平滑的(真)还是不是(假)。

如果你想有一个真正的像素艺术复古风格的效果,你需要手动创建几个角度旋转精灵图片,查看相应的子画面的phi当前值,并绘制它不旋转。这显然需要相当数量的艺术作品!

+0

手动创建+1。游戏的主要元素几乎是不可避免的。 – Robert 2012-07-20 23:28:42

1

(picture.width/2, picture.height/2)点并不总是工作。

(Math.floor(picture.width/2) + 0.5, Math.floor(picture.height/2) + 0.5)应该有所帮助。

+1

不,仍然模糊! – corazza 2012-07-14 18:02:56

+1

这只适用于线条,图像完全相反 - 总是使用整数。 – 2012-07-22 18:23:07

2

如果您要围绕其中心点旋转图像,请确保图像本身具有偶数个像素。一旦你在奇数坐标上结束,图像数据需要被插入目标画布。苹果有一些不错的documentation on translating and rotating the canvas

因此,对于任何图像,如上面建议使用舍入来捕捉全像素。

context.translate(Math.floor(img.width/2), Math.floor(img.height/2)); 

通过这种方式,图像的每个源像素将始终精确地绘制到画布内部的像素中,并且不会发生模糊。然而,这只适用于90度的倍数。

看来,所有浏览器在某种程度上都会在图像绘制中实现抗锯齿功能,因此您可能必须提供旋转的图像作为精灵。

根据这一Chromium bug report如果他们没有固定它但你可能会幸运那里。通读一读,你会发现伊恩希克森可能会反对将反锯齿图像绘制为可选项。

+0

*但是,这只对90度的倍数是真的。*是的,这是一个很大的问题...... – corazza 2012-07-20 19:15:28

+0

是的,这似乎是一个众所周知的问题,自2009年以来由Chromium团队讨论。我更新了我的相应地回答。 – 2012-07-22 18:22:07

0

嗯,实际上这是你无法回避

如果您旋转90度的倍数的图像,以便应用不插你的图书馆应该足够聪明。

但只要你从90度的多个不同的角度旋转图像,则需要进行插值。结果,你会得到平滑。如果你对这个理论感兴趣,你可以找一本关于计算机图形学或图像处理的书。

对于图像旋转的具体情况下,你可以看看本文, http://bigwww.epfl.ch/publications/unser9502.html

+0

-1因为“是你无法避开的东西” – 2012-07-20 14:18:44

+0

我很确定你可以避开它。也许不使用画布,但使用C++,但它绝对有可能。也就是说,不要使用任何插值法,只是画出一些粗糙的东西。也许这些都是最好的...另外,如果你提供了一些链接到上述文献,那将是非常好的。 – corazza 2012-07-20 14:33:53

+0

@Bane如何绘制一切原油是一个解决方案?结果会错过放入原始图像的所有小像素细节。此外,如果您将原始图形与插值混合,结果仍然模糊(并且粗糙)。我还没有找到一种方法将C++集成到JavaScript中,但当然可以将C++代码转换为JavaScript代码。仍然没有真正的方法来旋转任意光栅图像而不会丢失C++中的像素。使用基于矢量的图像会更容易。 – Robert 2012-07-20 23:55:42

0

只是一个提示:我不知道,如果你刚开始学习油画programmimg,但你可以使用ImpactJs帮助你建立一个复古的游戏。

+0

我不是,我已经用它构建了一些游戏,但我主要集中在模式,理论,面向对象和一般编码方面。我从来没有真正需要轮换,当我需要它的时候我并不关心模糊,但现在我正在构建一个引擎,并且我真的很想解决这个问题。 – corazza 2012-07-20 14:30:33

+1

此外,这更适合于评论,而不是答案。 – corazza 2012-07-20 14:31:04