安卓游戏滚动背景

4

我正在尝试找出在Android设备上运行滚动背景的最佳方法。目前我使用的方法非常卡顿。我使用线程,但我认为这不是Android平台的最佳选择。

@Override
    public void run() {
        // Game Loop
        while(runningThread){
            //Scroll background down
            bgY += 1;

            try {
                this.postInvalidate();
                t.sleep(10);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

    }

在onDraw函数中,postInvalidate函数会简单地将背景图片向下推。
canvas.drawBitmap(backgroundImage, bgX, bgY, null);

感谢您的提前帮助。
更新: 我已经确定问题所在。问题是我的播放器更新速率与背景滚动同步(看起来很生硬)。这是因为两者都在同一个函数中绘制。我不太确定如何解决这个问题,如果有任何帮助,将不胜感激。例如,将玩家移动与地图滚动分开处理。
此外,我该如何控制 onDraw(canvas)被调用的速度?
提前致谢。
然而,我已经组合了一个不同的运行循环,适用于遇到相同问题的人们。这部分源自 Google 的 jetboy 示例。
以下是我在 surfaceview 中的内部类:
class MapThread extends Thread{
    private Map map;
    private SurfaceHolder holder;
    private boolean run = false;

    public MapThread(Map map, SurfaceHolder holder){
        this.holder = holder;
        this.map = map;
        setRunning(true);
    }

    public void setRunning(boolean run){
        this.run = run;
    }

    @Override
    public void run(){
        while(run){
            try{
                Canvas c = null;

                 try {
                       c = holder.lockCanvas(null);
                       synchronized (holder) {
                            map.onDraw(c);
                     }
                 } finally {

                     if (c != null) {
                         holder.unlockCanvasAndPost(c);
                     }
                 }
        }
    }
}

SOLUTION

https://gamedev.stackexchange.com/questions/8127/android-game-scrolling-background


1
请参阅gamedev.stackexchange.com。 - Cheryl Simon
3个回答

3
使用SurfaceView实现在屏幕上绘制。这允许您更多地控制何时绘制以及绘制什么。

SurfaceView是View的一个特殊子类,它在View层次结构内提供了一个专用的绘图表面。其目的是将此绘图表面提供给应用程序的辅助线程,以便应用程序不必等待系统的View层次结构准备好绘制。

基本设计是拥有一个surfaceview,在while循环中连续绘制。然后添加一个if语句,条件为当计时器线程告诉您该绘制时为true。比如说,每30ms,就绘制位图。这将为您提供约33 fps。
现在,您还可以拥有另一个计时器线程,告诉您何时更新bgX或bgY值。例如,在每60ms时,它将设置一个布尔值updateFlag = true;然后在主线程中,您有一个if语句检查此标记,将其设置为false,并更新您的bgX和bgY值。通过精确控制计时器和bgX/bgY增量,您应该能够产生平滑的动画效果。
看一下Google提供的LunarLander源代码是个好主意。

0

我在我的SpaceQuestAlpha游戏的第二层使用这种方法。这使得滚动无缝。

我使用下面的两行代码来设置初始位置。

              moony=0;
              moon2y=-(heighty); 

然后这些行增加了背景图像的两个版本。一个从0开始,另一个从屏幕高度负值开始。每当其中一个图像超出屏幕底部时,它就会向上移动两倍的高度以将其移回到位置。我正在使用没有延迟问题的Surface View。

              moony+=5;
              moon2y+=5;


                 if(moon2y>=heighty) {moon2y=moon2y-(heighty*2);}
                     canvas.drawBitmap(lavabackground, 0, moon2y, null); 
                 if(moony>=heighty){moony=moony-(heighty*2);}
                     canvas.drawBitmap(lavabackground, 0, moony, null);

0

需要记住的一件事是,sleep非常不准确。为了解决这个问题,您可以跟踪睡眠期间经过的时间,并相应地更新移动物体的时间。

从您的代码中并不清楚,但您需要确保所有UI更新都发生在UI线程中。

您确实需要在UI线程之外进行定时,否则UI将永远不会更新。还有其他计时方法,例如使用Handler可能会更加简洁,但我认为它们的开销可能有点大,不适合您尝试做的事情。我认为一个简单的线程具有最小的开销。


谢谢您的回复。我尝试了这个网站,但目前只找到了 iPhone 版本。是的,所有 onDraw 图像都会在 postinvalidate 后更新整个 UI。目前它非常卡顿。 - Stevanicus
许多在 iPhone 中使用的概念可能适用,但那里有更多的游戏开发者,因此在那里提出问题可能会得到更好的答案,因为人们专注于该领域。 - Cheryl Simon
谢谢,我会发布它...如果我找到解决方案,我会更新这个帖子。 - Stevanicus

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