SurfaceView模擬遊戲組合圖形移動動畫-劉宇

SurfaceView在繪製圖形方面有什麼特點呢,我們都知道,在Android中,圖形view交互都是通過主線程來完成的,這樣在遊戲、應用等多圖形交互的時候會發生主線程阻塞,形成卡頓現象。而SurfaceView則是通過另外一個線程來完成的,這樣就大大解決了這個問題。下面我們來模擬一下游戲組合圖形的移動動畫。

 

值得注意的是:SurfaceView在繪畫的時候必須要在SurfaceView創建完成後才能繪畫;在繪畫的時候需要鎖住畫板,畫完解鎖;在繪製移動等動畫效果的時候需要將canvas保存,隨後進行再restore掉。

 

源碼下載:http://download.csdn.net/detail/liuyu973971883/9598434

 

效果圖:

——————————————————————————————————————————————————————————

首先先創建一個空項目,我們不需要佈局文件,只需要在SurfaceView中繪畫即可

類文件分爲5個文件:

GameView.java用來繪畫圖形的,繼承SurfaceView實現callback接口,此處callback是SurfaceView包下的

Container.java圖形view容器,用來存放多個view的

Rect.java繪畫矩形view

Circle.java繪畫圓形view

MainActivity.java

 

下面代碼和對應解釋如下:

MainActivity.java:

 

package com.oak.learnsurfaceview;

import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;

public class GameView extends SurfaceView implements Callback{
	private Contanier contanier;
	private Rect rect;
	private Circle circle;
	private Timer timer;
	private TimerTask timerTask;
	public GameView(Context context) {
		super(context);
		//實例化容器
		contanier = new Contanier();
		//實例化矩形類
		rect = new Rect();
		//實例化圓形類
		circle = new Circle();
		//將圓形類加入到rect的容器中
		rect.addChildView(circle);
		//然後將矩形類加入到整個大的contanier容器中
		contanier.addChildView(rect);
		//爲SufaceView設置回調
		getHolder().addCallback(this);
	}
	//寫一個畫方法,一定要在SurfaceView創建完畢後才能調用此方法
	private void draw(){
		//在SurfaceView中畫東西一定要先鎖住畫板
		Canvas canvas = getHolder().lockCanvas();
		//將畫板設置爲白色
		canvas.drawColor(0xFFFFFFFF);
		//將畫板傳入到容器中
		contanier.draw(canvas);
		//解鎖畫板
		getHolder().unlockCanvasAndPost(canvas);
	}
	//開始計時器,用於不斷畫出組合圖形,形成移動效果
	public void startTimer(){
		timer = new Timer();
		timerTask = new TimerTask() {
			@Override
			public void run() {
				draw();
			}
		};
		timer.schedule(timerTask, 10, 10);
	}
	//暫停計時器,用於在SurfaceView銷燬後暫停,如果在SurfaceView銷燬後繼續畫則拋出異常
	public void stopTimer(){
		if(timer != null){
			timer.cancel();
			timer = null;
		}
	}
	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		
	}
	//SurfaceView創建完畢
	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
		startTimer();
	}
	//SurfaceView銷燬之前調用
	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		stopTimer();
	}
}


Container.java:

 

 

 

 

package com.oak.learnsurfaceview;

import java.util.ArrayList;
import java.util.List;
import android.graphics.Canvas;

//這個類是一個容器,用於存放View的
public class Contanier {
	//設置一個list集合用於存放這個容器
	private List<Contanier> list;
	private float x = 0;//記住組合圖形的x座標
	private float y = 0;//記住組合圖形的y座標
	public Contanier() {
		//在這個容器實例化的時候爲這個list集合實例化
		list = new ArrayList<Contanier>();
	}
	//對外公開draw方法,調用這個方法即可畫出所有View
	public void draw(Canvas canvas){
		//在移動畫板等動畫操作,必須先將畫板保存,然後釋放
		canvas.save();
		//移動圖形
		canvas.translate(getX(), getY());
		//調用子View複寫的childViewDraw方法
		childViewDraw(canvas);
		//遍歷這個集合,從而實現每個View都能夠實現畫的功能
		for (Contanier c : list) {
			c.draw(canvas);
		}
		//釋放畫板
		canvas.restore();
	}
	//定義這個方法,來供子View重寫
	public void childViewDraw(Canvas canvas){}
	//將View存放的容器存放於list中
	public void addChildView(Contanier child){
		list.add(child);
	}
	//移除view容器
	public void removeChildView(Contanier child){
		list.remove(child);
	}
	//下面設置x和y的get和set方法
	public float getX() {
		return x;
	}
	public float getY() {
		return y;
	}
	public void setX(float x) {
		this.x = x;
	}
	public void setY(float y) {
		this.y = y;
	}
}


Rect.java:

 

 

 

 

package com.oak.learnsurfaceview;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
//畫一個矩形
public class Rect extends Contanier{
	//畫筆
	private Paint paint;
	public Rect() {
		//實例化畫筆
		paint = new Paint();
		//將畫筆顏色設置爲藍色
		paint.setColor(Color.BLUE);
	}
	//重寫Contanier中的childViewDraw方法,畫一個100x100的矩形
	@Override
	public void childViewDraw(Canvas canvas) {
		super.childViewDraw(canvas);
		canvas.drawRect(0, 0, 100, 100, paint);
		//將X和Y座標+1,這裏只需要將矩形的x和y座標自增即可,因爲圓形是矩形的子View
		this.setX(this.getX()+1);
		this.setY(this.getY()+1);
	}
}


Circle.java:

 

 

package com.oak.learnsurfaceview;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
//畫一個圓形
public class Circle extends Contanier{
	//畫筆
	private Paint paint;
	public Circle() { 
		//獲取畫筆實例
		paint = new Paint();
		//設置畫筆爲紅色
		paint.setColor(Color.RED);
	}
	//重寫Contanier中的childViewDraw方法
	@Override
	public void childViewDraw(Canvas canvas) {
		super.childViewDraw(canvas);
		//畫一個圓位置x:50 y:50,半徑爲50
		canvas.drawCircle(50, 50, 50, paint);
	}
}


MainActivity.java:

 

 

package com.oak.learnsurfaceview;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //將GameView呈現在主Activity中
        setContentView(new GameView(this));
    }
}

 

 

 

By:Brycen Liu

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章