android 如何使用surfaceview绘制类似游戏手柄的摇杆?
2011-12-26 17:08
711 查看
网上找到比较少关于此类的文章,估计是高手都比较忙,没空分享这样的东西。今天乘有空发表一下。
具体分3步:
1.创建一个holder,可以理解为我们美术生常用的画板架。
surfaceview的原理是在屏幕上不停的画图,通过不断地刷新每次画好的图,形成流畅的动画或其他图像,刷新频率极高,如同早期迪士尼动画一样。
2.Run the canvas! : canvas就是画布,不难理解了吧,我们往canvas 绘制circle ,绘制image,绘制矩形都在这里进行。注意会之前要将画布lock在holder上,画完后再unlock
3.定义onTouch事件,就是定义手指触碰摇杆时应该发生什么行为。重点语句在
具体分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单位?原来是60 public 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; } @Override public 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(); } } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceCreated(SurfaceHolder holder) { isStop = false; mThread=new Thread(this); mThread.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { isStop = true; mThread.interrupt(); } @Override public 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); } /** * 绘制图片 * * @param x 屏幕上的x坐标 * @param y 屏幕上的y坐标 * @param w 要绘制的图片的宽度 * @param h 要绘制的图片的高度 * @param bx图片上的x坐标 * @param by图片上的y坐标 * * @return null */ 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); } }下一集,我们专门讲解如何实现多点触碰进行摇杆控制
相关文章推荐
- android:如何用一天时间,写出“飞机大战”这样的游戏!(无框架-SurfaceView绘制)
- Android中使用SurfaceView和Canvas来绘制动画
- Android UI SurfaceView的使用-绘制单个图型或多个图形
- Android中如何使用ViewPager实现类似laucher左右拖动效果
- android 游戏开发 - 使用SurfaceView 创建你自己的View
- 【Android】SurfaceView中使用线程绘制图形
- Android UI SurfaceView的使用-绘制单个图型或多个图形
- Android中使用SurfaceView和Canvas来绘制动画
- Android UI SurfaceView的使用-绘制单个图型或多个图形
- Android 游戏开发笔记一、入门之SurfaceView的使用
- Android中SurfaceView的使用详解及如何在jni(hal层)直接显示
- Android中如何使用ViewPager实现类似laucher左右拖动效果
- 用SurfaceView实现Android游戏摇杆
- Android中如何使用ViewPager实现类似laucher左右拖动效果
- Android使用自定义View继承SurfaceView实现动态折线图的绘制
- Android中如何使用ViewPager实现类似laucher左右拖动效果
- android游戏开发初学之SurfaceView绘制图片
- Android游戏开发7:SurfaceView添加组件后如何全屏显示
- android 学习之路(surfaceView) --- 游戏手柄设计
- 【Android游戏开发十四】深入Animation,在SurfaceView中照样使用Android—Tween Animation!