标签:
View类和surfaceView详细介绍:
view类:
view类是Android的一个超类,这个类几乎包含了所有的屏幕类型,每一个view都有一个用于绘画 的画布,这个画布可以进行任意的扩展。布局视图可以通过Android的XML来进行。在游戏开发中当然也可以自定义视图(view),让这个画布的功能更能满足我们在游戏开发是的需要,在Android中,任何一个view类只需要重写onDraw方法来实现界面显示,自定义视图可以是复杂的3D实现,也可以是简单地文本形式等。
游戏中最重要的就是与玩家交互,比如键盘输入、触笔点击等事件,而我们该如何处理这些事件呢?OnKeyUp(按键弹起)、OnKeyDown(按键按下)、OoKeyMultiple(多个事件连续发生时调用)、OnTouchEvent(触摸事件)等方法,可以轻松的处理游戏内的事件消息。所以当你在继承view是,需要重载这几个方法,当有按键弹起或按下时,按键代码会自动传输给相应的方法来处理。
游戏的核心是不断地绘图和刷新界面,图我们已经知道,需要使用onDraw方法绘制。下面我们来分析一下如何刷新界面。Android中提供了invalidate方法来实现界面的刷新,注意,invalidate方法不能直接在线程中调用,因为它违背了单线程模型,Android UI 操作并不是线程安全的,并且这些操作必须在UI线程中执行,因此Android中最常用的方法是利用Handler来实现UI 线程的更新。
下面通过一个在屏幕上不停变换颜色的矩形来分析Android中界面的更新。
//新建一个类,扩展至View类
public class GameView extends View{
public int count =0 ; //用于控制颜色的转换
public static int y=100; //矩形的y轴坐标
public static int x=100; //矩形的x轴坐标
public GameView(Context context){
super(context);
}
//重写onDraw方法,用于绘制界面
public void onDraw(Canvas canvas){
if(count<100){
count++;
}else{
count=0;
}
Paint paint = new Paint();
switch(count%4){
case 0:
//设置画笔颜色
paint.setColor(Color.RED);
break;
case 1:
paint.setColor(Color.BLUE);
break;
case 2:
paint.setColor(Color.YELLOW);
break;
case 3:
paint.setColor(Color.GREEN);
break;
}
//绘制一个矩形
canvas.drawRect(x,y,300+x,y+300, paint);
}
}
上面的类主要用于绘制界面,下面我们还需要一个用来控制整个应用的操作,比如:事件处理、更新频率的类,这就需要实现一个Activity类。
public class MainActivity extends Activity {
//一个十六进制的整形数,用于判断接受到的信息是否是我们想要的信息
private static final int REFRESH = 0X00000001;
//声明GameView类对象
private GameView gameView = null;;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置无标题模式
requestWindowFeature(Window.FEATURE_NO_TITLE);
//实例化GameView对象
gameView = new GameView(this);
setContentView(gameView);
//启动一个线程
new Thread(new MyThread()).start();
}
//声明并创建一个Handler对象用于接受消息
Handler handler = new Handler(){
//接受到消息后的处理
public void handleMessage(Message msg) {
switch(msg.what){
case MainActivity.REFRESH:
gameView.invalidate();
}
super.handleMessage(msg);
}
};
/*class MyThread implements Runnable{
public void run(){
while(!Thread.currentThread().isInterrupted()){
Message message = new Message();
message.what = MainActivity.REFRESH;
//发送消息
handler.sendMessage(message);
}
try{
Thread.sleep(1000);
}catch(InterruptedException e){
Thread.currentThread().interrupt();
}
}
}*/
//安卓中还提供了postInvalidate()方法来更新界面,该方法使用简单,可以直接在线程中更新,同樣可以更新界面,並且不需要Handle接受消息
class MyThread implements Runnable{
public void run(){
while(!Thread.currentThread().isInterrupted()){
try{
Thread.sleep(1000);
}catch(InterruptedException e){
Thread.currentThread().interrupt();
}
gameView.postInvalidate();
}
}
}
public boolean onKeyDown(int keyCode,KeyEvent event){
switch(keyCode){
case KeyEvent.KEYCODE_DPAD_DOWN:
GameView.y += 10;
break;
case KeyEvent.KEYCODE_DPAD_LEFT:
GameView.x -= 10;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
GameView.x += 10;
break;
case KeyEvent.KEYCODE_DPAD_UP:
GameView.y -= 10;
break;
}
return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()!=MotionEvent.ACTION_DOWN){
return false;
}
GameView.x=(int) event.getX();
GameView.y=(int) event.getY();
return super.onTouchEvent(event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
surfaceView类介绍:
view类只适合开发一些需要被动更新界面的游戏,如棋牌类游戏,但是当需要开发复杂的游戏,而且对游戏的执行效率要求更高时,view类就不能满足需求了,这时就需要surfaceView类进行开发。例如对速度要求很高的游戏,可以使用双缓冲显示,游戏中的背景、人物、动画都需要绘制在一个画布(canvas)上,而surfaceView可以直接访问一个画布,surfaceview类是提供给需要直接画像素而不是使用窗口部件的应用使用的。安卓图形系统中一个重要的概念是surface,view,及其子类如(TextView,Button)要画在surface上,每个surface创建一个canvas对象(但属性时常改变),用来管理view在surface上的操作。
在使用surfaceView开发游戏时需要注意的是,使用它绘制时,一般的出现在最顶层,使用时还需对其进行创建、销毁,情况改变时进行监视,这就需要实现surfaceHolder.callback接口,如果要对被绘制的画布进行裁剪,控制其大小时都需要surfaceHolder来完成处理。在程序中,surfaceholder对象需要通过getHolder方法来获取,同时还需要addCallback方法添加“回调函数”。
surfaceChanged:在surface的大小发生改变时激发
surfaceCreated:在创建surface的时候激发
surfaceDestroyed:在销毁surface的时候激发】
addCallback:给surfaceView添加一个回调函数
lockCanvas:锁定画布,绘图之前,必须锁定画布才能得到当前画布对象
unlockCanvasAndPost:解锁画布,绘图完成后,需要解锁画布才能显示出来
removeCallback:从surfaceView中移除回调函数
surfaceview和view的明显不同之处在于,surfaceview不需要通过线程来更新视图,但在绘图之前必须通过lockCanvas放法锁定画布,得到画布对象,然后在画布上进行绘制,当绘制完成后,需要通过unlockCanvasAndPost方法解锁画布,于是才能显示在屏幕上,surfaceView和view的事件处理一样,这里不多做介绍 。
下面的程序实现了一个不断变化颜色的圆,用来分析通过surfaceView类开发游戏。
public class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
public static float x = 200;
public static float y = 200;
private SurfaceHolder surfaceHolder= null;
private boolean mLoop = false;
private int count = 0;
public MySurfaceView(Context context) {
super(context);
surfaceHolder = this.getHolder();
surfaceHolder.addCallback(this);
mLoop = true;
}
@Override
public void run() {
while(mLoop){
try{
Thread.sleep(10);
}catch(Exception e){
e.printStackTrace();
}
synchronized(surfaceHolder){
draw();
}
}
}
public void draw(){
Canvas canvas = surfaceHolder.lockCanvas();
if(canvas == null || surfaceHolder == null){
return;
}
if(count <100 ){
count ++;
}else{
count = 0;
}
Paint paint = new Paint();
paint.setColor(Color.BLACK);
canvas.drawRect(0,0,this.getWidth(),getHeight(),paint);
switch(count%4){
case 0:
paint.setColor(Color.RED);
break;
case 1:
paint.setColor(Color.BLUE);
break;
case 2:
paint.setColor(Color.YELLOW);
break;
case 3:
paint.setColor(Color.GREEN);
break;
}
canvas.drawCircle(x, y, 30, paint);
surfaceHolder.unlockCanvasAndPost(canvas);
}
@Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
new Thread(this).start();
}
@Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder arg0) {
mLoop = false;
}
}
Activity类:
public class MainActivity extends Activity {
private MySurfaceView mySurfaceView= null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mySurfaceView = new MySurfaceView(this);
setContentView(mySurfaceView);
}
public boolean onKeyUp(int keyCode,KeyEvent event){
if(keyCode == KeyEvent.KEYCODE_DPAD_DOWN){
MySurfaceView.y += 20;
}else if(keyCode == KeyEvent.KEYCODE_DPAD_UP){
MySurfaceView.y -= 20;
}else if(keyCode == KeyEvent.KEYCODE_DPAD_LEFT){
MySurfaceView.x -= 20;
}else if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT){
MySurfaceView.x += 20;
}
return super.onKeyUp(keyCode, event);
}
public boolean onTouchEvent(MotionEvent event){
MySurfaceView.x = event.getX();
MySurfaceView.y = event.getY();
return super.onTouchEvent(event);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
标签:
原文地址:http://www.cnblogs.com/Smart-Du/p/4299389.html