Android 中使用 Canvas.DrawBitmap 进行 Sprite 旋转。我很接近,我做错了什么?
我有这个精灵旋转算法(它的名字不好,只是用于测试)。它是如此接近,用它绘制的精灵确实会旋转。每一帧我都可以为其添加 +5 度,然后看到我漂亮的小精灵旋转。问题是,绘制到画布上的其他内容现在会闪烁。如果我不进行旋转,则常规绘制的精灵效果很好。我想我已经很接近了,但我只是不知道我错过了什么。下面是我的两个“Draw_Sprite”方法,一种只是将先前加载的资源位图绘制到传入的画布上。另一种方法是进行一些旋转,我知道如何将精灵旋转这么多度..然后绘制它。如果我有一个很好的游戏循环来绘制多个对象,则一种类型是旋转类型。然后,未旋转的精灵会闪烁,而旋转的精灵却不会闪烁。虽然如果我先绘制非旋转精灵,一切都很好,但是 Z 顺序可能会混乱(UI 元素顶部的精灵等)... 方法定义:
/*************************************************
* rotated sprite, ignore the whatever, its for ease of use and testing to have this argument list
* @param c canvas to draw on.
* @param whatever ignore
* @param rot degrees to rotate
* @return
*/
public int Draw_Sprite(Canvas c, int whatever, int rot) {
//rotating sprite
Rect src = new Rect(0, 0, width, height);
Rect dst = new Rect(x, y, x + width, y + height);
Matrix orig = c.getMatrix();
mMatrix = orig;
orig.setTranslate(0, 0);
orig.postRotate(rot, x+width/2, y+height/2);
c.setMatrix(orig);
c.drawBitmap(images[curr_frame], src, dst, null);
c.setMatrix(mMatrix); //set it back so all things afterwards are displayed correctly.
isScaled=false;
return 1;
}
/********************************************************
* draw a regular sprite to canvas c
* @param c
* @return
*/
public int Draw_Sprite(Canvas c) {
Rect src = new Rect(0, 0, width, height);
Rect dst = new Rect(x, y, x + width, y + height);
c.drawBitmap(images[curr_frame], src, dst, null);
isScaled=false;
return 1;
}
现在用法:
void onDraw(Canvas c)
{
canvas.drawRect( bgRect, bgPaint); //draw the background
//draw all game objects
// draw the normal items
for (GameEntity graphic : _graphics) {
graphic.toScreenCoords((int)player_x, (int)player_y);
if(graphic.getType().equals("planet")) //draw planets
graphic.Draw_Sprite(canvas); //before the rotation call draws fine
else
{
//rotate all space ships every frame so i see them spinning
//test rotation
mRot +=5;
if(mRot>=360)
mRot=0;
graphic.Draw_Sprite(canvas, 0, mRot); //yes function name will be better in future. this rotates spins draws fine
}
}
thePlayer.Draw_Sprite(canvas); //FLICKERS
drawUI(canvas);//all things here flickr
}
所以它确实可以它,调用旋转绘制后的东西被正确绘制。但问题是它闪烁。现在有人可能会说我应该做所有非旋转的事情并将其保存在最后,但是 zordering 将关闭......关于如何解决 zordering 或闪烁问题的建议?
I have this sprite rotating algorithm (its poorly named and just used for testing). It is so close, sprites drawn with it do rotate. Everyframe I can add +5 degrees to it and see my nice little sprite rotate around. The problem is, the other stuff drawn to the canvas now flickers. If I don't do the rotation the regular drawn sprites work great. I think I am close but I just don't know what piece I am missing. Below is my two "Draw_Sprite" methods, one just draws the previously resource loaded bitmap to the canvas passed in. The other one, does some rotation the best I know how to rotate the sprite by so x many degrees..and then draw it. If I have a nice game loop that draws several objects, one type is the rotated kind. Then the non-rotated sprites flicker and yet the rotated sprite never does. Though if I draw the non-rotated sprites first, all is well, but then the Z-Ordering could be messed up (sprites on top of UI elements etc)... The method definitions:
/*************************************************
* rotated sprite, ignore the whatever, its for ease of use and testing to have this argument list
* @param c canvas to draw on.
* @param whatever ignore
* @param rot degrees to rotate
* @return
*/
public int Draw_Sprite(Canvas c, int whatever, int rot) {
//rotating sprite
Rect src = new Rect(0, 0, width, height);
Rect dst = new Rect(x, y, x + width, y + height);
Matrix orig = c.getMatrix();
mMatrix = orig;
orig.setTranslate(0, 0);
orig.postRotate(rot, x+width/2, y+height/2);
c.setMatrix(orig);
c.drawBitmap(images[curr_frame], src, dst, null);
c.setMatrix(mMatrix); //set it back so all things afterwards are displayed correctly.
isScaled=false;
return 1;
}
/********************************************************
* draw a regular sprite to canvas c
* @param c
* @return
*/
public int Draw_Sprite(Canvas c) {
Rect src = new Rect(0, 0, width, height);
Rect dst = new Rect(x, y, x + width, y + height);
c.drawBitmap(images[curr_frame], src, dst, null);
isScaled=false;
return 1;
}
And now the usage:
void onDraw(Canvas c)
{
canvas.drawRect( bgRect, bgPaint); //draw the background
//draw all game objects
// draw the normal items
for (GameEntity graphic : _graphics) {
graphic.toScreenCoords((int)player_x, (int)player_y);
if(graphic.getType().equals("planet")) //draw planets
graphic.Draw_Sprite(canvas); //before the rotation call draws fine
else
{
//rotate all space ships every frame so i see them spinning
//test rotation
mRot +=5;
if(mRot>=360)
mRot=0;
graphic.Draw_Sprite(canvas, 0, mRot); //yes function name will be better in future. this rotates spins draws fine
}
}
thePlayer.Draw_Sprite(canvas); //FLICKERS
drawUI(canvas);//all things here flickr
}
So it does do it, things after a call to a rotational draw are drawn correctly. But the problem is it flickrs. Now One could say I should just do all my non rotational stuff and save that last, but the zordering would be off.... suggestions as to how to tackle this issue of zordering or the flickering?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
仅供下一个可能读到此内容的人使用。您只需几行代码即可完成此操作:
Just for the next guy who may read this. You can do this with only a few lines of code:
尝试在旋转之前使用 canvas.save() 并在操作完成后使用 canvas.restore() 。
当在画布上执行操作以更改对象的绘制方式时,您必须记住操作设置画布如何处理原点等...因此,如果您平移或旋转画布,这将在该画布的生命周期内进行设置帆布。为了避免这种情况,您首先调用 save,它会在操作画布矩阵之前保存画布矩阵的快照,然后运行所有更改,然后调用 Restore,这会将画布恢复到最后保存的点。否则,您的所有更改都会累积起来,并会得到意想不到的结果。
Try using canvas.save() before the rotation and canvas.restore() after manipulation is complete.
When performing manipulations on the canvas in order to change the way an object is drawn you have to remember the manipulations set how the canvas handles origins etc... So if you translate or rotate the canvas, that will be set for the lifetime of that canvas. In order to avoid this you first call save, which saves a snapshot of the canvas matrix before you manipulate it, then you run all your changes, then call restore which will restore the canvas back to the last saved point. Otherwise all your changes build up and you get unintended results.