ExcelVBAゲームプログラミング?

初心者でもきっとできる!
Excelさえ持っていれば特別なソフトは不要!
すぐにでも始められる簡単ゲームプログラミング!
今すぐ始めよう!

サンプルやゲームのダウンロードができる別館も好評運営中です。
ご意見やご質問、ゲームの感想等は掲示板までお気軽に。是非、皆さんの声を聞かせてください。運営、開発の励みになります。



各種ダウンロードはコチラ ↓ 意見・感想・質問はコチラ ↓
影倉庫 Shadow warehouse サポート掲示板
ブログの全体像はコチラ ↓ リンクのページはコチラ ↓
サイトマップ 自分本位なリンク


スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。






Chapter.63 [ ラジアンの活用:円運動 ]

■ラジアンでなにするの?

前回の講座でラジアンがなんであるかを、なんとなく解説しました。数学的な話なので、私の説明も必ずしも正しくはないかもしれません。しかし、ラジアンは意味よりも使い方が大事です。難しい数学の話は実はどうでもよくて、ラジアンをどのように使えばどんなことができるのか、大切なのはそっちです。

今回は、ラジアンの活用法のひとつとして、簡単な円運動のプログラムを作ってみましょう。今回のサンプルを通して、なんとなくラジアンというものの感触を掴んでいただけたらと思います。


それでは、円運動とは、具体的にはどんな運動でしょう。

辞書に載っている、正確な意味での円運動がどのように表されているかはわかりませんが、今回の講座で取り扱う円運動とは、次のような運動のことを指します。

ある地点を中心として、円を描くように動くこと

です。

円には必ず中心があります。皆さん小学生のときにコンパスで円を描きましたよね。そのときのことを思い出してくださいね。

今回のプログラムでは、まず初めに原点となる中心部分を決めてやり、そこを中心とした円を描くような感じで、イメージコントロールを動かしてみます。


■フォームの準備

それではユーザーフォームの準備をしましょう。
とはいっても、イメージコントロールひとつとコマンドボタンがあれば十分です。

ball.gif

このボールの画像をイメージコントロールにロードして、円運動をさせてみましょう。ちなみにこの画像のサイズは36×36ピクセルです。

ユーザーフォームを新規に作成し、イメージコントロールをひとつ配置します。そのイメージコントロールに先ほどの画像をロードしておきましょう。
あとはスタートボタンの役割を果たすコマンドボタンを配置して、ユーザーフォームの準備は完了です。簡単ですね。

360.gif

こんなかんじです。


■サイン・コサイン

まず、今回のサンプルをすんなり理解するために、サインとコサインについて簡単に書きます。もちろん、数学的な意味よりも、わかりやすさを重視した文面ですので、細かい突っ込みはご勘弁を。

サインとコサインは、『sin・cos』と表されることが多いです。これは三角関数の勉強をすると出てきます。三角関数の話とかになると、非常に眠たくなりそうなので、ここではサインとコサインについて、ズバリ言ってしまいます。

サインとコサインとは、ズバリ、角度から求められる、縦横の移動量です。
これには、直角三角形を使って考えます。簡単ですから、ちょっとだけつまらない図形を眺めてみてください。

361.gif

ふたつの三角形が並んでいます。そして、『θ(シータ)』と書かれている部分の角度が異なっています。左側の三角形のθよりも、右側の三角形のθのほうが角度が小さくなっています。

するとどうでしょう、左側の三角形では、辺Aのほうが辺Bよりも長いですね。しかし、右側の三角形では逆に、辺Aのほうが辺Bよりも短くなっています。

このことから、θの角度が変わると、直角三角形の縦の幅と横の幅の比率が変わってくるということがわかりますね。
θの角度が広くなるほど、縦の幅が長くなります。逆に、θの角度が狭くなるほど横の幅が長くなります。

つまり、要約すると次のようになります。

ある点から、任意の方向への移動量を計算するためには、縦の計算にはsinを、横の計算にはcosを使えばよい

これです。これこそがサインとコサインの正体です。

ある地点から、任意の角度の方向へ移動したいとき、サインとコサインを使うことによって移動する量を求めることができるのです。先ほどの三角形で表すなら、θの部分がどのように変化しても、サインとコサインを使えば辺Aの長さと辺Bの長さがわかるのです。これはつまり、縦に移動する量と横に移動する量がサインとコサインの力で即座にわかるということなのです。これはすごい! ……ですよね?

どうですか、なんとなく理解できましたでしょうか?


■コードの記述

それでは実際にコードを記述しましょう。
サインとコサインの性質を頭に思い描きながら、コードを見て考えてみてくださいね。

'標準モジュールに記述

'API宣言
Declare Function GetTickCount Lib "kernel32" () As Long
Declare Sub Sleep Lib "kernel32.dll" (ByVal dwMillsecounds As Long)


'円運動プロシージャ
Sub RollBall()
    
    Dim Radian As Single 'ラジアン
    Dim Angle As Long '度数
    Dim X As Single '原点座標 横位置
    Dim Y As Single '原点座標 縦位置
    
    Dim R As Single '円運動の半径
    Dim FLG As Boolean 'ループ管理フラグ
    Dim C As Long 'カウンターとして使う
    Dim STIME As Long '同期処理を行うために使う
    
    Const PI As Single = 3.14159 '円周率
    
    
    X = 100 '①
    Y = 100
    
    R = 30 '②
    FLG = False
    C = 0
    
    Do Until FLG
        STIME = GetTickCount
        C = C + 5 '③
        Angle = C Mod 360 + 1 '④
        Radian = Angle * PI / 180 '⑤
        With UserForm1.Image1
            .Left = X + R * Cos(Radian) '⑥
            .Top = Y + R * Sin(Radian)
            .Left = .Left - .Width / 2
            .Top = .Top - .Height / 2
        End With
        DoEvents
        Do
            Sleep 1
        Loop Until GetTickCount - STIME > 30
    Loop
    
End Sub


'ここから下はフォームモジュールに記述

Private Sub CommandButton1_Click()

    Call RollBall
    
End Sub


Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)

    End
    
End Sub

使われている変数がかなり多いですが、赤い字で書かれているコメントをよく見て、各変数の役割をイメージしてください。

まずは①の部分から。
ここでは、円の中心の位置を決めています。 X には中心の横の位置が入ります。そして同様に、 Y には中心の縦の位置が入ります。

次に②。ここでは、円の半径を決めています。今回は30に設定していますが、この数値を大きくすれば円運動の軌跡も大きくなります。逆にここで設定する数値を小さくすれば、小さな円を描くようにボールが移動するようになります。

③の部分は、一見すると何をやっているのかわかりにくいかもしれません。
ここでは、カウンターの役割を果たす、変数 C の値をループするごとに増やしています。そして次の④の行を見てください。ここで、Mod演算子を使って度数を決めていますね。

Angle = C Mod 360 + 1

Mod演算とは、割り算の余りを求める計算方法でしたね。つまり、変数 C の値は常にループするごとに増え続けますが、変数 Angle に入る値は『1~360』の間におさまり続けます。
変数 C が1回のループでプラスされる量を増やすと、結果的に角度が早く変化します。ということはつまり、円運動のスピードが速くなります。今回は、5度ずつ動かしていますが、10度ずつ動かしたほうがボールの移動が速くなりますね。

ここまでで求めた角度を使って、ラジアンを求めているのが⑤ですね。前回の講座で載せた、度数からラジアンへの変換公式が出てきています。

そして、実際の座標を計算しているのが⑥の部分です。

.Left = X + R * Cos(Radian)
.Top = Y + R * Sin(Radian)

Sinという関数と、Cosという関数が使われています。これらの関数には、ラジアンでの角度を指定しますので、先ほど計算したラジアンを引数に渡しています。

そして、 X Y は円の中心を表す座標でしたね。そこに、サインやコサインを掛け算した半径をプラスします。こうすることで、座標(X,Y)を中心とした、半径(R)の円を描かせることができます。

円運動の計算

横位置を求めるには……
    中心の横位置 + 円の半径 * Cos(ラジアンでの角度)

縦位置を求めるには……
    中心の縦位置 + 円の半径 * Sin(ラジアンでの角度)



■まとめ

今回のサンプルでは、変数に格納する初期値を変更することで、様々な大きさの円を描かせることができます。

例えば、中心の座標を変更したり、描かれる円の大きさを変更したりすることができます。いろいろ値を変更して実行してみると、結構面白いのではないでしょうか。

サインやコサインは、数学的な話になるので非常にとっつきにくく感じます。ですが、今回解説した計算方法さえわかっていれば、あまり突っ込んだ数学的知識はなくても、円運動を処理することができるはずです。

前回のラジアンに関する解説と、今回のサイン・コサインに関する解説を両方理解できれば、数学的なことはよくわからなくても、とりあえず何とかなります。これをどう活用していくのかは、皆さんのセンス次第ということになるでしょう。

別館よりサンプルがダウンロードできますので、実際にどう動くのか興味のある人はそちらを参考に。


サンプルダウンロード ⇒ コチラよりダウンロードできます。(別館)



■格言

サインとコサインは意味よりも
使い方を知ることが大切


ラジアンのときもそうですが、意味を理解するより、使い方をマスターするほうが得です。

スポンサーサイト






Chapter.64 [ ラジアンの活用:任意の角度へ移動する ]

■角度を決めて移動する

前回はラジアンを使って、円運動を行いました。
ある点を中心として、その周りを円を描くように移動することができましたね。

今回はこれを応用して、任意の方角へ向かってまっすぐに移動するプログラムを作ってみましょう。実は前回の講座で解説した内容を理解していれば、今回の内容はさほど難しくありません。頭を柔らかくしてチャレンジしてみてください。

さて、それでは円運動と、任意の角度でまっすぐ移動することと、そこには一体どんな関係があるのでしょうか。なんとなく角度が関係しているということは想像できますね。

円運動をするときは、移動先の座標を、少しずつ角度を増やしながら連続して処理することで実現しました。一番最初は1度の座標に、次は2度の座標に、次はまたもう少し増やした座標に……という具合に、少しずつ移動先の座標を変えることで、円を描いているような移動を実現することができましたね。

任意の方角へ移動させるということは、円運動とは違って、ずっと同じ方向へ向かって移動すればいいですね。ということは、毎回同じ角度の方向へ向かって移動させ続ければ、それで任意の方角へ向かって移動させることができるはずです。


■復習

それでは簡単にラジアンについて復習しておきましょう。

ラジアンとは、弧度法と呼ばれる角度の考え方の単位でしたね。円が360度で表現される度数法とは、全く異なる角度の単位で、内角と弧の比率から求められる角度の考え方です。

そして、度数法の『度数』から、弧度法の『ラジアン』を求めるには、次のような公式を使えばよかったのでしたね。

度数⇒ラジアン の変換公式

    rad = ang * 3.14 / 180

    rad……ラジアン
    ang……度数

ang の部分に好きな角度を入れて、上の式を計算すると、それに対応したラジアンの値を得ることができます。ここで取得したラジアンを使って、サインとコサインを計算すると、目的の角度にどのくらい移動すればいいのかがわかります。

今現在の位置が、横位置 X 、縦位置 Y 、で表されるとき、任意の角度の方角へ移動した座標を得るには、次のようにします。

現在の座標( X , Y )

移動先の横位置 = X + 移動する量 * Cos(ラジアン)

移動先の縦位置 = Y + 移動する量 * Sin(ラジアン)

ここで重要なのは、『横の移動量を計算するときにはコサイン(Cos)を使う』、『縦の移動量を計算するときにはをサイン(Sin)使う』というルールです。それさえわかっていれば、上の式の通りに計算すれば、任意の方角へ向かって移動するという計算が簡単にできます。

これをまとめると、角度による計算を行う場合には、次のような流れで計算すればいいのですね。

何度の角度で移動するか決める(この例では45度)

    ang = 45

角度からラジアンを求める

    rad = ang * 3.14 / 180

ラジアンを元に縦横の移動量を求める

    移動先横座標 = 現在の横位置 + 移動する量 * Cos(rad)
    移動先縦座標 = 現在の縦位置 + 移動する量 * Sin(rad)

円運動の時には、ang に入る角度を少しずつ増やしながら連続して処理しました。移動する量が一定であれば、移動先の座標の角度だけが変化するので、まるでコンパスで円を描くときのように、移動先が変化しました。

任意の角度へ向かってまっすぐ移動する場合には、角度が途中で変わってしまっては変ですね。ですから、現在の横位置や、現在の縦位置を常に更新しながら処理していきます。

Sub MoveBall(ang As Long)
    
    Dim rad As Single 'ラジアン
    Dim X As Single 'ボールの座標 横位置
    Dim Y As Single 'ボールの座標 縦位置
    
    Dim SPEED As Single '移動スピード
    Dim STIME As Long '同期処理を行うために使う
    Dim FLG As Boolean 'ループ終了フラグ
    Const PI As Single = 3.14159 '円周率
    
    X = 100 '最初の横位置座標を設定
    Y = 100 '最初の縦位置座標を設定
    
    FLG = False
    SPEED = 3 '移動スピードを設定
    rad = ang * PI / 180 'ラジアンを求める
    
    Do Until FLG
        STIME = GetTickCount
        With UserForm1.Image1
            X = X + SPEED * Cos(rad) '横位置を計算
            Y = Y + SPEED * Sin(rad) '縦位置を計算
            .Left = X - .Width / 2 'イメージコントロールの位置調整
            .Top = Y - .Height / 2 'イメージコントロールの位置調整
            If X > 200 Then FLG = True
            If X < 0 Then FLG = True
            If Y > 200 Then FLG = True
            If Y < 0 Then FLG = True
        End With
        DoEvents
        Do
            Sleep 1
        Loop Until GetTickCount - STIME > 30
    Loop
    
End Sub

前回のサンプルを少しいじったものです。

このプロシージャは、引数をひとつ取るようになっています。

Sub MoveBall(ang As Long)

ang の部分に任意の角度を引数として渡して、このプロシージャを呼び出せばいいのですね。

このコードは、ユーザーフォーム(UserForm1)上に、イメージコントロール(Image1)が配置されていないとうまくいきませんので注意してください。

今回もサンプルを用意していますので、そちらをダウンロードして動かしてみるのが一番わかりやすいと思います。
サンプルでは、スピンボタン(SpinButton)というコントロールを活用してコードを組んでいます。

370.gif

スピンボタンを使って、好きな角度を指定することができます。角度を決めて、コマンドボタンを押すと、ボールがその方角へ向かって移動します。
指定できる角度は、最低が1度、最大が360度です。色々変更してやってみると面白いと思います。

371.gif


サンプルダウンロード ⇒ コチラよりダウンロードできます。(別館)



■格言

角度を変えずに移動すれば斜めにも移動できる
シューティングやアクションに活用できる


円運動よりも、実は簡単かもしれませんね。







Chapter.65 [ APIによるサウンド再生:基礎 ]

■音のある世界

さて、今回からは待望(?)のサウンド再生処理に関する内容を解説していきます。

実は、VBA単体では、サウンドに関することはほとんどできません。唯一、私の知っている音に関する事と言えば、Beep というステートメントぐらいです。

このBeepですが、ゲームにはほとんど使えないと言っていいでしょう。メッセージを表示するMsgBoxを実行すると、ポン、とか、コン、みたいな音が鳴りますが、あんな程度の音しか扱えません。しかもメッセージの表示時に鳴る音やBeepで鳴らせる音は、パソコンの環境によって変わってきます。つまり、どんなときにも同じサウンド効果が得られるとは限らないのです。


ゲームでは、好きなときに好きな音を鳴らせないと意味がありません。しかも、できることならBGMを流しながら効果音も再生するという、いわゆる多重再生ができることが理想的ですよね。

VBAで多重再生などの高度なサウンド処理を行うためには、APIの力を借りなくてはいけません。ですから、これはけして簡単な処理ではありません。ハッキリ言って、これまで扱ってきた講座の内容のどの部分よりも、ある意味高度な領域です。
普段からC言語などでプログラムを組んでいる人からすると、それほど難解ではないかもしれません。ですが、確実にVBAプログラマーから見ると高度な領域です。ゆっくりでいいですから、少しずつでも理解していってください。

まずは講座内容をよく見ながら、仕組みを理解することから始めてくださいね。


■マルチメディアコントロール

ウィンドウズに始めから搭載されているAPIと呼ばれるライブラリ群については、以前の講座でも解説しましたね(Chapter30Chapter31を参照)。これらのAPIの中には様々な機能を持つものがあり、その中には、一般にMCIと呼ばれている関数群があります。

MCIとは『Multimedia Control Interface』の頭文字を取った略語です。マルチメディア、つまりサウンドやビデオなどの処理に関わる部分を一手に引き受けるのがMCIです。

MCIを本気で極めると、ウィンドウズメディアプレーヤー並みのアプリケーションを作成することもできます。サウンドだけでなく、ビデオファイルの再生などもできるのです。さらに言えば、再生停止だけの簡単な処理に留まらず、一時停止や、指定した場所からの再生や録音なんかもできてしまいます。

これだけ多機能で、非常に便利なMCIですが、当然デメリットもあります。それは『難解』、そして『扱いが難しい』ということです。
高度で多機能な分だけ、比例して扱いが難しくなるのですね。これは大抵どんなものでもそうでしょう。ですから、今回の講座では、非常に簡単な使い方を説明するに留めます。何度かに分割して、少しずつステップアップする形で習得を目指してほしいと思います。焦らず、ひとつひとつこなしていきましょう。


■文字を送る

上で散々難しいことを書いておいて今更ですが、MCIには、できるだけプログラマーが扱いやすいような仕様で設計されている、プログラマーに優しいAPIがあります。

それが『 mciSendString 』と呼ばれるAPIです。

このAPIの名前をよく見ると、MCIであることがすぐわかりますね。名前の先頭がそのまま『mci』となっています。そして次には、『 SendString 』と書かれています。これを訳すと『文字を送るMCI』という感じでしょうか。

mciSendStringというAPIは、その名の通り文字列を使ってプログラムを組むことができます。実はこれは、かなりプログラマーに優しい設計です。

本来、パソコンなどのコンピューターは、その全てが内部的には数字で管理されています。ものすごく深い部分まで行くと、最終的には 0 か、それとも 1 か、というふたつの選択肢だけで全ての処理が行われています。本質的には、コンピューターには『はい』か『いいえ』しかないのですね。

しかしこれでは、人間が困ってしまいます。0と1が並んだ数字の羅列を見ても、それがどんな意味を持っているのかわからないですものね。
まぁこの表現は少し極端ですが、要するに、機械には数字で命令しなくてはいけない場合が多く、その意味を全て憶えておくのは人間にとってそう簡単ではありません。そこで、人間は文字を使うことを考えたわけです。

例えば、『サウンドを再生しなさい』という命令が、機械の言葉でどう表現するのかは私にもわかりません。しかし、『 PLAY 』と書いてあるのを見れば、なんとなくどういう命令を出そうとしているのか想像がつきますよね。

mciSendStringは、非常に複雑でわかりにくい処理を、文字列を使って行うことによって、プログラマーが直感的にわかりやすくプログラミングできるような設計になっているのです。ありがたい話ですね。


さて、前置きが長くなりましたが、実際にmciSendStringの中身を見てみましょう。

次のコードは、mciSendStringの宣言文です。mciSendStringを使いたいときは、これをモジュールの先頭部分に記述します。

Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" _
(ByVal lpstrCommand As String, _
ByVal lpstrReturnString As String, _
ByVal uReturnLength As Long, _
ByVal hwndCallback As Long) As Long

な、なんだこれはー! という叫びが聞こえてきそうです。

たくさんの英語が並んでいて、ちょっとビビッてしまいますね。
mciSendStringは引数の意味がちょっとわかりにくいので、あえてここでは詳しい説明をしないことにします。これを一から全て説明していると、それだけで多分やる気がなくなってしまうと思いますので。

mciSendStringの引数で最も重要となるのが、第一引数である『 lpstrCommand As String 』です。データ型がString型ですから、ここに何らかの文字列を渡せばいいことがわかりますね。
mciSendStringは、この第一引数に渡された命令を実行する仕組みになっています。ですから、サウンドを再生したいときには、ここに再生を表す命令文字列を渡すことになります。


■それでどう使うの?

さて、mciSendStringの宣言文は準備できましたか? 宣言文が準備できたら、次に実際の使い方を見ていきましょう。

mciSendStringでサウンドを再生する場合には、あらかじめ、目的のオーディオファイルをオープン、つまり開いておかなくてはいけません。
しかし、開くといっても、それはあくまでもメモリ上に開いておくという意味です。

ここで???となった方、多分いらっしゃると思います。メモリ上に開いておくってどういうこと? という感じでしょう。でも心配要りません。それは勝手にmciSendStringがやってくれます。mciSendStringに、『オーディオファイルを開きなさい』と命令してやればいいのです。

Call mciSendString("open オーディオファイルのフルパス(場所) alias ファイルの仮名", vbNullString, 0, 0)

これが、オーディオファイルを開きなさいという命令をしているコードです。

まず始めに、 open が出てきていますね。これが、ファイルを開きなさいという命令を表す文字列です。どんなオーディオファイルを開くときでも、この部分は変わりません。

そして、次に『オーディオファイルのフルパス(場所)』とあります。これは、オーディオファイルが置かれている場所を表すアドレス(C:\Documents and Settings……など)を指定します。

ちょっとわかりづらいのが次のところでしょう。ここには『 alias ファイルの仮名 』と書かれていますね。
alias (エイリアス)というのは、一時的な仮の名前のようなもので、プログラムの中で、何かを判別したりするときにわかりやすくするための仕組みです。
mciSendStringでは、開いたファイルを後から再生したりする際に、ここで指定した仮の名前を使って識別します。複数のファイルを開いておいても、異なる名前をつけておくことで、どれを再生すればいいのか容易に判断がつきますね。エイリアスとはそのための仕組みです。

サンプルはこんな感じです。

Call mciSendString("open C:\WINDOWS\Media\chimes.wav alias Chime", vbNullString, 0, 0)

これで、『chimes.wav』というオーディオファイルが、『Chime』という仮の名前で開かれます。指定されたパスにファイルが存在しない場合には、オープンに失敗しますので注意してください。

そして、上記のようにして開いたオーディオファイルを再生するときは次のようになります。

Call mciSendString("play Chime", vbNullString, 0, 0)

簡単ですね。『 play 』という命令文字列を使って、オーディオファイルを開く際に定義した、仮の名前を指定すればいいのです。これで、サウンドが鳴るはずです。


■大事な話

さて、これで、目的のサウンドを鳴らすことができるようになりました。ただし、これで終わりではありません。大事なことが残っています。

先ほど、ファイルを開く際に『メモリ上に開く』という表現を使いました。実は、メモリ上に開かれたファイルの情報を、ほったらかしにしておくのはタブーです。
これは、オーディオファイルだけの話ではありません。APIなどでメモリ上に展開されたデータは、最後には必ず『解放』しなければいけません。これは一体どういうことでしょう。

ウィンドウズは、様々な処理を行うためにメモリを使います。そして、mciSendStringなどを使ってメモリ上にデータを展開するということは、それだけウィンドウズの領地を圧迫することと同じです。

ですから、メモリ上に展開されているデータをそのままにしておくと、ウィンドウズの肩身がどんどん狭まっていきます。そして最後には、必要なメモリ領域が足りなくなって、フリーズしたり変な動作をしたりするようになってしまうのです。

APIを使うことの恐さとはこういうことです。
MCIは高度な分だけ、難易度が高く扱いが難しいと最初に書きましたね。それがこういうことなのです。使い方をひとつ間違えると、パソコンにとって致命的なエラーが発生する可能性があるわけです。
昨今のパソコンでは、メモリがたくさん積まれているので、オーディオファイルをひとつふたつそのままにしておいても、フリーズしてしまうということは考えにくいです。しかし、こういった事情はプログラマーとして認識しておかなくてはいけません。

キチンと開いたファイルは閉じる、メモリを解放してきれいな状態にしておく、これを忘れずにやりましょう。

Call mciSendString("close Chime", vbNullString, 0, 0)

このように、『close』という命令文字列を渡してmciSendStringを呼び出せば、ファイルがクローズされてメモリが解放されます。忘れずにやる癖をつけておきましょう。


最後にmciSendStringを使用した例として、サンプルコードを載せておきます。

'mciSendString の宣言
Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" _
(ByVal lpstrCommand As String, _
ByVal lpstrReturnString As String, _
ByVal uReturnLength As Long, _
ByVal hwndCallback As Long) As Long

'--------------------------------------------------------------------

Sub MCI_Test()

    Dim P As String 'ファイルのパスを格納するための変数

    'ブックと同じ場所にあるオーディオファイルのパスを取得する例
    P = """" & ActiveWorkbook.Path & "\sample.wav"

    'ファイルを『sample』というエイリアスで開く
    Call mciSendString("open " & P & " alias sample", vbNullString, 0, 0)

    '再生する
    Call mciSendString("play sample", vbNullString, 0, 0)

    'ファイルをクローズする
    Call mciSendString("close sample", vbNullString, 0, 0)

End Sub

『開く』⇒『再生する』⇒『閉じる』という一連の流れをよく確認してみてください。また、別館にてサンプルも用意しています。下のリンクからダウンロードできますので、よかったら参考にしてください。


サンプルダウンロード ⇒ コチラよりダウンロードできます。(別館)



■格言

MCIを使えば高度なサウンド処理が可能
高機能な分扱いが難しい
開いたファイルはクローズする


ちょっと難しい話題でしたが、大丈夫でしょうか。







Chapter.66 [ APIによるサウンド再生:MIDIと多重再生 ]

■ゲームと多重再生

さて、前回は、MCIと呼ばれるAPI関数群について簡単に説明しました。今回は、前回の内容を応用しながら、もう少し突っ込んだ部分まで考えてみましょう。

とはいっても、実は前回の内容で基本的な部分はほとんど完成しています。既に、多重再生を行うこともできる仕様になっています。

ゲームでは多くの場合、BGMと効果音を同時に再生できないと困ります。何かの効果音を再生するたびに、BGMの演奏が止まってしまっては雰囲気が台無しになってしまいますものね。前回解説したmciSendStringというAPIは、多重再生にも対応していますので、前回の内容を適宜修正するだけで多重再生を行うことができます。


■多重再生の制約

早速ですが、多重再生を行う方法について解説しましょう。

まず最初に理解しておくべきことは、『同じエイリアスを同時に複数再生することはできない』、という事実です。
例えば『 audio1 』というエイリアスで開いたファイルがあったとします。これをmciSendStringで再生するには、次のように記述すればいいのでしたね。

Call mciSendString("play audio1", vbNullString, 0, 0)

play 』という文字列が、再生しなさいという意味の文字列命令でしたね。それに半角スペースを空けてエイリアスを指定すれば、これでサウンドが鳴ります。

そして、多重再生とは、単純に同時に音を鳴らせればいいので、次のように記述したくなりますね。

Call mciSendString("play audio1", vbNullString, 0, 0)
Call Sleep(100)
Call mciSendString("play audio1", vbNullString, 0, 0)

このように記述すると、Sleep関数によって約0.1秒待った後、音が重なって再生されるような気がします。

ですが、これはうまくいきません。

なぜなら、先ほども書いたように、同じエイリアスは同時に再生できないからです。既に再生が始まっているエイリアスを、後からもう一度再生しようとしているので、これではうまくいかないのです。

どうしても同じ音を重ねたい場合には、同じオーディオファイルから複数のエイリアスを作成しておかなくてはいけません。オーディオファイルを2回開いて、異なるエイリアス名で定義しておけば、重ねて再生することもできます。


■MIDIファイルってなに?

オーディオファイルには様々な種類がありますが、その中に『 MIDI 』と呼ばれるフォーマットがあります。

MIDI(ミディ)とは、正確には規格のことを指しますが、一般的にはオーディオファイルの種類のひとつとして認知されています。

waveファイルなどのデータとは異なり、MIDIファイルは音データそのものを保持しているわけではありません。MIDIファイルの中身には、音をどのように奏でるかを表す様々なコマンドが記述されています。
『どんな音域で』、『どんな音で』、『どのくらいの強さで』、『どのくらいの長さで』といった具合です。

MIDIファイルの再生が行われる際には、このコマンドを元に音が変換されて鳴る仕組みになっています。ですからMIDIファイルは普通、waveファイルよりも非常に小さいサイズになります。サウンドデータをそのまま持つよりも、コマンドで記述したほうがファイルサイズを小さくできるわけです。

そして、MIDIのコマンドからサウンドデータへの変換を行っているのが『シーケンサ』と呼ばれるソフトです。MIDIファイルの中身は全てコマンドです。つまり演奏される際の音色の美しさなどに直接影響するのは、MIDIファイルそのものではなく、音への変換に使われるシーケンサの性能です。

ウィンドウズには、標準のシーケンサが入っていますから、これがMIDIファイルの再生に使われます。同じシーケンサを使って演奏されるMIDIファイルの音色は全く同じになります。逆に、異なるシーケンサで演奏される場合には、同じ音色になるとは限りません。

シーケンサにはウィンドウズ標準のもの以外にもたくさんのものがあります。例えば、某大手楽器メーカーが提供するシーケンサは、非常に音がよいことで知られており、熱心なユーザーがたくさんいます。

こうして考えると、MIDIファイルとは『楽譜』のようなものであり、シーケンサが『オーケストラの楽団』のようなものであるということがわかります。

MIDIファイルはあくまでも、どのように音を奏でるかがコマンドによって記述されているファイルです。ですから楽譜のように、そこにはルールや規則が記述されているに過ぎません。
楽譜は同じでも、演奏するオーケストラの力量によっては、結果として聞こえる音はだいぶ変わってきます。これはつまり、シーケンサの性能がMIDIファイルの音質に多大な影響を与えることを意味します。
ウィンドウズの標準シーケンサがあれば、とりあえずMIDIファイルを聞くことはできますが、キチンと音に対するこだわりのある人は、やはり高級でレベルの高いシーケンサを使いたくなるのでしょうね。


ちょっと話が横道に逸れましたが、実は、MIDIファイルがシーケンサによって演奏されるということが、今回の講座の内容に関係してきます。

先ほど、同じwaveファイルを同時に再生したい場合には、異なるエイリアスで2回開くという話をしましたね。しかしこれは、MIDIファイルには使えない技法です。
なぜなら、MIDIファイルを演奏するシーケンサが、同時に複数のファイルを演奏できないからです。仮に、waveファイルのときと同じように、エイリアスを変えて2回MIDIファイルを開いていたとしても、これを同時に重ねて演奏することはできません。後から再生コマンドが送られたほうが優先して再生されるだけです。

異なるMIDIファイルであっても、やはり同時に再生することはできません。MIDIファイルは常に1つしか再生できないということになります。
これは注意してくださいね。


■まとめ

さて、ちょっとここまでの内容をまとめましょう。

多重再生するには
mciSendStringを使って、そのまま多重再生を行うことが可能。単純に同時に音を鳴らせばよい。


多重再生の制約1
同じエイリアスを同時に再生することはできない。後から送られたコマンドが優先される。


MIDIファイルとは
サウンドデータそのものではなく、音色や強さなどを表すコマンドによって記述されているファイル。演奏するためには、コマンドから音へ変換してくれるシーケンサが必要になる。
ウィンドウズには標準のシーケンサが含まれているので、演奏自体ができないということはあまりない。


多重再生の制約2
MIDIファイルを同時に再生することはできない。例えエイリアスを複数用意したとしても、シーケンサ側の制約なので、同時に再生することはできない。


上で挙げたような点に注意しておけば、あとは前回のコードを応用していくだけで、多重再生が可能です。wave形式のファイルでも、mp3形式のファイルでも、MIDI形式のファイルでも、再生を表す命令文字列をmciSendStringに渡して実行すれば、重ねて再生されます。

例えば、次のようにオーディオファイルを開きます。

Call mciSendString("open 中略sample.wav alias WAVE", vbNullString, 0, 0)
Call mciSendString("open 中略sample.mid alias MIDI", vbNullString, 0, 0)

これで、『 WAVE というエイリアスのwaveファイル』と、『 MIDI というエイリアスのMIDIファイル』が開けましたね。

そして、このふたつを多重再生するとなると次のようになります。

Sub MCI_Test2()

    'まずはBGMの再生を開始する
    Call mciSendString("play MIDI", vbNullString, 0, 0)

    '3秒間待つ
    Call Sleep(3000)

    '効果音を鳴らす
    Call mciSendString("play WAVE", vbNullString, 0, 0)

End Sub

例えばゲームの開始と同時にBGM用のMIDIファイルを演奏開始しておき、適宜効果音が必要な部分でwaveファイルを再生させるようにすれば、これで問題なく動作します。

ただし、このようなコードの記述では、1回目は音が鳴るんだけど2回目以降は効果音が鳴らない、などの不具合が出るかもしれません。この不具合はmciSendStringに渡す命令文字列を変えることで解消できるのですが、その話は次回です。

次回は、mciSendStringに渡す命令文字列について、もう少し詳しく解説する予定です。今回はとりあえず、MIDIファイルの仕組みや、多重再生を行う際の制約事項などをしっかり覚えておきましょう。


■格言

同じエイリアスでの多重再生はできない
MIDIとMIDIの同時再生はできない


MIDIは容量が小さいのでゲームを配布する際などに便利です。







Chapter.67 [ APIによるサウンド再生:MCIコマンドとループ再生 ]

■様々なコマンド

前回のサンプルでは、一度再生したサウンドが、2回目以降うまく再生されない可能性がありました。しかしこれはなぜなのでしょうか。

実は、前回、前々回と解説した、サウンドを再生するコマンド『 play 』が関係しています。
今回の講座では、もはやお馴染みとなったMCIコマンドである play や、その他の命令文字列について、もう少し詳しく見ていくことにしましょう。命令文字列、つまりMCIコマンドをよく知ることで、様々な処理が可能になります。応用すれば、メディアプレーヤーを自前で作成することもできるのです。がんばって取り組んでいきましょう。

まずは、mciSendStringで使うことができるMCIコマンドのうち、代表的なものを一覧にしてみましたので、それを見てみましょう。

MCIコマンド解説
openファイルを開く
closeファイルを閉じる
playサウンドを再生する
stop再生中のサウンドを停止する
pause再生を一時停止する
resume一時停止している状態から再生を再開する
status現在の状態を調べる

本当に代表的なところだけなので、これはMCIコマンドのほんの一部です。しかし、これらのコマンドさえ使いこなせれば、大体のことはできます。


■ open ・ close ・ play ・ stop

ファイルのオープン、そしてクローズ。これは前回までに解説しましたね。
mciSendStringでサウンドを再生するためには、必ずあらかじめサウンドファイルを開いておく必要がありました。そして、ファイルを開くという命令を出す文字列が『 open 』でしたね。

開いたサウンドデータは、ソフトが終了する前に、必ず閉じなくてはいけません。それを行うのが『 close 』でしたね。このMCIコマンドを使ってファイルを閉じておかないと、あとあと問題が起きる可能性があるので、必ず開いたファイルは閉じるようにしましょう。

ファイルを開く場合
mciSendString("open ファイルのパス alias エイリアス", vbNullString, 0, 0)

ファイルを閉じる場合
mciSendString("close エイリアス", vbNullString, 0, 0)


エイリアスというのは、開いたファイルにつける仮の名前で、プログラムの中では、このエイリアスを使ってファイルを識別する仕組みでした。

そして、サウンドを再生するには、『 play 』を、再生されているサウンドを停止するには『 stop 』を使います。

サウンドの再生
mciSendString("play エイリアス", vbNullString, 0, 0)

再生中のサウンドの停止
mciSendString("stop エイリアス", vbNullString, 0, 0)

ここで登場したMCIコマンドの『 play 』ですが、先ほどの表では、単にサウンドを再生する、という解説になっていました。しかし、実はこれは正しい解説とは言えません。
playというMCIコマンドを正しく解説するならば、『現在の位置からサウンドを再生する』となります。ここで重要なのが、現在の位置から、という部分です。

じつは、playというMCIコマンドは、現在の位置という概念にのっとって再生を開始します。あらかじめ現在の位置が変化している場合には、必ずしも最初から再生されるわけではないのです。これが、前回のサンプルで音が鳴らなくなることがあった原因です。

一度サウンドが再生されると、当然、現在の位置は常に変化し続けます。ですからplayコマンドを呼び出しても、正しく再生が行われていないような気がしてしまったのですね。

これを回避するには、MCIコマンドにひと手間加えます。それが次のコードです。

mciSendString("play エイリアス from 0", vbNullString, 0, 0)

from というオプション命令を追加しました。from は、再生を開始する場所を指定することができるコマンドです。そこに半角スペースを空けて、開始するポイントを指定します。上の例では 0 が指定されているので、強制的にサウンドの一番最初が指定されます。
この状態でplayコマンドを呼び出すようにすれば、mciSendStringが呼び出されるたびに、必ず最初からサウンドが再生されるようになります。


■ pause ・ resume

さて、今度は少しだけ発展した形をやってみます。『一時停止』と、『再生の再開』です。これにはそれぞれ『 pause 』と『 resume 』を使います。

再生中サウンドの一時停止
mciSendString("pause エイリアス", vbNullString, 0, 0)

一時停止中のサウンドの再生再開
mciSendString("resume エイリアス", vbNullString, 0, 0)

pause というMCIコマンドを使うと、現在再生されているサウンドを一時停止することができます。そして、resume というMCIコマンドで、停止した場所から再生を再開することができます。

実は、一時停止したサウンドは、playでも再生させることはできます。ただし、この場合には再生が開始される位置は、先述した from による指定が優先されることになります。 from を使わずに再生させたとしても、うまくいきません。
停止した場所から再生を再開するには、きちんと resume を使って再開させる必要があるのです。

ゲームのサウンド処理においては、ゲームにポーズ機能をつける場合や、アイテムの取得時などに特殊なサウンドを再生する場合などに、この一時停止と再開の機能が利用できそうですね。

ただし、注意すべきことがひとつあります。
実は、MIDIの処理では、 resume コマンドを使うことができません。一時停止することはできますが、そこから resume による再生の再開はできないので注意してください。


■ status

このMCIコマンドを使いこなせるかどうかで、かなりレベルが変わってきます。
実は、この『 status 』を有効に利用すると、自前でサウンドをループ再生するなどの処理が可能になります。

このMCIコマンドは、現在の各エイリアスの状態を調べることができるコマンドです。ですから、再生中かどうかを調べながら処理すれば、再生が終わったときにそれを察知することもできるのですね。
もし再生が終了して、エイリアスが停止状態だったときには、もう一度再生させることであたかもループ再生しているかのように振舞うことができるわけです。

このMCIコマンドを使うためには、今までとは違い、あらかじめ準備が必要です。その準備とは、『現在の状態を格納するために必要な、String型変数の準備』です。

そして、このString型の変数は、『固定長文字列変数』である必要があります。う~ん、わかりにくくなってきました。

まず、文字列型変数について簡単に解説しますね。
皆さんご存知の通り、文字列を扱う変数の型は、String型という変数の型でしたね。通常、String型で宣言された文字列は『可変長文字列型』となります。
可変長、つまり、長さを変えることができる文字列ということですね。1文字だけ文字を格納しておいてもいいし、逆に1億文字を入れておいてもいいのです。

これに対して、『固定長文字列型』というものが存在します。こちらは、固定長ですから、あらかじめ文字列の長さが決まっています。そして、固定長文字列を宣言する場合には、次のように変数を宣言します。

Dim mystr As String * 255

上記のように変数を宣言すると、255文字を格納できる、固定長文字列型の変数が宣言されます。この変数には、255よりも大きな文字数を格納することはできません。格納できるデータの量を制限することができるのですね。


さて、話を戻します。
status というMCIコマンドを使うために必要な文字列変数は、固定長文字列変数である必要があります。そして、固定長で宣言した文字列型の変数を、mciSendStringに引数として渡すことによって、現在の状態を取得することができます。

簡単な例を挙げると、次のようになります。

Sub GetStatus()

    Dim myStr As String * 255
    
    myStr = ""
    
    Call mciSendString("status エイリアス mode", myStr, 255, 0)
    
    MsgBox myStr
    
End Sub

固定長文字列の変数が宣言されていますね。これが変数 myStr です。
そして、mciSendStringの第二引数に、この変数 myStr が与えられています。第三引数には、変数 myStr の大きさを指定することになっているので、255となっています。

このようにmciSendStringを呼び出すと、変数 myStr に、現在の状態が格納される仕組みになっています。上記のような呼び出しを行った後で変数 myStr に入っている文字列を調べれば、エイリアスの現在の状態が取得できます。

もし、現在エイリアスが再生中の場合には、『 Playing 』が格納されています。停止中の場合には『 stopped 』が、一時停止中ならば『 paused 』が格納されているはずです。

これで、現在のエイリアスの状態を、好きなときに知ることができるようになります。ゲームの処理の最中に、適宜情報を取得する処理をはさむようにしておけば、BGMをループ再生することも可能です。情報を取得しながら適切に処理することで、かなり柔軟な処理を実現することができるのです。


■まとめ

さて、mciSendStringについて、3回にわたって解説してきました。かなり難しい内容だったのではないでしょうか。

MCIは非常に奥が深く、極めればほとんどのマルチメディアに関する処理を行うことができます。しかしその反面、扱いが難しく、難解な部分が多いです。
私が講座で解説した内容は、MCIの本当に簡単な使い方だけです。しかし、ゲームのサウンド処理を行ううえで、最低限必要なことは全て解説できたと思っています。

さらなる高みを目指すなら、APIに関する深い知識も必要になってきます。とりあえず、講座で解説してきた簡単な使い方を完全にマスターしてください。そこから先を目指すかどうかは、皆さん次第ということになるでしょう。



■格言

MCIコマンドを駆使して多彩な処理を行う
一時停止や再生の再開も可能
エイリアスの状況を取得することもできる


意外と status コマンドの使い方を知らない人も多いのではないでしょうか。有用な技術ですので、是非マスターしてください。







メールフォーム

影斬に物申すという方はこちら

名前 :
メール:
件名 :
本文 :

可能な限り要望には応えますが、必ず返信や回答ができることを、保障するものではありません。
ご了承ください。

Chapters

コンテンツ一覧


■Chapter 一覧■
    全てのChapterの一覧です。
    直接アクセスしたい方はこちらをご利用下さい。

    Chapter.1 [ 知っておくべき心得 ]
    Chapter.2 [ Excelってなんだろう ]
    Chapter.3 [ Excelの基本画面 ]
    Chapter.4 [ VBAとは? ]
    Chapter.5 [ モジュールについて ]
    Chapter.6 [ 変数 ]
    Chapter.7 [ 変数の型と宣言 ]
    Chapter.8 [ プロシージャとスコープ ]
    Chapter.9 [ ゲームつくる様々な手法 ]
    Chapter.10 [ ユーザーフォーム ]
    Chapter.11 [ プロパティウィンドウ ]
    Chapter.12 [ 乱数 ]
    Chapter.13 [ 条件分岐 ]
    Chapter.14 [ ゲーム画面のデザイン ]
    Chapter.15 [ コード記述の基本作法 ]
    Chapter.16 [ じゃんけんゲーム:1 名前をつける ]
    Chapter.17 [ じゃんけんゲーム:2 フォームの起動 ]
    Chapter.18 [ じゃんけんゲーム:3 乱数の種 ]
    Chapter.19 [ じゃんけんゲーム:4 イベント ]
    Chapter.20 [ じゃんけんゲーム:5 引数 ]
    Chapter.21 [ じゃんけんゲーム:6 役判定 ]
    Chapter.22 [ じゃんけんゲーム:7 予測と制限 ]
    Chapter.23 [ Withステートメント ]
    Chapter.24 [ 画像を表示させる ]
    Chapter.25 [ 画像表示の発展形 ]
    Chapter.26 [ 繰り返し処理 For文 ]
    Chapter.27 [ 繰り返し処理 Do~Loop文 ]
    Chapter.28 [ Exitステートメント ]
    Chapter.29 [ フォーム上の位置情報 ]
    Chapter.30 [ API基礎知識 ]
    Chapter.31 [ API補足知識 ]
    Chapter.32 [ メインループを考える ]
    Chapter.33 [ 同期処理の概念 ]
    Chapter.34 [ 移動処理その1:画面設定と考え方 ]
    Chapter.35 [ 移動処理その2:DoEvents ]
    Chapter.36 [ 移動処理その3:キー入力判定API ]
    Chapter.37 [ 条件分岐のさらなる探求 Select Case ]
    Chapter.38 [ アニメーション ]
    Chapter.39 [ 配列変数 ]
    Chapter.40 [ ゲームの初期化 ]
    Chapter.41 [ シューティングゲーム1:ゲーム設計 ]
    Chapter.42 [ シューティングゲーム2:メインプロセス ]
    Chapter.43 [ シューティングゲーム3:構造体 ]
    Chapter.44 [ シューティングゲーム4:定数 ]
    Chapter.45 [ シューティングゲーム5:プレイヤーキャラクター ]
    Chapter.46 [ シューティングゲーム6:ショットを撃つ① ]
    Chapter.47 [ シューティングゲーム7:ショットを撃つ② ]
    Chapter.48 [ シューティングゲーム8:Mod演算子の活用 ]
    Chapter.49 [ シューティングゲーム9:敵キャラクター登場 ]
    Chapter.50 [ シューティングゲーム10:衝突判定 ]
    Chapter.51 [ シューティングゲーム11:衝突の実体 ]
    Chapter.52 [ シューティングゲーム12:敵の攻撃 ]
    Chapter.53 [ シューティングゲーム13:爆発エフェクト ]
    Chapter.54 [ シューティングゲーム14:残機数表示① ]
    Chapter.55 [ シューティングゲーム15:残機数表示② ]
    Chapter.56 [ シューティングゲーム16:スコアの表示 ]
    Chapter.57 [ シューティングゲーム17:タイトル画面 ]
    Chapter.58 [ シューティングゲーム18:ボスキャラクター ]
    Chapter.59 [ シューティングゲーム19:最後の仕上げへ ]
    Chapter.60 [ シューティングゲーム20:いよいよ完成STG ]
    Chapter.61 [ カードゲームで使えるめくり効果 ]
    Chapter.62 [ ラジアンと角度 ]
    Chapter.63 [ ラジアンの活用:円運動 ]
    Chapter.64 [ ラジアンの活用:任意の角度へ移動する ]
    Chapter.65 [ APIによるサウンド再生:基礎 ]
    Chapter.66 [ APIによるサウンド再生:MIDIと多重再生 ]
    Chapter.67 [ APIによるサウンド再生:MCIコマンドとループ再生 ]
    Chapter.68 [ Function プロシージャ ]
    Chapter.69 [ 値渡しと参照渡し ]
    Chapter.70 [ デバッグ1:イミディエイトウィンドウ ]
    Chapter.71 [ デバッグ2:ローカルウィンドウ ]
    Chapter.72 [ デバッグ3:コード実行の中断 ]
    Chapter.73 [ オブジェクトってなんだ ]
    Chapter.74 [ プロパティ・メソッド・イベント ]
    Chapter.75 [ オブジェクト変数 ]
    Chapter.76 [ オブジェクトとコレクション ]
    Chapter.77 [ 特殊な繰り返し:For Each ]
    Chapter.78 [ エラー処理 ]
    Chapter.79 [ On Error と GoTo文 ]
    Chapter.80 [ Resumeステートメント ]
    Chapter.81 [ バイトとビット ]
    Chapter.82 [ ウィンドウメッセージとイベント ]
    Chapter.83 [ 文字列の基礎 ]
    Chapter.84 [ 文字列操作① ]
    Chapter.85 [ 文字列操作② ]
    Chapter.86 [ タイピングゲーム1:仕様を決める ]
    Chapter.87 [ タイピングゲーム2:キー入力検知 ]
    Chapter.88 [ タイピングゲーム3:文字列照合 ]
    Chapter.89 [ タイピングゲーム4:判定関数 ]
    Chapter.90 [ タイピングゲーム5:ゲーム画面設計 ]
    Chapter.91 [ タイピングゲーム6:問題文のソート ]
    Chapter.92 [ タイピングゲーム7:動的配列 ]
    Chapter.93 [ タイピングゲーム8:キーダウンイベント ]
    Chapter.94 [ タイピングゲーム9:正打数の表示 ]
    Chapter.95 [ タイピングゲーム10:タイムの表示 ]
    Chapter.96 [ クリックゲーム1:イベントの種類 ]
    Chapter.97 [ クリックゲーム2:画面設計 ]
    Chapter.98 [ クリックゲーム3:クリック座標検知 ]
    Chapter.99 [ クリックゲーム4:キャラクター準備 ]
    Chapter.100 [ クリックゲーム5:キャラクターの配置 ]
    Chapter.101 [ クリックゲーム6:キャラクター移動とNot演算子 ]
    Chapter.102 [ クリックゲーム7:クリックのヒット判定 ]
    Chapter.103 [ クリックゲーム8:ヒットマークエフェクト ]
    Chapter.104 [ クリックゲーム9:サウンド処理の実装 ]
    Chapter.105 [ クリックゲーム10:マウスカーソルの変更 ]
    Chapter.106 [ ブロック崩しゲーム1:仕様と概要を決める ]
    Chapter.107 [ ブロック崩しゲーム2:基本概念の確認 ]
    Chapter.108 [ ブロック崩しゲーム3:ベクトルとは ]
    Chapter.109 [ ブロック崩しゲーム4:変数や定数の宣言 ]
    Chapter.110 [ ブロック崩しゲーム5:初期化処理の実装 ]
    Chapter.111 [ ブロック崩しゲーム6:ブロックの配置 ]
    Chapter.112 [ ブロック崩しゲーム7:根幹処理とバーの処理 ]
    Chapter.113 [ ブロック崩しゲーム8:線分と線分の交差を判定 ]
    Chapter.114 [ ブロック崩しゲーム9:線分同士の交点 ]
    Chapter.115 [ ブロック崩しゲーム10:ボールの処理 ]
    Chapter.116 [ ブロック崩しゲーム11:最終調整して完成へ ]
    Chapter.117 [ テキストファイル操作基礎 ]
    Chapter.118 [ テキストファイル操作:読み込み編 ]
    Chapter.119 [ テキストファイル操作:CSV読み込み編 ]
    Chapter.120 [ テキストファイル操作:様々な読込編 ]
    Chapter.121 [ テキストファイル操作:バイナリ編 ]
    Chapter.122 [ テキストファイル操作:暗号化編 ]
    Chapter.123 [ テキストファイル操作:復号化編 ]
    Chapter.124 [ クラスモジュールとは ]
    Chapter.125 [ クラスモジュール:メソッド編 ]
    Chapter.126 [ クラスモジュール:プロパティ編 ]
    Chapter.127 [ クラスモジュール:イベント拡張編 ]
    Chapter.128 [ クラスモジュール:イベント自作編 ]
    Chapter.129 [ APIによる描画処理1:ハンドル ]
    Chapter.130 [ APIによる描画処理2:デバイスコンテキスト ]
    Chapter.131 [ APIによる描画処理3:ペン オブジェクト ]
    Chapter.132 [ APIによる描画処理4:ブラシ オブジェクト ]
    Chapter.133 [ APIによる描画処理5:図形描画準備編 ]
    Chapter.134 [ APIによる描画処理6:図形描画実践編 ]
    Chapter.135 [ APIによる描画処理7:画像描画の仕組み編 ]
    Chapter.136 [ APIによる描画処理8:ビットブロック転送編 ]
    Chapter.137 [ APIによる描画処理9:ラスタオペレーション ]
    Chapter.138 [ APIによる描画処理10:マスク描画 概念編 ]
    Chapter.139 [ APIによる描画処理11:マスク描画 実践編 ]


    コードやVBAに関する質問などはサポート掲示板(別館)までお気軽にどうぞ。




fc2 seotool Excel VBA ゲーム プログラミング 講座

Counter

twitter


Shadow BBS - 影掲示板

VBA 関連書籍



上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。