)
次のような onCreate メソッドがあります。
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
int frameBufferWidth = isLandscape ? 480 : 320;
int frameBufferHeight = isLandscape ? 320 : 480;
Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth,
frameBufferHeight, Config.RGB_565);
float scaleX = (float) frameBufferWidth
/ getWindowManager().getDefaultDisplay().getWidth();
float scaleY = (float) frameBufferHeight
/ getWindowManager().getDefaultDisplay().getHeight();
renderView = new AndroidFastRenderView(this, frameBuffer);
graphics = new AndroidGraphics(getAssets(), frameBuffer);
fileIO = new AndroidFileIO(this);
audio = new AndroidAudio(this);
input = new AndroidInput(this, renderView, scaleX, scaleY);
screen = getStartScreen();
setContentView(renderView);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame");
}
興味深い行は次のとおりです。
renderView = new AndroidFastRenderView(this, frameBuffer);
クラス AndroidFastRenderView(this, frameBuffer) のコード:
public class AndroidFastRenderView extends SurfaceView implements Runnable {
AndroidGame game;
Bitmap framebuffer;
Thread renderThread = null;
SurfaceHolder holder;
volatile boolean running = false;
public AndroidFastRenderView(AndroidGame game, Bitmap framebuffer) {
super(game);
this.game = game;
this.framebuffer = framebuffer;
this.holder = getHolder();
}
public void resume() {
running = true;
renderThread = new Thread(this);
renderThread.start();
}
public void run() {
Rect dstRect = new Rect();
long startTime = System.nanoTime();
while(running) {
if(!holder.getSurface().isValid())
continue;
float deltaTime = (System.nanoTime()-startTime) / 1000000000.0f;
startTime = System.nanoTime();
game.getCurrentScreen().update(deltaTime);
game.getCurrentScreen().present(deltaTime);
Canvas canvas = holder.lockCanvas();
canvas.getClipBounds(dstRect);
canvas.drawBitmap(framebuffer, null, dstRect, null);
holder.unlockCanvasAndPost(canvas);
}
}
public void pause() {
running = false;
while(true) {
try {
renderThread.join();
return;
} catch (InterruptedException e) {
// retry
}
}
}
}
私のアクティビティの後半には、onCreate の直後に実行される onResume メソッドがあります。
@Override
public void onResume() {
super.onResume();
wakeLock.acquire();
screen.resume();
renderView.resume();
}
ここでは、新しいスレッドを作成する renderView オブジェクトの resume メソッドが実行されていることがわかります (AnroidFastRenderView と比較してください)。
今私の質問。新しいスレッドは、run メソッドに含まれるコードを実行します。このコードは、ディスプレイに何かを描画する役割を果たします。しかし、新しいスレッドで何が実行され、何が実行されないのかわかりません。以下は、画面の例です。
public class MainMenuScreen extends Screen {
public MainMenuScreen(Game game) {
super(game);
}
public void update(float deltaTime) {
Graphics g = game.getGraphics();
List<TouchEvent> touchEvents = game.getInput().getTouchEvents();
game.getInput().getKeyEvents();
int len = touchEvents.size();
for(int i = 0; i < len; i++) {
TouchEvent event = touchEvents.get(i);
if(event.type == TouchEvent.TOUCH_UP) {
if(inBounds(event, 0, g.getHeight() - 64, 64, 64)) {
Settings.soundEnabled = !Settings.soundEnabled;
if(Settings.soundEnabled)
Assets.click.play(1);
}
if(inBounds(event, 64, 220, 192, 42) ) {
game.setScreen(new GameScreen(game));
if(Settings.soundEnabled)
Assets.click.play(1);
return;
}
if(inBounds(event, 64, 220 + 42, 192, 42) ) {
game.setScreen(new HighscoreScreen(game));
if(Settings.soundEnabled)
Assets.click.play(1);
return;
}
if(inBounds(event, 64, 220 + 84, 192, 42) ) {
game.setScreen(new HelpScreen(game));
if(Settings.soundEnabled)
Assets.click.play(1);
return;
}
}
}
}
private boolean inBounds(TouchEvent event, int x, int y, int width, int height) {
if(event.x > x && event.x < x + width - 1 &&
event.y > y && event.y < y + height - 1)
return true;
else
return false;
}
public void present(float deltaTime) {
Graphics g = game.getGraphics();
g.drawPixmap(Assets.background, 0, 0);
g.drawPixmap(Assets.logo, 32, 20);
g.drawPixmap(Assets.mainMenu, 64, 220);
if(Settings.soundEnabled)
g.drawPixmap(Assets.buttons, 0, 416, 0, 0, 64, 64);
else
g.drawPixmap(Assets.buttons, 0, 416, 64, 0, 64, 64);
}
public void pause() {
Settings.save(game.getFileIO());
}
public void resume() {
}
public void dispose() {
}
}
AnroidFastRenderView の run メソッドには、2 つの重要な行があります。
game.getCurrentScreen().update(deltaTime);
game.getCurrentScreen().present(deltaTime);
これらの両方の行は、MainMenuScreen の例の update メソッドと present メソッドを実行します。私の意見では、これは同じ新しいスレッドで引き続き発生します。したがって、現在起こっていることはすべて新しいスレッドによって行われます。アクティビティ クラスの onResume メソッドの後は、もう何もすることがないので、古いスレッドは何もする必要がありません。私の意見では、並行して起こることは何もありませんが、これが実際にはスレッドを追加する理由です。
どこが間違っていますか?
長い質問で申し訳ありません。あなたが私を助けてくれることを願っています。
ピーターに挨拶
PS: コードは本「Beginning Android Games」からのものです。