随着智能手机的普及,手游市场也逐渐发展起来。手机游戏的优点在于随时都能玩,但缺点也比较明显,那就是我们大部分的操作只能依靠触摸屏幕来实现。相比于传统的掌机,由于手机没有摇杆这一个工具,在某些游戏上手机版的手感体验要比掌机的差很多。举个例子,很多Android手机都没有实体的上下左右导航键,控制方向往往成为一道难题。为此Android游戏开发者利用Android手机的触屏特性,制作触屏式的全方位摇杆来模拟掌机的游戏方向键,从而提高玩家的手感体验。本次的讲解课课家笔者就简单为大家介绍如何制作触屏式的全方位游戏摇杆。
为了使大家读起来更加明了,下面笔者用分布讲解来给大家进行讲解。
①首先绘制两个圆形,为了区分圆心点重合的问题,我们设置不同颜色:灰色为固定不动的摇杆背景(摇杆的活动范围),红色为摇杆。
②由于红色摇杆是跟随手指触屏的位置而移动,所以我们在触屏事件中处理并将获取的触屏XY坐标赋值于摇杆XY坐标。
③圈定摇杆的活动区域(灰色区域)。大体思路为通过测量得到通过摇杆的坐标与触屏点的坐标得到所形成的角度Angle,接下来我们根据Angle,以及已知所在圆的半径,算出摇杆所在灰色圆形上做圆周运动的当前X,Y坐标。
【算出摇杆坐标与触屏坐标形成的角度】
由于已知摇杆当前坐标且当玩家触屏时的坐标也可以在触屏按键中得到,因此获取的方法我们可以写成一个代码实现,具体java代码实现如下所示:
/***
*得到两点之间的弧度
*/
publicdoublegetRad(floatpx1,floatpy1,floatpx2,floatpy2){
//得到两点X的距离
floatx=px2-px1;
//得到两点Y的距离
floaty=py1-py2;
//算出斜边长
floatxie=(float)Math.sqrt(Math.pow(x,2)+Math.pow(y,2));
//得到这个角度的余弦值(通过三角函数中的定理:邻边/斜边=角度余弦值)
floatcosAngle=x/xie;
//通过反余弦定理获取到其角度的弧度
floatrad=(float)Math.acos(cosAngle);
//注意:当触屏的位置Y坐标<摇杆的Y坐标我们要取反值-0~-180
if(py2
rad=-rad;
}
returnrad;
}
在这里值得大家注意的一点是,在Java中Math类中的反余弦函数返回的不是角度是弧度。另外因为三角函数角度范围是0~180度,所以反之应该是-0~-180度。通过此函数获取到摇杆与玩家触屏位置所形成的角度之后,我们就可以通过圆周公式来得到其摇杆的XY坐标了,具体Java代码实现如下所示:
/**
*
*@paramR
*圆周运动的旋转点
*@paramcenterX
*旋转点X
*@paramcenterY
*旋转点Y
*@paramrad
*旋转的弧度
*/
publicvoidgetXY(floatcenterX,floatcenterY,floatR,doublerad){
//获取圆周运动的X坐标
SmallRockerCircleX=(float)(R*Math.cos(rad))+centerX;
//获取圆周运动的Y坐标
SmallRockerCircleY=(float)(R*Math.sin(rad))+centerY;
}
圆周运动公式:通过三角函数定理得出。
X坐标:所在圆的半径*角度的余弦值
Y坐标:所在圆形半径*角度的正弦值
圆周的大小,由所在圆的半径R的大小来决定。
通过以上的公式我们就可以让摇杆在灰色圆形上做圆周运动了。另外我们在制作摇杆时还得注意以下三点:
* 做圆周运动的大小应该和灰色区域的半径相同。
* 触屏事件中应该首先判定玩家触屏的位置是否在灰色区域中,如果不在我们就应该获取摇杆与触屏点的角度然后获取摇杆应该在圆周运动上的XY坐标;如果在就不用处理了,只要将摇杆位置随着玩家点击位置就行了。
* 在触屏事件中,当玩家手指离开屏幕后,应该让摇杆的位置恢复到初始的位置状态。
为了给大家更直观和更整体的感受,下面笔者给出整个项目的MySurfaceView中的全部代码实现:
packagecom.rp;
importandroid.content.Context;
importandroid.graphics.Canvas;
importandroid.graphics.Color;
importandroid.graphics.Paint;
importandroid.util.Log;
importandroid.view.MotionEvent;
importandroid.view.SurfaceHolder;
importandroid.view.SurfaceView;
importandroid.view.SurfaceHolder.Callback;
publicclassMySurfaceViewextendsSurfaceViewimplementsCallback,Runnable{
privateThreadth;
privateSurfaceHoldersfh;
privateCanvascanvas;
privatePaintpaint;
privatebooleanflag;
//固定摇杆背景圆形的X,Y坐标以及半径
privateintRockerCircleX=100;
privateintRockerCircleY=100;
privateintRockerCircleR=50;
//摇杆的X,Y坐标以及摇杆的半径
privatefloatSmallRockerCircleX=100;
privatefloatSmallRockerCircleY=100;
privatefloatSmallRockerCircleR=20;
publicMySurfaceView(Contextcontext){
super(context);
Log.v("Himi","MySurfaceView");
this.setKeePScreenOn(true);
sfh=this.getHolder();
sfh.addCallback(this);
paint=newPaint();
paint.setAntiAlias(true);
setFocusable(true);
setFocusableInTouchMode(true);
}
publicvoidsurfaceCreated(SurfaceHolderholder){
th=newThread(this);
flag=true;
th.start();
}
/***
*得到两点之间的弧度
*/
publicdoublegetRad(floatpx1,floatpy1,floatpx2,floatpy2){
//得到两点X的距离
floatx=px2-px1;
//得到两点Y的距离
floaty=py1-py2;
//算出斜边长
floatxie=(float)Math.sqrt(Math.pow(x,2)+Math.pow(y,2));
//得到这个角度的余弦值(通过三角函数中的定理:邻边/斜边=角度余弦值)
floatcosAngle=x/xie;
//通过反余弦定理获取到其角度的弧度
floatrad=(float)Math.acos(cosAngle);
//注意:当触屏的位置Y坐标<摇杆的Y坐标我们要取反值-0~-180
if(py2
rad=-rad;
}
returnrad;
}
@Override
publicbooleanonTouchEvent(MotionEventevent){
if(event.getAction()==MotionEvent.ACTION_DOWN||
event.getAction()==MotionEvent.ACTION_MOVE){
//当触屏区域不在活动范围内
if(Math.sqrt(Math.pow((RockerCircleX-(int)event.getX()),2)
+Math.pow((RockerCircleY-(int)event.getY()),2))>=RockerCircleR){
//得到摇杆与触屏点所形成的角度
doubletempRad=getRad(RockerCircleX,RockerCircleY,event.getX(),event.getY());
//保证内部小圆运动的长度限制
getXY(RockerCircleX,RockerCircleY,RockerCircleR,tempRad);
}else{//如果小球中心点小于活动区域则随着玩家触屏点移动即可
SmallRockerCircleX=(int)event.getX();
SmallRockerCircleY=(int)event.getY();
}
}elseif(event.getAction()==MotionEvent.ACTION_UP){
//当释放按键时摇杆要恢复摇杆的位置为初始位置
SmallRockerCircleX=100;
SmallRockerCircleY=100;
}
returntrue;
}
/**
*
*@paramR
*圆周运动的旋转点
*@paramcenterX
*旋转点X
*@paramcenterY
*旋转点Y
*@paramrad
*旋转的弧度
*/
publicvoidgetXY(floatcenterX,floatcenterY,floatR,doublerad){
//获取圆周运动的X坐标
SmallRockerCircleX=(float)(R*Math.cos(rad))+centerX;
//获取圆周运动的Y坐标
SmallRockerCircleY=(float)(R*Math.sin(rad))+centerY;
}
publicvoiddraw(){
try{
canvas=sfh.lockCanvas();
canvas.drawColor(Color.WHITE);
//设置透明度
paint.setColor(0x70000000);
//绘制摇杆背景
canvas.drawCircle(RockerCircleX,RockerCircleY,RockerCircleR,paint);
paint.setColor(0x70ff0000);
//绘制摇杆
canvas.drawCircle(SmallRockerCircleX,SmallRockerCircleY,
SmallRockerCircleR,paint);
}catch(Exceptione){
//TODO:handleexception
}finally{
try{
if(canvas!=null)
sfh.unlockCanvasAndPost(canvas);
}catch(Exceptione2){
}
}
}
publicvoidrun(){
//TODOAuto-generatedmethodstub
while(flag){
draw();
try{
Thread.sleep(50);
}catch(Exceptionex){
}
}
}
publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,intheight){
Log.v("Himi","surfaceChanged");
}
publicvoidsurfaceDestroyed(SurfaceHolderholder){
flag=false;
Log.v("Himi","surfaceDestroyed");
}
}
以上就是本次制作触屏式全方位游戏摇杆的代码实现演示。
本次的简单制作触屏式的全方位触屏游戏摇杆的讲解到此就暂告一段落,如果以后有什么相关的内容进行补充或者修改的话,笔者会继续在此进行相关的内容的补充或者修改的工作,同时也欢迎大家对本次的讲解提出自己的建议和补充。最后笔者希望本次的讲解对大家学习游戏开发能够起到一定的帮助作用!
¥698.00
¥98.00
¥108.00
¥98.00