I have a menu action and game activity that starts from the menu. Some (most) times when I start the game; all inputs freeze for a few (up to 10-ish) seconds and then play out in hyperspeed until I get this in logcat:
11-20 18:24:27.873: WARN/WindowManager(2473): Key dispatching timed out sending to southgrove.game/southgrove.game.Game 11-20 18:24:27.873: WARN/WindowManager(2473): Previous dispatch state: {{KeyEvent{action=1 code=4 repeat=0 meta=0 scancode=28 mFlags=8} to Window{4866c7a0 southgrove.game/southgrove.game.Game paused=false} @ 1290273811209 lw=Window{4866c7a0 southgrove.game/southgrove.game.Game paused=false} lb=android.os.BinderProxy@484e8a58 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4866c7a0 southgrove.game/southgrove.game.Game paused=false}}} 11-20 18:24:27.873: WARN/WindowManager(2473): Current dispatch state: {{null to Window{4833d500 southgrove.game/southgrove.game.Game paused=false} @ 1290273867876 lw=Window{4833d500 southgrove.game/southgrove.game.Game paused=false} lb=android.os.BinderProxy@485487b0 fin=false gfw=true ed=true tts=0 wf=false fp=false mcf=Window{4833d500 southgrove.game/southgrove.game.Game paused=false}}}
Menu Activity:
package southgrove.game; import southgrove.game.R; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.view.KeyEvent; import android.view.View; import android.view.View.OnClickListener; public class Menu extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.menu); View playButton = findViewById(R.id.play); playButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { startActivityForResult(new Intent(Menu.this, Game.class), 0); } }); View testButton = findViewById(R.id.test); testButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { startActivityForResult(new Intent(Menu.this, Test.class), 0); } }); View closeButton = findViewById(R.id.close); closeButton.setOnClickListener(new OnClickListener() { public void onClick(View view) { showDialog(QUIT_DIALOG); } }); } @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { showDialog(QUIT_DIALOG); } return super.onKeyDown(keyCode, event); } @Override protected Dialog onCreateDialog(int id) { Dialog dialog; switch (id) { case QUIT_DIALOG: AlertDialog.Builder quitDialogBuilder = new AlertDialog.Builder(this); quitDialogBuilder.setMessage("Exit the game?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Menu.this.finish(); } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); dialog = quitDialogBuilder.create(); break; default: dialog = null; } return dialog; } private final int QUIT_DIALOG = 0; }
Game action:
package southgrove.game; import southgrove.droidgl.DroidGL; import southgrove.droidgl.core.Camera; import southgrove.droidgl.core.Node; import southgrove.droidgl.core.RootNode; import southgrove.game.R; import southgrove.game.board.BoardBase; import southgrove.game.board.core.*; import southgrove.game.cameras.StupidCamera; import southgrove.input.OnTouchFilter; import android.app.Activity; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.os.Vibrator; import android.widget.TextView; public class Game extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.game); // Get fpsTextView reference fpsTextView = (TextView) findViewById(R.id.fpsTextView); // Build meshes TetrominoMesh.buildMeshes(); // Setup the DroidGL surface droidgl = (DroidGL) findViewById(R.id.droidGL); droidgl.setLongClickable(true); droidgl.setOnTouchListener(new GameSurfaceOnTouchFilter(false)); // Create and add camera final Camera camera = new StupidCamera(); camera.move(0, 0, 14); droidgl.registerCamera(camera); DroidGL.setActiveCamera(camera); // Create and add root node final Node rootNode = new RootNode(); droidgl.setRootNode(rootNode); // Create and add game board gameBoard = new GameBoard(droidgl, 32, 32, 8); rootNode.addChild(gameBoard); // start up updateHandler updateHandler = new UpdateHandler(); updateHandler.sleep(1); // get vibrator service vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE); } @Override public void onBackPressed() { showDialog(QUIT_DIALOG); } @Override protected Dialog onCreateDialog(int id) { Dialog dialog; switch (id) { case QUIT_DIALOG: AlertDialog.Builder quitDialogBuilder = new AlertDialog.Builder(this); quitDialogBuilder.setMessage("Really quit?") .setCancelable(false) .setPositiveButton("Yup!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { Game.this.finish(); } }) .setNegativeButton("Nope!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); dialog = quitDialogBuilder.create(); break; default: dialog = null; } return dialog; } @Override protected void onPause() { super.onPause(); droidgl.onPause(); } protected void onUpdate() { fpsTextView.setText("fps: " + String.valueOf(droidgl.getFps())); updateHandler.sleep(500); } @Override protected void onResume() { super.onResume(); droidgl.onResume(); } private DroidGL droidgl; private GameBoard gameBoard; private TextView fpsTextView; private Vibrator vibrator; private UpdateHandler updateHandler; private final int QUIT_DIALOG = 0; private class UpdateHandler extends Handler { @Override public void handleMessage(Message msg) { Game.this.onUpdate(); } public void sleep(long delayMillis) { this.removeMessages(0); if (!Game.this.isFinishing()) sendMessageDelayed(obtainMessage(0), delayMillis); } } private class GameSurfaceOnTouchFilter extends OnTouchFilter { public GameSurfaceOnTouchFilter(Boolean consumeEvent) { super(consumeEvent); } private float flipDeltaX; private float flipDeltaY; protected void doubleTap(float x, float y) { super.doubleTap(x, y); synchronized (gameBoard) { if (gameBoard.dropCursorTetromino()) { gameBoard.resetReactorTimer(); gameBoard.setCursorTetromino((int) (Tetromino.NUM_TYPES * Math.random() - 1), 0); if (gameBoard.removeConnectedTetrominoes(3)) { gameBoard.startShockWave(0, 0, 10f, 0.35f); vibrator.vibrate(300); } else { vibrator.vibrate(50); } } } } protected void down(int pointer, float x, float y) { super.down(pointer, x, y); if (pointer == 0) { } if (pointer == 1) { flipDeltaX = 0; flipDeltaY = 0; } } protected void up(int pointer, float x, float y) { super.up(pointer, x, y); synchronized (gameBoard) { } } protected void move(int pointer, float x, float y, float dx, float dy) { super.move(pointer, x, y, dx, dy); synchronized (gameBoard) { if (pointer == 0) { gameBoard.addInertia(-dx * 0.0045f, dy * 0.0045f); } if (pointer == 1) { flipDeltaX -= dx; flipDeltaY += dy; if (Math.abs(flipDeltaX) > 45 || Math.abs(flipDeltaY) > 45) { vibrator.vibrate(50); if (Math.abs(flipDeltaX) > Math.abs(flipDeltaY)) { if (flipDeltaX > 0) { gameBoard.rotateCursorTetromino(1); } else { gameBoard.rotateCursorTetromino(-1); } } else { if (flipDeltaY > 0) { gameBoard.rotateCursorTetromino(1); } else { gameBoard.rotateCursorTetromino(-1); } } flipDeltaX = 0; flipDeltaY = 0; } } } } } private class GameBoard extends BoardBase { public GameBoard(DroidGL droidGL, int width, int height, int depth) { super(droidGL, width, height, depth); } public void resetReactorTimer() { synchronized (this) { reactorTimer = 0; } } public void startShockWave(int gridPosX, int gridPosY, float length, float magnitude) { synchronized (this) { for (int i = 0; i < tetrominoes.size(); i++) { tetrominoes.get(i).bounce( (float) (Math.random() * 0.12f), (float) (Math.random() * magnitude) ); } } } @Override protected void onSetup() { synchronized (this) { setCursorTetromino((int) (Tetromino.NUM_TYPES * Math.random()), 0); for (int i = 0; i < 1024; i++) { addTetromino( (int) (Math.random() * Tetromino.NUM_TYPES), (int) (Math.random() * width / 2) * 2, (int) (Math.random() * height / 2) * 2, (int) (Math.random() * 2), (int) (Math.random() * 4)); } removeConnectedTetrominoes(3); } } @Override protected void onLogic(float timeFactor) { synchronized (this) { if (shiftTimer > shiftTime || tetrominoes.size() < 15) { shiftTimer = 0; shiftTime -= shiftTime / 5; shiftUp(); for (int i = 0; i < 256; i++) { addTetromino( (int) (Math.random() * Tetromino.NUM_TYPES), (int) (Math.random() * width / 2) * 2, (int) (Math.random() * height / 2) * 2, 0,// (int) (Math.random() * (depth - 1)), (int) (Math.random() * 4)); } } if (reactorTimer > 1f) { reactorTimer = 0; drop(); removeConnectedTetrominoes(3); } reactorTimer += timeFactor; shiftTimer += timeFactor; } } private float shiftTime = 60 * 5; private float reactorTimer; private float shiftTimer; } }
What could be the reason for this? Any ideas / specs are welcome. And yes, I know that a rather massive wall of code is sifted through.