Skip to content

Commit

Permalink
Improve keyboard/dpad/controller support (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
dozingcat authored Mar 18, 2022
1 parent a3a83e8 commit 475ed6e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 33 deletions.
88 changes: 55 additions & 33 deletions app/src/main/java/com/dozingcatsoftware/bouncy/BouncyActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ public class BouncyActivity extends Activity {
final boolean useOpenGL20 = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;

View buttonPanel;
Button switchTableButton;
Button startGameButton;
Button resumeGameButton;
Button endGameButton;
Button switchTableButton;
CheckBox unlimitedBallsToggle;
final static int ACTIVITY_PREFERENCES = 1;

Expand Down Expand Up @@ -137,8 +139,10 @@ public class BouncyActivity extends Activity {
scoreView.setHighScores(highScores);

buttonPanel = findViewById(R.id.buttonPanel);
switchTableButton = findViewById(R.id.switchTableButton);
startGameButton = findViewById(R.id.startGameButton);
resumeGameButton = findViewById(R.id.resumeGameButton);
endGameButton = findViewById(R.id.endGameButton);
switchTableButton = findViewById(R.id.switchTableButton);
unlimitedBallsToggle = findViewById(R.id.unlimitedBallsToggle);

// TODO: allow field configuration to specify whether tilting is allowed
Expand Down Expand Up @@ -176,6 +180,7 @@ public void receivedOrientationValues(float azimuth, float pitch, float roll) {
}
// Reset frame rate since app or system settings that affect performance could have changed.
fieldDriver.resetFrameRate();
updateButtons();
}

@Override public void onPause() {
Expand All @@ -197,7 +202,7 @@ public void receivedOrientationValues(float azimuth, float pitch, float roll) {
glFieldView.onResume();
}
fieldViewManager.draw();
showPausedButtons();
updateButtons();
}
else {
unpauseGame();
Expand All @@ -211,13 +216,13 @@ public void receivedOrientationValues(float azimuth, float pitch, float roll) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (field.getGameState().isGameInProgress() && !field.getGameState().isPaused()) {
pauseGame();
showPausedButtons();
return true;
}
}
return super.onKeyDown(keyCode, event);
}


public void pauseGame() {
VPSoundpool.pauseMusic();
if (field.getGameState().isPaused()) return;
Expand All @@ -226,6 +231,8 @@ public void pauseGame() {
if (orientationListener != null) orientationListener.stop();
fieldDriver.stop();
if (glFieldView != null) glFieldView.onPause();

updateButtons();
}

public void unpauseGame() {
Expand All @@ -238,16 +245,34 @@ public void unpauseGame() {
fieldDriver.start();
if (glFieldView != null) glFieldView.onResume();

if (field.getGameState().isGameInProgress()) {
buttonPanel.setVisibility(View.GONE);
}
updateButtons();
}

void showPausedButtons() {
endGameButton.setVisibility(View.VISIBLE);
switchTableButton.setVisibility(View.GONE);
unlimitedBallsToggle.setVisibility(View.GONE);
buttonPanel.setVisibility(View.VISIBLE);
void updateButtons() {
GameState state = field.getGameState();
if (state.isPaused()) {
buttonPanel.setVisibility(View.VISIBLE);
startGameButton.setVisibility(View.GONE);
resumeGameButton.setVisibility(View.VISIBLE);
endGameButton.setVisibility(View.VISIBLE);
switchTableButton.setVisibility(View.GONE);
unlimitedBallsToggle.setVisibility(View.GONE);
resumeGameButton.requestFocus();
}
else {
if (state.isGameInProgress()) {
buttonPanel.setVisibility(View.GONE);
}
else {
buttonPanel.setVisibility(View.VISIBLE);
startGameButton.setVisibility(View.VISIBLE);
resumeGameButton.setVisibility(View.GONE);
endGameButton.setVisibility(View.GONE);
switchTableButton.setVisibility(View.VISIBLE);
unlimitedBallsToggle.setVisibility(View.VISIBLE);
startGameButton.requestFocus();
}
}
}

@Override public void onDestroy() {
Expand Down Expand Up @@ -335,10 +360,7 @@ void updateHighScoreAndButtonPanel() {
if (!field.getGameState().isGameInProgress()) {
// game just ended, show button panel and set end game timestamp
this.endGameTime = System.currentTimeMillis();
endGameButton.setVisibility(View.GONE);
switchTableButton.setVisibility(View.VISIBLE);
unlimitedBallsToggle.setVisibility(View.VISIBLE);
buttonPanel.setVisibility(View.VISIBLE);
updateButtons();

// No high scores for unlimited balls.
if (!state.hasUnlimitedBalls()) {
Expand Down Expand Up @@ -445,14 +467,23 @@ public void doStartGame(View view) {
return;
}
if (!field.getGameState().isGameInProgress()) {
buttonPanel.setVisibility(View.GONE);
resetFieldForCurrentLevel();
// https://github.com/dozingcat/Vector-Pinball/issues/91
// These actions need to be synchronized so that we don't try to
// start the game while the FieldDriver thread is updating the
// Box2d world. It's not clear what should be synchronized and what
// shouldn't; for example pauseGame() above should not be
// synchronized because that can deadlock the FieldDriver thread.
// All of this concurrency is badly in need of refactoring.
synchronized (field) {
buttonPanel.setVisibility(View.GONE);
resetFieldForCurrentLevel();

if (unlimitedBallsToggle.isChecked()) {
field.startGameWithUnlimitedBalls();
}
else {
field.startGame();
if (unlimitedBallsToggle.isChecked()) {
field.startGameWithUnlimitedBalls();
}
else {
field.startGame();
}
}
VPSoundpool.playStart();
endGameTime = null;
Expand Down Expand Up @@ -482,19 +513,10 @@ public void scoreViewClicked(View view) {
}
else {
pauseGame();
showPausedButtons();
}
}
else {
// https://github.com/dozingcat/Vector-Pinball/issues/91
// doStartGame() needs to be synchronized so that we don't try to
// start the game while the FieldDriver thread is updating the
// Box2d world. But pauseGame() above should not be synchronized
// because that can deadlock the FieldDriver thread. Yes, all of
// this concurrency is badly in need of refactoring.
synchronized (field) {
doStartGame(null);
}
doStartGame(null);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ private void updateFlippersFromTouchEvent(boolean left, boolean right) {
KeyEvent.KEYCODE_SPACE, KeyEvent.KEYCODE_ENTER, KeyEvent.KEYCODE_DPAD_CENTER);

public boolean handleKeyDown(int keyCode, KeyEvent event) {
android.util.Log.i("FMV", "key down: " + event.getKeyCode());
if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
synchronized (field) {
// Don't let a pressed flipper key start a game, but do launch a ball if needed.
Expand All @@ -354,6 +355,7 @@ public boolean handleKeyDown(int keyCode, KeyEvent event) {
}

public boolean handleKeyUp(int keyCode, KeyEvent event) {
android.util.Log.i("FMV", "key up: " + event.getKeyCode());
if (event.getAction() == KeyEvent.ACTION_UP) {
synchronized (field) {
if (!field.getGameState().isGameInProgress() || field.getGameState().isPaused()) {
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/res/layout/main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
android:layout_width="fill_parent"
android:layout_height="0px"
android:layout_weight="1"
android:focusable="false"
android:onClick="scoreViewClicked" />

<FrameLayout
Expand Down Expand Up @@ -37,12 +38,32 @@
android:orientation="vertical"
android:padding="20dp">

<Button
android:id="@+id/startGameButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:onClick="doStartGame"
android:focusableInTouchMode="true"
android:text="@string/start_game_button_label" />

<Button
android:id="@+id/resumeGameButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:onClick="doStartGame"
android:focusableInTouchMode="true"
android:text="@string/resume_game_button_label"
android:visibility="gone" />

<Button
android:id="@+id/endGameButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:onClick="doEndGame"
android:focusableInTouchMode="true"
android:text="@string/end_game_button_label"
android:visibility="gone" />

Expand All @@ -53,6 +74,7 @@
android:layout_marginBottom="10sp"
android:maxLines="1"
android:onClick="doSwitchTable"
android:focusableInTouchMode="true"
android:text="@string/change_table_button_label" />

<Button
Expand All @@ -61,6 +83,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="10sp"
android:onClick="doAbout"
android:focusableInTouchMode="true"
android:text="@string/help_button_label" />

<Button
Expand All @@ -69,12 +92,14 @@
android:layout_height="wrap_content"
android:layout_marginBottom="10sp"
android:onClick="doPreferences"
android:focusableInTouchMode="true"
android:text="@string/preferences_button_label" />

<CheckBox
android:id="@+id/unlimitedBallsToggle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusableInTouchMode="true"
android:text="@string/unlimited_balls_label" />
</TableLayout>

Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
<string name="change_table_button_label">Change Table</string>
<string name="help_button_label">Help</string>
<string name="preferences_button_label">Preferences</string>
<string name="start_game_button_label">Start Game</string>
<string name="resume_game_button_label">Resume Game</string>
<string name="end_game_button_label">End Game</string>
<string name="unlimited_balls_label">Unlimited Balls</string>

Expand Down

0 comments on commit 475ed6e

Please sign in to comment.