Я использую SurfaceView и поток рендеринга для разработки игры на основе структуры, такой как LunarLander.
Однако у меня возникло много проблем, и здесь я хочу указать на них все. Я желаю, чтобы любой, кто хочет развить игру, больше не должен бороться с ними. И любой, кто лучше разбирается в структуре, может поделиться своим опытом, потому что я все еще новичок в андроиде и очень хочу учиться:)
[1] Функция thread.start()
не должна вызываться более одного раза.
Многие статьи, упомянутые для создания потока при создании поверхности, чтобы снова выполнить операцию после приостановки действия с помощью метода:
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();
}
Вы можете видеть, что если поток не завершается и функция вызывается, активность падает.
[2] Если вы нажали кнопку "power" или "red phone", или телефон простаивает в течение нескольких минут, это будет состояние onPause()
, но поток все еще работает. Это действительно плохая практика, поэтому мне нужно найти способ, чтобы остановить поток и начать снова, когда onResume()
.
[3] Если блокировка экрана является портретной/альбомной, а ваша игра привязана к другой ориентации, блокировка экрана заставила вас "ориентироваться" один раз. Это значит снова начать свою деятельность. Я до сих пор не могу найти решение. (как я упоминал в ошибка ориентации экрана Android)
Вот мой код для устранения этих проблем:
UIThread
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());
}
}
}
Gameview
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()
для нового потока. И я установил boolean surfaceCreated
, чтобы знать, что onResume()
поступает с момента создания приложения в первый раз или происходит из ситуации "выключить экран".
Таким образом, нить умирает каждый раз, когда вызывается onPause()
. Кажется, это хорошая практика. Другой способ, чтобы поток остановить, а затем возобновить снова, это синхронизировать объект и вызвать wait/notify. Но я не знаю, что это лучше или нет.
Есть ли лучший способ управлять потоком рендеринга?