2012-01-08 107 views
2

使用下面的代码滚动 我有一个Surfaceview线程和正在生成(更改),第一行(行),每帧,然后复制一个位置(行)在常规的SurfaceView位图上做滚动效果,然后我继续绘制其他的东西。那么这就是我真正想要的,但是即使我为屏幕外位图创建单独的画布,我也无法使其工作。它只是不滚动。如何滚动屏幕内存位图

我换句话说,我有一个内存位图,与Surfaceview画布相同,我需要每帧滚动(移位)一行,然后用新的随机纹理替换顶部行,然后在常规Surfaceview上绘制它帆布。

这是我认为会工作;

我surfaceChanged,我指定位图,画布和启动线程:

@Override 
    public void surfaceCreated(SurfaceHolder holder) { 
    intSurfaceWidth = mSurfaceView.getWidth(); 
    intSurfaceHeight = mSurfaceView.getHeight(); 

    memBitmap = Bitmap.createBitmap(intSurfaceWidth, intSurfaceHeight, 
      Bitmap.Config.ARGB_8888); 
    memCanvas = new Canvas(memCanvas); 

    myThread = new MyThread(holder, this); 
    myThread.setRunning(true); 
    blnPause = false; 
    myThread.start(); 
} 

我的线索,只显示必要的中间传动部分:

@Override 
public void run() { 
    while (running) {  
    c = null; 
try { 
    // Lock canvas for drawing 
    c = myHolder.lockCanvas(null);     

    synchronized (mSurfaceHolder) { 
     // Scroll down off screen canvas and hopefully underlying bitmap bitmap 
     Rect src = new Rect(0, 0, intSurfaceWidth, intSurfaceHeight - 1); 
     Rect dst = new Rect(0, 1, intSurfaceWidth, intSurfaceHeight); 
     memCanvas.drawBitmap(memBitmap, src, dst, null); 

     // Note scrolling up like this works fine 
     // Rect src = new Rect(0, 1, intSurfaceWidth, intSurfaceHeight + 1); 
     // Rect dst = new Rect(0, 0, intSurfaceWidth, intSurfaceHeight); 
     // memCanvas.drawBitmap(memBitmap, src, dst, null); 

     // Create random one line(row) texture bitmap 
     textureBitmap = Bitmap.createBitmap(imgTexture, 0, rnd.nextInt(intTextureImageHeight), intSurfaceWidth, 1); 

     // Now add this texture bitmap to top of screen canvas and hopefully underlying bitmap 
     memCanvas.drawBitmap(textureBitmap, 
       intSurfaceWidth, 0, null); 

     // Draw above updated off screen bitmap to regular canvas, at least I thought it would update (save changes) shifting down and add the texture line to off screen bitmap the off screen canvas was pointing to. 
     c.drawBitmap(memBitmap, 0, 0, null); 

     // Other drawing to canvas comes here 


    } finally { 
     // do this in a finally so that if an exception is thrown 
     // during the above, we don't leave the Surface in an 
     // inconsistent state 
     if (c != null) { 
      myHolder.unlockCanvasAndPost(c); 
     } 
    } 
}  
} 

对于我的比赛隧道运行,https://market.android.com/details?id=com.zubima.TunnelRun,现在我有一个工作的解决方案,我有一个位图阵列,表面高度的大小,我用我的随机纹理填充,然后在每个帧的循环中下移。我每秒获得50帧,但我认为我可以通过滚动位图来做得更好。

+0

完成题外话,但在市场上的应用程序描述是全文,没有段落,没有什么......你应该构造它!首先想到的是:tldr – WarrenFaith 2012-01-08 15:08:44

+0

好的建议,补充段落谢谢,但不知道你的意思是“全文......没有”。这是一个纯文本字段,我不能将图像添加到此。 – DKDiveDude 2012-01-08 16:05:36

+0

是的,但是你的文本格式非常难看。我不想在说明中提供完整的“如何使用/播放”指南。想想它更像是一个广告文字。总结列表中的一些很酷的功能,让读者对你的游戏感兴趣。 – WarrenFaith 2012-01-08 17:46:35

回答

0

有画布内的drawBitmap功能具有以下特征:

public void drawBitmap (Bitmap bitmap, Rect src, RectF dst, Paint paint); 

你可以让你的DST画布的大小,和你的src可以设置为新

Rect(0,offset,width,height+offset) 

然后,您可以每帧增加偏移量,并在视图中获得平滑滚动位图。

+0

感谢您的建议。我已经试过了,看到我的代码更改如上所述,因为它不适合这里,但本质上它滚动位图的方式错误,并将偏移量反转为-1不会使其向下滚动 – DKDiveDude 2012-01-08 15:00:50

+0

在您的示例中,我认为你是来源和目的地可能会倒退。源是您正在查看的位图的区域,目标是显示器上的区域。 另外,你的代码是向下滚动的? – nmjohn 2012-01-08 15:35:46

+0

好吧我理解我的增加的评论可能看起来令人困惑,所以让我修改原始代码并摆脱添加 – DKDiveDude 2012-01-08 16:09:38

1

您正在尝试在自己的顶部绘制位图,这是从未在Android AFAIK上工作过的。我的第一场比赛是一个叫做Mole Miner的侧滚轮,我陷入了这个确切的问题。

问题很简单:drawBitmap()本质上是一种特殊类型的memcpy(),其中字节始终为转发。这很好,最好使用L1缓存等,但如果源和目标区域(a)重叠,并且(b)源地址为dest地址,那么显然会出现问题。

(的memcpy(),顺便说一下,检查是否有这种可能性,如果需要向后做副本的真正实现。Canvas.drawBitmap()并没有这样做。)

我用鼹鼠矿工的解决方法将有两个离屏位图,并在替代帧之间切换它们。但那是在2009年,现在我可能根本不会使用滚动。

+0

是的,它认为这是一个错误/糟糕的实现。我会尝试两个离屏位图,并在今天晚些时候在它们之间切换,如果它有效,我相信您的答案,谢谢! – DKDiveDude 2012-01-16 15:39:49

+0

如果您只是向一个方向滚动(向下),则可以更改此设置,以便将位图颠倒绘制并滚动*向上*。如果dest <源,则不会出现问题。 – 2012-01-16 16:04:03

+0

也许我无法正确可视化这一点,但这似乎并不奏效。随着时间的推移,我游戏中的隧道宽度逐渐缩小。想象一下,在一个屏幕上,隧道从最大宽度到最小宽度到倒V,向下滚动将完美地生成这个动画。在一个屏幕隧道上再次镜像位图会从最大宽度到最小宽度,它看起来像V的右侧,其中新的位图材料(行)将在底部ond中刷新,然后向上滚动,该动画似乎是完全关闭。如果我错了,请纠正我,谢谢! – DKDiveDude 2012-01-16 18:24:04