求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
Android游戏开发之单点触摸与多点触摸的响应方式(十三)
 

发布于 2011-11-01

 

游戏开发中的触摸事件

在游戏开发中监听屏幕触摸事件须要在View中重写父类onTouchEvent方法,在重写的方法中拦截用户触摸屏幕的一些信息,比如触摸屏幕的X 、 Y坐标 触摸屏幕发生的事件 触摸按下 触摸抬起 触摸移动,触摸屏幕发生的时间 等等, 我们先看看onTouchEvent的函数原型。

函数中的Event 参数的意思为当前触摸事件的对象,这个对象中包含着当前触摸事件的一切信息。比如ecent.getAction()可以拿到当前触摸事件的名称,根据触摸事件的名称可以判断当前是触摸按下 还是 触摸移动 还是 触摸抬起。 event.getX()与 event.getY()可以拿到当前触摸屏幕的X Y坐标。event.getEventTime(); 可以拿到当前触发触摸事件的时间,等等所有的信息。

@Override  

public boolean onTouchEvent(MotionEvent event) {  

    int action = event.getAction();  

    mPosX = (int) event.getX();  

    mPosY = (int) event.getY();  

    switch (action) {  

    // 触摸按下的事件  

    case MotionEvent.ACTION_DOWN:  

    Log.v("test""ACTION_DOWN");  

    break;  

    // 触摸移动的事件  

    case MotionEvent.ACTION_MOVE:  

    Log.v("test""ACTION_MOVE");  

    break;  

    // 触摸抬起的事件  

    case MotionEvent.ACTION_UP:  

    Log.v("test""ACTION_UP");  

    break;  

    }  

/       return super.onTouchEvent(event);  

    return true;  

这个函数是具有有返回值的,须要返回一个布尔值。大家发现我将return super.onTouchEvent(event)注释掉了而是直接return ture。 我给同学们解释一下为什么要着么操作。onTouchEvent方法不是我们手动调用的而是系统调用的 它的返回值会直接通知系统是否回调方法。如果说在这里return false onTouchEvent方法永远不会在被回调也就是说它只能响应触摸按下操作,触摸移动事件 和触摸抬起事件永远都不会在被响应 ,log只会打印出"ACTION_DOWN"。 如果这里return super.onTouchEvent(event); 调用父类的方法来得到返回值返回 ,这样也是有问题的因为调用父类的onTouchEvent方法可能也会返回false 这样一来依然会无法响应触摸移动事件和触摸抬起事件。所以为了正确的处理触摸事件在这里我们直接return ture 这样一来就万无一失了,Log中会将所有信息都打印出来。

1.单点触摸

在下面这个DEMO中 用手触摸 移动 屏幕后 下面的icon图片会跟随这我的手势移动。 代码实现主要是在onTouchEvent方法中时时去计算手触摸屏幕各个状态的坐标 然后调用 postInvalidate(); 方法去通知UI刷新屏幕重新显示图片 文字的位置以及内容。 具体相关内容见Android游戏开发之构建游戏框架View与SurFaceView的区别(五)

import android.app.Activity;  

import android.content.Context;  

import android.graphics.Bitmap;  

import android.graphics.BitmapFactory;  

import android.graphics.Canvas;  

import android.graphics.Color;  

import android.graphics.Paint;  

import android.os.Bundle;  

import android.util.Log;  

import android.view.MotionEvent;  

import android.view.View;  

public class ViewActivity extends Activity {  

    @Override  

    public void onCreate(Bundle savedInstanceState) {  

    super.onCreate(savedInstanceState);  

    setContentView(new MyView(this));  

    }  

    public class MyView extends View {  

    /** 触摸后绘制的图片 **/  

    Bitmap mBitmap = null;  

    /** 游戏画笔 **/  

    Paint mPaint = null;  

    /** 触摸后在屏幕中显示的位置 **/  

    int mPosX = 0;  

    int mPosY = 0;  

    /**事件触发时间**/  

    Long mActionTime = 0L;  

    public MyView(Context context) {  

        super(context);  

        /** 设置当前View拥有控制焦点 **/  

        this.setFocusable(true);  

        /** 设置当前View拥有触摸事件 **/  

        this.setFocusableInTouchMode(true);  

        /** 加载图片 **/  

        mBitmap = BitmapFactory.decodeResource(getResources(),  

            R.drawable.item);  

        mPaint = new Paint();  

        mPaint.setColor(Color.WHITE);  

    }  

    @Override  

    protected void onDraw(Canvas canvas) {  

        /** 绘制图片 **/  

        canvas.drawBitmap(mBitmap, mPosX, mPosY, mPaint);  

        canvas.drawText("当前X坐标:"+mPosX, 020, mPaint);  

        canvas.drawText("当前Y坐标:"+mPosY, 040, mPaint);  

        canvas.drawText("事件触发时间:"+mActionTime, 060, mPaint);  

        super.onDraw(canvas);  

    }  

    @Override  

    public boolean onTouchEvent(MotionEvent event) {  

        int action = event.getAction();  

        mPosX = (int) event.getX();  

        mPosY = (int) event.getY();  

        switch (action) {  

        // 触摸按下的事件  

        case MotionEvent.ACTION_DOWN:  

        Log.v("test""ACTION_DOWN");  

        break;  

        // 触摸移动的事件  

        case MotionEvent.ACTION_MOVE:  

        Log.v("test""ACTION_MOVE");  

        break;  

        // 触摸抬起的事件  

        case MotionEvent.ACTION_UP:  

        Log.v("test""ACTION_UP");  

        break;  

        }  

        /**得到事件触发时间**/  

        mActionTime = event.getEventTime();  

        /** 通知UI线程刷新屏幕 **/  

        postInvalidate();  

        // return super.onTouchEvent(event);  

        return true;  

    }  

    }  

2.多点触摸

由于模拟器只能用鼠标点击一个点 无法模拟多点触摸,所以我用真机来调试多点触摸。下面这张图是我用豌豆荚在真机中截的图,此时我两只手指正在手机屏幕中触摸移动。界面中正确的根据我的手势来移动图片以及显示的内容。这里强调一下多点触摸并不是所有手机都支持 有些手机支持很多点有些手机可能只支持单点。就那我的手机来说只支持两点触摸。所以无论我用多少根手指头在我的手机屏幕上比划 也只会出现2个触摸点,如下图所示。

下面我们详细的说一下代码的实现方式,多点触摸和单点触摸一样都是在onTouchEvent中去监听触摸事件。调用方法event.getPointerCount(); 可以拿到当前屏幕同时触摸点的数量 以我的手机为例因为只支持两点触摸所以在我的手机上调用该方法最多只会返回2。 拿到了触摸屏幕点的数量以后 可以使用for循环来遍历当前屏幕的所有触摸点,调用event.getX(i); 与 event.getY(i); 方法 将ID作为参数传入会得到每个点在屏幕中显示的X Y坐标值。最后根据坐标值将图片与内容绘制在手机屏幕中。

import android.app.Activity;  

import android.content.Context;  

import android.graphics.Bitmap;  

import android.graphics.BitmapFactory;  

import android.graphics.Canvas;  

import android.graphics.Color;  

import android.graphics.Paint;  

import android.os.Bundle;  

import android.util.Log;  

import android.view.MotionEvent;  

import android.view.SurfaceHolder;  

import android.view.SurfaceView;  

import android.view.Window;  

import android.view.WindowManager;  

import android.view.SurfaceHolder.Callback;  

public class SurfaceViewAcitvity extends Activity {  

    MyView mAnimView = null;  

    @Override  

    public void onCreate(Bundle savedInstanceState) {  

    super.onCreate(savedInstanceState);  

    // 全屏显示窗口  

    requestWindowFeature(Window.FEATURE_NO_TITLE);  

    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  

        WindowManager.LayoutParams.FLAG_FULLSCREEN);  

    // 显示自定义的游戏View  

    mAnimView = new MyView(this);  

    setContentView(mAnimView);  

    }  

    public class MyView extends SurfaceView implements Callback {  

    /** 触摸后绘制的图片 **/  

    Bitmap mBitmap = null;  

    /** 游戏画笔 **/  

    Paint mPaint = null;  

    SurfaceHolder mSurfaceHolder = null;  

    /** 控制游戏更新循环 **/  

    boolean mRunning = false;  

    /** 游戏画布 **/  

    Canvas mCanvas = null;  

    public MyView(Context context) {  

        super(context);  

        /** 设置当前View拥有控制焦点 **/  

        this.setFocusable(true);  

        /** 设置当前View拥有触摸事件 **/  

        this.setFocusableInTouchMode(true);  

        /** 加载图片 **/  

        mBitmap = BitmapFactory.decodeResource(getResources(),  

            R.drawable.item);  

        /** 拿到SurfaceHolder对象 **/  

        mSurfaceHolder = this.getHolder();  

        /** 将mSurfaceHolder添加到Callback回调函数中 **/  

        mSurfaceHolder.addCallback(this);  

        /** 创建画布 **/  

        mCanvas = new Canvas();  

        /**创建画笔**/   

        mPaint = new Paint();  

        mPaint.setColor(Color.WHITE);  

    }  

    @Override  

    public boolean onTouchEvent(MotionEvent event) {  

        /** 拿到触摸的状态 **/  

        int action = event.getAction();  

        /** 控制当触摸抬起时清屏 **/  

        boolean reset = false;  

        switch (action) {  

        // 触摸按下的事件  

        case MotionEvent.ACTION_DOWN:  

        Log.v("test""ACTION_DOWN");  

        break;  

        // 触摸移动的事件  

        case MotionEvent.ACTION_MOVE:  

        Log.v("test""ACTION_MOVE");  

        break;  

        // 触摸抬起的事件  

        case MotionEvent.ACTION_UP:  

        Log.v("test""ACTION_UP");  

        reset = true;  

        break;  

        }  

        // 在这里加上线程安全锁  

        synchronized (mSurfaceHolder) {  

        /** 拿到当前画布 然后锁定 **/  

        mCanvas = mSurfaceHolder.lockCanvas();  

        /** 清屏 **/  

        mCanvas.drawColor(Color.BLACK);  

        if (!reset) {  

            /** 在屏幕中拿到同时触碰的点的数量 **/  

            int pointCount = event.getPointerCount();  

            /** 使用循环将每个触摸点图片都绘制出来 **/  

            for (int i = 0; i < pointCount; i++) {  

            /** 根据触摸点的ID 可以讲每个触摸点的X Y坐标拿出来 **/  

            int x = (int) event.getX(i);  

            int y = (int) event.getY(i);  

            int showX = i * 150;  

            mCanvas.drawBitmap(mBitmap, x, y, mPaint);  

            mCanvas.drawText("当前X坐标:"+x, showX, 20, mPaint);  

            mCanvas.drawText("当前Y坐标:"+y, showX, 40, mPaint);  

            mCanvas.drawText("事件触发时间:"+event.getEventTime(), showX, 60, mPaint);  

            }  

        }else {  

            mCanvas.drawText("请多点触摸当前手机屏幕" ,020, mPaint);  

        }  

        /** 绘制结束后解锁显示在屏幕上 **/  

        mSurfaceHolder.unlockCanvasAndPost(mCanvas);  

        }  

        // return super.onTouchEvent(event);  

        return true;  

    }  

    @Override  

    public void surfaceChanged(SurfaceHolder holder, int format, int width,  

        int height) {  

    }  

    @Override  

    public void surfaceCreated(SurfaceHolder holder) {  

    }  

    @Override  

    public void surfaceDestroyed(SurfaceHolder holder) {  

    }  

    }  


相关文章

深度解析:清理烂代码
如何编写出拥抱变化的代码
重构-使代码更简洁优美
团队项目开发"编码规范"系列文章
相关文档

重构-改善既有代码的设计
软件重构v2
代码整洁之道
高质量编程规范
相关课程

基于HTML5客户端、Web端的应用开发
HTML 5+CSS 开发
嵌入式C高质量编程
C++高级编程

 
分享到
 
 
     


android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...