xamarin.android SurfaceView 实现 游戏 触摸摇杆
先上图
页面
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:gridSpec="1|8|#0093eeff|K:#ee8700ff:16,l:72,l:16,r|S:#0000ffff:16,0,l:16,56,l:16,0,r"> <LinearLayout android:id="@+id/ll_controller" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_gravity="center" android:layout_weight="1" android:orientation="vertical"/> </RelativeLayout>
代码
[Activity(Label = "@string/app_name", Theme = "@style/AppTheme", MainLauncher = true)] public class MainActivity : AppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); Xamarin.Essentials.Platform.Init(this, savedInstanceState); // Set our view from the "main" layout resource SetContentView(Resource.Layout.activity_main); LinearLayout relativeLayout = FindViewById<LinearLayout>(Resource.Id.ll_controller); RemoteSurfaceView remoteSurfaceView = new RemoteSurfaceView(this); var a = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MatchParent, RelativeLayout.LayoutParams.MatchParent); remoteSurfaceView.LayoutParameters = a; relativeLayout.AddView(remoteSurfaceView); } public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults) { Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults); base.OnRequestPermissionsResult(requestCode, permissions, grantResults); } }
public class RemoteViewBg { private Bitmap bitmapBg; public RemoteViewBg(Bitmap bitmap) { bitmapBg = bitmap; } //背景的绘图函数 public void draw(Canvas canvas, Paint paint, Rect src0, Rect dst0) { canvas.DrawBitmap(bitmapBg, src0, dst0, paint); } }
1 public class RemoteSurfaceView : SurfaceView, ISurfaceHolderCallback, IRunnable 2 { 3 // private float scale = this.Resources().getDisplayMetrics().density; 4 private Thread th; 5 private ISurfaceHolder sfh; 6 private Canvas canvas; 7 private Paint paint; 8 private bool flag; 9 10 private int bigCircleX = 0; 11 private int bigCircleY = 0; 12 private int bigCircleR = 0; 13 //摇杆的X,Y坐标以及摇杆的半径 14 private float smallCircleX = 0; 15 private float smallCircleY = 0; 16 private float smallCircleR = 0; 17 18 19 private Bitmap bitmap; 20 private RemoteViewBg remoteViewBg; 21 public RemoteSurfaceView(Context context) : base(context) 22 { 23 sfh = this.Holder; 24 sfh.AddCallback(this); 25 paint = new Paint(); 26 paint.AntiAlias = true; 27 Focusable = true; 28 FocusableInTouchMode = true; 29 SetZOrderOnTop(true); 30 Holder.SetFormat(Format.Transparent); 31 } 32 public void SetLayoutParams() { } 33 /*** 34 * 得到两点之间的弧度 35 */ 36 public float getRad(float px1, float py1, float px2, float py2) 37 { 38 float x = px2 - px1; 39 40 float y = py1 - py2; 41 //斜边的长 42 float z = (float)Java.Lang.Math.Sqrt(Java.Lang.Math.Pow(x, 2) + Java.Lang.Math.Pow(y, 2)); 43 float cosAngle = x / z; 44 float rad = (float)Java.Lang.Math.Acos(cosAngle); 45 46 if (py2 < py1) 47 { 48 rad = -rad; 49 } 50 return rad; 51 } 52 53 public void GetXY(float x, float y, float R, double rad) 54 { 55 56 smallCircleX = (float)(R * Java.Lang.Math.Cos(rad)) + x; 57 58 smallCircleY = (float)(R * Java.Lang.Math.Sin(rad)) + y; 59 } 60 61 public void draw() 62 { 63 try 64 { 65 canvas = sfh.LockCanvas(); 66 canvas.DrawColor(Color.White);//Resources.GetColor(Resources.GetColor("colorAccent").)); 67 Rect src = new Rect(0, 0, bitmap.Width, bitmap.Height); 68 Rect dst = new Rect(bigCircleX - bigCircleR, bigCircleY - bigCircleR, bigCircleX + bigCircleR, bigCircleY + bigCircleR); 69 // 绘制图片 70 remoteViewBg.draw(canvas, paint, src, dst); 71 paint.Color = Color.AliceBlue; 72 //绘制摇杆 73 canvas.DrawCircle(smallCircleX, smallCircleY, smallCircleR, paint); 74 } 75 catch (Java.Lang.Exception e) 76 { 77 // TODO: handle exception 78 } 79 finally 80 { 81 try 82 { 83 if (canvas != null) 84 sfh.UnlockCanvasAndPost(canvas); 85 } 86 catch (Java.Lang.Exception e2) 87 { 88 e2.PrintStackTrace(); 89 } 90 } 91 } 92 93 public void Run() 94 { 95 while (flag) 96 { 97 draw(); 98 try 99 { 100 //Thread.Sleep(50); 101 } 102 catch (Java.Lang.Exception ex) 103 { 104 ex.PrintStackTrace(); 105 } 106 } 107 } 108 109 public void SurfaceCreated(ISurfaceHolder holder) 110 { 111 int width = Width; 112 int height = Height; 113 bigCircleX = width / 2; 114 bigCircleY = height / 2; 115 bigCircleR = width / 4; 116 smallCircleX = width / 2; 117 smallCircleY = height / 2; 118 smallCircleR = width / 8; 119 bitmap = BitmapFactory.DecodeResource(Resources, Resource.Mipmap.fangxiang); 120 remoteViewBg = new RemoteViewBg(bitmap); 121 th = new Thread(this); 122 flag = true; 123 th.Start(); 124 } 125 public override bool OnTouchEvent(MotionEvent e) 126 { 127 if (e.Action == MotionEventActions.Down || e.Action == MotionEventActions.Move) 128 { 129 // 范围外触摸 130 if (Java.Lang.Math.Sqrt(Java.Lang.Math.Pow((bigCircleX - (int)e.GetX()), 2) + 131 Java.Lang.Math.Pow((bigCircleY - (int)e.GetY()), 2)) >= bigCircleR) 132 { 133 134 double tempRad = getRad(bigCircleX, bigCircleY, e.GetX(), e.GetY()); 135 136 GetXY(bigCircleX, bigCircleY, bigCircleR, tempRad); 137 } 138 else 139 {//范围内触摸 140 smallCircleX = (int)e.GetX(); 141 smallCircleY = (int)e.GetY(); 142 } 143 } 144 else if (e.Action == MotionEventActions.Up) 145 { 146 smallCircleX = bigCircleX; 147 smallCircleY = bigCircleY; 148 149 } 150 return true; 151 } 152 public void SurfaceDestroyed(ISurfaceHolder holder) 153 { 154 flag = false; 155 } 156 157 public void SurfaceChanged(ISurfaceHolder holder, [GeneratedEnum] Format format, int width, int height) 158 { 159 160 } 161 }