詳解android studio游戲搖桿開發(fā)教程,仿王者榮耀搖桿
最近在做一個(gè)山寨版的王者榮耀,剛開始做的時(shí)候毫無(wú)頭緒 搖桿的多點(diǎn)觸控做的特別爛
經(jīng)過幾天的思考已完美解決所有問題,下面就和大家分享下這個(gè)搖桿的開發(fā)思路
若有不正之處,請(qǐng)多多諒解并歡迎指正。
首先這個(gè)搖桿要用到較多的數(shù)學(xué)知識(shí),小編的數(shù)學(xué)特別爛也就高中水平吧
我們這個(gè)搖桿一共就五個(gè)按鈕,一個(gè)移動(dòng)搖桿、三個(gè)技能搖桿和一個(gè)普通攻擊按鈕
最終效果
好了廢話少說讓我們開始吧
新建一個(gè)項(xiàng)目
建好項(xiàng)目之后,我們先新建一個(gè)類叫做“畫”。也是我們的主View
修改Hua.java的代碼
public class Hua extends RelativeLayout implements Runnable{ //繼承RelativeLayout 實(shí)現(xiàn)Runnable接口 private Paint p;//畫筆 public Hua(Context context) { super(context); p=new Paint(); setBackgroundColor(Color.BLACK);//背景顏色設(shè)為黑色 } @Override protected void onDraw(Canvas g) {//重寫onDraw方法 super.onDraw(g); } @Override public void run() { } }
接下來(lái)我們做移動(dòng)搖桿
我們要準(zhǔn)備一張圖片(待會(huì)我會(huì)把圖片都丟在附件里)
首先用ps畫一個(gè)這樣半透明的圓ps部分就不做教程了
把背景隱藏掉 保存為png格式
把我們剛剛制作的圖片添加進(jìn)來(lái)
先新建一個(gè)類 my.java
public class my { //這個(gè)類當(dāng)一個(gè)全局變量使用 public static int w,h;//屏幕的寬高 public static float bili; public static MainActivity main; public static RectF re=new RectF(); public static int ontouchAlpha=100;//觸控區(qū)透明度0-255 0為透明,為了測(cè)試我們先設(shè)為100 }
修改 MainActivity 的代碼
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); my.main=this; getSupportActionBar().hide();//隱藏標(biāo)題欄 this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏 隱藏狀態(tài)欄 //判斷當(dāng)前是否橫屏 如果不是就設(shè)為橫屏,設(shè)為橫屏之后會(huì)自動(dòng)調(diào)用onCreate方法 if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { //獲取屏幕的寬高 DisplayMetrics dis = getResources().getDisplayMetrics(); my.w = dis.widthPixels; my.h = dis.heightPixels; //獲取屏幕分辨率和1920*1080的比例 以便適應(yīng)不同大小的屏幕 my.bili = (float) (Math.sqrt(my.w * my.h) / Math.sqrt(1920 * 1080)); setContentView(new Hua(this)); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);// 橫屏 } } }
新建類 Move.java
package com.yaogan.liziguo.yaogan; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; /** * Created by Liziguo on 2018/6/15. */ public class Move { private float x1,y1;//按下時(shí)的坐標(biāo) 大圓 private float x2,y2;//移動(dòng)后的坐標(biāo) 小圓 private final float r1,r2;//r1大圓的半徑 r2小圓的半徑 public float angle;//x1y1指向x2y2的角度 弧度制 public boolean down=false;//判斷是否被按下 public boolean in=false;//判斷小圓是否在大圓里面,簡(jiǎn)單的說就是防止小圓被脫太遠(yuǎn) public boolean move=false;//判斷手指按下后是否移動(dòng)(MY實(shí)際開發(fā)中用到,該教程用不到此變量) public Bitmap img;//大圓小圓的圖片 public Move(){ r1 = 480 * 0.5f * my.bili;//乘上一個(gè)比例 適應(yīng)不同大小的屏幕 r2 = 300 * 0.5f * my.bili; img= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.yaogan);//初始化搖桿圖片 } public void down(float xx,float yy){ //搖桿按下后的操作 if(xx<r1) x1=r1; else x1 = xx; if(my.h-yy<r1) y1=my.h-r1; else y1 = yy; //上面的代碼是防止按下的位置太靠近屏幕邊緣 //跟x1=xx;y1=yy;區(qū)別不大,待會(huì)可以改成x1=xx;y1=yy;看看效果有什么不同 down=true; } public void move(float xx,float yy){ //按下?lián)u桿后移動(dòng)的操作 angle=getAngle(xx,yy); in=in(xx, yy); move=isMove(xx,yy); if (!in) { //下面會(huì)做解釋 xx= (float) (x1+ Math.sin(angle)*r1*0.7f); yy= (float) (y1+ Math.cos(angle)*r1*0.7f); } x2=xx; y2=yy; } public void up(){ //松開后的操作 down=false; } public float getAngle(float xx,float yy){ //獲取x1y1指向x2y2的角度 double angle,k; if (y1==yy)//斜率不存在時(shí) if (x1 > xx)//判斷x1指向x2的方向 angle=-Math.PI/2; else angle=Math.PI/2; else{ k=(x1-xx)/(y1-yy); //兩點(diǎn)的坐標(biāo)求斜率,至于為什么是(x1-x2)/(y1-y2)不是(y1-y2)/(x1-x2)待會(huì)我們?cè)僮鼋忉? if (y1 > yy) {//判斷x1y1指向x2y2的方向 // 用反tan求角度 這個(gè)高中好像沒學(xué)過 既然Math類已經(jīng)幫我們封裝好了就直接拿來(lái)用吧 angle=Math.atan(k) + Math.PI; } else { angle=Math.atan(k); } //這段可寫可不寫 讓計(jì)算出來(lái)的角度屬于-PI/2到PI/2 if(angle>Math.PI) angle-=Math.PI*2; else if(angle<-Math.PI) angle+=Math.PI*2; } return (float) angle; } public boolean in(float xx, float yy) { //防止小圓被脫太遠(yuǎn) 拖動(dòng)范圍不超出r1的70% double r = Math.sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy));//兩點(diǎn)間距離公式 if (r < r1*0.7f) return true; else return false; } public boolean isMove(float xx, float yy) { //判斷按下?lián)u桿后 是否移動(dòng),如果x1y1 x2y2的距離大于r1*0.15視為移動(dòng) // MY實(shí)際開發(fā)中用到,該教程用不到此變量 double r = Math.sqrt((x1 - xx) * (x1 - xx) + (y1 - yy) * (y1 - yy));//兩點(diǎn)間距離公式 if (r > r1*0.15f) return true; else return false; } public void onDraw(Canvas g, Paint p){ //畫搖桿 if(down) { //當(dāng)搖桿被按下時(shí) 才顯示 //怎么用Canvas畫圖這里就不說了 my.re.left = x1 - r1; my.re.top = y1 - r1; my.re.right = x1 + r1; my.re.bottom = y1 + r1; g.drawBitmap(img, null, my.re, p); //畫大圓 my.re.left = x2 - r2; my.re.top = y2 - r2; my.re.right = x2 + r2; my.re.bottom = y2 + r2; g.drawBitmap(img, null, my.re, p); //畫小圓 } } }
新建類 OnTouchMove.java
package com.yaogan.liziguo.yaogan; import android.content.Context; import android.graphics.Color; import android.view.MotionEvent; import android.view.View; /** * Created by Liziguo on 2018/6/16. */ public class OnTouchMove extends View { //這個(gè)view負(fù)責(zé)監(jiān)聽移動(dòng)搖桿的手勢(shì) private Move m; public OnTouchMove(Context context,Move move) { super(context); this.m=move; setBackgroundColor(Color.WHITE);//背景色設(shè)為白色 getBackground().setAlpha(my.ontouchAlpha);//設(shè)置觸控區(qū)透明度 setOnTouchListener(new OnTouchListener() { //設(shè)置觸控監(jiān)聽 @Override public boolean onTouch(View v, MotionEvent ev) { //加上getX() getY()因?yàn)檫@個(gè)view不是分布在左上角的 final float xx = ev.getX() + getX(), yy = ev.getY() + getY(); if (ev.getAction() == MotionEvent.ACTION_DOWN) { m.down(xx, yy);//按下時(shí)的操作 // m.move(xx, yy); } m.move(xx, yy);//移動(dòng)時(shí)的操作 if (ev.getAction() == MotionEvent.ACTION_UP) { m.up();//松開時(shí)的操作 } return true;//不要返回false } }); } }
修改 Hua.java 的代碼
package com.yaogan.liziguo.yaogan; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.widget.RelativeLayout; /** * Created by Liziguo on 2018/6/15. */ public class Hua extends RelativeLayout implements Runnable{ //繼承RelativeLayout 實(shí)現(xiàn)Runnable接口 private Paint p;//畫筆 private Move m=new Move();//移動(dòng)搖桿 public Hua(Context context) { super(context); p=new Paint(); setBackgroundColor(Color.BLACK);//背景顏色設(shè)為黑色 //實(shí)例化一個(gè)OnTouchMove OnTouchMove onTouchMove=new OnTouchMove(context,m); //把onTouchMove添加進(jìn)來(lái) 寬度為屏幕的1/3 高度為屏幕的1/2 addView(onTouchMove,my.w/3,my.h/2); //設(shè)置onTouchMove的位置 onTouchMove.setX(0); onTouchMove.setY(my.h/2); new Thread(this).start();//啟動(dòng)重繪線程 } @Override protected void onDraw(Canvas g) {//重寫onDraw方法 super.onDraw(g); m.onDraw(g,p);//畫移動(dòng)搖桿 } @Override public void run() { //每隔20毫秒刷新一次畫布 while(true){ try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();} postInvalidate();//重繪 在子線程重繪不能調(diào)用Invalidate()方法 } } }
好的 現(xiàn)在我們的搖桿可以說已經(jīng)做好一大半了,因?yàn)槭O碌脑矶家粯?/p>
先運(yùn)行一遍看看效果吧
左下角的白色矩形是我們的OnTouchMove類,為了更好的測(cè)試我們先讓他顯示出來(lái) 等做好了再隱藏掉
下面我們來(lái)解釋一下為什么斜率k=(x1-x2)/(y1-y2)而不是(y1-y2)/(x1-x2)吧
因?yàn)槲覀兪謾C(jī)上的平面直角坐標(biāo)系跟數(shù)學(xué)上的平面直角坐標(biāo)系不一樣
數(shù)學(xué)上的平面直角坐標(biāo)系是這樣的
而我們手機(jī)是這樣的
有沒有發(fā)現(xiàn)把手機(jī)的坐標(biāo)系 逆時(shí)針旋轉(zhuǎn)一下就是數(shù)學(xué)里的坐標(biāo)系了,不過x跟y調(diào)了一下位置
所以我們?cè)趯懘a的時(shí)候把x y換一下就行了
數(shù)學(xué)坐標(biāo)系中k=1的直線
程序中k=1的直線
再解釋下 Move 類的 move方法
public void move(float xx,float yy){ //按下?lián)u桿后移動(dòng)的操作 angle=getAngle(xx,yy); in=in(xx, yy); move=isMove(xx,yy); if (!in) { //下面會(huì)做解釋 xx= (float) (x1+ Math.sin(angle)*r1*0.7f); yy= (float) (y1+ Math.cos(angle)*r1*0.7f); } x2=xx; y2=yy; }
好的下面我們開始做技能搖桿,這教程做的比較累啊
下面的技能類是我直接從我游戲里拷貝過來(lái)的并做了些小修改
解釋可能沒那么清楚畢竟原理都一樣
只不過是多了幾個(gè)功能而已
準(zhǔn)備圖片
添加到工程里
由于圖片比較多 我們加載圖的代碼位置改一下
修改 MainActivity。java 和 my.java
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); my.main=this; getSupportActionBar().hide();//隱藏標(biāo)題欄 this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏 隱藏狀態(tài)欄 //判斷當(dāng)前是否橫屏 如果不是就設(shè)為橫屏,設(shè)為橫屏之后會(huì)自動(dòng)調(diào)用onCreate方法 if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { //獲取屏幕的寬高 DisplayMetrics dis = getResources().getDisplayMetrics(); my.w = dis.widthPixels; my.h = dis.heightPixels; //獲取屏幕分辨率和1920*1080的比例 以便適應(yīng)不同大小的屏幕 my.bili = (float) (Math.sqrt(my.w * my.h) / Math.sqrt(1920 * 1080)); //加載圖片 my.border= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.border); my.cancel= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.cancel); my.down= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.down); my.yaogan= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.yaogan); my.cd= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.cd); setContentView(new Hua(this)); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);// 橫屏 } } }
public class my { //這個(gè)類當(dāng)一個(gè)全局變量使用 public static int w,h;//屏幕的寬高 public static float bili; public static MainActivity main; public static RectF re=new RectF(); public static int ontouchAlpha=100;//觸控區(qū)透明度0-255 0為透明,為了測(cè)試我們先設(shè)為100 public static Bitmap border,cancel,down,yaogan,cd; public static Skill skill;//當(dāng)前正在使用的技能 現(xiàn)在會(huì)報(bào)錯(cuò) 因?yàn)槲覀冞€沒新建技能Skill類 }
修改 Move 類的構(gòu)造方法
public Move(){ r1 = 480 * 0.5f * my.bili;//乘上一個(gè)比例 適應(yīng)不同大小的屏幕 r2 = 300 * 0.5f * my.bili; // img= BitmapFactory.decodeResource(my.main.getResources(),R.mipmap.yaogan);//初始化搖桿圖片//////////////////////// img=my.yaogan;//////////////////////////////////////////////////// }
新建技能類 Skill.java
package com.yaogan.liziguo.yaogan; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; /** * Created by Liziguo on 2018/6/16. */ public abstract class Skill { public int jineng; private final float x,y;//技能圖標(biāo)中心位置,不是按下時(shí)的位置 private float x2, y2;//技能按下移動(dòng)后手指的坐標(biāo) private float xxx,yyy;//判斷拖動(dòng)點(diǎn)是否超出兩倍r的范圍 private final float calcelx, cancely; public float angle;//技能按下后 x y指向xx yy的角度 public Bitmap img, imgborder, imgdown, imgyaogan,imgcd,imgcancel; private final float r2; private final float r3=50*my.bili; public boolean down=false; public boolean down_main=false;//down_main 只觸發(fā)一次; public boolean cancel=false; public int cdmax; public long last,cd=0;//last最后一次釋放技能的時(shí)間 /* 0 普通攻擊 1 技能1 2 技能2 3 技能3 */ public Skill(int jineng, int cd, Bitmap image){ this.jineng=jineng; switch (jineng){ case 0: x= my.w*0.87f; y= my.h*0.8f; break; case 1: x= my.w*0.7f; y= my.h*0.88f; break; case 2: x= my.w*0.75f; y= my.h*0.62f; break; case 3: x= my.w*0.9f; y= my.h*0.5f; break; default:x=y=0; } cdmax=cd; if(jineng == 0) r2=125*my.bili; else r2=80*my.bili; calcelx =my.w-r2*2; cancely =my.h/4; img=image; imgborder=my.border; imgdown=my.down; imgyaogan=my.yaogan; imgcd=my.cd; imgcancel=my.cancel; } // public abstract void down(); // public abstract void move(); // public abstract void up(); public void down(){ //DOWN 由ontouch觸發(fā) if(cd>0)return; down=true; my.skill=this; } public abstract void down_main(); //DOWN 教程用不到該抽象方法 public void move(float x,float y){//按下技能后 由ontouch觸發(fā) x2 =x; y2 =y; angle=getAngle(x2, y2); cancel=incancel(x,y); if (jineng !=0 && !in2(x,y)) { xxx= (float) (this.x+ Math.sin(angle)*r2*2); yyy= (float) (this.y+ Math.cos(angle)*r2*2); }else{ xxx=x; yyy=y; } } public abstract void move_main();//按下技能后 由MyActor觸發(fā) 教程用不到該抽象方法 public abstract void up(); //松開后 由MyActor觸發(fā) 釋放技能 public boolean in(float xx,float yy){ //判斷是否被點(diǎn)中 double r= Math.sqrt((x - xx)*(x-xx)+(y-yy)*(y-yy)); if(r<r2) return true; else return false; } public boolean in2(float xx, float yy) { //判斷拖動(dòng)點(diǎn)是否超出兩倍r的范圍 double r = Math.sqrt((x - xx) * (x - xx) + (y - yy) * (y - yy)); if (r < r2 * 2) return true; else return false; } public boolean incancel(float xx,float yy){ //判斷是否取消 double r= Math.sqrt((calcelx - xx)*(calcelx -xx)+(cancely -yy)*(cancely -yy)); if(r<r2) return true; else return false; } public float getAngle(float xx,float yy){ //x y指向xx yy的角度 float angle,k; if (y==yy) if (x > xx) angle= (float) (-Math.PI/2); else angle= (float) (Math.PI/2); else{ k=(x-xx)/(y-yy); if (y > yy) { angle= (float) (Math.atan(k) + Math.PI); } else { angle= (float) Math.atan(k); } if(angle>Math.PI) angle-=Math.PI*2; else if(angle<-Math.PI) angle+=Math.PI*2; } return angle; } private float drawpx=10*my.bili; public void next(){ //計(jì)算技能冷卻時(shí)間 cd=cdmax-System.currentTimeMillis()+last; } //按下的時(shí)候技能圖標(biāo)下移 顯示藍(lán)色框框 public void onDraw(Canvas g, Paint p){ my.re.left=x-r2; my.re.top=y-r2; my.re.right=x+r2; my.re.bottom=y+r2; if(down){ // new RectF(x-r2,y-r2,x+r2,y+r2); // new RectF(x-r2,y-r2+10*my.bili,x+r2,y+r2+10*my.bili); // my.re.left=x-r2; // my.re.top=y-r2; // my.re.right=x+r2; // my.re.bottom=y+r2; if(jineng!=0){ final float bl=2; my.re.left=x-r2*bl; my.re.top=y-r2*bl; my.re.right=x+r2*bl; my.re.bottom=y+r2*bl; //藍(lán)色框框未下移 g.drawBitmap(imgdown,null,my.re,p); } my.re.left=x-r2; my.re.top=y-r2; my.re.right=x+r2; my.re.bottom=y+r2; /////////////////////////////////////////////////////////// //技能圖片和技能邊框下移 my.re.top+=drawpx; my.re.bottom+=drawpx; g.drawBitmap(img,null,my.re,p); my.re.left-=drawpx; my.re.top-=drawpx; my.re.right+=drawpx; my.re.bottom+=drawpx; g.drawBitmap(imgborder,null,my.re,p); if(jineng!=0){ my.re.left=xxx-r3; my.re.top=yyy-r3; my.re.right=xxx+r3; my.re.bottom=yyy+r3; g.drawBitmap(imgyaogan,null,my.re,p); //cancle my.re.left= calcelx -r2; my.re.top= cancely -r2; my.re.right= calcelx +r2; my.re.bottom= cancely +r2; g.drawBitmap(imgcancel,null,my.re,p); } }else{ g.drawBitmap(img,null,my.re,p); if(jineng!=0 && cd>0) { p.setTextSize(40*my.bili); p.setColor(Color.WHITE); g.drawBitmap(imgcd,null,my.re,p); float f=cd/100f; f=(int)f; f=f/10; g.drawText(String.valueOf(f),x-p.getTextSize()*4/5,y+p.getTextSize()/3,p); } my.re.left-=drawpx; my.re.top-=drawpx; my.re.right+=drawpx; my.re.bottom+=drawpx; g.drawBitmap(imgborder,null,my.re,p); } } }
新建一個(gè)類 OnTouchSkill.java 他也是一個(gè)監(jiān)聽view
這樣多點(diǎn)觸控會(huì)好寫很多,剛開始我是用一個(gè)view做監(jiān)聽的 寫到我心態(tài)爆炸。。。
package com.yaogan.liziguo.yaogan; import android.content.Context; import android.graphics.Color; import android.view.MotionEvent; import android.view.View; /** * Created by Liziguo on 2018/6/16. */ public class OnTouchSkill extends View { /* A 普通攻擊 Q 技能1 W 技能2 E 技能3 R 沒有R */ public Skill A,Q,W,E; public OnTouchSkill(Context context,Skill a,Skill q,Skill w,Skill e) { super(context); A=a;Q=q;W=w;E=e; setBackgroundColor(Color.WHITE); getBackground().setAlpha(my.ontouchAlpha);//0-255 setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent ev) { final float xx = ev.getX() + getX(), yy = ev.getY() + getY(); if (ev.getAction() == MotionEvent.ACTION_DOWN) { if ( A.in(xx, yy)) { A.down(); } else if ( Q.in(xx, yy)) { Q.down(); } else if ( W.in(xx, yy)) { W.down(); } else if ( E.in(xx, yy)) { E.down(); } } if (my.skill != null) my.skill.move(xx, yy); if(ev.getAction()==MotionEvent.ACTION_UP){ A.down = false; Q.down = false; W.down = false; E.down = false; } return true; } }); } }
把監(jiān)聽控件添加到Hua,修改 Hua.java
package com.yaogan.liziguo.yaogan; import android.content.Context; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.widget.RelativeLayout; /** * Created by Liziguo on 2018/6/15. */ public class Hua extends RelativeLayout implements Runnable{ //繼承RelativeLayout 實(shí)現(xiàn)Runnable接口 private Paint p;//畫筆 private Move m=new Move();//移動(dòng)搖桿 /* A 普通攻擊 Q 技能1 W 技能2 E 技能3 R 沒有R */ public Skill A=new Skill(0,100, BitmapFactory.decodeResource(getResources(),R.mipmap.putonggongji)) { @Override public void down_main() { } @Override public void move_main() { } @Override public void up() { } }; public Skill Q=new Skill(1,1000, BitmapFactory.decodeResource(getResources(),R.mipmap.skill1)) { @Override public void down_main() { } @Override public void move_main() { } @Override public void up() { down_main=false; if(!cancel){ //技能冷卻時(shí)間 last= System.currentTimeMillis(); } } }; public Skill W=new Skill(2,1000, BitmapFactory.decodeResource(getResources(),R.mipmap.skill2)) { @Override public void down_main() { } @Override public void move_main() { } @Override public void up() { down_main=false; if(!cancel){ last= System.currentTimeMillis(); } } }; public Skill E=new Skill(3,1000, BitmapFactory.decodeResource(getResources(),R.mipmap.skill3)) { @Override public void down_main() { } @Override public void move_main() { } @Override public void up() { down_main=false; if(!cancel){ last= System.currentTimeMillis(); } } }; public Hua(Context context) { super(context); p=new Paint(); setBackgroundColor(Color.BLACK);//背景顏色設(shè)為黑色 //實(shí)例化一個(gè)OnTouchMove OnTouchMove onTouchMove=new OnTouchMove(context,m); //把onTouchMove添加進(jìn)來(lái) 寬度為屏幕的1/3 高度為屏幕的1/2 addView(onTouchMove,my.w/3,my.h/2); //設(shè)置onTouchMove的位置 onTouchMove.setX(0); onTouchMove.setY(my.h/2); //添加技能搖桿監(jiān)聽 OnTouchSkill onTouchSkill=new OnTouchSkill(context,A,Q,W,E);//后添加的優(yōu)先級(jí)高 addView(onTouchSkill); onTouchSkill.setX(my.w*0.7f-85*my.bili); onTouchSkill.setY(my.h/2-85*my.bili); new Thread(this).start();//啟動(dòng)重繪線程 } @Override protected void onDraw(Canvas g) {//重寫onDraw方法 super.onDraw(g); m.onDraw(g,p);//畫移動(dòng)搖桿 //畫技能 A.onDraw(g,p); Q.onDraw(g,p); W.onDraw(g,p); E.onDraw(g,p); } @Override public void run() { //每隔20毫秒刷新一次畫布 while(true){ try {Thread.sleep(20);} catch (InterruptedException e) {e.printStackTrace();} //計(jì)算冷卻時(shí)間 A.next(); Q.next(); W.next(); E.next(); //釋放技能 if (my.skill != null) { my.skill.down_main();//教程用不到該方法 my.skill.move_main();//教程用不到該方法 if (my.skill.down == false) { my.skill.up(); my.skill = null; } } postInvalidate();//重繪 在子線程重繪不能調(diào)用Invalidate()方法 } } }
運(yùn)行下看看效果吧
修改 my.java
public class my { //這個(gè)類當(dāng)一個(gè)全局變量使用 public static int w,h;//屏幕的寬高 public static float bili; public static MainActivity main; public static RectF re=new RectF(); public static int ontouchAlpha=0;//把觸控區(qū)透明度改成0 public static Bitmap border,cancel,down,yaogan,cd; public static Skill skill;//當(dāng)前正在使用的技能 }
再運(yùn)行下
大功告成
下載地址:
android studio游戲搖桿開發(fā)教程 仿王者榮耀搖桿
以上所述是小編給大家介紹的android studio游戲搖桿開發(fā)教程詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
android 對(duì)話框彈出位置和透明度的設(shè)置具體實(shí)現(xiàn)方法
在android中我們經(jīng)常會(huì)用AlertDialog來(lái)顯示對(duì)話框。通過這個(gè)對(duì)話框是顯示在屏幕中心的。但在某些程序中,要求對(duì)話框可以顯示在不同的位置。2013-07-07Android編程實(shí)現(xiàn)圖片的瀏覽、縮放、拖動(dòng)和自動(dòng)居中效果
這篇文章主要介紹了Android編程實(shí)現(xiàn)圖片的瀏覽、縮放、拖動(dòng)和自動(dòng)居中效果,以具體實(shí)例形式分析了Android針對(duì)圖片各種常見顯示效果的布局及功能實(shí)現(xiàn)技巧,需要的朋友可以參考下2015-11-11Android 有效的解決內(nèi)存泄漏的問題實(shí)例詳解
這篇文章主要介紹了Android 有效的解決內(nèi)存泄漏的問題的相關(guān)資料,這里舉例說明,如何實(shí)現(xiàn)解決內(nèi)存泄漏,需要的朋友可以參考下2016-11-11android中soap協(xié)議使用(ksoap調(diào)用webservice)
kSOAP是如何調(diào)用ebservice的呢,首先要使用SoapObject,這是一個(gè)高度抽象化的類,完成SOAP調(diào)用??梢哉{(diào)用它的addProperty方法填寫要調(diào)用的webservice方法的參數(shù)2014-02-02Android自定義ViewGroup實(shí)現(xiàn)彈性滑動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android自定義ViewGroup實(shí)現(xiàn)彈性滑動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Android中Fab(FloatingActionButton)實(shí)現(xiàn)上下滑動(dòng)的漸變效果
這篇文章主要給大家介紹了Android中FloatingActionButton(簡(jiǎn)稱FAB)是如何實(shí)現(xiàn)上下滑動(dòng)的漸變效果,文中給出了詳細(xì)的示例代碼,相信對(duì)大家具有一定的參考價(jià)值,有需要的朋友們可以一起看看吧。2017-02-02Android中DialogFragment自定義背景與寬高的方法
DialogFragment 彈出框默認(rèn)是在屏幕的中央,左右還有留白,那么如何自定義背景和寬高呢?下面這篇文章就來(lái)給大家介紹了關(guān)于Android中DialogFragment自定義背景與寬高的方法,需要的朋友可以參考下。2017-08-08Flutter應(yīng)用集成極光推送的實(shí)現(xiàn)示例
這篇文章主要介紹了Flutter應(yīng)用集成極光推送的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-02-02