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

 

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