一、Activity生命周期
遊戲開發時我們隻需要重載onCreate(), onResume(), 和onPause() 方法,因為無論如何onResume(), 和onPause() 都會調用。當onPause() 之後,系統可能由於內存過低殺掉該activity,然後onStop() 和onDestroy()就不會被執行,而onStart()要在onStop()執行瞭才會被調用,onpause()之後喚醒activity隻會調用onResume().
1)In onCreate(), we set up our window and UI component that we
render to and receive input from.
2)In onResume(), we (re)start our main loop thread (discussed in the last
chapter).
3)In onPause(), we simply pause our main loop thread, and if
Activity.isFinishing() returns true, we also save any state we want
to persist to disk.
二、事件處理
1)多點觸控
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;//獲取點擊事件的種類
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;//獲取點擊事件的索引
int pointerId = event.getPointerId(pointerIndex);//獲取點擊事件的ID
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
touched[pointerId] = true;
x[pointerId] = (int)event.getX(pointerIndex);
y[pointerId] = (int)event.getY(pointerIndex);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
touched[pointerId] = false;
x[pointerId] = (int)event.getX(pointerIndex);
y[pointerId] = (int)event.getY(pointerIndex);
break;
比單點觸控多的新事件:
1、MotionEvent.ACTION_POINTER_DOWN: This event happens for any additional finger that
touches the screen after the first finger touches. The first finger will still produce a
MotionEvent.ACTION_DOWN event.
2、MotionEvent.ACTION_POINTER_UP: This is analogous the previous action. This gets
fired when a finger is lifted up from the screen and more than one finger is touching
the screen. The last finger on the screen to go up will produce a
MotionEvent.ACTION_UP event. This finger doesn’t necessarily have to be the first
finger that touched the screen.
利用單點觸控處理多點觸控
For this to happen, the merged events have to have the
same type. In reality this will only happen for the MotionEvent.ACTION_MOVE event, so we
only have to deal with this fact when processing said event type. To check how many
events are contained in a single MotionEvent, we use the
MotionEvent.getPointerCount() method, which tells us for how many fingers the
MotionEvent contains coordinates for. We then can fetch the pointer identifier and
coordinates for the pointer indices 0 to MotionEvent.getPointerCount() – 1 via the
MotionEvent.getX(), MotionEvent.getY(), and MotionEvent.getPointerId() methods.
case MotionEvent.ACTION_MOVE:
int pointerCount = event.getPointerCount();//獲取點擊事件的數量
for (int i = 0; i < pointerCount; i++) {
pointerIndex = i;
pointerId = event.getPointerId(pointerIndex);
x[pointerId] = (int)event.getX(pointerIndex);
y[pointerId] = (int
三、按鍵事件
public boolean onKey(View view, int keyCode, KeyEvent event)
keycode:代表手機上按鍵的唯一標示符,例如KeyCode.KEYCODE_A代表按瞭A鍵
keyEvent:它和MotionEvent類似,有兩個重要方法
KeyEvent.getAction(): 這個方法返回KeyEvent.ACTION_DOWN,
KeyEvent.ACTION_UP, and KeyEvent.ACTION_MULTIPLE.
KeyEvent.getUnicodeChar() :將點擊事件當做字符處理
註:獲取按鍵事件,view必須獲取瞭focus,View.setFocusableInTouchMode(true); View.requestFocus();
四、加速度感應器
1、通過Context接口獲取感應器服務
SensorManager manager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
2、檢測是否含有加速度感應器(可選,因為所有的android設備都裝有加速度感應器)
boolean hasAccel = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).size() > 0;
3、註冊監聽器
Sensor sensor = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
boolean success = manager.registerListener(listener, sensor,
SensorManager.SENSOR_DELAY_GAME);
五、音效處理
context.setVolumeControlStream(AudioManager.STREAM_MUSIC); //設置音量鍵為調節音量大小
用soundpool播放實時音效
1、SoundPool soundPool = new SoundPool(20, AudioManager.STREAM_MUSIC, 0);
2、把音效文件加載到內存
AssetManager assetManager = getAssets();
AssetFileDescriptor descriptor = assetManager.openFd("explosion.ogg"); //遊戲開發通常把音效圖片等資源放到assets中,便於用分級文件夾管理
int explosionId = soundPool.load(descriptor, 1);
3、播放
soundPool.play(explosionId, 1.0f, 1.0f, 0, 0, 1);
4、當不用的時候記得釋放內存
soundPool.unload(explosionId);
SoundPool.release();//釋放所有SoundPool所用的資源
用MediaPlayer播放背景音樂
1、MediaPlayer mediaPlayer = new MediaPlayer();
2、AssetManager assetManager = getAssets();
AssetFileDescriptor descriptor = assetManager.openFd("music.ogg");
mediaPlayer.setDataSource(descriptor.getFileDescriptor(), descriptor.getStartOffset(),
descriptor.getLength());
3、 打開音樂文件並檢查是否可播放
mediaPlayer.prepare();
4、播放
mediaPlayer.start();
mediaPlayer.pause();
mediaPlayer.stop(); //再次播放需要先mediaPlayer.prepare(),再mediaPlayer.start()
mediaPlayer.setLooping(true);
5釋放資源
mediaPlayer.release();
MediaPlayer占用相當大的資源,所以隻用於播放背景音樂
六、2D圖像處理
1、加載圖片
AssetManager assetManager = context.getAssets();
InputStream inputStream = assetManager.open("bob.png");
Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
inputStream.close();
2、繪制
Canvas.drawBitmap(Bitmap bitmap, float topLeftX, float topLeftY, Paint paint);
或Canvas.drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint);
2、釋放圖片資源
Bitmap.recycle();
Unless absolutely necessary, refrain from drawing bitmaps scaled. If
you know their scaled size, prescale them offline or during loading
time.
Always make sure you call the Bitmap.recycle() method if you no
longer need a Bitmap. Otherwise you’ll get some memory leaks or run
low on memory.
SurfaceView
SurfaceView比View的好處是可以在一個單獨的線程中處理遊戲邏輯,從而避免阻塞UI線程
1、在構造函數中獲取SurfaceHolder
SurfaceHolder holder = surfaceView.getHolder();
The SurfaceHolder is a wrapper around the Surface, and does some bookkeeping for
us. It provides us with two methods:
Canvas SurfaceHolder.lockCanvas(); //鎖定要繪制的Surface並返回一個可用的Canvas
SurfaceHolder.unlockAndPost(Canvas canvas); //解鎖Surface並且將我們剛才在Canvas上的繪制在屏幕上顯示
2、繪制
Canvas canvas = holder.lockCanvas();
canvas.draw#ff0000;
holder.unlockCanvasAndPost(canvas);
作者:shangdahao