用SurfaceView实现Android游戏摇杆
2016-04-13 20:50
549 查看
这段时间研究自定义控件,遂想起游戏里的摇杆的实现挺有意思,于是来自己写一套熟悉熟悉,关于SurfaceView的特性网上也有很多,故不赘述,反正绘图用起来挺爽就是了,永远的告别了JAVA GUI手动实现双缓冲的时代了……
1、Rudder类的实现:
2、MathUtils类的实现:
3、界面布局的实现:
4、Activity中的调用:
文章转自:http://www.android100.org/html/201306/06/3004.html
1、Rudder类的实现:
import com.game.graphics.utils.MathUtils; import android.content.Context; 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.util.AttributeSet; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.SurfaceHolder.Callback; public class Rudder extends SurfaceView implements Runnable,Callback{ private SurfaceHolder mHolder; private boolean isStop = false; private Thread mThread; private Paint mPaint; private Point mRockerPosition; //摇杆位置 private Point mCtrlPoint = new Point(80,80);//摇杆起始位置 private int mRudderRadius = 20;//摇杆半径 private int mWheelRadius = 60;//摇杆活动范围半径 private RudderListener listener = null; //事件回调接口 public static final int ACTION_RUDDER = 1 , ACTION_ATTACK = 2; // 1:摇杆事件 2:按钮事件(未实现) public Rudder(Context context) { super(context); } public Rudder(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);//抗锯齿 mRockerPosition = new Point(mCtrlPoint); setFocusable(true); setFocusableInTouchMode(true); setZOrderOnTop(true); mHolder.setFormat(PixelFormat.TRANSPARENT);//设置背景透明 } //设置回调接口 public void setRudderListener(RudderListener rockerListener) { listener = rockerListener; } @Override public void run() { Canvas canvas = null; while(!isStop) { try { canvas = mHolder.lockCanvas(); canvas.drawColor(Color.TRANSPARENT,Mode.CLEAR);//清除屏幕 mPaint.setColor(Color.CYAN); canvas.drawCircle(mCtrlPoint.x, mCtrlPoint.y, mWheelRadius, mPaint);//绘制范围 mPaint.setColor(Color.RED); canvas.drawCircle(mRockerPosition.x, mRockerPosition.y, mRudderRadius, mPaint);//绘制摇杆 } 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) { mThread.start(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { isStop = true; } @Override public boolean onTouchEvent(MotionEvent event) { 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()); }else{ //设置摇杆位置,使其处于手指触摸方向的 摇杆活动范围边缘 mRockerPosition = MathUtils.getBorderPoint(mCtrlPoint, new Point((int)event.getX(), (int)event.getY()), mWheelRadius); } if(listener != null) { float radian = MathUtils.getRadian(mCtrlPoint, new Point((int)event.getX(), (int)event.getY())); listener.onSteeringWheelChanged(ACTION_RUDDER,Rudder.this.getAngleCouvert(radian)); } } //如果手指离开屏幕,则摇杆返回初始位置 if(event.getAction() == MotionEvent.ACTION_UP) { mRockerPosition = new Point(mCtrlPoint); } 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); } } //回调接口 public interface RudderListener { void onSteeringWheelChanged(int action,int angle); } }
2、MathUtils类的实现:
import android.graphics.Point; public class MathUtils { //获取两点间直线距离 public static int getLength(float x1,float y1,float x2,float y2) { return (int)Math.sqrt(Math.pow(x1-x2, 2) + Math.pow(y1-y2, 2)); } /** * 获取线段上某个点的坐标,长度为a.x - cutRadius * @param a 点A * @param b 点B * @param cutRadius 截断距离 * @return 截断点 */ public static Point getBorderPoint(Point a, Point b,int cutRadius) { float radian = getRadian(a, b); return new Point(a.x + (int)(cutRadius * Math.cos(radian)), a.x + (int)(cutRadius * Math.sin(radian))); } //获取水平线夹角弧度 public static float getRadian (Point a, Point b) { float lenA = b.x-a.x; float lenB = b.y-a.y; float lenC = (float)Math.sqrt(lenA*lenA+lenB*lenB); float ang = (float)Math.acos(lenA/lenC); ang = ang * (b.y < a.y ? -1 : 1); return ang; } }
3、界面布局的实现:
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:layout_width="fill_parent" android:layout_height="fill_parent" android:scaleType="fitXY" android:src="@drawable/xx"/> <RelativeLayout android:id="@+id/ctrls" android:layout_width="fill_parent" android:layout_height="fill_parent"> <com.game.demo.views.Rudder android:id="@+id/rudder" android:layout_width="480dip" android:layout_height="160dip" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true"/> </RelativeLayout> </FrameLayout>
4、Activity中的调用:
setContentView(R.layout.main); Rudder rudder = (Rudder) findViewById(R.id.rudder); rudder.setRudderListener(new RudderListener() { @Override public void onSteeringWheelChanged(int action, int angle) { if(action == Rudder.ACTION_RUDDER) { //TODO:事件实现 } } });
文章转自:http://www.android100.org/html/201306/06/3004.html
相关文章推荐
- Android自定义View的一些理解
- 个人加快android studio编译速度(不改),加个ssd就不用看了- -
- Android的Bitmap的一些知识点
- Android用Gson解析复杂Json
- android 非activity如何得到布局文件(layout)
- Android实现横屏以及全屏的小技巧
- Android实现横屏以及全屏的小技巧
- android实战项目五做一个倒计时的button
- Android 布局深度优化(减少布局层次)
- Android peferenceActivity 自己定义标题简单方法
- Android Jni开发之Android Studio中使用Android.mk
- Android开发工具的下载
- Android Activity启动过程简读 <1>
- 【Android】在activity中使用menu菜单
- android 之activity生命周期
- 解决Mac上android设备不显示的问题
- 【Android控件】呼吸效果的动画
- 深入理解Android中的View
- Android客户端性能优化(魅族资深工程师毫无保留奉献)
- Android中Parcelable接口的应用