VBAアクションゲーム?Excelで動かそう!世留と仙人第3章

   


第3章 3箇条その3 同期Wait処理〜前編〜


第3章で作成されるxlsファイル

カステラを食べながらコードに思いを巡らす世留少年、何かを思い出した様子で「ごちそ
うさま」を言うと同時に話し出しました。

世留 仙人、カステラおいしかったです。でね、一つ思い出したんですよ。

仙人 ん?何をじゃ?

世留 7を狙えるようにする方法です。

仙人 おお、既に3箇条目「同期Wait処理」は知っているということじゃな。

世留 いえ、そうじゃないんです。多分駄目だと思います。

仙人 何を言っておるのか、さっぱりわからん。コードを書いて見なされ。

世留 うーん、駄目だと思うんだけど
   (コードを書き始める)

Do While GameFlag = True
 Range("A1").Value = Int(Rnd * 10)
 For i2=1 to 10000
 ’何もしない
 Next i2
 If GetAsyncKeyState(16) <> 0 Then
 
・・・・・・・・・

仙人 (少し感心した様子)
   ほほおー。

世留 昔コードの処理の方が早すぎて困ったことがあって、その時こうしたんです。処理を
   遅らせたい時はこうやってループを1つ作って何もさせない。その時はこれで上手く
   いったんですが、色々問題があって。

仙人 どんな問題があったんじゃ?

世留 自分のパソコンなら上手くいったんですよ。でも、学校の古いパソコンで動かしてみたら、
   止まっちゃった。

仙人 あははは。学校では相当古いパソコンを使っているようじゃのう。止まったわけでは
   なく「何もさせない」ループの処理に時間がかかったのじゃろう。じゃがのう、お前
   さんのやり方は、間違ってはおらん。色々整理してみようかの。

世留 はい。

仙人 今回は数字の表示が速過ぎて見えないというのが問題じゃの。別の処理を行わせて、
   数字の表示処理を遅らせるのは良い考えじゃ。これをWaitというぞ。

世留 Waitですか。待つという意味ですね。

仙人 その通り、お前さんがした方法で、まさにWaitを入れたことになるのじゃよ。
   For〜Next文の中では何もさせないとはいえ、ループそのものに時間がかかる。見事な
   Waitじゃ。空ループとも言うぞ。ただ空ループは致命的な欠陥があってのお、パソコンの
   
性能によってその処理時間が変わってしまう。繰り返しという単純な処理じゃからパソ
   コンの演算速度がもろに影響するのじゃ。わかるか世留君。

世留 わかります。だから学校のパソコンでは上手くいかなかったんだ。

仙人 そうじゃそうじゃ。パソコンによってアクションゲームの速度が変わってしまっては、
   
困りもんじゃからのう。そこでじゃ、世留君、一ついい方法を教えよう。

世留 読めてきました、仙人。いい命令があるのですね。

仙人 よい勘をしておる。ずばりSleepというAPI関数をつかうのじゃ。

世留 げっAPI・・・でも大丈夫です。教えて下さい。

仙人 わはは。これは簡単じゃから心配する必要はないぞ。

(さらさらとコードを書く)

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

 Do While GameFlag = True
  Range("A1").Value = Int(Rnd * 10)
  Sleep(1000)

  If GetAsyncKeyState(16) <> 0 Then
  
・・・・・・・・・

世留 あれ、Waitを入れたいところにSleep(1000)と入れただけですねえ。

仙人 SleepというAPIはミリ秒単位で指定した時間の間、処理を止める、つまり次の処理に
   
移らないでくれる便利な関数じゃ。3秒Waitを入れたいのならSleep3000と書く・・・
   
それだけじゃ。さあ、まずはコードを完成させて見なされ。

世留 はい、えーと数字は2秒に1回変わるように500にすればいいかな。
   (さらさらとコードを書く)

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub strat()
 Dim i As Integer
 GameFlag = True
 Do While GameFlag = True
  Range("A1").Value = Int(Rnd * 10)
  
Sleep(500)  ’ここで0.5秒待つ
  If GetAsyncKeyState(16) <> 0 Then
   If Range("A1").Value = 7 Then
    MsgBox "大当たり!"
    GameFlag = False  
   ElseIf Range("A1").Value = 3 Then
    MsgBox "当たり!"
    GameFlag = False
   Else: MsgBox "はずれ!"
   End If
  End If
 Loop
End Sub

   できた!簡単簡単。
   (ボタンを押す)

   あはっ。ゆっくり数字が変わってる!これなら「7」も狙えますね!
   仙人、ありがとうございます。やっと出来たなあ。これで完成完成。3箇条も完璧だよ。

仙人 (ちょっと困って)
   実はな、世留君、3箇条目はまだじゃよ。

世留 えっ、だってWaitはSleepを使えばいいんですよね。Sleepが3箇条目じゃないんですか?

仙人 (苦笑して)
   誰もSleepが3箇条目とは言っておらん。まあ、この場合はSleepで十分かもしれんがのう。

世留 でも仙人、これで0.5秒に1回、数字が変わってますよ。ちゃんとミリ秒単位で制御
   しているじゃないですか。

仙人 じゃからこの場合はこれでもよいかもしれんと言っておる。Sleepという関数はじゃな、
   
ミリ秒単位で指定できるお休み関数じゃ。たしかに正確にに0.5秒づつお休みさせてい
   
るので、何となく0.5秒に1回数字が変わったように思える。じゃがな、それでは制御
   
とは言えん。

世留 ・・・・・・

仙人 ミリ秒単位で制御してこそアクションゲームじゃ。世留君、Sleep以外のところで、つまり
   お休み以外の時にパソコンは何しておる?

世留 えーと、数字を表示させたり、当たりの判定をしていますね。

仙人 そこじゃ。今回はたいした処理をしておらんから目立たんが、通常アクションゲーム
   では重い処理となるぞ。敵を動かしたり、弾を出したり、当たりの判定をしたりじゃな。
   
それがようやく終わった後に、Sleepで0.5秒お休みさせたら、0.5秒ごとに制御してる
   とは言えんじゃろ。

世留 ・・・・仙人、わかってきました。単にSleepを指定するだけじゃ駄目だということですね。
   0.5
秒に1回数字を変えて表示させたいのなら、0.5秒から他の処理時間を引いて、たとえば
   他の処理に0.1秒かかるのであれば、0.5秒−0.1秒で0.4秒、つまりSleep(400)と指定すれば
   OKですね。

仙人 (黙って頷く)

世留 ちょっと待てよ。でも、さっきの空ループのように、Sleep以外の処理はパソコンの能力に
   よって速さが違うから、パソコンによってSleepで指定すべき時間が変わってしまう・・・
   
仙人、これはむずかしいよ。

仙人 ほっほっほ、お前さんも賢くなったものじゃのう。パソコン個体の処理速度に関係なく、
   
常に同一の速度で処理をする・・・これがアクションゲーム第3箇条「同期Wait処理」じゃ。

世留 わあ、やっぱりいいやり方があるんだ。早く早く教えて下さいよ。

仙人 まあまあ、しばらく考えて見なされ。そこまでわかっておるのなら後は発想の変換だけじゃ。
   よい頭の体操にな・・・・・

(にゃーん)

仙人 ・・・ん?庭の方にハイネが来たようじゃの。どれ、見てこよう。  

世留 仙人、行っちゃうんですか。ハイネって?

仙人 なに、最近よく来る猫ちゃんじゃよ。わしの所に来るところをみると猫のくせにVBA好きかも
   しれん。すぐ戻るからお前さん、しばらく知恵を絞ってみるのじゃ。

世留 (既に考え出している)

   ・・・・・・・・


動かすメモ4 ※API関数Sleepを使ったWait処理

※実行をお休みさせ指定時間(ミリ秒)待機させる。

Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub strat()
  
Sleep(1000)  ’1秒間お休み
End Sub  


VBAアクションゲーム?Excelで動かそう!世留と仙人第2章