Skip to content

Commit

Permalink
Added another check to the music player for proper memory allocation.…
Browse files Browse the repository at this point in the history
… If there is insufficient memory to allocate a track buffer, the music player won't run.

Added an explicit call to System.gc() when the music player loads a new song, as garbage collection per the default Android heuristics was sometimes inadequate to meet the dynamic memory demands of the game, especially when completing many levels in very rapid succession.

Improved the efficiency of the network protocol significantly for WiFi multiplayer with improved handling of the timing of player status messages.
  • Loading branch information
forteri76 committed May 16, 2014
1 parent d15453f commit 733c660
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 21 deletions.
13 changes: 6 additions & 7 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.jfedor.frozenbubble"
android:versionCode="27"
android:versionName="2.3">
android:versionCode="28"
android:versionName="2.4">

<supports-screens
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:smallScreens="true"
android:normalScreens="true"
android:largeScreens="true"
android:anyDensity="true"/>

<uses-sdk
Expand All @@ -21,7 +21,6 @@

<application
android:allowBackup="true"
android:debuggable="false"
android:icon="@drawable/app_frozen_bubble"
android:label="@string/app_name">

Expand All @@ -39,7 +38,7 @@

<activity
android:name="org.jfedor.frozenbubble.InterstitialActivity"
android:label="Interstitial" >
android:label="Interstitial">
</activity>

<activity
Expand Down
4 changes: 2 additions & 2 deletions src/com/efortin/frozenbubble/ModPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ public void loadNewSong(int songId, boolean startPlaying) {
// Pause the current song.
resplayer.PausePlay();
// Load the current MOD into the player.
resplayer.LoadMODResource(songId);
resplayer.LoadMODResource(songId, true);
if (startPlaying)
resplayer.UnPausePlay();
}
Expand All @@ -112,7 +112,7 @@ private void newMusicPlayer(Context context,
// Create a new music player.
resplayer = new MODResourcePlayer(context);
// Load the mod file.
resplayer.LoadMODResource(songId);
resplayer.LoadMODResource(songId, false);
// Loop the song forever.
resplayer.setLoopCount(PlayerThread.LOOP_SONG_FOREVER);
// Turn the music on or off.
Expand Down
34 changes: 25 additions & 9 deletions src/com/efortin/frozenbubble/NetworkGameManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -796,15 +796,6 @@ else if (newAction.playerID == remotePlayer.playerID) {
}
remoteActionList.add(newAction);
}
/*
* If this action is the most current, then we can postpone the
* cyclic status message. This is because we just received the
* data that the status message is supposed to prompt the remote
* player to send.
*/
if (newAction.localActionID == localStatus.remoteActionID) {
setStatusTimeout(STATUS_TIMEOUT);
}
}
}
}
Expand Down Expand Up @@ -1082,6 +1073,15 @@ public boolean getRemoteAction() {
}
remoteInterface.gotAction = true;
localStatus.remoteActionID++;
/*
* The local player status was updated. Set the status
* timeout to expire immediately and wake up the network
* manager thread.
*/
setStatusTimeout(0L);
synchronized(this) {
notify();
}
break;
}
}
Expand Down Expand Up @@ -1476,6 +1476,13 @@ public void reserveGameID() {
if (session != null) {
session.setFilter(myGameID);
}
/*
* The transport layer message format has been updated, so send
* an immediate status message to notify peers that we have
* reserved a game ID. This function is called directly from
* the network manager thread, so there is no need to notify the
* thread to wake up.
*/
setStatusTimeout(0L);
break;
}
Expand Down Expand Up @@ -1587,6 +1594,15 @@ public void sendLocalPlayerAction(int playerId,
tempAction.aimPosition = aimPosition;
addAction(tempAction);
transmitAction(tempAction);
/*
* The most current action IDs are being transmitted with this
* action. Postpone the player status message as it will be mostly
* redundant with the information in this message, albeit the
* delayed game field checksums may potentially lead to a more
* significant game synchronization discrepancy if one is currently
* present.
*/
setStatusTimeout(STATUS_TIMEOUT);
}

/**
Expand Down
16 changes: 15 additions & 1 deletion src/com/peculiargames/andmodplug/MODResourcePlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ public MODResourcePlayer(Context context) {
* MOD/XM song file, e.g. R.raw.coolsong
* @param modresource - Android resource id for a MOD/XM/etc. (tracker
* format) song file.
* @param gc - if <code>true</code>, perform garbage collection prior
* to loading the file.
*/
public boolean LoadMODResource(int modresource) {
public boolean LoadMODResource(int modresource, boolean gc) {
byte[] modData = null;
int currfilesize = 0;
InputStream mModfileInStream;
Expand All @@ -141,6 +143,18 @@ public boolean LoadMODResource(int modresource) {
* Allocate a buffer that can hold the current MOD file data.
*/
try {
/*
* This is a very critical and often very large memory allocation.
* Force the system to perform garbage collection to free up
* memory for the allocation.
*
* This is not recommended practice, as it can affect system
* performance. This should only be called when the user is not
* interacting with the system.
*/
if (gc) {
System.gc();
}
modData = new byte[currfilesize];
} catch (OutOfMemoryError oome) {
// Auto-generated catch block.
Expand Down
11 changes: 9 additions & 2 deletions src/com/peculiargames/andmodplug/PlayerThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,14 @@ public void run() {
* greater than the minbuffer size the audio system reports in the
* contructors...
*/
short[] mBuffer = new short[BUFFERSIZE];
short[] mBuffer;
try {
mBuffer = new short[BUFFERSIZE];
} catch (OutOfMemoryError oome) {
// Auto-generated catch block.
oome.printStackTrace();
mBuffer = null;
}

if (mStart_paused) {
mPlaying = false;
Expand All @@ -564,7 +571,7 @@ public void run() {
/*
* Main play loop.
*/
if (mMytrack != null) {
if ((mMytrack != null) && (mBuffer != null)) {
mMytrack.play();
}
else {
Expand Down

0 comments on commit 733c660

Please sign in to comment.