【问题标题】:How to scroll off screen memory bitmap如何滚动屏幕内存位图
【发布时间】:2012-01-08 03:13:31
【问题描述】:

使用下面的代码滚动 我有一个 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);
        }
    }
}       
}

对于我的游戏 Tunnel Run,https://market.android.com/details?id=com.zubima.TunnelRun,现在我有一个可行的解决方案,我有一个位图数组,表面高度的大小,我用我的随机纹理填充,然后在每个循环中向下移动框架。我每秒获得 50 帧,但我认为通过滚动位图可以做得更好。

【问题讨论】:

  • 完全跑题了,但是你在市场上的应用描述是全文,没有段落,什么都没有……你应该结构化它!第一个想法是:tldr
  • 好建议,添加段落谢谢,但不确定您所说的“全文......没有什么”是什么意思。这是一个纯文本字段,我无法向其中添加图像。
  • 没错,但你的文本格式很丑。我不想在描述中提供完整的“如何使用/播放”指南。把它想象成一个广告文字。在列表中总结一些很酷的功能,让读者对你的游戏感兴趣。

标签: java android bitmap scroll surfaceview


【解决方案1】:

您正在尝试在其自身之上绘制位图,这在 Android AFAIK 上从未起作用。我的第一款游戏是一款名为 Mole Miner 的横向卷轴游戏,我就掉进了这个洞。

问题非常简单:drawBitmap() 本质上是一种特殊的 memcpy(),其中字节总是被寻址转发。这很好,并且最佳地使用 L1 缓存等,但如果源和目标区域 (a) 重叠,并且 (b) 源地址

(顺便说一下,memcpy() 的实际实现,检查这种可能性并在必要时向后复制。Canvas.drawBitmap() 不这样做。)

我为 Mole Miner 使用的解决方法是使用 两个 屏幕外位图,并在交替帧上在它们之间切换。但那是在 2009 年,这些天我可能根本不会使用滚动。

【讨论】:

  • 是的,我认为这是一个错误/错误的实现。我将在今天晚些时候尝试这两个屏幕外位图并在它们之间切换,如果它有效,我感谢你的答案,谢谢!
  • 如果您只在一个方向(向下)滚动,您可以更改此设置,以便将位图倒置并滚动向上。如果 dest 你不会遇到问题
  • 也许我无法正确地想象这一点,但这似乎不起作用。我的游戏中的隧道宽度随着时间的推移而减小。想象一下,在一个屏幕上,隧道从底部的最大宽度到最小宽度再到倒置的 V,向下滚动会完美地制作动画。在一个屏幕隧道上再次镜像位图会从最大宽度变为最小宽度,它看起来像 V 的右侧向上,其中新的位图材料(线)将在底部刷新然后向上滚动,该动画似乎是完全关闭。如有错误请指正,谢谢!
  • Ok Reuben 我奖励你解释为什么它不能工作,虽然你提供了两个位图的解决方法,但我认为这不会再加快我的代码速度。我可以通过其他方式进行更多优化,现在在我的 HTC EVO 4G 上我每秒获得 52 帧
  • 52fps 对任何人来说都应该足够了。 :) 关于。颠倒的想法,我的意思是在逻辑上颠倒存储位图......更改'memCanvas.drawBitmap(textureBitmap,intSurfaceWidth,0,null);'在 bottom 行而不是顶部绘制,然后更改滚动代码,以便复制一个像素行 up 而不是向下一行。最后,您将 c.drawBitmap() 更改为使用矩阵,因此它会颠倒绘制位图......这当然似乎会以正确的方式向上显示(并按预期滚动 down )。
【解决方案2】:

画布中有一个drawBitmap函数,签名如下:

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

你可以让你的dst变成画布的大小,你的src可以设置成新的

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

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

【讨论】:

  • 感谢您的建议。我已经尝试过了,请参阅上面的代码更改,因为它不适合此处,但本质上它以错误的方式滚动位图,并且将偏移量反转为 -1 不会使其向下滚动
  • 在你的例子中,我认为你的来源和目的地可能是倒退的。 Source 是您正在查看的位图区域,Destination 是显示器上的区域。另外,您的向下滚动代码是什么?
  • 好的,我明白了,我添加的 cmets 可能看起来很混乱,所以让我修改原始代码并去掉添加
  • 这就是我在逻辑上认为应该使用 drawBitmap Rect Src 和 Dst 将当前(源)位图从第一行向下移动到底部上方的方式,并将其向下移动一个位置,到(目标) 第一行;矩形 src = new Rect(0, 0, intSurfaceWidth, intSurfaceHeight - 1);矩形 dst = new Rect(0, 1, intSurfaceWidth, intSurfaceHeight); MemCanvas.drawBitmap(memBitmap, src, dst, null);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-07-31
  • 1970-01-01
  • 1970-01-01
  • 2015-06-15
  • 1970-01-01
相关资源
最近更新 更多