SurfaceView 闪烁/撕裂

7
我正在试图解决我的问题。我已经阅读了http://groups.google.com/group/android-developers/browse_thread/thread/a2aac88a08cb56c2/b7dff4ba388cd664?lnk=gst&q=SurfaceView#b7dff4ba388cd664,它在某种程度上回答了我的问题,但据我所知,这是一种“不幸”的答案。所以这就是我的问题:
我正常使用SurfaceView(lock/unlockAndPost)来绘制游戏背景的位图,每当表面发生变化时(例如方向等),我都会渲染一系列移动的圆(最多30个,半径约为25.f)。这些圆的位置的x、y数据来自服务器,一切都很顺利。 所有圆对象都存储在列表中,并更新其位置,确保此更新是同步的。 然而,在将这些圆形绘制到屏幕上(在canvas.lock()期间)时,大多数情况下它们会正常显示,但偶尔(例如每隔几秒钟)一些圆形似乎会在一个帧中短暂地撕裂或闪烁。圆的数量始终保持不变,因此这不是问题,并且列表中没有并发修改圆的位置(如我所说,它是同步的)。 我甚至尝试在每个渲染循环中将所有这些圆形绘制到位图上,并将该位图绘制到主画布上。这只会更加影响性能(与直接将圆形绘制到主画布上相比,从大约30FPS降至13FPS)。 对不起,如果信息有点模糊(试图让公司开心:p),但我想知道是否有人能给我一些提示?或者我只是没那么幸运。我应该指出,来自服务器的定位数据是实时数据,渲染反映这些实时位置非常重要。
感谢任何帮助! Chris
编辑:
好吧。这是渲染线程的run()。
@Override
    public void run() {
        Canvas c;
        while (mRun) {
            c = null;
            try {
                c = mSurfaceHolder.lockCanvas(null);
                synchronized (mSurfaceHolder) {
                    panel.onDraw(c);
                }
            } finally {
                if (c != null) {
                    mSurfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }

相当标准(几乎是月球着陆器的翻版 :p)
@Override
public void surfaceCreated(SurfaceHolder holder) {
    mBackground= Bitmap.createBitmap(this.getWidth(), this.getHeight(), Bitmap.Config.RGB_565);
    screenOrientation = getResources().getConfiguration().orientation;
    if(thread.getState()== Thread.State.TERMINATED){
        thread = new RenderThread(holder, this);
        thread.setRunning(true);
        thread.start();
    }else {
        thread.setRunning(true);
        thread.start();
    }
}



@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    Canvas c = new Canvas(mField);
    c.drawARGB(255,0,144,0);
    backgroundDetails.renderOnPanel(c, this);
    screenOrientation = getResources().getConfiguration().orientation;
}

很容易理解,只需在方向更改时重新绘制背景位图并启动渲染线程。
public void onDraw(Canvas canvas) {
    canvas.drawBitmap(mField,0,0,null);
    drawPositionBeans(canvas, this);
}

最后:
    public void onDraw(Canvas canvas, RadarView radarView) {
    float beanX=0, beanY=0;
    float radius = 25.0f;
    final List<PositionBean> copyOfList = Collections.synchronizedList(positionBeans.getPositionBeans());
    synchronized(copyOfList){
        try {
            for (final PositionBean pb : copyOfList)
            {
                if (panel.getOrientation() == Configuration.ORIENTATION_PORTRAIT) {
                    beanX = (float)pb.getY()*(-1);
                    beanY = (float)pb.getX();
                } else {
                    beanX = (float)pb.getY()*(-1);
                    beanY = (float)pb.getX()*(-1);
                }
                mPaint.setARGB(255,pb.getRgbColor().getR(), pb.getRgbColor().getG(), pb.getRgbColor().getB());
                panel.drawSpot(canvas, beanX, beanY, radius, mPaint);

                mPaint.setStyle(Paint.Style.STROKE);
                mPaint.setARGB(255,255,222,1);
                for (int j = 0; j < selectedBean.size(); ++j)
                {
                    if(pb.getTrack()==selectedBean.get(j)) {
                        panel.drawSpot(canvas, beanX, beanY, radius+1, mPaint);
                    }
                }
                mPaint.setStyle(Paint.Style.FILL);
            }

        } catch(Exception e) {
            Log.e("render", "Exception Drawing Beans: " + e);
        }
    }
}

再次感谢大家。

Chris

不看你的游戏循环和绘制代码,无法回答。 - Sebi
和Sebi说的一样-提供一个代码示例会很有帮助。不过你有没有考虑过你偶尔接收到的位置是错误的可能性?这只是一个想法,解释为什么这些圆圈可能会“闪烁”,如果它们被临时定位在视野之外。同样的,没有任何代码将无法回答这个问题。 - Seidr
非常感谢大家的帮助。但是我确信定位数据是正确的。 - Sonoman
我现在也注意到我的positionUpdate线程以500-1000 FPS的速度运行(我知道,范围很广),我接收的数据包速率约为20-70 FPS,而渲染速率在15-30 FPS之间。这会引起任何问题吗?我本以为渲染的同步性质会阻止这方面的问题? - Sonoman
4个回答

1

1
我曾经遇到过这个问题。对我来说,适合的解决方案是同步onDraw方法和更新变换矩阵的方法。因为在矩阵相同的帧中(即新Matrix()的初始值),下一帧中它会有正确的值。

1

0

我发现在阅读有关Surface View的内容后,如果您调用

getHolder().lockCanvas();

你需要重新绘制所有内容。

除非你提供你的脏区域。

getHolder().lockCanvas(Rect dirty);

如果您只想重绘由Rect定义的区域

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接