【问题标题】:Programming with SurfaceView and thread strategy for game development使用 SurfaceView 和线程策略进行游戏开发的编程
【发布时间】:2010-10-30 16:16:51
【问题描述】:

我正在使用 SurfaceView 和渲染线程来开发基于 LunarLander 等结构的游戏。

但是,我遇到了很多问题,在这里我想一一指出。我希望任何想要开发游戏的人都不再需要与他们抗争。任何对结构有更好了解的人都可以分享他们的经验,因为我还是 android 新手并且渴望学习:)

[1] 函数thread.start() 不应被多次调用。

很多文章提到在创建surface时创建线程,以便在activity暂停后使用该方法再次渲染:

public void surfaceCreated(SurfaceHolder holder) {
    // start the thread here so that we don't busy-wait in run()
    // waiting for the surface to be created
    if (thread.getState() == Thread.State.TERMINATED)
    {
        thread = new LunarThread(getHolder(), getContext(), getHandler());
    }
    thread.setRunning(true);
    thread.start();
}

你可以看到,如果线程没有被终止并且函数被调用,activity就会崩溃。

[2] 如果您按下“电源”或“红色电话”按钮,或者电话空闲几分钟,活动将处于onPause() 状态,但线程仍在运行。这是一个非常糟糕的做法,所以我需要找到一种方法让线程停止,并在onResume() 时重新开始。

[3] 如果屏幕锁定是纵向/横向,并且您的游戏被粘在另一个方向,屏幕锁定会强制您“定位”一次。这意味着再次开始活动。我仍然找不到解决方案。 (正如我在Android screen orientation bug 中提到的)

这是我解决这些问题的代码:

UI线程

public class UIThread extends Activity
{
    private gameView gameview;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        gameview = (gameView) findViewById(R.id.gameview);
    }
    protected void onPause()
    {
        super.onPause();
        Log.v("MY_ACTIVITY", "onPause");
        gameview.terminateThread();
        System.gc();
    }
    protected void onResume()
    {
        super.onResume();
        Log.v("MY_ACTIVITY", "onResume");
        if (gameview.surfaceCreated == true)
        {
            gameview.createThread(gameview.getHolder());
        }
    }
}

游戏视图

public class gameView extends SurfaceView implements SurfaceHolder.Callback
{
    boolean surfaceCreated;
    class gameThread extends Thread{}
    public gameView(Context context, AttributeSet attrs)
    {
        super(context, attrs);context.getResources();
            Log.v("MY_ACTIVITY", "gameView");
        surfaceCreated = false;
    }
    public void createThread (SurfaceHolder holder)
    {
            thread = new gameThread(holder);
        thread.run = true;
        thread.start();
    }
    public void terminateThread ()
    {
        thread.run = false;
        try
        {
            thread.join();
        }
        catch (InterruptedException e)
        {
            Log.e("FUNCTION", "terminateThread corrupts");
        }       
    }
    public void surfaceCreated(SurfaceHolder holder)
    {
        Log.v("MY_ACTIVITY", "surfaceCreated");
        if (surfaceCreated == false)
        {
            createThread(holder);
            surfaceCreated = true;
        }
    }
    public void surfaceDestroyed(SurfaceHolder holder) 
    {
        Log.v("MY_ACTIVITY", "surfaceDestroyed");
        surfaceCreated = false;
    }
}

清单

<activity android:name=".UIThread"
          android:screenOrientation="landscape"
          android:configChanges="orientation">

我使用onResume() 而不是surfaceCreated() 来创建新线程。我设置了一个布尔值surfaceCreated 来知道onResume() 来自第一次创建应用程序,或者来自“屏幕关闭”情况。

所以每次调用onPause() 时线程都会死掉。似乎是一个很好的做法。让线程停止然后再次恢复的另一种方法是同步对象并调用等待/通知。但不知道好不好。

有没有更好的方法来控制渲染线程?

【问题讨论】:

标签: android multithreading android-activity surfaceview


【解决方案1】:

解决办法在这里

public void surfaceCreated(SurfaceHolder holder){

            if (plot_thread.getState() == Thread.State.TERMINATED) {
                plot_thread = new WaveformPlotThread(getHolder(), this);
                plot_thread.setRunning(true);
                plot_thread.start();
            }
            else {
                plot_thread.setRunning(true);
                plot_thread.start();
            }
        }

【讨论】:

    【解决方案2】:

    希望对你有帮助

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    
       //if it is the first time the thread starts
       if(thread.getState() == Thread.State.NEW){
        thread.setRunning(true);//riga originale
        thread.start();//riga originale
       }
    
       //after a pause it starts the thread again
       else
       if (thread.getState() == Thread.State.TERMINATED){
           thread = new MainThread(getHolder(), this);
           thread.setRunning(true);
           thread.start();  // Start a new thread
           }
       }
    

    还有这个

        @Override
        protected void onPause() {
        Log.d(TAG, "Pausing...");
        MainThread.running=false;//this is the value for stop the loop in the run()
        super.onPause();
        }
    

    【讨论】:

    • 鲍里斯非常感谢您的回答,经过长时间的搜索,它的简单和工作。
    • 我使用了这个代码。我在某些设备上的问题是创建表面需要时间;几秒钟。有什么解决办法吗?
    【解决方案3】:

    我一直在处理同样的问题。我正在学习 Android 上的游戏开发,并且我的第一个项目也基于 Lunar Lander 示例。我发现 Chris Pruett 创建的SpriteMethodTest 项目在线程管理方面实现了更好的方法。不过,这都是关于使用通知和等待方法的。我不知道它是否比您的解决方案更好。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-18
      • 2012-03-06
      • 2019-04-21
      • 1970-01-01
      • 1970-01-01
      • 2020-06-01
      • 1970-01-01
      相关资源
      最近更新 更多