Delphi开发Android用虚拟摇杆VirtualJoystic
生活随笔
收集整理的這篇文章主要介紹了
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的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: GB35114---聊聊SM2签名格式
- 下一篇: linux中mysql忘记密码