【Android游戏开发二十四】360°平滑游戏摇杆(触屏方向导航)

Himi原创,转载务必注明出处!

原文地址:http://blog.youkuaiyun.com/xiaominghimi/archive/2011/05/16/6423983.aspx

,

此章节为正在创作的游戏开发书籍中的一部分,由于写书的缘故很久没有更新了,挺对不起大家的;那么今天放出书中的一部分,让大家先睹为快吧;

在Android系统的手机,有的根本没有实体的上下左右导航按键,所以很多游戏都会有利用Android手机都具有触屏的特性,制作360度摇杆来取代游戏方向键,这样不仅能使界面UI变得很美观,而且更加的方便操作;

下面先来看效果吧:


下面开始实现:

首先,肯定是绘制两个圆形,无可置疑;圆心点重合,为了区分 ,所以设置了不同颜色;

灰色:固定不动的摇杆背景(也意味着摇杆的活动范围);

红色:摇杆;

然后考虑:红色摇杆肯定跟随手指触屏的位置而移动,那么这个很easy啦,只要在触屏事件中处理,将获取的触屏XY坐标赋值与摇杆XY坐标即可;这个没问题;但是紧接着在思考一个问题:

一般情况下,我们不可能希望摇杆一直跟随手指位置,所以需要一个摇杆的活动区域,也就如同上图中的灰色区域,在灰色区域内摇杆可以随着用户的触屏位置移动,但是一旦用户触屏位置在活动区域之外,摇杆就不应该跑出灰色区域;所以具体实现步骤如下:

1) 得到通过摇杆的坐标与触屏点的坐标得到所形成的角度Angle

2) 根据Angle,以及已知所在圆的半径,算出摇杆所在灰色圆形上做圆周运动的当前X,Y坐标;

首先第一步: 算出摇杆坐标与触屏坐标形成的角度

我们肯定已知摇杆当前坐标,并且当用户触屏时的坐标也可以在触屏按键中得到,那么获取的方法就可以写成一个方法,方法如下:

/*** * 得到两点之间的弧度 */ public double getRad(float px1, float py1, float px2, float py2) { //得到两点X的距离 float x = px2 - px1; //得到两点Y的距离 float y = py1 - py2; //算出斜边长 float xie = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); //得到这个角度的余弦值(通过三角函数中的定理 :邻边/斜边=角度余弦值) float cosAngle = x / xie; //通过反余弦定理获取到其角度的弧度 float rad = (float) Math.acos(cosAngle); //注意:当触屏的位置Y坐标<摇杆的Y坐标我们要取反值-0~-180 if (py2 < py1) { rad = -rad; } return rad; }

在Java中 Math类中的反余弦函数返回的不是角度是弧度,这一点要格外注意;

另外一点就是,因为三角函数角度范围是0~180度,所以反之应该是-0~-180度;

通过此函数获取到摇杆与用户触屏位置所形成的角度之后,我们就可以通过圆周公式来得到其摇杆的XY坐标了;方法如下:

/** * * @param R * 圆周运动的旋转点 * @param centerX * 旋转点X * @param centerY * 旋转点Y * @param rad * 旋转的弧度 */ public void getXY(float centerX, float centerY, float R, double rad) { //获取圆周运动的X坐标 SmallRockerCircleX = (float) (R * Math.cos(rad)) + centerX; //获取圆周运动的Y坐标 SmallRockerCircleY = (float) (R * Math.sin(rad)) + centerY; }

圆周运动公式:通过三角函数定理得出:

X坐标:所在圆的半径*角度的余弦值

Y坐标:所在圆形半径*角度的正弦值

圆周的大小,由所在圆的半径R的大小来决定;

通过以上的公式我们就可以让摇杆在灰色圆形上做圆周运动,当然除此之外我们还要注意三点:

1:做圆周运动的大小,应该跟灰色区域的半径相同;

2:触屏事件中应该首先判定用户触屏的位置是否在灰色区域中,如果不在,我们就应该获取摇杆与触屏点的角度然后获取摇杆应该在圆周运动上的XY坐标;如果在,就没有处理了,只要将摇杆位置随着用户点击位置就好了;

3:在触屏事件中,当用户手指离开屏幕后,应该让摇杆的位置恢复到初始的位置状态;

下面是整个项目的MySurfaceView中全部代码:

package com.rp; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.Log; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.SurfaceHolder.Callback; public class MySurfaceView extends SurfaceView implements Callback, Runnable { private Thread th; private SurfaceHolder sfh; private Canvas canvas; private Paint paint; private boolean flag; //固定摇杆背景圆形的X,Y坐标以及半径 private int RockerCircleX = 100; private int RockerCircleY = 100; private int RockerCircleR = 50; //摇杆的X,Y坐标以及摇杆的半径 private float SmallRockerCircleX = 100; private float SmallRockerCircleY = 100; private float SmallRockerCircleR = 20; public MySurfaceView(Context context) { super(context); Log.v("Himi", "MySurfaceView"); this.setKeepScreenOn(true); sfh = this.getHolder(); sfh.addCallback(this); paint = new Paint(); paint.setAntiAlias(true); setFocusable(true); setFocusableInTouchMode(true); } public void surfaceCreated(SurfaceHolder holder) { th = new Thread(this); flag = true; th.start(); } /*** * 得到两点之间的弧度 */ public double getRad(float px1, float py1, float px2, float py2) { //得到两点X的距离 float x = px2 - px1; //得到两点Y的距离 float y = py1 - py2; //算出斜边长 float xie = (float) Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); //得到这个角度的余弦值(通过三角函数中的定理 :邻边/斜边=角度余弦值) float cosAngle = x / xie; //通过反余弦定理获取到其角度的弧度 float rad = (float) Math.acos(cosAngle); //注意:当触屏的位置Y坐标<摇杆的Y坐标我们要取反值-0~-180 if (py2 < py1) { rad = -rad; } return rad; } @Override public boolean onTouchEvent(MotionEvent event) { 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) { //得到摇杆与触屏点所形成的角度 double tempRad = getRad(RockerCircleX, RockerCircleY, event.getX(), event.getY()); //保证内部小圆运动的长度限制 getXY(RockerCircleX, RockerCircleY, RockerCircleR, tempRad); } else {//如果小球中心点小于活动区域则随着用户触屏点移动即可 SmallRockerCircleX = (int) event.getX(); SmallRockerCircleY = (int) event.getY(); } } else if (event.getAction() == MotionEvent.ACTION_UP) { //当释放按键时摇杆要恢复摇杆的位置为初始位置 SmallRockerCircleX = 100; SmallRockerCircleY = 100; } return true; } /** * * @param R * 圆周运动的旋转点 * @param centerX * 旋转点X * @param centerY * 旋转点Y * @param rad * 旋转的弧度 */ public void getXY(float centerX, float centerY, float R, double rad) { //获取圆周运动的X坐标 SmallRockerCircleX = (float) (R * Math.cos(rad)) + centerX; //获取圆周运动的Y坐标 SmallRockerCircleY = (float) (R * Math.sin(rad)) + centerY; } public void draw() { 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 (Exception e) { // TODO: handle exception } finally { try { if (canvas != null) sfh.unlockCanvasAndPost(canvas); } catch (Exception e2) { } } } public void run() { // TODO Auto-generated method stub while (flag) { draw(); try { Thread.sleep(50); } catch (Exception ex) { } } } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.v("Himi", "surfaceChanged"); } public void surfaceDestroyed(SurfaceHolder holder) { flag = false; Log.v("Himi", "surfaceDestroyed"); } }

如果大家想美化摇杆,那就让你们的美工给出两张圆形图吧;还在等什么,立刻为你的游戏加上摇杆吧~娃哈哈

好啦,其实这里只是给大家介绍思路,具体的书中,我已经将此封装成了一个摇杆类,这样更加的OOP,至于如何封装,大家可以根据需要自由来设计;今天的博文写的可能不是很清晰,因为我现在脑子昏昏沉沉的 - - 。

从写书开始到现在,每天都3-4点睡觉,唉、不过值得高兴的是,如果没有特殊情况,6月底书籍就要交稿了,大家期待下吧;我也会继续努力这最后两个月的;

项目下载地址:http://download.youkuaiyun.com/source/3260901

还对了,以前上传的项目资源分都将资源调整成0分了,全部设置为免费下载,方便大家;

【AndroidStudio】安卓虚拟摇杆组件 1.标准化的安卓页面虚拟摇杆 2.可获取虚拟摇杆的X、Y偏离值 3.横屏左右两个虚拟摇杆。 具体使用查看文章:https://blog.youkuaiyun.com/xanadw/article/details/124234671 立即下载

相关推荐

手把手教你用Qt和QScada框架,从零搭建一个简易的工业组态监控界面

本文详细介绍了如何使用Qt和QScada框架从零搭建工业组态监控界面,涵盖环境配置、界面设计、动态数据绑定及高级功能实现。通过实战案例演示,帮助开发者快速掌握SCADA系统开发技巧,提升工业自动化项目的开发效率。

weixin_32932149的博客 340

【AndroidStudio开发】(二)加入摇杆控制

系列文章目录 【AndroidStudio开发】(一):新建页面切换项目 【AndroidStudio开发】(二):加入摇杆控制 【AndroidStudio开发】(三):蓝牙BLE连接设备 摇杆目录系列文章目录前言一、摇杆组件二、导入摇杆库1.文件复制2.主函数引入3.页面文件修改4.效果验证总结 前言 第一篇文章讲述了如何用AndroidStudio(以下简称AS)新建一个页面切换的项目,这篇文章则是对第一篇文章的页面进行升级。第一篇文章的页面非常简单明了,就一个按钮,点击跳转,现在需要在这个页面加

xanadw的博客 7503

pdf.js 移动端手势缩放功能实现与原生事件集成

本文详细解析了如何为pdf.js的viewer.html移动端页面实现流畅的双指捏合手势缩放功能。通过深入分析pdf.js的缩放机制,并利用原生触摸事件(touchstart、touchmove、touchend)进行集成,在不修改核心源码的前提下,为用户提供媲美原生应用的顺滑缩放体验,有效提升了移动端PDF阅读的专业性和用户满意度。

brandy的博客 488

微信小程序开发实战(12):滑杆组件(slider)和form组件

slider组件用于通过滑杆改变数值,form是表单组件。本文会详细讲解这两个组件的用法

一个被知识诅咒的人 2094

YOLOv5+Astra Pro Plus深度相机:手把手教你实现实时目标检测(附ROS配置技巧)

本文详细介绍了如何将YOLOv5目标检测算法与Astra Pro Plus深度相机结合,构建实时目标检测系统。内容涵盖从硬件选型、环境搭建、ROS配置到YOLOv5部署与深度信息融合的完整流程,并分享了性能优化、避障算法等实战技巧,帮助开发者在机器人视觉等场景中快速实现智能感知应用。

weixin_28292761的博客 386

彩票预测的可能性与算法分析

彩票作为一种以随机数为基础的赌博形式,吸引了大量希望一夜暴富的参与者。尽管许多人希望通过某种方式预测彩票结果,以增加中奖几率,但彩票预测的可能性依然是一个充满争议和误解的话题。本文将探讨彩票是否能够预测的理论依据,分析可能的预测算法,并解释这些算法为何在实际应用中难以奏效。

m0_38012434的博客 2万+

(转)【Android游戏开发二十四】360°平滑游戏摇杆(触屏方向导航)

李华明Himi 原创,转载务必在明显处注明: 转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/android-game/384.html  ,   此章节为正在创作的游戏开发书籍中的一部分,由于写书的缘故很久没有更新了,挺对不起大家的;那么今天放出书中的一部分,让大家先睹为快吧;   在Android系统的手机,有的

gxj1680的专栏 1103

vnpy_ctp源码下载后转变为python可用的处理过程

vnpy_ctp源码下载后在window中编译使用

m0_37967652的博客 3327

【ANDROID游戏开发二十四】360°平滑游戏摇杆(触屏方向导航)

此章节为正在创作的游戏开发书籍书稿中的一部分,由于写书的缘故很久没有更新了,挺对不起大家的;那么今天放出书稿中的一部分,让大家先睹为快吧; 在Android系统的手机,有的根本没有实体的上下左右导航按键,所以很多游戏都会有利用Android手机都具有触屏的特性,制作360度摇杆来取代游戏方向键,这样不仅能使界面UI变得很美观,而且更加的方便操作; 下面先来看效果吧:

GitLqr的博客 2942

innovus:ccopt_design流程

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?spec文件可以只创建一次,无需多次创建。2)virtual balance阶段。3)Full Balancing阶段。4)Clock Routing阶段。1)clustering阶段。

m0_61544122的博客 2475

【HALCON 25.11 + C#】 01:2026年工业机器视觉实战详解(从入门到精通)

2026年机器视觉市场规模将突破230亿美元,HALCON 25.11的革命性更新与C#的工业集成优势形成黄金技术栈。本文作为付费专栏开篇序章,聚焦“为什么现在必须学25.11+C#”的核心问题,通过真实工业案例、五项核心技术突破、联合编程架构优势及30篇系统学习路线,全方位论证其投资价值。读者将掌握持续学习、深度OCR加速等关键技能,获得可直接上产线的工业级代码资产与架构设计思维,解决柔性生产、边缘部署等核心痛点,成为具备技术溢价的机器视觉工程师。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1215
上一篇: 【Android游戏开发二十三】自定义ListView【通用】适配器并实现监听控件!
下一篇: 【Android游戏开发二十五】在Android上的使用《贝赛尔曲线》!
iteye_6921
博客等级 码龄8年 0粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值