InputQuery は関数で、OKかCancelかをBoolean で返す。
procedure TfrmMain.Button1Click(Sender: TObject); var tmpString: String; begin InputBox('', '', tmpString); ShowMessage(tmpString); if InputQuery('', '', tmpString) then ShowMessage(tmpString); end;
InputQuery は関数で、OKかCancelかをBoolean で返す。
procedure TfrmMain.Button1Click(Sender: TObject); var tmpString: String; begin InputBox('', '', tmpString); ShowMessage(tmpString); if InputQuery('', '', tmpString) then ShowMessage(tmpString); end;
delphi for iOS 開発ファーストステップガイド など
全般にわたって、開発について知っておきたいことが書かれている。
素材を探すのにとても便利なサイト
uses
FMX.Dialogs,
System.UITypes;
を追加
列挙型は、型から書くのがFiremonkey流らしい。
if mrOk = MessageDlg('ゲームを終了していいですか。', TMsgDlgType.mtConfirmation, [TMsgDlgBtn.mbOk, TMsgDlgBtn.mbCancel], 0) then begin GameStep := gsGameEnd; Viewer.MainTabPage := mtTitle; end;
データベースを使おうと思ったり理由は、実機テストで信じられないくらい時間がかかったため。
Win32 では数秒の処理が数十分かかった。
これはどうも、動的配列を逐次大きくして追加していた部分にあったみたい
procedure TWordList.AddItem(aWordRecord: TWordRecord); begin SetLength(Self.Items, Length(Self.Items) + 1); Self.Items[High(Items)].Assign(aWordRecord); end; procedure TWordList.Load(aPathFileName: string); var i: Integer; tmpWordRecord: TWordRecord; tmpRecordList: TStringList; tmpFieldList: TStringList; tmpString: String; begin // DeleteFile(aPathFileName); self.Clear; if FileExists(aPathFileName) then begin tmpFieldList := TStringList.Create; tmpRecordList := TStringList.Create; tmpRecordList.LoadFromFile(aPathFileName); for i := 0 to tmpRecordList.Count - 1 do begin tmpFieldList.Delimiter := chr(DEMILITR_CHR); tmpFieldList.StrictDelimiter := False; tmpString := tmpRecordList[i]; tmpFieldList.DelimitedText := tmpString; tmpWordRecord.Word := trim(tmpFieldList[0]); tmpWordRecord.Japanese := trim(tmpFieldList[1]); tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_COMMA_CHR), ',', [rfReplaceAll]); tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_SPACE_CHR), ' ', [rfReplaceAll]); self.AddItem(tmpWordRecord); end; tmpRecordList.Free; tmpFieldList.Free; end; end;
最初に配列の大きさを決定して、代入するととてつもなく早くなった。
これで、データベースを使う必要はなくなった。
procedure TWordList.Load(aPathFileName: string); var i: Integer; tmpWordRecord: TWordRecord; tmpRecordList: TStringList; tmpFieldList: TStringList; tmpString: String; begin self.Clear; if FileExists(aPathFileName) then begin tmpFieldList := TStringList.Create; tmpRecordList := TStringList.Create; tmpRecordList.LoadFromFile(aPathFileName); SetLength(Self.Items, tmpRecordList.Count); for i := 0 to tmpRecordList.Count - 1 do begin tmpFieldList.Delimiter := chr(DEMILITR_CHR); tmpFieldList.StrictDelimiter := False; tmpString := tmpRecordList[i]; tmpFieldList.DelimitedText := tmpString; tmpWordRecord.Word := trim(tmpFieldList[0]); tmpWordRecord.Japanese := trim(tmpFieldList[1]); tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_COMMA_CHR), ',', [rfReplaceAll]); tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_SPACE_CHR), ' ', [rfReplaceAll]); Self.Items[i].Assign(tmpWordRecord); // self.AddItem(tmpWordRecord); end; tmpRecordList.Free; tmpFieldList.Free; end; end;
InterBase のライセンス認証で四苦八苦する。
メールで送られてきたライセンス使用許諾ファイルをどこに置くかわからない。
製品: IBLite XE3 for iOS Deployment License
メールで説明されている手順:
1. まず、添付ファイルをハード ドライブ上の任意のフォルダ (“マイ ドキュメント” など) に保存します。
2. RAD Studio XE4 ユーザーのお客様が IBLite ライセンスを必要とされる場合には、上記のライセンス ファイルを “%IBREDISTDIR%” フォルダにコピーします。
3. その後、RAD Studio の配置ウィザードの指示に従って進みます。ファイルは必ず、アプリケーションと一緒にターゲット プラットフォーム向けにバンドルし、ターゲット プラットフォームの interbase/license フォルダ パスに配布してください。
実際にうまくいった手順:
ライセンス ファイルを “%IBREDISTDIR%” フォルダにコピーして、reg_iblite にリネームする。
“%IBREDISTDIR%” フォルダとは
C>ユーザー>パブリック>パブリックのドキュメント>InterBase>redist>InterBaseXe3 (OS:Windows 7)
製品: InterBase XE3 ToGo Test Deployment
RAD Studio XE4 ユーザー様の場合:
ライセンス使用許諾ファイルを “%IBREDISTDIR%” フォルダに reg_ibtogo.txt という名前で保存します。これは、Windows、MacOSX、iOS への配置に適用されます。
とりあえず、iOS Simulator では動作を確認、しかし、実機でのテストではエラー発生。配置のミスか?
実機テストでテキストファイルを読めるようになったが・・・
データ数は40000ぐらい。
Win32 では1秒
iOS simulator では20秒
実機テストでは20分はかかる。
大きいデータではこの方法は無理。
InterBase を使う方向で考える。
procedure TWordList.Load(aPathFileName: string); var i: Integer; tmpWordRecord: TWordRecord; tmpRecordList: TStringList; tmpFieldList: TStringList; tmpString: String; begin // DeleteFile(aPathFileName); self.Clear; if FileExists(aPathFileName) then begin tmpFieldList := TStringList.Create; tmpRecordList := TStringList.Create; tmpRecordList.LoadFromFile(aPathFileName); for i := 0 to tmpRecordList.Count - 1 do begin tmpFieldList.Delimiter := chr(DEMILITR_CHR); tmpFieldList.StrictDelimiter := False; tmpString := tmpRecordList[i]; tmpFieldList.DelimitedText := tmpString; tmpWordRecord.Word := trim(tmpFieldList[0]); tmpWordRecord.Japanese := trim(tmpFieldList[1]); tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_COMMA_CHR), ',', [rfReplaceAll]); tmpWordRecord.Japanese := StringReplace(tmpWordRecord.Japanese, chr(ESCAPE_SPACE_CHR), ' ', [rfReplaceAll]); self.AddItem(tmpWordRecord); end; tmpRecordList.Free; tmpFieldList.Free; end; end;
配置マネージャーで、画像や音声を初回起動時に配置しているが、同名ファイルがあった場合は新たに配置ない仕様になっているみたい。
まず、古いファイルを手動で削除する必要がある。
それにしても、配置マネージャーは使い勝手が悪い。コピー、ペーストもできないし、すべてタイプしなくてはいけないなんて。
みんなどうしてるのかな?
uses に System.Generics.Collections を追加
private
FUndoList: TList<TUndoRecord>;
で
FUndoList := TList<TUndoRecord>.Create;
アクセスは直接
GameModel.TileManager.TileList.Assign(FUndoList[tmpUndoStep].UndoTileList);
といった形で。
これは型キャストの必要がないので、コードがすっきり。
iOS Simulator でも動作することを確認。
あまり行儀のよくない型キャストが win32 と iOS系では動作が違うような気がする。
GameModel.TileManager.TileList.Assign(TUndoRecord(FUndoList[tmpUndoStep]).UndoTileList);
このあたりをジェネリクスを使って、書き換えることにする。
ハイスコア関係で手間取り、やっと実機テスト。
どうやら辞書ファイルが読まれていないようだ。
ファイルサイズの上限があるのか?
DB化する必要があるのか?
実はi-Simulator でもアクセス違反のエラーがまだ取れていない。
デザイン、音関係もこれから。
あと3日ではたしてどこまでできるのか。
リファクタリング>名前の変更で
コンポーネント名を変更すると、まったく関係のない型名の変更が行われる。
やってはいけない。(XE4)
type TSortArray = array of Integer; procedure QuickSortWithOrderList(var vSortArray: TSortArray; var vOrderArray:TSortArray); var i: Integer; procedure DoQuickSort(vSortArray:TSortArray; vSortOrderArray:TSortArray; start,last:integer); var tmpCompareIndex, tmpSwapIndex, tmpCompareValue: integer; procedure swapValue(aIndexA, aIndexB: Integer); var tmpDummyValue: Integer; begin tmpDummyValue := vSortArray[aIndexA]; vSortArray[aIndexA] := vSortArray[aIndexB]; vSortArray[aIndexB] := tmpDummyValue; tmpDummyValue := vSortOrderArray[aIndexA]; vSortOrderArray[aIndexA] := vSortOrderArray[aIndexB]; vSortOrderArray[aIndexB] := tmpDummyValue; end; begin tmpSwapIndex := (start + last) div 2; swapValue(start, tmpSwapIndex); tmpCompareValue := vSortArray[start]; tmpSwapIndex := start + 1; tmpCompareIndex := start + 1; while tmpCompareIndex <= last do begin if vSortArray[tmpCompareIndex] < tmpCompareValue then // 降順 begin swapValue(tmpCompareIndex, tmpSwapIndex); Inc(tmpSwapIndex); end; Inc(tmpCompareIndex); end; Dec(tmpSwapIndex); swapValue(start, tmpSwapIndex); if tmpSwapIndex-start > 1 then DoQuickSort(vSortArray,vSortOrderArray,start,tmpSwapIndex); if last-tmpSwapIndex > 1 then DoQuickSort(vSortArray,vSortOrderArray,tmpSwapIndex+1,last); end; begin SetLength(vOrderArray, Length(vSortArray)); for i :=0 to Length(vOrderArray) - 1 do vOrderArray[i] := i; DoQuickSort(vSortArray, vOrderArray, LOW(vSortArray), HIGH(vSortArray)); end;
数値配列の整列 ~QuickSort~
http://www5d.biglobe.ne.jp/~tomoya03/shtml/algorithm/QSort.htm
procedure QuickSort(vSortArray:TSortArray; start,last:integer); var tmpCompareIndex, tmpSwapIndex, tmpCompareValue: integer; procedure swapValue(aIndexA, aIndexB: Integer); var tmpDummyValue: Integer; begin tmpDummyValue := vSortArray[aIndexA]; vSortArray[aIndexA] := vSortArray[aIndexB]; vSortArray[aIndexB] := tmpDummyValue; end; begin tmpSwapIndex := (start + last) div 2; swapValue(start, tmpSwapIndex); tmpCompareValue := vSortArray[start]; tmpSwapIndex := start + 1; tmpCompareIndex := start + 1; while tmpCompareIndex <= last do begin if vSortArray[tmpCompareIndex] < tmpCompareValue then // 降順 begin swapValue(tmpCompareIndex, tmpSwapIndex); Inc(tmpSwapIndex); end; Inc(tmpCompareIndex); end; Dec(tmpSwapIndex); swapValue(start, tmpSwapIndex); if tmpSwapIndex-start > 1 then QuickSort(vSortArray,start,tmpSwapIndex); if last-tmpSwapIndex > 1 then QuickSort(vSortArray,tmpSwapIndex+1,last); end;
エラーがでないのでいけるかなと思ったけどやっぱり無理
type TStageScore = Record private FTileCount : Integer; FWordPoint : Integer; FItemPoint : Integer; FIsCleared : Boolean; FIsOnTime : Boolean; FIsNoDeleteItem : Boolean; FIsNoUndo : Boolean; FDoubleUpItemCount: Integer; FIsStageFinished : Boolean; function getStageScore: Integer; function getBasicPoint: Integer; public CompleteWordArray: TWordArray; procedure Init(aTileCount: Integer); procedure Assign(aStageScore: TStageScore); // 受信系 procedure AddCompleteWord(aWord: String); procedure AddItemPoint(aPoint: Integer); procedure ClearedStage(aTimePoint: Integer); procedure GiveUpStage(aTimePoint: Integer); procedure BreakMoDeteteItem(); procedure BreakNoUnDo(); procedure UseDoubleUpItem(); Property WordPoint : Integer read FWordPoint; Property ItemPoint : Integer read FItemPoint; Property TileCount : Integer read FTileCount; Property IsCleared : Boolean read FIsCleared; Property IsOnTimet : Boolean read FIsOnTime; Property IsNoDeleteItem : Boolean read FIsNoDeleteItem; Property IsNoUndo : Boolean read FIsNoUndo; Property DoubleUpItemCount: Integer read FDoubleUpItemCount; Property IsStageFinished : Boolean read FIsStageFinished; Property BasicPoint : Integer read getBasicPoint; Property StageScore : Integer read getStageScore; end; type TGameScore = record private // FItems: array of TStageScore; function getItem(aIndex: Integer): TStageScore; procedure setItem(aIndex: Integer; const Value: TStageScore); public FItems: array of TStageScore; // 初期化 procedure Init(); procedure Assign(aGameScore: TGameScore); function AverageScore(): Single; function AverageWordLength(): Single; function CountWhereWordLengthIs(aWordLength: Integer): Integer; function GameScore(): Integer; Property Items[aIndex: Integer]: TStageScore read getItem write setItem; default; end;
修正後
FItems を public にした
type TGameScore = record private public Items: array of TStageScore; // 初期化 procedure Init(); procedure Assign(aGameScore: TGameScore); function AverageScore(): Single; function AverageWordLength(): Single; function CountWhereWordLengthIs(aWordLength: Integer): Integer; function GameScore(): Integer; end;
継承する場合
class のみ
初期化が必要な場合、要素に class をもつ場合
class が望ましい
それ以外
record でOK (メモリー管理が用意、ただし、index が溢れた場合予測不可能なエラーがおこる)
カーソル位置のクラスを補完に不具合がある模様。delphi の再起動で解決。
今朝、シリアルの記載されたメールが届いていたので、インストール
ついでにメモリ関係のデバッガ?AQtimeもインストール。
実はここまでの開発はトライアル版を使っていた。
トライアル期間が過ぎたのでprofessional を リオス e-shop で購入
翌日から、ダウンロードして利用できるらしい。
商品名: Delphi XE4 Professional ESD キャンペーン版
商品コード: HDBX04MLENWBC
数量:1 個
金額:¥ 95,000
商品名: Mobile Add-On Pack for Delphi XE4 Professional キャンペーン版
商品コード: HDLX04MLENWBC
数量:1 個
金額:¥ 47,500
———————————————————–
小 計 ¥ 142,500 (うち消費税 ¥6,784)
XE4、すごいソフトだと思うけど、やっぱり趣味で買う人はなかなかいないよね。