Delphi开发Android用虚拟摇杆VirtualJoystic
Delphi11新鲜出炉后一直没有去试用,最近几天有空下了个Lite版来玩,发现编译速度快了很多,编译后的尺寸也变小了一些,前些时候在github上看到一个Delphi无引擎版的小游戏,决定调试一下,目前Windows下运行正常,像这个样子:
安卓下暂时没有运行起来,界面是这个样子:
使用的MouseDown和MouseUp事件驱动,也就是说按左、右的时候,没法跳,所以想着改造一下,整个虚拟摇杆来操控,于是有了这一篇博文(顺便吐槽一下Delphi11有时编辑器会完全消失,欢迎页面也一起消失了)。
一、首先顺便弄一下,做个摇杆的样子,和按键的样子:
二、摇杆在屏幕左半边,按键在屏幕右半边,也就是说点击屏幕左半边任意一点就是 摇杆的中心位置,然后滑动触控点,一通计算得到方向,同时兼顾右边的按键触控即可。
单元代码如下(网上其他的方法太复杂难懂,下面主要就3个方法2个事件):
unit Unit7;interfaceusesSystem.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects,FMX.Gestures, FMX.ExtCtrls, FMX.Controls.Presentation, FMX.StdCtrls, FMX.Ani,FMX.Memo.Types, FMX.ScrollBox, FMX.Memo, System.Math, FMX.Layouts;typeTForm7 = class(TForm)Label1: TLabel;Label2: TLabel;chk8Dir: TCheckBox;Memo1: TMemo;Layout1: TLayout;Circle1: TCircle;Circle2: TCircle;Circle3: TCircle;Circle4: TCircle;joyBorder: TCircle;joyCenter: TCircle;tmrJoyUp: TTimer;Label0: TLabel;procedure chk8DirChange(Sender: TObject);procedure FormTouch(Sender: TObject; const Touches: TTouches;const Action: TTouchAction);procedure FormCreate(Sender: TObject);procedure tmrJoyUpTimer(Sender: TObject);privateFStartPt: TPointF;FBtns: TArray<TCircle>;function CalcDirection(A: integer): Char;procedure JoyDown(X, Y: Single);procedure JoyMove(X, Y: Single);procedure JoyUp;{ Private declarations }public{ Public declarations }end;varForm7: TForm7;implementation{$R *.fmx}varA2D8: array [0..7] of Integer = (23, 68, 112, 158, 203, 248, 293, 338);A2C8: array [0..7] of Char = ('↑', '↗', '→', '↘', '↓', '↙', '←', '↖');A2D4: array [0..3] of Integer = (45, 135, 225, 315);A2C4: array [0..3] of Char = ('↑', '→', '↓', '←');function TForm7.CalcDirection(A: integer): Char;
varI: integer;
beginif chk8Dir.IsChecked thenbegin//计算八方向下当前摇杆的方向Result := A2C8[0];for I := 1 to 7 doif (A >= A2D8[I-1]) and (A < A2D8[I]) thenbeginResult := A2C8[I];exit;end;endelsebegin//计算四方向下当前摇杆的方向Result := A2C4[0];for I := 1 to 3 doif (A >= A2D4[I-1]) and (A < A2D4[I]) thenbeginResult := A2C4[I];exit;end;end;
end;procedure TForm7.chk8DirChange(Sender: TObject);
beginif chk8dir.IsChecked thenchk8dir.Text := '八方向'elsechk8dir.Text := '四方向';
end;procedure TForm7.FormCreate(Sender: TObject);
begin//初始化摇杆按键SetLength(FBtns, 4);FBtns[0] := Circle4;FBtns[1] := Circle3;FBtns[2] := Circle2;FBtns[3] := Circle1;{$IFDEF Android}FullScreen := True;{$ENDIF}Label0.Text := Format('屏幕:%d x %d', [Width, Height]);
end;procedure TForm7.FormTouch(Sender: TObject; const Touches: TTouches;const Action: TTouchAction);
varI, J, R: Integer;JoyOk, KeyOk: Boolean;pt: TPoint;
begin//假设屏幕左半边只能用来操作摇杆,按键必须在屏幕右半边//不能使用MouseDown\MouseMove\MouseUp事件+Touch事件的方式//因为第一个触控的点会被当成Mouse事件,也就是说先按按键的话,摇杆就操作不了//所以要使用OnTouch事件进行多点触控//另外OnTouch事件有个特点,有触控时才触发,若只操作摇杆再松开的话则无事件触发//也不能用MouseUp来触发,因为只有第一个点松开时才发触发MouseUp,若一直按差按键//再滑动摇杆,则摇杆松开也没法产生事件使摇杆复位//解决方案:用joyCenter.Tag作为标志,当屏幕左半边有点触发时Tag=1,设定一个Timer//在0.5秒内归0,下一个OnTouch事件中仍有这个点,则再次执行Tag=1JoyOk := False;KeyOk := False;memo1.Lines.BeginUpdate;memo1.Lines.Clear;for I := 0 to length(Touches) - 1 dobeginpt := Touches[I].Location.Round;memo1.Lines.Add(Format('(%.3d, %.3d)', [pt.X, pt.Y]));if pt.X < Width/2 thenbeginif JoyOk thenContinue;JoyOk := True;tmrJoyUp.Enabled := False;if joyCenter.Tag = 1 thenJoyMove(pt.X, pt.Y)elseJoyDown(pt.X, pt.Y);tmrJoyUp.Enabled := True;end//一次最多触发一个按键(摇杆由Mouse事件触发了)else if KeyOk thenContinue;//遍历按键for J := 0 to Length(FBtns) - 1 dobegin//计算按键半么(按键是圆的)R := System.Math.Min(Round(FBtns[J].Width / 2), Round(FBtns[J].Height / 2));//检测触控点是否在按钮区域内if PtInCircle(pt, FBtns[J].Position.Point.Round + Point(R, R), R) thenbeginKeyOk := True;//TODO 执行按键操作FBtns[J].StopPropertyAnimation('fill.color');FBtns[J].Fill.Color := TAlphaColors.Chartreuse;FBtns[J].AnimateColor('fill.color', TAlphaColors.Aliceblue, 0.5);end;end;end;memo1.Lines.EndUpdate;
end;procedure TForm7.JoyDown(X, Y: Single);
beginif X >= Layout1.Width/2 thenExit;if X < joyBorder.Width/2 thenExit;if Y > Layout1.Height-joyBorder.Height/2 thenExit;joyBorder.Position.X := X - joyBorder.Width / 2;joyBorder.Position.Y := Y - joyBorder.Height / 2;joyCenter.Position.X := (joyBorder.Width - joyCenter.Width) / 2;joyCenter.Position.Y := (joyBorder.Height - joyCenter.Height) / 2;if joyCenter.Tag = 0 thenbeginFStartPt.X := X;FStartPt.Y := Y;end;joyCenter.Tag := 1;Label1.Text := Format('原点:(%.0f, %.0f)', [FStartPt.X, FStartPt.Y]);
end;procedure TForm7.JoyMove(X, Y: Single);
varpt: TPointF;I, A: Integer;r, mr, aa: Single;c: Char;
beginpt.X := X;pt.Y := Y;aa := pt.Angle(FStartPt);//弧度//弧度*180/PI => X轴正方向为0度,X轴顺时针为0~180度,逆时针为0~-180角//所以+360度 => X轴顺时针0~360,(A+90)%360 => 调整为正北为0度A := Round(360 + aa*180/3.1415926 + 90) mod 360;r := pt.Distance(FStartPt);//最大半径要减去摇杆球的半么mr := joyBorder.Width/2 - joyCenter.Width/2;if r > mr thenr := mr;//使用极坐标公式 x = r*cos(a), y = r*sin(a)通过角度、半径计算出虚拟摇杆球的位置joyCenter.Position.X := joyBorder.Width/2 + r*Cos(aa) - joyCenter.Width/2;joyCenter.Position.Y := joyBorder.Height/2 + r*Sin(aa) - joyCenter.Height/2;C := CalcDirection(A);Label2.Text := Format('远点:(%.0f, %.0f),方位角:%d°,强度:%.0f%%,方向:%s', [pt.X, pt.Y, A, r/mr*100, c]);
end;procedure TForm7.JoyUp;
begin//摇杆复位joyCenter.Tag := 0;joyCenter.Position.X := (joyBorder.Width - joyCenter.Width) / 2;joyCenter.Position.Y := (joyBorder.Height - joyCenter.Height) / 2;
end;procedure TForm7.tmrJoyUpTimer(Sender: TObject);
begintmrJoyUp.Enabled := False;JoyUp;memo1.Lines.Clear;
end;end.
最终效果是这个样子(HUAWEI P20):
完整工程含APK《下载地址》
Delphi开发Android用虚拟摇杆VirtualJoystic相关推荐
- 尝鲜delphi开发android/ios_环境搭建
Delphi这又老树发新枝了,开始做终端程序开发了,这个东西的准确名字是:RAD Studio XE5,可以使用delphi和c++ builder进行终端开发. 我尽可能讲啰嗦一些,免得回头被人问. ...
- 《Delphi XE6 android 编程入门教程》推荐
近5.6年已经没有看见关于delphi的新技术的书出来了(看来在国内delphi的使用量确实很低了), 高勇同学最近出了一本<Delphi XE6 android 编程入门教程>,上周刚拿 ...
- 微信小程序之蓝牙开发虚拟摇杆
文章用于学习记录 文章目录 前言 一.App Inventor 二.uni-app 三.微信小程序 3.1 示例&应用 3.2 服务值与特征值 3.3 控制指令 3.4 测试 3.5 十六进制 ...
- delphi android 蓝牙,Android实例-Delphi开发蓝牙官方实例解析(XE10+小米2+小米5)
[实例简介] 2.保证无毒 3.简单,方便,实用 4.实例可以自行改用 5.如有非法,本人无法律责任,由改动代码人负责! 6.需要更多本人作品,查找标签"朱建强" 7.请下载,杀毒 ...
- 二丶Android如何自定义一个可移动的飞行虚拟摇杆?
摘要: 上次我们自定义了一个固定位置摇杆,此摇杆无法调整杆量,且位置固定,这次我们就来定义一个可以自由调整杆量和变换位置的虚拟摇杆. 下面就写一下需要实现此虚拟摇杆的步骤: 一丶初始化资源 我们需要美 ...
- DELPHI XE Android 开发笔记
DELPHI XE Android 开发笔记 第一次编译时,设定android SDK: F:\RAD Studio XE6\PlatformSDKs\adt-bundle-windows-x86-2 ...
- Delphi 开发跨平台 Android / iOS 程序的多语言
使用 Delphi 的 FireMonkey 框架,开发跨平台的程序,可以做到一个源码,编译成 Windows, Mac OS, Android, iOS,甚至是 Linux 上面运行的程序. 简单说 ...
- Cocos2d-x虚拟摇杆控制精灵上下左右运动----之游戏开发《赵云要格斗》(1)
这里是Evankaka的博客,欢迎大家前面讨论与交流------ 转载请注明出处http://blog.csdn.net/evankaka/article/details/4204350 ...
- cocos2dx游戏开发学习——虚拟摇杆(8方向)讲解
写这篇博客的目的主要是记录一下 虚拟摇杆的实现过程.虚拟摇杆一般分文四方向和八方向,也主要根据项目需求来决定.直接进入主题吧. 先上效果图: 方向的思路分析 看图,说先我们可以将8个方向在坐标系中画出 ...
- 开发Android必知的工具
程序开发有时候非常依赖使用的开发工具,好的完备的开发工具可以让开发人员的工作效率有大幅度的提高.开发Android也是如此,大家可能都离不开Eclipse或Android Studio这些工具,但他们 ...
最新文章
- 面向对象设计领域的OCP原则
- DDR的前世与今生(一)
- Python中使用requests和parsel爬取喜马拉雅电台音频
- 剥开比原看代码(十七):比原是如何显示交易的详细信息的?
- python输入三个整数、输出最大的数_题目:使用Python编程,输入三个整数x,y,z,请把这三个数由小到大输出...
- php点击弹出文字代码,js实现鼠标点击页面弹出自定义文字效果
- 第 14 章 程序员常用 10 种算法
- 桌面版应用_【Nordic博文分享系列】开发你的第一个NCS(Zephyr)应用程序
- log4j.dtd_Eclipse log4j.xml –无法将log4j.dtd验证为XML定义
- 安装php项目后图片路径不对,解决织梦CMS栏目绑定二级域名后图片不显示,路径错误办法...
- mysql内容_mysql 的基本内容
- 20210729 线性增长条件和全局Lipschitz条件的关系
- IOS逆向学习之路之iPod touch4 越狱心得
- PHP京东商城爬取网页乱码问题解决
- 多目标跟踪算法中之图匹配——匈牙利算法和KM算法详解
- go语言的类型之间的相互转化和float保留小数时的四舍五入
- 元宇宙来了,用好名字好概念赋能中国制造国际营销的初步构想
- 《Python程序设计与算法基础教程(第二版)》江红 余青松,第十章课后习题答案
- PHPExcel导出Excel基本操作,实现设置字体、合并单元格、加粗等功能
- Java子类访问父类私有变量的思考
热门文章
- IBM Rhapsody 报错找不到 VC11 目录的解决方法
- php 将日期转换时间戳,php怎么将日期转换为时间戳?
- idea 谷歌翻译
- 创建数据库常用SQL语句
- Android系统QFIL刷机流程
- “跟着吴恩达老师入门机器学习”学习笔记(二)
- hitool java_第三章:使用HiTool下载程序
- mysql varbinary blob_MySQL BIT、BINARY、VARBINARY、BLOB(二进制类型)
- java ojdbc14 查询数据表,Oracle10g JDBC ojdbc14 DATE类型hibernate查询时分秒问题
- linux下编译opendds,求教OpenDDS的交叉编译!