android 如何使用surfaceview绘制类似游戏手柄的摇杆?

来源:互联网 发布:手机淘宝退运费险流程 编辑:程序博客网 时间:2024/05/01 08:24

        网上找到比较少关于此类的文章,估计是高手都比较忙,没空分享这样的东西。今天乘有空发表一下。

具体分3步:

1.创建一个holder,可以理解为我们美术生常用的画板架。

surfaceview的原理是在屏幕上不停的画图,通过不断地刷新每次画好的图,形成流畅的动画或其他图像,刷新频率极高,如同早期迪士尼动画一样。

2.Run the canvas! : canvas就是画布,不难理解了吧,我们往canvas 绘制circle ,绘制image,绘制矩形都在这里进行。注意会之前要将画布lock在holder上,画完后再unlock

3.定义onTouch事件,就是定义手指触碰摇杆时应该发生什么行为。重点语句在

mRockerPosition.set((int)event.getX(), (int)event.getY()),mRockerPosition随手指的点坐标改变而改变,令canvas的每次绘制摇杆的位置都有所不同,这就形成了手柄效果。

import com.wincent.wavegenerator.R;import com.wincent.wavegenerator.activity.WaveGeneratorActivity;import com.wincent.wavegenerator.test.Rudder2.RudderListener;import com.wincent.wavegenerator.tools.MathUtils;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.graphics.PixelFormat; import android.graphics.Point; import android.graphics.PorterDuff.Mode;import android.graphics.Rect;import android.graphics.RectF;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.hardware.Sensor;import android.hardware.SensorEvent;import android.hardware.SensorEventListener;import android.hardware.SensorManager; import android.util.AttributeSet;import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView;import android.view.SurfaceHolder.Callback;import android.view.View;public class RudderSample extends SurfaceView implements Runnable,Callback{  private float sensorX;private float sensorY;private SurfaceHolder mHolder;private boolean isStop = false;private Thread mThread;private Paint  mPaint;public Point  mRockerPosition; //摇杆位置public static boolean sensorOn=false;public int mWheelRadius = 60;//摇杆活动范围半径,难道这个是DP单位?原来是60public Point  mCtrlPoint;// = new Point(mRudderRadius+mWheelRadius,mRudderRadius+mWheelRadius);//摇杆起始位置public RudderListener listener = null; //事件回调接口public int d;public int orientation=1;private float sensorXinCirle;private float sensorYinCirle;public SensorManager sensorMgr;private Sensor sensor;public SensorEventListener lsn;private Bitmap rudder;private boolean isDestroyed=false;private int testRadius;private Paint paintBlack;public Point testPoint;private Point centerPoint=new Point(80,80);public static final int ACTION_RUDDER = 1 , ACTION_ATTACK = 2; // 1:摇杆事件 2:按钮事件(未实现)public RudderSample(Context context) {super(context);//mCtrlPoint.set(WaveGeneratorActivity.rudderCenter.x,WaveGeneratorActivity.rudderCenter.y);    }public RudderSample(Context context, AttributeSet as) {super(context, as);this.setKeepScreenOn(true);mHolder = getHolder();mHolder.addCallback(this); mThread = new Thread(this);mPaint = new Paint();mPaint.setColor(Color.GREEN);//mPaint.setAntiAlias(true);//抗锯齿mPaint.setStyle(Paint.Style.STROKE);//测试代码paintBlack=new Paint();paintBlack.setColor(Color.RED);paintBlack.setAntiAlias(true);mRockerPosition=new Point();testPoint=new Point();mRockerPosition.set(centerPoint.x,centerPoint.y);mCtrlPoint=new Point();mCtrlPoint.set(centerPoint.x,centerPoint.y);//mCtrlPoint.set();setFocusable(true);setFocusableInTouchMode(true);setZOrderOnTop(true);mHolder.setFormat(PixelFormat.TRANSPARENT);//设置背景透明        rudder =  BitmapFactory.decodeResource(getResources(),R.drawable.rudder);        }                     //设置回调接口public void setRudderListener(RudderListener rockerListener) {listener = rockerListener;}@Overridepublic void run() {Canvas canvas = null;while(!isStop) {try {//----11.30修改,加入代码,测试那个圆到底有多大canvas = mHolder.lockCanvas();canvas.drawColor(Color.TRANSPARENT,Mode.CLEAR);//清除屏幕canvas.drawCircle(mCtrlPoint.x, mCtrlPoint.y, testRadius, mPaint); //摇杆可活动范围圆环drawImage(canvas, rudder, mRockerPosition.x, mRockerPosition.y,rudder.getWidth(), rudder.getHeight(), 0, 0);//canvas.drawRect(testPoint.x, testPoint.y, testPoint.x+40, testPoint.y+40, paintBlack);} catch (Exception e) {  e.printStackTrace(); } finally {   if(canvas != null) { mHolder.unlockCanvasAndPost(canvas);  }}  try {  Thread.sleep(30);} catch (InterruptedException e) {  e.printStackTrace();}}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {}@Overridepublic void surfaceCreated(SurfaceHolder holder) {isStop = false;mThread=new Thread(this);mThread.start();  }@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {isStop = true;mThread.interrupt();}@Overridepublic boolean onTouchEvent(MotionEvent event) {   if(!sensorOn){//----int len = MathUtils.getLength(mCtrlPoint.x, mCtrlPoint.y, event.getX(), event.getY());int len = MathUtils.getLength(mCtrlPoint.x, mCtrlPoint.y, event.getX(), event.getY());if(event.getAction() == MotionEvent.ACTION_DOWN) {//如果屏幕接触点不在摇杆挥动范围内,则不处理if(len >mWheelRadius) { return true;}}if(event.getAction() == MotionEvent.ACTION_MOVE){if(len <= mWheelRadius) { //如果手指在摇杆活动范围内,则摇杆处于手指触摸位置 mRockerPosition.set((int)event.getX(), (int)event.getY());//Point  d=len;}else{ //设置摇杆位置,使其处于手指触摸方向的 摇杆活动范围边缘 mRockerPosition = MathUtils.getBorderPoint(mCtrlPoint, new Point((int)event.getX(), (int)event.getY()), mWheelRadius); d=60; }if(listener != null) {Log.v("len",event.getX()+","+event.getY());float radian = MathUtils.getRadian(mCtrlPoint, new Point((int)event.getX(), (int)event.getY()));double radianUnsigned=(float) MathUtils.angUnsigned;listener.onSteeringWheelChanged(ACTION_RUDDER,radianUnsigned,d);Log.v("sensor",d+","+radianUnsigned);}}//如果手指离开屏幕,则摇杆返回初始位置if(event.getAction() == MotionEvent.ACTION_UP) {mRockerPosition = new Point(mCtrlPoint);d=0;} return true;}else{if(lsn!=null){float radian = MathUtils.getRadian(mCtrlPoint, new Point((int)sensorXinCirle, (int)sensorYinCirle));radianUnsigned=(float) MathUtils.angUnsigned;listener.onSteeringWheelChanged(ACTION_RUDDER,radianUnsigned,d);Log.v("sensor",d+","+radianUnsigned);}} return true;}//获取摇杆偏移角度 0-360°private int getAngleCouvert(float radian) {int tmp = (int) Math.round(radian/Math.PI*180);if(tmp < 0) {return -tmp;}else{return 180 + (180 - tmp);}}int MAX_TOUCHPOINTS=3;public float radianUnsigned;public boolean center=false;//回调接口public interface RudderListener {void onSteeringWheelChanged(int action,double radianUnsigned, int d);}/** * 绘制图片 * * @paramx 屏幕上的x坐标 * @paramy 屏幕上的y坐标 * @paramw 要绘制的图片的宽度 * @paramh 要绘制的图片的高度 * @parambx图片上的x坐标 * @paramby图片上的y坐标 * * @returnnull */public void drawImage(Canvas canvas, Bitmap blt, int x, int y, int w, int h, int bx, int by){Rect src = new Rect();// 图片Rect dst = new Rect();// 屏幕src.left = bx;src.top = by;src.right = bx + w;src.bottom = by + h;dst.left = x-(w/2);dst.top = y-(h/2);dst.right = x + (w/2);dst.bottom = y + (h/2);canvas.drawBitmap(blt, src, dst, null);src = null;dst = null;} public void enableSensor(){//----周日删除 sensorOn=true;sensorMgr.registerListener(lsn, sensor, SensorManager.SENSOR_DELAY_GAME);}public void disableSensor(){//----周日删除sensorOn=false;sensorMgr.unregisterListener(lsn, sensor);mRockerPosition=new Point(mCtrlPoint);}}
下一集,我们专门讲解如何实现多点触碰进行摇杆控制


原创粉丝点击