これまで画面上の座標はピクセル単位で扱ってきたが,科学技術計算等を図示する場合には,一般に用いられているデカルト座標系に置き換えることができれば,より容易に描画が可能となる.
そこで,VBのピクチャボックス内での座標系を再設定する方法を学ぶ.1)VBでの座標系の設定
Form1上にピクチャボックスを配置した場合,初期状態ではTwipという単位(1論理インチ 1440 Twip)という単位で扱われることになる.これまでは,これをよりわかりやすいように,ピクセル単位に変換するという作業を行なってきた.しかし,いずれの方法によってもピクチャボックスの左上隅の点が原点とした,下方向に+,右方向に+という座標系となる.
一方,デカルト座標系では,上方向に+という座標系であるから,デカルト座標系をもとにした数式を計算する場合に,その座標変換を行う必要がある.
ピクチャボックスコントロールでは,この座標変換を容易に設定することが可能である.(これは既往のBASICでも同様である)例えば,原点(0,0)を中心し,左上隅が(-1,1),右下隅が(1,-1)となる座標系をもつウィンドウを定義するとしよう.
プロパティの変更による方法
1)ピクチャコントロールボックスをForm1上に貼り付ける.
2)ピクチャコントロールボックスの大きさを正方形になるように設定する.
(プロパティ Picture1.WidthとPicture1.Heightが同じ値になる)
3)以下のようにPicture1のプロパティを修正する.(コード内からの変更も可能である)
Picture1.ScaleMode = 0
Picture1.ScaleHeight = -2
Picture1.ScaleWidth = 2
Picture1.ScaleTop = 1
Picture1.ScaleLeft = -1
これにより原点を中心とする座標系が定義される.メソッドを用いた方法
1)ピクチャコントロールボックスをForm1上に貼り付ける.
2)ピクチャコントロールボックスの大きさを正方形になるように設定する.
3)以下のコードをプログラム内で呼び出す.
Picture1.Scale (-1,1)-(1,-1)
これにより原点を中心とする座標系が定義される.
Scaleメソッド
Picture1.Scale (左上隅の座標)-(右下隅の座標)
2)円の描画
例えば,この座標系で円を描画してみよう. (以前にピクセルモードで書いた円のプログラムをそのまま利用できる)Option Explicit
Const PAI = 3.1415Private Sub Form_Load()
Picture1.Width = 3000
Picture1.Height = 3000
Picture1.ScaleMode = 0
Picture1.ScaleHeight = -2
Picture1.ScaleWidth = 2
Picture1.ScaleTop = 1
Picture1.ScaleLeft = -1
End SubPrivate Sub Command1_Click()
Dim n As Integer
Dim x As Single, y As Single
For n = 0 To 360
x = Cos(n / 180 * PAI)
y = Sin(n / 180 * PAI)
If n = 0 Then
Picture1.PSet (x, y)
Else
Picture1.Line -(x, y)
End If
Next
End Sub
3)多角形の描画
上述のプログラムの
For n = 0 To 360
の部分に
例えば,For n = 0 TO 360 Step 60
などのように,Stepとして設定する数値を90,120等と変えれば,任意の正多角形の描画が可能となる.
タイマーコントロールを用いれば,アニメーションの速度を制御することができることは,前回の資料に記載しているが,ここでは,タイマーコントロールを用いることによって,実行しているプログラムがCPUを独占するということを避けるためのタイマーコントロールの利用について述べる.例えば,時計を表示したいという場合に,
Do
Text1.Text = Time 'Timeは現在の時間を返す関数である.
Loop
という処理を行なうと,プログラムは常に動きつづけ,CPUを独占してしまう.
時計は1秒毎に描画が更新されればよいのであるから,ここで1秒毎にプログラムを実行するようにタイマーコントロールを用いる.1)タイマーコントロールとラベル(Aと表示されたコントロール)をForm1上に貼り付ける.
2)Form1上からOption Explicit上記のようにタイマーコントロールを利用したプログラムを実行すれば,1秒毎にプログラムが稼動するため,CPUの独占ということを避けることができる.
Private Sub Form_Load()
Label1.Caption = ""
Timer1.Interval = 1000
Timer1.Enabled = True
End SubPrivate Sub Timer1_Timer()
Label1.Caption = Time
End Sub
(参考)アラーム機能
例えばテキストボックスを追加し,以下のようなコードを追加すれば,アラーム機能が追加可能Private Sub Timer1_Timer()
Label1.Caption = Time
If Time >= Text1.Text Then Beep
End Sub
(参考)TIme関数からの時間,分,秒の抽出
Timeで得られた時間の文字列から,以下のように文字列を抽出することが可能である.
H = Val( Left$(Time, 2))
M= Val( Mid$(Time,4,2))
S = Val( Mid$(Time,7,2))
Val 関数は文字列を数値化する関数
Left$関数は,文字列の左側から,指定した文字列を抽出する関数
Mid$関数は,文字列中の指定した位置から,指定した文字数を抽出する関数なお,これらの抽出を用いなくとも,VBの標準関数を用いれば,HMSの抽出は容易である.
H = Hour(Now)
M = Minute(Now)
S = Second(Now)
シミュレーション(Simulation):
2次元アニメーションを作成するためには,単位時間あたりにおける物体の移動方向と移動量を数値的に得て,それをシミュレートする必要がある.そのためには,若干の数学的知識や物理に関する知識が必要とならざるを得ない.
電子計算機を用い複雑な自然現象や経済現象などについてモデルを作り, 予測結果をはじきだす手法, 模擬実験. (ニューアンカー英和辞典より)
例えば,投げたボールについてアニメーションしてみよう.(ただし空気抵抗は考慮しない)
時間t に対するボールの変位 y は,落下運動の式をもとにすれば,以下の式により表現される.y = vy0t - gt2/2 vy0:y方向への初速度,g:重力加速度(9.8m/s2)
右辺第2項が負となるのは, ボールを上に投げることにより,負の重力加速度が働くからである.一方,x方向への変位は,
x =vx0t vx0:x方向への初速度さらに投げたボールが再び地面に達したときには,そこで衝突による力の減衰が働くから,ここで初速度を再設定するとともに,再びtの値を初期化して計算を行う必要がある.
これらを実際にプログラミングすると以下のようになる.
Option ExplicitDim t As Single, x0 As Single, y0 As Single, vx0 As Single, vy0 As Single, reduce As Single
Const g = 9.8 '重力加速度の設定Private Sub Form_Load()
Picture1.AutoRedraw = True
Picture1.BackColor = &HFFFFFF
Picture1.ScaleMode = 0
Picture1.Width = 6000
Picture1.Height = 3000
Picture1.ScaleWidth = 200
Picture1.ScaleHeight = -100
Picture1.ScaleTop = 98
Picture1.ScaleLeft = -50
Timer1.Enabled = False
Timer1.Interval = 100
x0 = -50 'ホールの初期位置(X方向)
y0 = 0 'ボールの初期位置(y方向)
reduce = 0.7 '衝突時の速度減衰率
End SubPrivate Sub Command1_Click()
If Timer1.Enabled = True Then
Timer1.Enabled = False
Else
t = 0 '時間の初期化
vx0 = 10 'x方向初速度(m/s)
vy0 = 40 'y方向初速度(m/s)
Timer1.Enabled = True
End If
End SubPrivate Sub Timer1_Timer()
Dim x As Single, y As Single
x = vx0 * t + x0 'x方向の位置計算
y = vy0 * t - g * t ^ 2 / 2 'y方向の位置計算
Picture1.Cls
Picture1.FillStyle = 0
Picture1.FillColor = &HFF
Picture1.Circle (x, y), 2, &HFF
If t > Timer1.Interval / 1000 And y <= 0 Then '地面に達したら
t = 0 '時間を初期化
x0 = x '現在の位置を初期位置に再設定
y0 = y
vy0 = vy0 * reduce '速度の減衰を行なう.
vx0 = vx0 * reduce
End If
t = t + Timer1.Interval / 1000 '次の計算時間tを計算
End Sub