Android游戏开发之触摸轨迹曲线的实现处理(二十四)

91
回复
661694
查看
  [复制链接]

249

主题

278

帖子

17

安币

初级码农

Rank: 1

发表于 2011-9-3 00:56:13 | 显示全部楼层 |阅读模式
Android游戏开发之触摸轨迹曲线的实现处理




        在上一章的学习中我们已经知道如何处理游戏中的触摸事件,这一章将向同学们介绍绘制游戏触摸轨迹的曲线图,在onTouchEvent方法中我们可以拿到手指在屏幕中触摸点 X Y时时的坐标,这章我们研究的课题就是如何把这些点变成一种无规则轨迹并且将这条无规则曲线显示在屏幕中。

        Android提供了一个Path类 , 顾名思义这个类可以设置曲线路径轨迹。任何无规则的曲线实际上都是由若干条线段组成,而线段的定义为两点之间最短的一条线。path类就 可以记录这两点之间的轨迹,那么若干个Path 就是我们须要绘制的无规则曲线。

下面介绍一下API 中path类设置轨迹路径的方法
public class
Path
extends Object
java.lang.Object
        android.graphics.Path
quadTo(float x1, float y1, float x2, float y2)
Add a quadratic bezier from the last point, approaching control point (x1,y1), and ending at (x2,y2).

解释:
参数1 轨迹起始点X坐标
参数2 轨迹起始点Y坐标
参数3 轨迹结束点X坐标
参数4 轨迹结束点Y坐标
所以根据这个参数就可以设置一条线段轨迹。

         同学们,我们先看一张效果图。 为了设置一条比较圆滑好看的曲线我们需要对游戏画笔进行一些设置。注释已经在代码中写的很清楚了,在这里我详细说一下 设置画笔风格  mPaint.setStyle(Paint.Style.STROKE); 意思是设置画笔的风格 android 画笔一共提供了三种风格Paint.Style.STROKE 、Paint.Style.FILL、Paint.Style.FILL_AND_STROKE 意思分别为 空心 、实心、实心与空心 。如果不设置的话默认为 Paint.Style.FILL,在这里必需设置成空心 因为如果一旦设置成实心或者实心与空心那么画笔会把path路径中间包住这样就不是曲线线段了,所以同学们注意一下这里。
  1.             /** 创建曲线画笔 **/
  2.             mPaint = new Paint();
  3.             mPaint.setColor(Color.BLACK);
  4.             /**设置画笔抗锯齿**/
  5.             mPaint.setAntiAlias(true);
  6.             /**画笔的类型**/
  7.             mPaint.setStyle(Paint.Style.STROKE);
  8.             /**设置画笔变为圆滑状**/
  9.             mPaint.setStrokeCap(Paint.Cap.ROUND);
  10.             /**设置线的宽度**/
  11.             mPaint.setStrokeWidth(5);
复制代码


        在触摸按下事件中 通过moveTo() 方法设置触摸屏幕点为轨迹的起始点,这样在触摸移动事件中设置曲线的轨迹 起始点为上次触摸点 结束点为本次触摸点。使用quadTo方法记录每次移动产生的一个曲线线段 然后将所有的曲线线段绘制在屏幕中,如果触摸抬起将调用reset()方法重置曲线轨迹。
  1.         @Override
  2.         public boolean onTouchEvent(MotionEvent event) {
  3.             /** 拿到触摸的状态 **/
  4.             int action = event.getAction();
  5.             float x = event.getX();
  6.             float y = event.getY();
  7.             switch (action) {
  8.             // 触摸按下的事件
  9.             case MotionEvent.ACTION_DOWN:
  10.                 /**设置曲线轨迹起点 X Y坐标**/
  11.                 mPath.moveTo(x, y);
  12.                 break;
  13.             // 触摸移动的事件
  14.             case MotionEvent.ACTION_MOVE:
  15.                 /**设置曲线轨迹**/
  16.                 //参数1 起始点X坐标
  17.                 //参数2 起始点Y坐标
  18.                 //参数3 结束点X坐标
  19.                 //参数4 结束点Y坐标
  20.                 mPath.quadTo(mposX, mposY, x, y);
  21.                 break;
  22.             // 触摸抬起的事件
  23.             case MotionEvent.ACTION_UP:
  24.                 /**按键抬起后清空路径轨迹**/
  25.                 mPath.reset();
  26.                 break;
  27.             }
  28.            //记录当前触摸X Y坐标
  29.             mposX = x;
  30.             mposY = y;
  31.             return true;
  32.         }
复制代码
游戏绘制中调用drawPath方法将onTouchEvent中记录的路径曲线绘制在屏幕当中。
  1.         private void Draw() {
  2.             /**清空画布**/
  3.             mCanvas.drawColor(Color.WHITE);
  4.             /**绘制曲线**/
  5.             mCanvas.drawPath(mPath, mPaint);
  6.        
  7.             /**记录当前触点位置**/
  8.             mCanvas.drawText("当前触笔 X:" + mposX, 0, 20,mTextPaint);
  9.             mCanvas.drawText("当前触笔 Y:" + mposY, 0, 40,mTextPaint);
  10.         }
复制代码

给出整体代码的实现

详细的注释已经在代码中写出 欢迎大家阅读
  1. import android.app.Activity;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Color;
  5. import android.graphics.Paint;
  6. import android.graphics.Path;
  7. import android.os.Bundle;
  8. import android.view.MotionEvent;
  9. import android.view.SurfaceHolder;
  10. import android.view.SurfaceView;
  11. import android.view.Window;
  12. import android.view.WindowManager;
  13. import android.view.SurfaceHolder.Callback;


  14. public class SurfaceViewAcitvity extends Activity {

  15.     MyView mAnimView = null;

  16.     @Override
  17.     public void onCreate(Bundle savedInstanceState) {
  18.         super.onCreate(savedInstanceState);
  19.         // 全屏显示窗口
  20.         requestWindowFeature(Window.FEATURE_NO_TITLE);
  21.         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  22.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);
  23.         // 显示自定义的游戏View
  24.         mAnimView = new MyView(this);
  25.         setContentView(mAnimView);
  26.     }

  27.     public class MyView extends SurfaceView implements Callback,Runnable {

  28.          /**每50帧刷新一次屏幕**/  
  29.         public static final int TIME_IN_FRAME = 50;

  30.         /** 游戏画笔 **/
  31.         Paint mPaint = null;
  32.         Paint mTextPaint = null;
  33.         SurfaceHolder mSurfaceHolder = null;

  34.         /** 控制游戏更新循环 **/
  35.         boolean mRunning = false;

  36.         /** 游戏画布 **/
  37.         Canvas mCanvas = null;

  38.         /**控制游戏循环**/
  39.         boolean mIsRunning = false;
  40.        
  41.         /**曲线方向**/
  42.         private Path mPath;
  43.        
  44.         private float mposX, mposY;
  45.        
  46.         public MyView(Context context) {
  47.             super(context);
  48.             /** 设置当前View拥有控制焦点 **/
  49.             this.setFocusable(true);
  50.             /** 设置当前View拥有触摸事件 **/
  51.             this.setFocusableInTouchMode(true);
  52.             /** 拿到SurfaceHolder对象 **/
  53.             mSurfaceHolder = this.getHolder();
  54.             /** 将mSurfaceHolder添加到Callback回调函数中 **/
  55.             mSurfaceHolder.addCallback(this);
  56.             /** 创建画布 **/
  57.             mCanvas = new Canvas();
  58.             /** 创建曲线画笔 **/
  59.             mPaint = new Paint();
  60.             mPaint.setColor(Color.BLACK);
  61.             /**设置画笔抗锯齿**/
  62.             mPaint.setAntiAlias(true);
  63.             /**画笔的类型**/
  64.             mPaint.setStyle(Paint.Style.STROKE);
  65.             /**设置画笔变为圆滑状**/
  66.             mPaint.setStrokeCap(Paint.Cap.ROUND);
  67.             /**设置线的宽度**/
  68.             mPaint.setStrokeWidth(5);
  69.             /**创建路径对象**/
  70.             mPath = new Path();
  71.             /** 创建文字画笔 **/
  72.             mTextPaint = new Paint();
  73.             /**设置颜色**/
  74.             mTextPaint.setColor(Color.BLACK);
  75.             /**设置文字大小**/
  76.             mTextPaint.setTextSize(15);
  77.         }

  78.         @Override
  79.         public boolean onTouchEvent(MotionEvent event) {
  80.             /** 拿到触摸的状态 **/
  81.             int action = event.getAction();
  82.             float x = event.getX();
  83.             float y = event.getY();
  84.             switch (action) {
  85.             // 触摸按下的事件
  86.             case MotionEvent.ACTION_DOWN:
  87.                 /**设置曲线轨迹起点 X Y坐标**/
  88.                 mPath.moveTo(x, y);
  89.                 break;
  90.             // 触摸移动的事件
  91.             case MotionEvent.ACTION_MOVE:
  92.                 /**设置曲线轨迹**/
  93.                 //参数1 起始点X坐标
  94.                 //参数2 起始点Y坐标
  95.                 //参数3 结束点X坐标
  96.                 //参数4 结束点Y坐标
  97.                 mPath.quadTo(mposX, mposY, x, y);
  98.                 break;
  99.             // 触摸抬起的事件
  100.             case MotionEvent.ACTION_UP:
  101.                 /**按键抬起后清空路径轨迹**/
  102.                 mPath.reset();
  103.                 break;
  104.             }
  105.            //记录当前触摸X Y坐标
  106.             mposX = x;
  107.             mposY = y;
  108.             return true;
  109.         }
  110.         
  111.         private void Draw() {
  112.             /**清空画布**/
  113.             mCanvas.drawColor(Color.WHITE);
  114.             /**绘制曲线**/
  115.             mCanvas.drawPath(mPath, mPaint);
  116.        
  117.             /**记录当前触点位置**/
  118.             mCanvas.drawText("当前触笔 X:" + mposX, 0, 20,mTextPaint);
  119.             mCanvas.drawText("当前触笔 Y:" + mposY, 0, 40,mTextPaint);
  120.         }
  121.        
  122.         @Override
  123.         public void surfaceChanged(SurfaceHolder holder, int format, int width,
  124.                 int height) {

  125.         }

  126.         @Override
  127.         public void surfaceCreated(SurfaceHolder holder) {
  128.             /**开始游戏主循环线程**/
  129.             mIsRunning = true;
  130.             new Thread(this).start();
  131.         }

  132.         @Override
  133.         public void surfaceDestroyed(SurfaceHolder holder) {
  134.             mIsRunning = false;
  135.         }

  136.         @Override
  137.         public void run() {
  138.             while (mIsRunning) {

  139.                 /** 取得更新游戏之前的时间 **/
  140.                 long startTime = System.currentTimeMillis();

  141.                 /** 在这里加上线程安全锁 **/
  142.                 synchronized (mSurfaceHolder) {
  143.                     /** 拿到当前画布 然后锁定 **/
  144.                     mCanvas = mSurfaceHolder.lockCanvas();
  145.                     Draw();
  146.                     /** 绘制结束后解锁显示在屏幕上 **/
  147.                     mSurfaceHolder.unlockCanvasAndPost(mCanvas);
  148.                 }

  149.                 /** 取得更新游戏结束的时间 **/
  150.                 long endTime = System.currentTimeMillis();

  151.                 /** 计算出游戏一次更新的毫秒数 **/
  152.                 int diffTime = (int) (endTime - startTime);

  153.                 /** 确保每次更新时间为50帧 **/
  154.                 while (diffTime <= TIME_IN_FRAME) {
  155.                     diffTime = (int) (System.currentTimeMillis() - startTime);
  156.                     /** 线程等待 **/
  157.                     Thread.yield();
  158.                 }

  159.             }

  160.         }
  161.     }
  162. }
复制代码
总体来说这章内容还是比较简单的,老规矩每篇文章都会附带源代码,最后如果你还是觉得我写的不够详细 看的不够爽 不要紧我把源代码的下载地址贴出来 欢迎大家一起讨论学习

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x

0

主题

380

帖子

715

安币

代码手工艺人

Rank: 4

发表于 2011-9-3 20:06:52 | 显示全部楼层
学习了~!

14

主题

361

帖子

199

安币

程序猿

Rank: 2

发表于 2011-9-7 12:40:14 | 显示全部楼层
Android游戏开发之触摸轨迹曲线的实现处理(二十四)

0

主题

160

帖子

114

安币

程序猿

Rank: 2

发表于 2011-9-9 09:52:07 | 显示全部楼层
正好要学习这个东西,十分感谢

0

主题

160

帖子

114

安币

程序猿

Rank: 2

发表于 2011-9-9 09:52:18 | 显示全部楼层
正好要学习这个东西,十分感谢

0

主题

72

帖子

69

安币

程序猿

Rank: 2

发表于 2011-9-9 09:59:58 | 显示全部楼层
非常感谢分享!学习了

0

主题

49

帖子

19

安币

程序猿

Rank: 2

QQ达人

发表于 2011-9-13 16:57:58 | 显示全部楼层
学习了~!

0

主题

21

帖子

0

安币

初级码农

Rank: 1

发表于 2011-9-14 13:55:00 | 显示全部楼层
谢谢楼主分享
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

领先的中文移动开发者社区
18620764416
7*24全天服务
意见反馈:1294855032@qq.com

扫一扫关注我们

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粤ICP备15117877号 )