我正在制作一个自上而下的射击游戏,它依赖于始终旋转指向鼠标光标的头像。我实现了这样的轮换:
//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
设置为非零值时(实际上,当它不是0
,Pi/2
,Pi
,Pi+Pi/2
或2Pi
时),图像失去了它的清晰度,不再能看到单个像素,因为它们模糊了。
这是一个屏幕截图(对于屏幕截图的一般质量不好而感到抱歉,但我认为差异非常明显):
这是有点不可接受的。我不能让图像总是模糊不清! 为什么会发生这种情况,我可以解决吗?
答案 0 :(得分:17)
你可以尝试
context.imageSmoothingEnabled = false;
请参阅docs:
context.imageSmoothingEnabled [= value]
返回图案填充和drawImage()方法是否会尝试平滑图像(如果必须重新缩放图像)(而不是仅使用“大像素”渲染图像)。
可以设置,更改图像是否平滑(true)与否(false)。
如果你想要一个真正的像素艺术复古风格效果,你需要手动创建几个角度的旋转精灵图像,查找适当的精灵为当前值phi
,并绘制它而不旋转。这显然需要大量的艺术作品!
答案 1 :(得分:3)
如果围绕中心点旋转图像,请确保图像本身具有偶数个像素。一旦最终得到奇数坐标,就需要为目标画布插入图像数据。 Apple有一些不错的documentation on translating and rotating the canvas。
因此,对于任何图像,如上所述,使用舍入来捕捉全像素。
context.translate(Math.floor(img.width/2), Math.floor(img.height/2));
这样,图像的每个源像素将始终精确地绘制到画布内的像素中,并且不会出现模糊。然而,这仅适用于90度的倍数。
似乎所有浏览器在某种程度上都在图像绘制中进行抗锯齿处理,因此您可能必须提供旋转图像作为精灵。
根据这个Chromium bug report你可能很幸运,如果他们还没有解决它。通读后,您将了解Ian Hickson可能反对将抗锯齿图像绘制选项。
答案 2 :(得分:1)
(picture.width/2, picture.height/2)
点不会一直有效。
(Math.floor(picture.width/2) + 0.5, Math.floor(picture.height/2) + 0.5)
应该有帮助。
答案 3 :(得分:0)
嗯,实际上这是你无法解决的问题
如果您将图像旋转90度的倍数,您的库应该足够智能,以便不应用插值。
但是,只要将图像旋转不同于90度的倍数的角度,就需要进行插值。结果,你得到了平滑。如果你对这个理论感兴趣,你可能会找一本关于计算机图形学或图像处理的书。
对于图像旋转的具体情况,您可以查看本文, http://bigwww.epfl.ch/publications/unser9502.html