Mr.Nom接口框架实现:
AndroidFileIO.javapackage com.gamestudy.mrnom.framework.impl; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import android.content.res.AssetManager; import android.os.Environment; import com.gamestudy.mrnom.framework.FileIO; public class AndroidFileIO implements FileIO { AssetManager assets; String externalStoragePath; public AndroidFileIO(AssetManager assets) { this.assets = assets; this.externalStoragePath = Environment.getExternalStorageDirectory() .getAbsolutePath() + File.separator; } @Override public InputStream readAsset(String fileName) throws IOException { return assets.open(fileName); } @Override public InputStream readFile(String fileName) throws IOException { return new FileInputStream(externalStoragePath + fileName); } @Override public OutputStream writeFile(String fileName) throws IOException { return new FileOutputStream(externalStoragePath + fileName); } }
package com.gamestudy.mrnom.framework.impl; import java.io.IOException; import android.content.res.AssetFileDescriptor; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import com.gamestudy.mrnom.framework.Music; public class AndroidMusic implements Music, OnCompletionListener { MediaPlayer mediaPlayer; boolean isPrepared = false; public AndroidMusic(AssetFileDescriptor assetDescriptor) { mediaPlayer = new MediaPlayer(); try { mediaPlayer.setDataSource(assetDescriptor.getFileDescriptor(), assetDescriptor.getStartOffset(), assetDescriptor.getLength()); mediaPlayer.prepare(); isPrepared = true; mediaPlayer.setOnCompletionListener(this); } catch (Exception e) { throw new RuntimeException("Couldn't load music"); } } @Override public void dispose() { if (mediaPlayer.isPlaying()) mediaPlayer.stop(); mediaPlayer.release(); } @Override public boolean isLooping() { return mediaPlayer.isLooping(); } @Override public boolean isPlaying() { return mediaPlayer.isPlaying(); } @Override public boolean isStopped() { return !isPrepared; } @Override public void play() { if (mediaPlayer.isPlaying()) return; try { synchronized (this) { if (!isPrepared) mediaPlayer.prepare(); mediaPlayer.start(); } } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } @Override public void setLooping(boolean isLooping) { mediaPlayer.setLooping(isLooping); } @Override public void setVolume(float volume) { mediaPlayer.setVolume(volume, volume); } @Override public void stop() { mediaPlayer.stop(); synchronized (this) { isPrepared = false; } } @Override public void onCompletion(MediaPlayer player) { synchronized (this) { isPrepared = false; } } @Override public void pause() { if (mediaPlayer.isPlaying()) mediaPlayer.pause(); } }
package com.gamestudy.mrnom.framework.impl; import android.media.SoundPool; import com.gamestudy.mrnom.framework.Sound; public class AndroidSound implements Sound { int soundId; SoundPool soundPool; public AndroidSound(SoundPool soundPool, int soundId) { this.soundId = soundId; this.soundPool = soundPool; } @Override public void play(float volume) { soundPool.play(soundId, volume, volume, 0, 0, 1); } @Override public void dispose() { soundPool.unload(soundId); } }
package com.gamestudy.mrnom.framework.impl; import java.io.IOException; import android.app.Activity; import android.content.res.AssetFileDescriptor; import android.content.res.AssetManager; import android.media.AudioManager; import android.media.SoundPool; import com.gamestudy.mrnom.framework.Audio; import com.gamestudy.mrnom.framework.Music; import com.gamestudy.mrnom.framework.Sound; public class AndroidAudio implements Audio { AssetManager assets; SoundPool soundPool; public AndroidAudio(Activity activity) { activity.setVolumeControlStream(AudioManager.STREAM_MUSIC); this.assets = activity.getAssets(); this.soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0); } @Override public Music newMusic(String filename) { try { AssetFileDescriptor assetDescriptor = assets.openFd(filename); return new AndroidMusic(assetDescriptor); } catch (IOException e) { throw new RuntimeException("Couldn't load music '" + filename + "'"); } } @Override public Sound newSound(String filename) { try { AssetFileDescriptor assetDescriptor = assets.openFd(filename); int soundId = soundPool.load(assetDescriptor, 0); return new AndroidSound(soundPool, soundId); } catch (IOException e) { throw new RuntimeException("Couldn't load sound '" + filename + "'"); } } }
package com.gamestudy.mrnom.framework.impl; import android.content.Context; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; public class AccelerometerHandler implements SensorEventListener { float accelX; float accelY; float accelZ; public AccelerometerHandler(Context context) { SensorManager manager = (SensorManager) context .getSystemService(Context.SENSOR_SERVICE); if (manager.getSensorList(Sensor.TYPE_ACCELEROMETER).size() != 0) { Sensor accelerometer = manager.getSensorList( Sensor.TYPE_ACCELEROMETER).get(0); manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME); } } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // nothing to do here } @Override public void onSensorChanged(SensorEvent event) { accelX = event.values[0]; accelY = event.values[1]; accelZ = event.values[2]; } public float getAccelX() { return accelX; } public float getAccelY() { return accelY; } public float getAccelZ() { return accelZ; } }
尽管onSensorChanged()方法有可能在别的线程被调用,这里也没有用synchronization.因为java的内存模式可以保证原始类型譬如boolean,int和byte操作的原子性。
如果不是目前代码情况,需要加上适当的同步保护,譬如说如果在onSensorChanged()中有对成员变量的操作。
package com.gamestudy.mrnom.framework.impl; import java.util.ArrayList; import java.util.List; public class Pool<T> { public interface PoolObjectFactory<T> { public T createObject(); } private final List<T> freeObjects; private final PoolObjectFactory<T> factory; private final int maxSize; public Pool(PoolObjectFactory<T> factory, int maxSize) { this.factory = factory; this.maxSize = maxSize; this.freeObjects = new ArrayList<T>(maxSize); } public T newObject() { T object = null; if (freeObjects.size() == 0) object = factory.createObject(); else object = freeObjects.remove(freeObjects.size() - 1); return object; } public void free(T object) { if (freeObjects.size() < maxSize) freeObjects.add(object); } }