ブロック崩しゲームの作成(WindowsとAndroidで動作) ~Delphiソースコード集
Delphiを起動してプロジェクトを作成し、オブジェクトを配置し、プロパティを設定する
Delphiを起動し[ファイル]→[新規作成]→[マルチデバイスアプリケーション-Delphi]をクリックします。[空のアプリケーション]を選択して[OK]ボタンを押します。
ツールパレットからTTimerを2つフォームへドラッグ&ドロップします。(名前はデフォルトのままTimer1とTimer2)
TImage(名前はデフォルトのままImage1)もフォームへドラッグ&ドロップします。
Timer2のIntervalプロパティを1にします。
Form1のプロパティClientHeightを480に、ClientWidthプロパティを410に設定します。
Image1のnameプロパティをimgにします。またWidthプロパティとHeightプロパティを410に設定し、AlignプロパティをFitに設定します。
プログラミング
変数、Form1のOnCreateイベント、Timer1のOnTimerイベント、Timer2のOnTimerイベント、imgのOnMouseMoveイベント、imgのOnMouseDownイベント等、 以下のソースと同じように入力(コピペ?)します。unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Objects, FMX.Layouts, FMX.Controls.Presentation, FMX.StdCtrls; type TForm1 = class(TForm) Timer1: TTimer; img: TImage; Timer2: TTimer; procedure FormCreate(Sender: TObject); procedure Timer1Timer(Sender: TObject); procedure imgMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); procedure Timer2Timer(Sender: TObject); procedure imgMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); private { private 宣言 } public { public 宣言 } block_x:array of integer; block_y:array of integer; block_f:array of boolean; c:integer; ball_x:double; ball_y:double; ball_wx:double; ball_wy:double; racket_x:double; racket_w:double; procedure MyDraw(); end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.Timer2Timer(Sender: TObject); begin timer2.Enabled:=False; img.Bitmap.Width:=410; img.Bitmap.Height:=410; img.Bitmap.BitmapScale:=img.Width/img.Bitmap.Width; Timer1.Enabled:=True; end; procedure TForm1.FormCreate(Sender: TObject); var i:integer; begin c:=30; SetLength(block_x,c); SetLength(block_y,c); SetLength(block_f,c); for i := 0 to c-1 do begin block_x[i]:=(i mod 10)*40 + 10; block_y[i]:=(i div 10) *30 + 30; block_f[i]:=true; end; racket_x:=80; racket_w:=50; ball_x:=30; ball_y:=150; ball_wx:=1; ball_wy:=2; end; procedure TForm1.imgMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Single); var xx:single; begin xx:=x/img.Bitmap.BitmapScale; racket_x:=xx-racket_w / 2; if racket_x<0 then racket_x:=0; if racket_x>(img.Bitmap.Width-racket_w ) then racket_x:=(img.Bitmap.Width-racket_w ); end; procedure TForm1.imgMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Single); var xx:single; begin xx:=x/img.Bitmap.BitmapScale; racket_x:=xx-racket_w / 2; if racket_x<0 then racket_x:=0; if racket_x>(img.Bitmap.Width-racket_w ) then racket_x:=(img.Bitmap.Width-racket_w ); end; procedure TForm1.MyDraw; var bmp:TBitmap; i:integer; dstrect,srcrect:TRectF; begin bmp:=TBitmap.Create; bmp.Width:=410; bmp.Height:=410; try if bmp.Canvas.BeginScene() then begin bmp.Canvas.Fill.Kind:=TBrushKind.Solid; bmp.Canvas.Fill.Color:=$FFFFFFFF; //背景を白色で塗りつぶし bmp.Canvas.FillRect( RectF(0,0,bmp.Width,bmp.Height), 0,0,[],1 ); for i := 0 to c-1 do begin if block_f[i] then begin bmp.Canvas.Fill.Kind:=TBrushKind.Solid; bmp.Canvas.Fill.Color:= TAlphaColors.Black; bmp.Canvas.FillRect( RectF(block_x[i],block_y[i],block_x[i]+30,block_y[i]+20), 0,0,[],1 ); end; end; bmp.Canvas.Fill.Kind:=TBrushKind.Solid; bmp.Canvas.Fill.Color:= TAlphaColors.Black; bmp.Canvas.FillEllipse(RectF(racket_x,300,racket_x+racket_w,300+5),1); bmp.Canvas.FillRect( RectF(racket_x,300,racket_x+racket_w,300+5), 0,0,[],1 ); bmp.Canvas.DrawEllipse(RectF(trunc(ball_x-2),trunc(ball_y-2),trunc(ball_x+2),trunc(ball_y+2)),1 ); bmp.Canvas.EndScene; srcrect:=RectF(0,0,bmp.Width,bmp.Height); dstrect:=RectF(0,0,img.Bitmap.Width,img.Bitmap.Height); img.Bitmap.Canvas.BeginScene(); img.Bitmap.Canvas.DrawBitmap( bmp, srcrect,dstrect, 1,false ); img.Bitmap.Canvas.EndScene; end; finally bmp.Free; end; end; procedure TForm1.Timer1Timer(Sender: TObject); var i:integer; begin ball_x:=ball_x+ball_wx; ball_y:=ball_y+ball_wy; //ラケットに当たったとき if (ball_y>=300) and (ball_y<=305) then begin if (ball_x>=racket_x) and (ball_x<=(racket_x+racket_w)) then begin ball_wy:=-ball_wy; ball_x:=ball_x+ball_wx; ball_y:=ball_y+ball_wy; ball_wx:=-(racket_x+(racket_w / 2)-ball_x) / 10; end; end; //壁に当たったとき if ball_y<=0 then begin ball_wy:=-ball_wy; ball_y:=0; end; if ball_x<=0 then begin ball_wx:=-ball_wx; ball_x:=0; end; if ball_x>=img.Bitmap.width then begin ball_wx:=-ball_wx; ball_x:=img.Bitmap.Width; end; //blockにあたったとき for i := 0 to c - 1 do begin if (block_x[i]<=ball_x) and (ball_x<=(block_x[i]+30)) and (block_y[i]<=ball_y) and (ball_y<=(block_y[i]+20)) and block_f[i]=true then begin if ((block_x[i]-1)<=ball_x) and (ball_x<=(block_x[i]+1)) then ball_wx:=-ball_wx else ball_wy:=-ball_wy; block_f[i]:=false; end; end; if ball_y>=img.Height then begin timer1.Enabled:=false; MessageDlg('ゲームオーバー',TMsgDlgType.mtInformation,[TMsgDlgBtn.mbOK],0, procedure(const AResult:TModalResult) begin ball_x:=30; ball_y:=150; ball_wx:=1; ball_wy:=2; timer1.Enabled:=true; end ); end; MyDraw(); end; initialization begin FMX.Types.GlobalUseDirect2D:=False; end; end.
実行ボタンを押す
実行ボタンを押すと、コンパイルして起動します。マウスでラケットを左右に動かしてブロックを削除してください。
Androidでも動く
ターゲットプラットフォームをAndroidに切り替えて、実機をUSBで接続して実行しても動きます。マウスではなく指で操作することになります。