home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fun CD 26
/
OTACD26.ISO
/
etc
/
nawkk
/
yane0310
/
ygs2k156.lzh
/
manual
/
スクリプトマニュアル.txt
< prev
next >
Wrap
Text File
|
2000-05-19
|
127KB
|
3,825 lines
< ゲームスクリプト目次 >
§1.言語仕様
§1-1 数値
§1-2 変数
§1-3 関数
§1-4 main関数
§1-5 コメント行
§1-6 命令
§1-7 変数宣言
§1-8 配列への代入
§1-9 演算子
§1-10 条件判断
§1-11 選択文
§1-12-1 制御構文(loop)
§1-12-2 制御構文(goto)
§1-12-3 制御構文(for,while,do)
§1-12-4 制御構文(jump)
§1-13 モジュール化の勧め
§1-14 コンパイルエラーについて
§1-15 文字列の取り扱いについて
§1-16 メモリ確保
§1-17 DLLファイルの読み込み機能と、その作成手順
§1-18 ライブラリのimport
§1-19 漢字対応
§2.ゲーム上で利用できる関数
§2-1 WAVE関数
§2-2 CDDA関数
§2-3 プレーン操作(ビットマップ関数)
§2-4 画面効果
§2-4-1 フェイドイン/フェイドアウト等
§2-4-2 画面のフラッシュ(色の反転)
§2-4-3 画面のモザイク
§2-4-4 セカンダリの転送オフセット
§2-5 バックアッププレーン
§2-6 セカンダリプレーンを他プレーンと入れ換える機能
§2-7 タイマー管理関数
§2-8 FPS表示機能
§2-9 文字列表示関数
§2-10 文字列操作関数
§2-11-1 キー入力関連(キーボード)
§2-11-2 キー入力関連(ジョイスティック)
§2-11-3 キー入力関連(MIDI INPUT)
§2-11-4 キー入力関連(MOUSE入力)
§2-12 MIDIファイルの再生関連
§2-13 ゲームデータの簡易ロード/セーブ関数
§2-14 簡易ファイル操作
§2-15 他のスクリプトを呼び出す機能
§2-16 ゲーム終了関数
§2-17 乱数の発生
§2-18 シナリオファイルの表示機能
§2-19 画面モードの切り替え
§2-20 フォルダ関連
§2-21 各種定数を設定する機能
§2-22 各種定数を取得する機能
§3.その他の必要事項
§3-1 ゲーム上で利用できる内部変数
§3-2 HALT命令について(重要)
§3-3 イニシャライザについて
§4.サンプル
§4.1 デバッグ用出力
§4-2-1 WAVEの再生
§4-2-2 WAVEのループ再生
§4-3-1 CDの再生サンプル
§4-3-2 CDのカレントポジションについて
§4-4-1 画面描画
§4-4-2 左から右にスクロールさせる
§4-4-3 画面全体に、32×32のビットマップを敷き詰める
§4-4-4 FPS設定機能、FPS表示機能のサンプル
§4-4-5 マシンスピードに依存しない移動速度で描画する
§4-4-6 フェードアウトのサンプル
§4-4-7 フェードアウト/フェードインのサンプル
§4-4-8 理想的なフェードイン/フェードアウト
§4-4-9 クリップ機能つき転送
§4-4-10 2画面スクロールサンプル
§4-4-11 αブレンドのサンプル
§4-5-1 メッセージ表示のサンプル
§4-5-2 長い長い文字列を表示する。
§4-5-3 文字列をフェードインさせる。
§4-5-4 文字列をフェードイン/フェードアウトさせる。
§4-6-1 文字列操作関数のサンプル
§4-6-2 文字列の連結
§4-6-3 stringにstringの連結
§4-6-4 stringを利用して数字の埋め込み
§4-6-5 stringを利用して2つの数字の埋め込み
§4-6-6 stringを利用して2つの数字と、stringの埋め込み
§4-7-1 キー入力に応じて、上下左右にビットマップを移動
§4-7-2 MIDIキー入力サンプル
§4-8 バックアッププレーンを利用してフェードイン・フェードアウト関数を作成
§4-9 ゲームフラグの読み込み/保存のサンプル
§4-10 シナリオの表示サンプル
§4-11 MIDI出力のサンプル
§5.Q&A
§6.更新履歴
//////////////////////////////////////////////////////////////////////////////
§1.言語仕様
言語は、一見、C言語風です。しかし、それは見かけだけなので、BASICや
マクロのような感覚で書いて行けば良いです。基本的に必要な関数を呼び出すだけ
のものです。
ファイルは、テキストファイルです。拡張子は、テキストエディタで編集できる
ように、cか、txtにしておくと良いでしょう。
スクリプトは、実行ファイルの存在するフォルダに、scriptというフォルダを作って、
そこに入れておかれることをお勧めします。
//////////////////////////////////////////////////////////////////////////////
§1-1 数値
数値は、特に指定がなければ10進数です。
16進数を書きたい場合は、
x = 0x100; // xに100H(=10進数で256)が入る。
というように、0xで書き始めます。
//////////////////////////////////////////////////////////////////////////////
§1-2 変数
変数の型は、longしかありません。longとは、32ビットの符号付き整数です。
ゲーム上では、それしか必要ないと思われるからです。(※ intも使えますが、
longと同じ意味に解釈します。longが気持ち悪ければintと書いても構いません)
ゲーム上のフラグ(アイテムを所有しているかだとか、ゲーム上の時刻だとか
そういったもの)も、このlong型の変数に保管します。
ゲームのユーザーデータとして、セーブ/ロードしなくてはならないデータ群は、
特定の領域に書き込むことによって、セーブして残しておくことが可能になります。
(後述します)
//////////////////////////////////////////////////////////////////////////////
§1-3 関数
関数は、以下のようなスタイルで書きます。
void main() { ...(この部分に関数の中身を書く) }
void test(x,y) { ...(この部分に関数の中身を書く) }
long test(s,t,u) { ...(この部分に関数の中身を書く) }
このへんは、C言語に似ています。
見ての通り、まず最初に関数の返し値(longか、あるいは、返し値のないものの
場合はvoid)、そして関数名、そのあと"("があって引数パラメータの並び、")"が
あって、"{" "}"の中に、実際の命令を書いていきます。ただ、引数には、型宣言は
ありません(※ 書いても構いません) これは、longしか型が存在しないので、
暗黙的にlongだからです。(※ 型名を省略時には、longと解釈するの意味です)
関数呼出しの例を書きます。
void main() {
long x; // long型のxを使うという宣言
x = test(1,2,3);
// xには1+2+3で6が代入されて返ってくる。
print_num(x,100,100); // xを100,100の座標に表示する。6が表示される
// (ただし、こんな関数はありません。あくまで、サンプルです)
}
long test(x,y,z){
return x+y+z; // (x+y+z)を返します
}
こうすると、main関数からtest関数にパラメータ1,2,3が入って呼び出され、
test関数で、それを加算したものが返されるので、関数mainにある変数xには
6が入ってきます。
//////////////////////////////////////////////////////////////////////////////
§1-4 main関数
スクリプトは、通常、ファイルが読み込まれたあと、mainという名前の
関数が呼び出されることになっています。単独のスクリプト等は、すべて
そうです。
よって、必ずmain関数を用意してください。
//////////////////////////////////////////////////////////////////////////////
§1-5 コメント行
ここから、具体的に、スクリプトの言語仕様について書いていきます。
少し難しい部分もあります。すべてを理解する必要はないと思います。
CDを再生する・ビットマップを動かす・画面をフェードアウトする、
マップを表示するなどは、あらかじめ用意されている関数を呼び出す
だけだからです。
また、言語規則でわからないことがあった場合は、C言語の入門書が参考に
なるかも知れません。
例)
// "//"のあとは、その行末まで無視されます。
// これは、コメント文です。
例)
/*
このようにすれば
複数行がコメント行になります。
*/
例)
/*
/*
また、/* */のネストもサポートしています。
ここはコメント文です。
*/
ここもコメント文です。
*/
//////////////////////////////////////////////////////////////////////////////
§1-6 命令
命令は、;で終わります。必ず文末には;が必要です。
このへん、C言語と同じです。
x = 5 ; // 文末に;が必要
x
=
5
; // 何行にわたっても、構わない。
//////////////////////////////////////////////////////////////////////////////
§1-7 変数宣言
変数は、使用するにあたり宣言が必要です。
つまり、
long x; // xという変数を宣言
long y[10]; // yという配列を宣言。
// この場合、C言語と同じくy[0]からy[9]の10個の配列が
// 使えるようになります。
long s,w[4]; // sと配列wを宣言
変数の宣言は関数の一番最初で行ないます。(注意:関数の途中では変数宣言
できません)
そのスクリプトのなかで共通して使いたい変数は、関数の外で宣言します。
long x; // これは、グローバル変数。このスクリプト内であれば
// どこからでも参照できる
void main() { }
のようにします。
グローバル変数もまた、使用に先立って宣言しておかねばなりません。
(使用する場所より、上の行で宣言されている必要があります)
関数のパラメータ(引数)部分の変数については宣言は不要です。
long test(x,y) {
x = 10; // x,yは、宣言しなくて良い
}
//////////////////////////////////////////////////////////////////////////////
§1-8 配列への代入
配列への代入は、以下のようにします。
void main() {
long t[5]; // 配列を宣言
t[2] = 2; // 配列に代入
t[3] = 4; // 配列に代入
}
このへんは、BASICとかと同じですので、問題ないと思います。
グローバルな配列・変数に限り、初期値を設定できます。
例)
long t[5] = {1,2,3,4,5};
例)
int x[5] = { 1,2,3,4,5 }; // int x[] = { 1,2,3,4,5 };は不可
int y = 12345;
int x = 3, y , z = 5; // xは3,zは5に初期化
//////////////////////////////////////////////////////////////////////////////
§1-9 演算子
四則計算、ビット演算、条件判断を提供します。
x = y + z; // 足し算
x = y - z; // 引き算
x = y * z; // 掛け算
x = y / z; // 割り算(0で割り算してはいけません)
x = y % z; // 剰余(yをxで割った余り)
x = !x; // 否定。0ならば1、非0ならば0になります
x = ~x; // 補数演算子。全ビット反転します。
x = y & z; // ビットごとの論理AND
x = y | z; // ビットごとの論理OR
x = y ^ z; // ビットごとの論理XOR
x = y > z; // y>zならば、1、さもなくば0がxに代入されます
x = y >= z; // y>=zならば、1、さもなくば0がxに代入されます
x = y == z; // y==zならば(等しいならば) 1、さもなくば0がxに代入されます
x = y != z; // y!=zならば(等しくないならば)1、さもなくば0がxに代入されます
x = y <= z; // y<=zならば、1、さもなくば0がxに代入されます
x = y < z; // y<zならば、1、さもなくば0がxに代入されます
x = y << z; // ビットシフト演算子。yを左にzビットシフト。
// x = 5 << 3; ならば、5が3回シフトされて5×2×2×2=40になります
x = y >> z; // ビットシフト演算子。yを右にzビットシフト。
// x = 40 >> 3; ならば、40が3回シフトされて40/2/2/2=5になります。
難しいところもあると思いますが、条件判断の結果も数値として扱っていることに
注意してください。真ならば1(非0)。偽ならば0です。このへん、意識せずにも使える
のですが、一応、理解していると何かと良いです。
なお、C言語に準じて、&&と||も使えるようにしてありますが、内部的には、それぞれ
&と|であると解釈しています。よって、
if (f() || g()) { ... }
としていた場合、C言語なら、f()が真のときはg()は実行されませんが、このスクリプト
ではg()も実行します。つまり、&&と||には、ショートカットオペレータとしての役割は無い
というわけです。
その他の演算子
++ → インクリメント(1だけ加算する)
-- → デクリメント (1だけ減算する)
C言語の++と--と似ていますが、使用には制限があって、
x++;というように、変数の後ろにつけて使うのみとなっています。
x++ = y;や、x = y++;というような使用は出来ません。
配列の要素に対するインクリメント(x[2]++;とか)は可です。
%% → 剰余 % の別仕様のもの。
剰余は、-1 % 30などとマイナスの値に対して行なうと、結果がマイナスに
なるので、0~29の値が得られることを期待して使っているときに困ります。
-1 %% 30と剰余すれば、この結果は29になります。
//////////////////////////////////////////////////////////////////////////////
§1-10 条件判断
if ( y > z)
x = 10; // 条件成立時に実行する
のように書きます。この場合、y>zならばxに10が代入されます。
複文をとる場合は、{ }で囲みます。
if ( y > z) {
x = 5; // 条件成立時に、実行します
y = 10;
}
このへん、C言語と同じですが、慣れていないと、とまどうかもしれません。ご注意ください。
ifの中身は、0か非0かだけで判断しています。y > zの部分は、上述のように、
y>zならば1,さもなくば0が返ってくる演算ですので、その結果、うまくifが
実行できるという仕組みです。
例)
if ((x > z) | ( y >= w)) {
a = 10; // x > z または、 y>= w ならば aに10が入ります
} else {
b = 20; // さもなくば、bに20が入ります
}
例)
if (x-5 > y) { // if文では計算式も使えます
a = 5; // x-5 > yならば、aに5が入ります
}
例)
if (!(x-5 > y)) { // 否定演算子も使えます
a = 5; // x-5 > yでないならば、aに5が入ります
}
例)
if (x[5] == 3) { // 配列も使えます
// 等しいかどうかの比較は==を使い、
// = ではないので注意しましょう
a = 5; // x[5]が3ならば、aに5が入ります
}
例)
if ((x!=y) & (y!=w)) {
a = b*2; // xがyと等しくなくて、かつ、yがwと等しくないならば
// aにb*2が入ります
} else if (x==100) { // 上の条件を満たしていなくて、xが100ならば
c = 10; // cに10が入ります
d = 20;
} else if (y==100) { // 上の2つの条件を満たしていなくてyが100ならば
d = 20;
} else if (z==100) { // 上の3つの条件を満たしていなくてzが100ならば
e = 30;
} else {
f = 50; // 上の4つの条件を満たしていないならfに50を代入
}
//////////////////////////////////////////////////////////////////////////////
§1-11 選択文
ifの最後の例のようにif~elseで連ねて書いていくのは、なれていないと
やりにくく、見通しも悪いものになってしまいがちいです。そこで、これを
すっきり書くための構文を用意しています。
実際の使用方法を見ていただいたほうが、わかりやすいでしょう。
alt { // これが選択構文
case (x!=y) & (y!=w): // 条件は"case 式:"のように書きます
a = b*2;
case x==100 : { // 複文である場合は { }でくくることを忘れないこと
c = 10;
d = 20;
}
case y==100 :
d = 20;
case z==100 :
e = 30;
default : // どの条件にも満たない場合
f = 50;
}
以上は、if文の最後の例と同じ内容を実行する例です。
見比べてみてください。
//////////////////////////////////////////////////////////////////////////////
§1-12-1 制御構文(loop)
loop {
// この部分が永久ループになる
}
と書きます。
永久ループだとまずいので、その中に終了条件を書きます。
loop {
x = x+1; // xに1を加算する
if (x==10) break; // xが10に等しければ、loopから抜ける
}
このように、breakを使えば、”一番内側の”loopから抜けることが出来ます。
これによって、繰り返しが可能になります。
例)
loop{
x = 0;
loop {
x = x+1;
if (x==10) break;
}
// 上のbreakでは、ここに抜けてくる。
}
この例では外側のloopから抜けないことに注意してください。
breakのあと、loopを抜ける個数を指定できます。
例)
loop{
x = 0;
loop {
x = x+1;
if (x==10) break 2; // 2つ分loopを抜ける
}
}
// 上のbreakで、ここに抜けてくる
これによって、複数のloopから一気に脱出できます。
途中にいくつloopがあるかは問題ではありません。
外側に向かって、抜けます。
例)
loop{
x = 0;
loop {
x = x+1;
if (x==10) break 2; // 2つ分loopを抜ける
}
loop {
}
loop {
}
}
// 上のbreakで、ここに抜けてくる
ループ繰り返しには、for文もあります。
//////////////////////////////////////////////////////////////////////////////
§1-12-2 制御構文(goto)
goto命令もサポートしています。
ジャンプは、関数内に限ります。
loop {
if (x==y) goto label1; // xとyが等しければlabel1にジャンプ
break;
}
x = 100;
label1: // label1は、ここ!
//////////////////////////////////////////////////////////////////////////////
§1-12-3 制御構文(for,while,do)
C言語に近づけるため、C言語と同じ命令をいくつかサポートしています。
for(A;B;C) 文 → C言語のforとまったく同じです。10回のループならば
for(i=0;i<10;i++) { ... }
というようにやります。for文中でbreakも使えます。
for(i=0;i<10;i++) {
...
if (i==5) break; // for文から抜ける
}
while (式) 文 → C言語のwhileとまったく同じです。
while文中でbreakも使えます。
while (x==y) {
// xとyが等しい間、ここが実行される
}
do 文 while (式); → C言語のdo~whileとまったく同じです。
do文中でbreakも使えます。
do
// xとyが等しい間、ここが実行される
} while (x==y);
先のwhileの構文との違いは、こちらは最低1回は実行されるということです。
//////////////////////////////////////////////////////////////////////////////
§1-12-4 制御構文(jump)
☆ jump命令(高速分岐命令)
書式 : jump(式,ジャンプラベル1,ジャンプラベル2,...);
alt文だと、ひとつひとつの条件を比較していくため、条件が100個あれば
最後までたどりつくのには最悪100回の比較が必要となります。このとき
60FPSを達成するためには、6000回もの比較が必要になり、速度面で非常
に不利です。
そこで、テーブルジャンプを用意しています。
テーブルジャンプとは、数値に応じてジャンプ先を変更するというものです。
例)
jump(x,label1,label2,label3);
// 変数xの値が0のときはlabel1,xが1のときはlabel2,
// xが2のときはlabel3にジャンプする
例)
jump(x-30,label1,label2,...);
// xの値が30ならばlabel1にジャンプ,31ならばlabel2にジャンプする。
※ 範囲外のチェックはしていないので、たとえばジャンプラベルが4つ
しかないのにxが0~3以外の値であった場合の動作は未定義です。
※ ジャンプラベルは、カンマ(,)で区切って、無数に書くことが出来ます。
※ 途中のジャンプラベルは","で省略することが出来ます。
jump(2,label1,,label3,,,label6); // label3に飛ぶ
//////////////////////////////////////////////////////////////////////////////
§1-13 モジュール化の勧め
フェードイン・フェードアウト等、頻繁に使用するものは、関数化して
必要に応じてincludeして使うと良いでしょう。
includeは、プログラムの最初などで、
include "script/fademacro.c"
とすれば、そのファイルがその場所にあるものとしてコンパイルされます。
このincludeするファイルの中で、さらに他のファイルをincludeして行くことも
可能であり、最大で16ファイルまでネスト(ファイルの中で他のファイルをincludeして
そのファイルの中でまた他のファイルをincludeして...という繰り返し)することが
出来ます。
是非、活用してみてください。
//////////////////////////////////////////////////////////////////////////////
§1-14 コンパイルエラーについて
コンパイル中に、何らかのエラーが発生した場合、EXEのあるフォルダに、
CompileError.txt
という名前のテキストファイルが生成されます。その中に、エラー内容が書かれて
います。
実行中の内部的なエラーは、ErrorLog.txtに出力されます。(※ 詳しくは、
イニシャライザについて参照してください)
//////////////////////////////////////////////////////////////////////////////
§1-15 文字列の取り扱いについて
スクリプト中では、文字列は" "(ダブルクォーテーション)でくくった部分を
文字列として扱います。実は、long型以外に、str型というのがあって、文字列を
代入できます。
つまり、
LoadWave("testwav/se01.wav",0);
とやるべきところを、
str x;
x = "testwav/se01.wav";
LoadWave(x,0);
と変数を経由させても可能だということです。
(型チェックはしていないので、str型でなく、long型であっても、これができて
しまうのですが...)
使用する際に、特に意識される必要はないと思いますが、
str x;
alt {
case y==1: x = "testwav/se01.wav";
case y==2: x = "testwav/se02.wav";
case y>=3: x = "testwav/se03.wav";
}
LoadWave(x,0); // yの値に応じて、再生するwavを切り替える
PlayWave(0);
というようなことも可能になってきます。この例でしたら、
alt {
case y==1: LoadWave("testwav/se01.wav",0);
case y==2: LoadWave("testwav/se02.wav",0);
case y>=3: LoadWave("testwav/se03.wav",0);
}
PlayWave(0);
とすれば済むことなので、あまり意味はありませんが、他の関数に文字列を
渡したりできるということを知っていると何かと便利です。
☆ 長い文字列の取り扱い
長い文字列を表示したいときなど、一行に収まらないこともあります。
そういうときは、
long main() {
InnerLogMes("Too" +
"Long"+
"String"+
"Sample");
}
というように、+記号でいくらでもつなげていくことが可能です。
ただし、文字列型の変数に対して+記号が使えるわけではなく、あくまで、
" "(ダブルクォーテーション)で囲まれた文字列同士を+記号でつなげることが
出来るだけですので、ご注意ください。
文字列操作のさらなる操作に関しては、yanestr.dllという文字列操作ライブラリを
ご用意しましたので、そちらご利用ください。
//////////////////////////////////////////////////////////////////////////////
§1-16 メモリ確保
new,delete → これは、C言語のnewとdeleteに似ています。
実行時に配列を確保したいときに使うと良いでしょう。
long* p;
p = new(1000*4); // 4000バイト確保。そのアドレスがpに入る
// これでp[0]~p[999]まで使える。
for(i=0;i<1000;i++) {
p[i] = 5; // 確保したメモリに数字を入れる
}
delete(p); // 使い終わったらdeleteする。
※ 注意すべき点は、確保するのはバイト単位であるということ。
そして、使い終わったらdeleteしなくてはならないということです。
//////////////////////////////////////////////////////////////////////////////
§1-17 DLLファイルの読み込み機能と、その作成手順
DLLファイルとは、実行時に読み込む外部ライブラリのことで、特定目的の関数を
外部から供給できる機構を与えることで、このスクリプトの閉塞性を補おうとする
ものです。
例)
int handle; // ライブラリのハンドル
function func; // 関数ポインタ(functionというのは、実はlongと同義)
handle = LoadLibrary("script/test.dll");
// ライブラリを読み込む(エラーなら0が返る)
func = GetFunction(handle,"test1");
// test.dll内にあるtest1という関数のアドレスを得る(存在しないときは0が返る)
func(1,2,3); // test1を呼び出してみる。(このように変数に括弧をつけると
// 変数の示すアドレスにある関数が呼び出される)
FreeLibrary(handle); // 使用終了後のDLLファイルの解放
備考)
DLLファイルをユーザー側で用意することによって、スクリプトだけでは解決出来ないような
機能を提供することが出来ます。
使用後は必ずFreeLibraryするようにしてください。(終了時はFreeLibraryしなくても
自動的に解放します)
※ DLLを作成される方のために
DLL側の関数は、LONG 関数名(LONG *p);という形でなければなりません。
引数リストを示すポインタがpに入ります。スクリプト側からfunc(1,2,3)のようにして
関数を呼び出したときには、*p == 1,*(p+1) == 2,*(p+2) == 3です。引数の数のチェックを
行なう機構はありません。
※ DLL側サンプル
スクリプトの範囲外なので、あまり深くは説明しませんが、たとえばVC++でならば、
#define DLL_EXPORT extern "C" __declspec(dllexport)
DLL_EXPORT long test1(long*p){
return *p + *(p+1) + *(p+2); // 第一引数、第二引数、第三引数を足したものを返す
}
これで、test1という関数を用意できます。
//////////////////////////////////////////////////////////////////////////////
§1-18 ライブラリのimport
(未サポート。次バージョンでサポート予定)
//////////////////////////////////////////////////////////////////////////////
§1-19 漢字対応
漢字に対応しています。
変数名・関数名に漢字が使えます。
全角スペースは、スペース扱いになります。
//////////////////////////////////////////////////////////////////////////////
§2 ゲーム上で利用できる関数
//////////////////////////////////////////////////////////////////////////////
ここでは、ゲーム上で利用できる関数について書きます。
これらについては、いつでも呼び出しが可能です。
ここに出てくる関数は、特に断りがない限り、実行が成功した時に0,失敗した時に非0を返します。
失敗したかどうかは、それを利用して知ることが出来ます。
例)
if (LoadBitmap("test.bmp",1,1)!=0) {
// 読み込み失敗...
}
ただ、実際のゲームでは、このようなチェックは不要だと思います。
/////////////////////////////////////////////////////////////////
§2-1 WAVE関数
/////////////////////////////////////////////////////////////////
LoadWave("ファイル名",channelNo); // 指定のチャンネルナンバーにWaveを読み込みます。
PlayWave(channelNo); // 指定のチャンネルナンバーのWaveを再生します。
StopWave(channelNo); // 指定のチャンネルナンバーのWaveを停止させます。
PauseWave(channelNo); // 指定のチャンネルナンバーのWaveをpause(一時停止)します。
ReplayWave(channelNo); // 指定のチャンネルナンバーのWaveのpauseを解除します。
IsPlayWave(channelNo); // 指定のチャンネルナンバーのWaveが再生されていれば1
// さもなくば0を返します。
ReleaseWave(channelNo); // 指定のチャンネルナンバーのWaveバッファを解放します。
ReleaseWaveAll(); // すべてのチャンネルナンバーのWaveバッファを解放します
実際の使用例につきましては、サンプルのWaveの再生のところを見てください。
複数チャンネルを同時に再生することも可能です。
チャンネル数は、0~31の32個に設定しています。
もし、必要であれば、もう少し大きな数字にしますが、ことあるごとにLoadWaveすれば良い
と思うので、とりあえず32にしています。
また、LoadWaveすれば、前回LoadWaveで読み込んでいたバッファは自動的に解放してから
新しいWaveファイルがLoadされますので、LoadWaveの直前にReleaseWaveする必要はありません。
SetLoopModeWave(channelNo,bool);
// Waveをループ再生モードに設定します。boolと書いてある部分は、
1ならば、yes,0ならばnoの意味になるということです。
例)
SetLoopModeWave(0,0); // チャンネルナンバー0番はループモードではない。
SetLoopModeWave(0,1); // チャンネルナンバー0番はループモード。
初期状態では、非ループモードです。バッファを次にLoadWaveで読み直すまで
ループモードの設定は有効です。
SetVolumeWave(channelNo,volume); // ヴォリュームを設定する
SetVolumeWaveAll(volume); // 全チャンネルのヴォリュームを設定する
ヴォリューム値は、
減衰なし : 0
無音 : -10000
の間で指定します。初期状態では0です。
※ マスターヴォリュームを変更するのではなく、チャンネルごとに減衰をかけることで
音量設定をしています。
/////////////////////////////////////////////////////////////////
SetWaveFormat(int type); // プライマリサウンドバッファの周波数変更
再生周波数等を変更する。
typeのビット0→0ならばモノラル,1ならばステレオ
ビット1→0ならば8ビット,1ならば16ビット
ビット3,2→ 00ならば11KHz,01ならば22KHz,11ならば44KHz
ディフォルトは、22KHz,16ビット,ステレオなので、0111b = 7である。
このディフォルト値である限りは、DirectSoundを協調モードで使用することが出来る。
これ以外の値である場合は、優先モードで使用しなければならない。(他のソフトからは
DirectSoundを利用できない状態になる)
※ このSetWaveFormatを実行した時点で、CSoundのバッファ内容はすべて解放されます。
※ 読み込むWAVEファイルと、このプライマリサウンドバッファの周波数とが違うと、
読み込んだ後にフォーマット変換を内部的に行なうので、その分、処理に時間がかかります。
/////////////////////////////////////////////////////////////////
§2-2 CDDA関数
/////////////////////////////////////////////////////////////////
OpenCD(); // CDを回転させます。
初期化です。CDを再生するときは、必ずこれを最初に実行してください。
CDがまわります。CDがスタンバイしている状態です。
よって、次のPlayCDで即座(?)に再生することが可能です。
本当は、これを行なわなくてもPlayCD一発で再生することが出来るのですが、
一応、お約束ということで。
CloseCD(); // CDの回転を止めます。CDの使用が終了したときは、
これを呼び出してください。
StopCD(); // 演奏を止めます。回転は止めません。
PauseCD(); // 再生中ならば、いったん停止させます。再生中でないならば何も
起こりません。
ReplayCD(); // PauseCDで停止させたCDの再生を再開します。前回停止させた
ポイントから再生を再開します。
PlayCDFromStart();
// CDをトラック1から再生します。
PlayCD(トラック番号); // CDを指定のトラックから再生します。
PlayCDFromTo(開始トラック番号,終了トラック番号);
IsPlayCD(); // CDが再生中なのかをチェックします。再生中ならば非0を、
さもなくば0を返します。「Isなんとか」という名前の関数は、すべてそのような
仕様になっています。よって、返し値をif (IsPlayCD()) ... としてif文中で
使うことが出来ます。詳しくは、サンプルプログラムのほうを見てください。
GetSongMaxCD(); // CDの総トラック数を取得(CDはOpenCDされていなくてはならない)
EjectCD(bool); // CDメディアをEjectします。
※ この関数を呼び出したときもCloseCDは行なってください。
※ 非0ならば、eject。0ならば、逆ejectです。
SetLoopModeCD(bool);
// CDをループ再生モードに設定します。boolと書いてある部分は、
1ならば、yes,0ならばnoの意味になるということです。
例)
SetLoopModeCD(0); // CDはループモードではない。
SetLoopModeCD(1); // CDはループモードである。
ループモードにするとどうなるかというと、指定された部分の再生が終わったあと、
また指定されていた最初のポイントまで戻って再生を再開するということです。
つまり、PlayCDでトラック指定で再生していた場合なら、そのトラック終了後、
そのトラックの先頭部分に戻って再生を再開。
PlayCDFromToで2トラック間再生をしていた場合、最終トラックが終わったのちに、
最初のトラックに。
PlayCDFromStartの場合であれば、CD全体を再生し終わったら、また先頭から
再生。
というのがループ再生機能です。延々とBGMを流しておきたいときには、
ループモードにしてから再生すると良いでしょう。
初期状態では、再生に関して、ループモードではありません。また、前の設定が残って
いるとも限らないので、再生の際には必ずどちらかに設定するようにしてください。
この関数の発行するタイミングは、CDのOpen前、Open後、再生中、Pause中など、
どこであっても構いません。
また、CloseCDは、ゲーム終了時に必ず行なわれるため、CDをまわしっぱなしに
して、スタンバイさせておくほうが再生までの時間が稼げるという考えから、CloseCD
させずに使用するような方法も考えられます。このようなソフトとしては、アリス
ソフトの戦巫女がありますが、どうもこの方法はCDドライブに負担をかけるため
最近では使用されていないのではないかと思います。(最近のCDドライブならば
シークが速いのでPlayCDすれば、ほとんど即座に再生されるためでしょうか...)
あと、ループ処理は、メッセージ通知のタイミングに行なわれます。
要は、halt;でメッセージ処理したときに、再生停止通知が来てて、さらに
ループモードであれば、ループ再生を行なうわけで、halt;が無いようなプログラムでは
ループ再生しません。
///////////////////////////////////////////////////////////////////////
// 各トラック長さを調べるための変数
SongLengthCD[n] // nはトラックナンバー。0ならば、トータル長さ
SongStartCD[n] // nはトラックナンバー。各曲のスタートポジションを得る
OpenCD();したあと、上の2つの配列にトラックデータが入ります。
GetCurrentPosCD(); // 現在の再生ポジションが入ります。
単位は秒。SongStartCD[]とから、うまく差し引きすれば再生
残り時間を調べることが出来ます。
PlayCDPos(開始位置,終了位置);
GetCurrentPosCDで表される値で再生指定を行なう。
これを使えば、CDの中途半端な位置から、一部だけを再生することが可能。
例)
PlayCDPos(0x0809,0x0a0b);
// CD先頭から9分8分の位置から11分10秒の位置まで再生する
GetCurrentPosCDの値について詳しくは、サンプルにある「CDのカレント
ポジションについて」をご覧ください。
/////////////////////////////////////////////////////////////////
§2-3 プレーン操作(ビットマップ関数)
/////////////////////////////////////////////////////////////////
GetBpp(); // ピクセル当たりのビット数を返します。(Bpp = Bit Per Pixel)
// 256色モードであれば8が,65536色モードであれば16,
// 16777216色モードであれば24,trueカラーならば32が返ります。
例)
if (GetBpp()==8) LoadBitmap("256.bmp",1); else LoadBitmap("fullcolor.bmp");
// 256色モードならば256.bmpを、フルカラーモードであればfullcolor.bmpを
// 読み込みます。
LoadBitmap("ファイル名",プレーンナンバー,パレット初期化);
ビットマップファイルを特定のプレーンナンバーに読み込みます。
プレーンナンバーは、あとで画面に転送するときに必要になってきます。
ビットマップ表示は、何番のプレーンをどこそこに移動させないという形式で
指定するからです。
プレーンナンバーは、0番から127番の128枚に設定しています。
パレット初期化の部分は、読み込んだビットマップファイルのパレットを
画面に反映させるのかを指定するためのものです。
(非0ならば、反映させる。0ならば反映させない)
256色モード以外では無視されます。
通常使用であれば、「反映させる」にしてください。
※ ただし、この後、RealizePaletteを実行しないと、反映されません。
反映させない場合、現在のパレットを見ながら、適切な色に割り当てて
読み込まれます。これは、どういうときに使用するかというと、たとえば
モノクロビットマップファイルを読み込むような場合にです。パレットを
「反映させる」にしてしまうと、現在のパレットが潰れてしまうため、
困るからです。
使用例)
LoadBitmap("test.bmp",2,1); // test.bmpを2番のプレーンに読み込み、
// そのパレットを反映させる
LoadBitmapW("256色ファイル名","非256色ファイル名",プレーンナンバー,パレット初期化);
これは、256色モードのときと、非256色モードのときとで読み込むファイルを
違うものにしたいときに使用します。その他は、LoadBitmapと同じです。
GetBpp()を使用してもこれと同じことが出来そうですが、この関数を使用しておけば、
表示中に画面モードが切り替わった場合、自動的にその画面モードに合ったビットマップ
ファイルを読み直しに行くので、都合が良いです。
使用例)
LoadBitmap("test256.bmp","testFullColor.bmp",2,1);
ReleaseBitmap(プレーンナンバー);
プレーンナンバーに読み込んでいたビットマップを解放します。
スクリプトから抜けるときや、新しいビットマップを読み込むときは、
自動的に解放しますので、明示的に呼び出す必要はありませんが、しばらく使わないことが
わかっているプレーンは、この関数でビットマップを解放しておくとメモリを圧迫しなくて
済みます。(Waveのときと同じです)
SetColorKeyRGB(プレーンナンバー,Rの値,Gの値,Bの値);
カラーキー(透過キー。ヌキの色指定。転送のときに、指定した色だけは転送されない)を
設定します。R,G,Bの値で設定します。R,G,Bは、各256段階(0~255)で指定します。
256色モードでも、うまく動作します。
一つのプレーンに対して、複数のカラーキーは設定できません。
一つのプレーンに対して2度実行すると、前回のものは破棄されます。
別のプレーンであれば、別のカラーキーを設定することができます。
カラーキーを設定していても、それを転送の際にそれを無視して転送することも出来ます。
詳しくは、Blt関数を参照してください。
SetColorKeyPos(プレーンナンバー,x,y); // (x,y)の点を透過キーに設定する
こちらは、色ではなく位置でカラーキーを設定します。
ビットマップの左上ならば(0,0)です。
その他仕様はSetColorKeyRGBと同じです。
SetColorKeyRGBかSetColorKeyPosのどちらでも設定することが出来ますが、ひとつのプレーンに
対するカラーキーは、つねに一つですので、以前の設定は、新しくこれらの関数が呼び出された
時点で破棄されます。
GetPlaneSize(プレーンナンバー,&x,&y); // プレーンのサイズを取得します。
例)
long x,y;
GetPlaneSize(0,&x,&y); // xとyに0番プレーンのサイズが入る
SaveBitmap(保存ファイル名,プレーンナンバー,x,y,sx,sy); // プレーンをファイルに保存する。
プレーンのある矩形範囲をファイルに保存します。セカンダリプレーンを保存する必要が
ある場合は、SwapToSecondaryと組み合わせてご使用ください。
// 矩形転送
Blt(プレーンナンバー,dx,dy); // プレーンまるごと転送(透過キー有効)
BltRect(プレーンナンバー,dx,dy,sx,sy,hx,hy); // 矩形領域の転送(透過キー有効)
BltFast(プレーンナンバー,dx,dy); // プレーンまるごと転送
BltFastRect(プレーンナンバー,dx,dy,sx,sy,hx,hy); // 矩形領域の転送
BlendBlt(プレーンナンバー,dx,dy,ar,ag,ab,br,bg,bb); // ブレンド機能つきプレーンまるごと転送
BlendBltRect(プレーンナンバー,dx,dy,sx,sy,hx,hy,ar,ag,ab,br,bg,bb); // ブレンド機能つき矩形領域の転送
EnableBlendColorKey(プレーンナンバー,b); // ブレンドbltのカラーキーを有効にする 1=有効 0=無効(初期値)
// 転送先クリップ機能つき
ClipBlt(プレーンナンバー,dx,dy,cx,cy,chx,chy); // プレーンまるごと転送(透過キー有効)
ClipBltRect(プレーンナンバー,dx,dy,sx,sy,hx,hy,cx,cy,chx,chy); // 矩形領域の転送(透過キー有効)
ClipBltFast(プレーンナンバー,dx,dy,cx,cy,chx,chy); // プレーンまるごと転送
ClipBltFastRect(プレーンナンバー,dx,dy,sx,sy,hx,hy,cx,cy,chx,chy); // 矩形領域の転送
ClipBlendBlt(プレーンナンバー,dx,dy,cx,cy,chx,chy,ar,ag,ab,br,bg,bb); // プレーンまるごと転送(透過キー有効)
ClipBlendBltRect(プレーンナンバー,dx,dy,sx,sy,hx,hy,cx,cy,chx,chy,,ar,ag,ab,br,bg,bb); // 矩形領域の転送(透過キー有効)
読み込んだプレーンを表示するためのものです。
(dx,dy)転送先座標 (sx,sy)転送元座標 (hx,hy)転送元矩形サイズ
(cx,cy)転送先クリッピングの座標 (chx,chy)転送先クリッピングの矩形サイズ
(ar,ag,ab),(br,bg,bb)ブレンド比率。
関数名になんとかRectと付いているものは、転送元のプレーンの矩形領域を指定できると
いうものです。これのついていないものは、プレーン全体がそのまま転送されます。
関数名になんとかFastと付いているものは、透過キーは無効型の転送です。
転送先が、画面外に差し掛かっていた場合でも、クリッピングしてうまく転送できます。
転送先は、画面外の値でも構いません。
逆に、転送元は、プレーンの範囲外に差し掛かっているとうまく転送できません。
これは仕様です。
Clipなんとかで始まるのは、転送先クリッピング機能つきの転送です。
Clipのついていないものと同等の機能を転送先クリッピング機能つきで提供します。
Clipのついていないものよりパラメータは4つ増えています。これは、クリップする
矩形領域の開始座標、その矩形サイズを指定するためのものです。
(詳しくは描画サンプル9をご覧ください)
Blendなんとかとついているものは、ブレンド機能つきの転送です。
(これに限り256色モードは非対応)
RGBごとにブレンド比率を指定してバックバッファ(裏画面)とブレンドしながら
転送します。描画サンプル11にそのサンプルがあります。
バックバッファの減衰率(ar,ag,ab)に対して、プレーン側の減衰率(br,bg,bb)で
ブレンドします。(ar,ag,ab)は、バックバッファを減衰させる率をR,G,Bごとに
指定できます。0~256の257段階で指定します。
※ ブレンド機能は、ビデオカードによっては、SetBrightnessと同じく、
SystemMemoryを利用するモードになっていないと非常に遅いです。この関数を
リアルタイム性の要求されるような場所(60FPS必要な場所など)で使用
するのは疑問です。
※ 今回のゲームでメッセージ表示部等に、この機能を使いたかったのですが、
256色対応は難しいので、次回、ハイカラー以上専用のゲームを作るときに
しましょうか。
☆ 拡大縮小系bltについて
※ 上で示した転送系の命令は、BltならばBltRというように、関数の最後にRを
追加したバージョンが存在します。これは、拡大縮小機能つきです。
もとの関数より、引数が二つだけ多く、その最後のパラメータで拡大縮小率を
指定します。(横方向と縦方向の倍率を別個に指定します)
拡大縮小率は、65536で等倍です。65536/2ならば50%、65536*2ならば200%での
表示になります。
<注意>
プレーンのサイズには(DirectDraw側の)制限があって、640×480が上限です。
これ以上のビットマップを2画面スクロールのようにしたい場合、2つのプレーンを
用意してやる必要があります。描画サンプル10に、それがあります。
ClearSecondary();
背景(セカンダリプレーン)をクリアします。
ClearSecondaryRect(int x,int y,int sx,int sy);
背景(セカンダリプレーン)の、指定された矩形領域をクリアします。
SetFillColor(fillcolor);
ClearSecondaryでの背景塗りつぶし色を設定します。
fillcolor = 0; // 黒
fillcolor = 0xffffffff; // 白
(これらの色以外は、どうなるのか私もよくわかりません...256色モードでは
うまく設定できないようなので、黒・白以外は使わないということでお願いします。
その他の色で塗りつぶす必要が生じた場合は、ClearSecondaryは使用せずに、
32×32程度のビットマップを用意して、それを画面全体にBltFastすることで
クリアすると良いと思います)
→ 上のSetFillColorでは、色が指定できないのでRGBで色を指定できる関数を追加
しました。
SetFillColorRGB(red,green,blue); // RGBそれぞれ256段階で指定する。
※ 256色モードのときは、この関数を実行する瞬間にパレットが
リアライズされていることが前提となります。
/////////////////////////////////////////////////////////////
描画手順は、
1.ClearSecondary(); で背景をクリア
2.Bltなんたら(); で、LoadBitmapで読み込んでおいたプレーンを転送
3.すべて転送し終わったら、描画のためhalt(haltの説明を見てください)
という3手順から成ります。
haltが必要なわけは、bltではチラつきをなくすため、裏画面に転送しているからで、
それを表画面に一気に転送するのがhaltというわけです。
あとは、実際の描画のサンプルをご覧になってください。
/////////////////////////////////////////////////////////////////
§2-4 画面効果
/////////////////////////////////////////////////////////////////
ここでは、画面上に入れることが出来るさまざまな画面効果について
説明します。
§2-4-1 フェイドイン/フェイドアウト等
SetBrightness(明るさ);
画面の明るさ(フェードアウトのための減衰率)を設定します。
0~256の257段階で指定します。
0ならば、完全に黒。256であれば、もとのままの色となります。
256色モードであれば、ハードウェアパレットを使用します。
それ以外であれば、ソウトウェア的に再現するため、とても遅いです。
ビデオカードの種類によってはね次の関数を使っていない場合、
3FPSぐらいにまで落ち込むかも知れません。
使用後は、必ずSetBrightness(256);として、もとの明るさにするように
してください。
また、256色モード以外では、haltした瞬間に、裏画面に対して
色の減衰を行なうので、裏画面は、減衰された絵になります。
よって、SetBrightnessで256以外を指定して減衰を開始させている場合、
次のhaltまでに裏画面を再描画することを忘れてはいけません。
実際の使用例は、描画サンプル6.と7.をご覧になってください。
SetSystemMemoryUse(0か1); // 0ならばビデオメモリ 1ならばシステムメモリ
プレーンをビデオカードメモリではなくシステムメモリに読み込みます。
LoadBitmapより前に行なってください。これを行なうと、多色モードで
SetBrightnessを行なうと異様に遅かったビデオカードでも20~30FPSという
数字が出ます。
ただし、ユーザー側が、ゲームオプションで描画にシステムメモリを使用しない
を選んでいる場合は、これをやっても変更されません。逆に、システムメモリを
常時使用する設定にしている場合、SetSystemMemoryUse(0);としても無視されます。
システムメモリでの描画は、ビデオカードのハードを利用できないので、
ハードウェアで描画するときの80%程度の速度(ビデオカードによっては
大差が出ることもあります)しか出ませんが、フェードイン/フェードアウト
技術とは切っても切れないものだと思います。
スクリプト終了後、自動的にこの設定は、もとの設定に戻ります。
/////////////////////////////////////////////////////////////////
※ 256色モードでの明るさの変更について
256色モードでは、いくつか注意すべき点があります。
RealizePalette(プレーンナンバー); // このプレーンのパレットをリアライズ!
この関数を使用して、そのプレーンナンバーのパレットをリアライズします。
リアライズとは、実現すること、ここでは実際に画面に反映させることを意味します。
LoadBitmapでプレーンにビットマップを読み込んだ直後にこの関数を呼び出します。
読み込むビットマップは、256色のビットマップでなければなりません。
(LoadBitmapWで読み込むのであれば、このへん注意しなくて済みますが)
こうしておいてはじめて、そのプレーンのパレットが、SetBrightnessを
使うときに使用されます。
少しややこしいですが、まとめると、こうです。
1.256色モードでのSetBrightnessを利用するには、256色のビット
マップファイルが必要(パレットのみのファイルでも構いません)
2.その256色のビットマップをLoadBitmapでプレーンに読み込んだあと、
RealizePaletteする必要がある。
の2点です。
FlushPalette(); // Paletteをフラッシュする
☆ パレットをリアライズするタイミングについて
256色モードでは、パレットはハードウェアパレットで、
画面描画の直後にリアライズ(実現)を行ないます。
画面描画前にやってしまうと、いま画面にあるものに対して影響を
受けてしまうからです。
しかし、フェードインするような場合、事前にパレットがリアライズされて
いないと、これからフェードインしようとしているものが見えてしまい、
困ることがあります。そこで、いますぐパレットを実現する、というような
場合、FlushPalette();とします。いますぐSetBrightness等で設定した値に
従ってリアライズされます。
バックアッププレーンのサンプルにそういう処理があるので、そちらも
ご覧になってください。
/////////////////////////////////////////////////////////////////
§2-4-2 画面のフラッシュ(色の反転)
/////////////////////////////////////////////////////////////////
FlushBlt(プレーンナンバー,x,y,sx,sy);
プレーンナンバーは、プレーンナンバーを指定します。→§2-3参照
x,yは開始座標、sx,syはサイズを指定します。
この関数を実行すると、プレーンのある領域の色(ネガポジ)が反転します。
※ ただし256色モードでは、パレットの関係上、色の正しい色の
反転ではありません。
セカンダリに対して行ないたいときは、以下のようにやります。
例)
SwapToSecondary(10); // セカンダリプレーンを、ダミーでプレーン10と入れ替える
FlushBlt(10,100,100,200,100); // プレーン10に対してフラッシュ操作を行なう
SwapToSecondary(10); // 戻す
※ 上記の例では、プレーンナンバー10を確保しておく必要はありません。
また、このときプレーンナンバー10は、何の副作用も受けません。
※ 画面のフラッシュには結構時間がかかるので、速度が要求されるような
シーンで行なうのはお勧めできません。
/////////////////////////////////////////////////////////////////
§2-4-3 画面のモザイク
/////////////////////////////////////////////////////////////////
MosaicBlt(プレーンナンバー,x,y,sx,sy,d);
プレーンナンバーは、プレーンナンバーを指定します。→§2-3参照
x,yは開始座標、sx,syはサイズを指定します。
dは量子化レベルを指定します。(たとえばd=5ならば、(x,y,sx,sy)で指定
した矩形が、5*5のサイズの単色の矩形にモザイクされます)
この関数を実行すると、プレーンのある領域にモザイクがかかります。
セカンダリに対して行ないたいときは、以下のようにやります。
例)
SwapToSecondary(10); // セカンダリプレーンを、ダミーでプレーン10と入れ替える
MosaicBlt(10,100,100,200,100,5); // プレーン10に対してフラッシュ操作を行なう
SwapToSecondary(10); // 戻す
※ 上記の例では、プレーンナンバー10を確保しておく必要はありません。
また、このときプレーンナンバー10は、何の副作用も受けません。
※ 画面のモザイクには結構時間がかかるので、速度が要求されるような
シーンで行なうのはお勧めできません。
/////////////////////////////////////////////////////////////////
§2-4-4 セカンダリの転送オフセット
/////////////////////////////////////////////////////////////////
セカンダリプレーンは、haltした瞬間にプライマリプレーンに転送される
のですが(§3-2参照)、このとき、一定量ずらして転送することが
出来ます。連続的にこれを行なうことにより、画面を揺らすような効果を
与えることが出来ます。
SetSecondaryOffset(OffsetX,OffsetY);
例)
SetSecondaryOffset(10,20);
// 画面左端から(10,20)だけずれた場所にセカンダリプレーンをbltする。
使用後は、かならず
SetSecondaryOffset(0,0);
をするようにしてください。
また、転送先をずらしたため、画面(ウィンドゥモードならば窓内部)に
生じる空洞の空間は、自動的にSetFillColorで指定された色で塗りつぶされます。
/////////////////////////////////////////////////////////////////
§2-5 バックアッププレーン(フェードイン/フェードアウト等のアシスト関数)
/////////////////////////////////////////////////////////////////
EnableBackupPlane(); // バックアッププレーンの使用開始
DisableBackupPlane(); // バックアッププレーンの使用終了
BltFromBackupPlane(); // バックアッププレーンからのBlt
SnapToBackupPlane(); // バックアッププレーンに、セカンダリの内容を保存
SaveBackupPlane(ファイル名); // バックアッププレーンの内容を
// ビットマップファイルとして保存
フェードイン・フェードアウトのときなど、いちいちすべての画面要素を
Bltして、haltするようなループを作るのでは、結構、面倒です。
そこで、いまの画面内容をそのまま別のところに保存しておき、一発でそれを
表示しようというのがバックアッププレーンの考えかたです。
実際、これらの関数を使用して、フェードイン・フェードアウトの汎用的な
関数を作ることが出来ます。(バックアッププレーンのサンプル参照のこと)
まず、使用するためには、バックアッププレーンを使う前に、
EnableBackupPlane();
として、終了後は、
DisableBackupPlane();
とします。(バックアッププレーンは、画面サイズ分のメモリを必要としますので、
多色モードでは、ビデオメモリ(あるいはシステムメモリ)を圧迫します。
使い終わったら、即座にDisableBackupPlane();で解放しましょう)
まず、EnableBackupPlane();したあと、普通に、ClearSecondary()からBlt等を
使って、セカンダリ(裏画面)を構築します。その後、
SnapToBackupPlane();
と一度やったあと、halt;します。すると、本来ならば、裏画面が表画面に転送される
はずが、裏画面が、バックアッププレーンに転送されます。これが、仕掛けその1です。
その後、必要なタイミングで、BltFromBackupPlane();とすれば、バックアッププレーンの
内容がまるごと裏画面に転送されるという仕掛けです。(よって、このときClearSecondary();
する必要はありません) あとは、halt;するだけで、それが表示されるのです。
実際に、バックアッププレーンを用いて、フェードイン・フェードアウトのアシスト関数を
用意しましたので、そちらも活用してください。
※ 注意
バックアッププレーンからBltFromBackupPlane();したのちにhaltするとき、
何らかのLayerを使用していると、haltのときに、それも表示されてしまうことになるので、
BltFromBackupPlaneするときは、Layerはオフにしておくようにしましょう。
※ バックアッププレーン使用上の注意
バックアッププレーンは、画面解像度切り替え時に、潰れてしまいます。
これは、DirectDraw側の仕様なので仕方ありません。画面解像度を切り替えられて
潰れてしまってまずいような場所でバックアッププレーンは使うべきでないと言えます。
”潰れた”バックアッププレーンをBltFromBackupPlane();した場合、ClearSecondary();と
同じ効果が得られます。(こうしてあるから、最悪でも、画面がぐちゃぐちゃになる
可能性はありません)
例)バックアッププレーンを利用して、現在の画面をビットマップファイルに保存する
EnableBackupPlane();
SnapToBackupPlane();
halt;
SaveBackupPlane("画面写真01.bmp");
DisableBackupPlane();
ゲーム内容によっては、使えるかも知れませんね。
※ 単に現在のプレーンをビットマップに保存するにはSaveBitmapが使えます。
また、現在の表示されている画面を保存するならば、SwapToSecondaryとSaveBitmapを
組み合わせます。
/////////////////////////////////////////////////////////////////
§2-6 セカンダリプレーンを他プレーンと入れ換える機能
/////////////////////////////////////////////////////////////////
ブレンド系のblt等は非常に時間がかかるので、事前に別のプレーンにbltしておければ
良いのに…と思いながらも、転送先は、セカンダリプレーン固定なので、それならば
一時的にセカンダリプレーンと他のプレーンとを入れ替えてしまう機能をつければどうか
と思ったわけです。
SwapToSecondary(プレーンナンバー);
がそれで、一度実行すると、そのプレーンがセカンダリプレーンと入れ替わります。
その状態にして、がしがしBltします。そして、転送が終わったら再度SwapToSecondary()
を呼び出して、もとに戻します。非常に便利です。セカンダリプレーンから、他の
プレーンに転送したいときなども、これを使用することが出来ると思います。
ただし、SwapToSecondaryして、プレーンと入れ替えているときにhaltで描画はしないで
ください。フルスクリーンモードで、うまく動かないはずですので。
CreateSurface(プレーンナンバー,X方向サイズ,Y方向サイズ);
SwapToSecondary()でセカンダリプレーンと入れ替えるのですが、その入れ換える
プレーンは、“事前”に大きさを決めて確保しておかなくてはなりません。それが、この
CreateSurfaceです。解放するときは、ReleaseBitmap(プレーンナンバー);で解放して
ください。
例)
LoadBitmap("script/MapBitmap.bmp",0,1);
CreateSurface(3,200,300); // サイズは200*300で確保
SwapToSecondary(3);
Blt(0,0,0); // これは、プレーン0から3への転送を意味する
SwapToSecondary(3);
また、DirectDrawの制限により、現在のスクリーンサイズより大きなサーフェースは
動作保証外になっています。640*480の画面である場合、640*640等の縦長の画面は、
たいていうまく動くようですが、ビデオカードによっては動かない等が考えられるの
で、使用しないほうが無難でしょう。
/////////////////////////////////////////////////////////////////
§2-7 タイマー管理関数
/////////////////////////////////////////////////////////////////
SetFPS(fps値); // FPSの設定
FPS(Frame Par Second = 秒間のフレーム数)の値を設定します。
例)
SetFPS(30); // 30FPSに設定します。
i = 0;
loop {
halt; // 画面描画
i = i + 1; if (i>=30) break; // 30回回る
}
のようなプログラムがあれば、このループは1秒で抜けることになります。
SetFPSで設定された値にFPSがなるように、haltで画面描画をしたあとに
ウェイトが入るからです。
逆に、画面描画等に時間がかかって、このFPSを守れないこともあります。
よって、このSetFPSで設定された値というのは、FPS上限値だとお考え下さい。
動きの少ないビジュアルシーンなどであれば、遅いマシーンのことを考慮して
低いFPS値を設定するようなことも考えられます。
あるいは、一時的にSetFPS(3);などとして、一枚転送するごとにhaltを掛けて
表示するようなことも考えられます。いろいろ活用してみてください。
GetFPS(); // FPSの取得
SetFPSで設定された値を取得します。
GetRealFPS(); // FPSの取得(測定値)
実際のFPS測定値を取得します。過去16回分の描画の平均です。
SetFPSが行なわれた直後は、16回描画されるまで0を返します。
ResetTime(タイマー番号); // 内部タイマーをリセットします。
GetTime(タイマー番号); // 内部タイマーの値を得ます
GetTimeは1ms秒(1秒=1000ms秒)単位の高精度タイマーの値を返します。
ResetTimeは、このタイマーを0にリセットします。つまり、その直後ならば、
GetTimeの値は0です。
タイマー番号は、0~15までの16個用意しています。
例)3秒待つ
ResetTime(0); // 0番のタイマーをリセット
loop {
halt;
if (GetTime(0)>=3000) break;
// 0番のタイマーが3000を超えていれば脱出
}
PauseTime(タイマー番号); // 内部タイマーをPauseします
RestartTime(タイマー番号); // 内部タイマーをPauseを解除する
PauseTimeAll(); // すべての内部タイマーをPauseします。
RestartTimeAll(); // すべての内部タイマーのPause解除します。
/////////////////////////////////////////////////////////////////
§2-8 FPS表示機能
/////////////////////////////////////////////////////////////////
FPSLayerOn(x,y); // FPSカウンタをx,yの座標に表示します。
FPSLayerOff(); // FPSカウンタを非表示にします。
使用例は、描画のサンプル4にあります。
SetFPSと組み合わせて、どれだけのFPSが出てているのかを
確認するのに使うと良いでしょう。
/////////////////////////////////////////////////////////////////
§2-9 文字列表示関数
/////////////////////////////////////////////////////////////////
※ 文字列を取り扱いますので、同時に、「文字列」の項目もご覧ください。
// 必須
TextLayerOn(n,x,y); // 文字列ボックスnを(x,y)の座標に設定します。
TextLayerOff(n); // 文字列ボックスを非表示にします。
TextOut(n,文字列); // 文字列ボックスnに、文字列を表示します。
TextMove(n,x,y); // 文字列ボックスnを(x,y)の座標に移動させます。
// 文字列の属性設定
TextSize(n,サイズ); // 文字列ボックスnに表示する文字の初期サイズを設定します。(初期値16)
TextHeight(n,サイズ); // 文字列ボックスnの、次の行までのドット数(初期値:20)
TextColor(n,R,G,B); // 文字列ボックスnに表示する文字の色を設定します。
TextBackColor(n,R,G,B); // 文字列ボックスnに表示する文字に影を付けます。
TextBacKColorDisable(n); // 文字列ボックスnに表示する文字の影を無効にする。
// 次にTextBackColorを使用するまで有効
TextBlend(n,ブレンド比率); // 文字列ボックスnはブレンド表示します。
使用方法は、FPS表示関数に似ています。
順を追って説明します。
1.文字列を表示するためには、まず文字列ボックスを有効にします。
具体的には、
TextLayerOn(1,100,200); // 文字列ボックス1を(100,200)の座標に設定する。
2.このようにしてから、文字列ボックスに対してメッセージを送ります。
TextOut(1,"こんにちは"); // 文字列ボックス1に「こんにちは」と表示されます。
3.使い終わったら、
TextLayerOff(1); // 文字列ボックス1は使用終了
とします。
初期状態では、影ありで、文字色=RGB(255,255,255),影=(128,128,128)に
なっています。この設定が案外見やすいと思いますがいかがでしょうか。
☆ 文字列ボックスについて
文字列ボックスは、0~63の64個用意しています。それぞれの文字ボックスごとに異なった
文字属性、表示位置情報を持つことが出来ます。(普段は、1つしか使わないかも知れませんね)
☆ 文字列の色指定について
R,G,Bカラーで指定できます。
例)
TextColor(2,15,255,255); // 文字列ボックス2に表示する文字の色は、RGB = (15,255,255)
この色設定は、フェードイン/フェードアウト関数の影響を受けます。
(受けるようにしてあります)
文字を表示したまま、フェードアウト、あるいは、フェードインさせることが出来ます。
色は、RGBで指定しますが、256色モードで、その色が存在しない場合は、近くの色を選ぶように
なっています。ご注意ください。
☆ なんとかLayerについて
FPSLayerと同じく、なんとかLayerとなっているものは、いったん表示を宣言すると、
haltでの表示ごとに自動的に描画されます。(それ以外のものは、再描画されないので
モーションごとにbltで自前で再転送してやる必要がある) それが、大きな利点です。
実際に、文字列表示のサンプルと、ビットマップ表示のサンプルとを見比べてください。
☆ 改行について
改行表示は、\nで可能です。詳しくは、サンプルの文字出力をご覧ください。
TextHeightで設定した分だけ、行間を空けます。(その行と次の行とのy方向のドット数
なので、厳密には行間とはまた違うのですが...)
☆ 文字列の途中で色や文字サイズを変更するには?
途中での変更はできません。別の文字列ボックスを用意して実現します。
ただ、Windowsの特性上、希望する文字フォントが確実にあるとは限らず、
フォントの横幅が環境によって微妙に違うことがあるようです。(仕様の上では)
☆ 表示するメッセージの中に数字等を埋め込むには?
文字列操作関数を利用すれば可能です。
文字列操作関数と、そのサンプルを参照してください。
注意:数値変数(long型)を直接表示することは出来ません。
sprintf(string[0],"%d",x);
TextOut(0,string[0]);
のように、いったんstringに入れてから表示するようにしてください。
☆ 文字フォント選択機能について
文字フォントが95とNTで異なる(ディフォルトフォントが異なるため、
大きな文字にしていると横幅がかなり違ってくるようです)→MS ゴシックを
ディフォルトと変更しました。
TextLayerの文字フォントを変更するには、次の関数を使います。
TextFont(n,フォント); // 文字列ボックスnのフォントを変更する。
フォントの部分は、
0ならばMS ゴシック(ディフォルト)
1ならばMS Pゴシック
2ならばMS 明朝
3ならばMS P明朝
あるいは、"極太POP体"というようにフォント名を文字列で指定することも
出来ます。(ただし、そのマシンにインストールされていない場合、その
動作は未定義なので気をつけてください)
☆ 行の高さについて
文字フォントのサイズを指定すると、その瞬間にTextHeight(); をその値で
呼び出します。つまり、フォントサイズ=30に設定すれば、次の行までの
サイズも30として設定します。これが気にいらなければ、TextSizeの直後に
TextHegihtで、行の高さを設定するようにしましょう。
☆ 文字列のブレンドについて
TextBlend(n,ブレンド比率);で指定するブレンド比率は0-256で、0ならば
何も表示されず、256ならば文字が普通に表示されるという状態です。ぼわっと
出現させるには、0から開始して、256に持っていくような感じです。ブレンド
なのでかなりマシンパワーを消費します。また、HIGHカラー以上のモードでしか
ブレンド機能は使えないので、256色モードでこの機能を使ったときの動作は、
保証外です。
☆ 文字列を直接描画する機能
TextLayerは、Layerであって、haltした瞬間にしか描画されません。
バックアッププレーンや、SwapToSecondary()などと絡めて、いますぐ文字を
描画したい!ってこともあります。そういうときには、
TextBlt(n); // 文字列ボックスnをいますぐ描画します。
を使ってください。いますぐそのテキストボックスが描画されます。
☆ 文字列の大きさを取得する機能
センタリングしようとしたりするとき、文字列の大きさがわからないと困り
ますよね。そこで、
TextGetSize(n,&x,&y); // 文字列ボックスnの横幅、高さを取得します。
とすることによって、xとyに文字列ボックスの横幅、高さが取得できます。
文字列は複数行に渡っている場合でも、正しく取得できます。
/////////////////////////////////////////////////////////////////
§2-10 文字列操作関数
/////////////////////////////////////////////////////////////////
変数stringというのを用意しました。文字列バッファ配列です。
文字列操作のサンプルを見ていただいたほうが早いかも知れません。
要は、string[0]からstring[15]までの16個の文字列を扱えるという
ことです。それぞれは、512バイト(=全角で256文字)まで代入する
ことが出来ます。
strcpy(文字列代入先,文字列代入元); // 文字列をコピーします。
strncpy(文字列代入先,文字列代入元,コピーする文字数); // 文字列をn文字コピーします。
// (改行,漢字は1文字と数える)
strcat(文字列代入先,文字列代入元); // 文字列を追加します。
※ strncpyの返し値は、文字列代入元がコピーする文字数と同じか満たなかった場合、非0です。
これを利用して、非0が返ってくるまでコピーする文字数をどんどん増やしていくように
使えば便利です。
例)
void main(){
long n;
n = 0;
loop {
if (strncpy(string[0],"これを順番にコピーしていくのだ",n)) break;
InnerLogMes(string[0]);
n = n + 1;
}
}
sprintf(文字列代入先,出力文字列,パラメータ1,パラメータ2,パラメータ3,...);
これは、文字列中に数字を埋め込んだりするのに使います。
出力文字列中に、以下のような特殊な文字が現れると、その部分に
パラメータ1,パラメータ2,パラメータ3と順番に埋め込まれます。
%d => パラメータが数字として埋め込まれます
%s => パラメータが文字として埋め込まれます
%.2d => パラメータを2桁の数字として埋め込みます
(2の部分はいくらにでも変更可能)
%x => パラメータを16進数で埋め込み
%.4x => パラメータを16進数4桁で埋め込み
実は、この他にもC言語の出力書式をすべてそのまま使用できます。
ゲームで使用できそうなものは、上のいくつかに限られてきそうなので
ここでは割愛させていただきます。
※ さらに高度な文字列操作は、yanestr.dllとして、DLL形式で
ご用意していますので、そちらをご利用ください。
/////////////////////////////////////////////////////////////////
§2-11-1 キー入力関連(キーボード)
/////////////////////////////////////////////////////////////////
KeyInput(); // このタイミングでキー入力を行ないます。
IsPressUpKey(); // 現在上キーが押されているかを判定します。
IsPressDownKey(); // 現在下キーが押されているかを判定します。
IsPressLeftKey(); // 現在左キーが押されているかを判定します。
IsPressRightKey(); // 現在右キーが押されているかを判定します。
IsPressReturnKey(); // 現在Returnキーが押されているかを判定します。
IsPressSpaceKey(); // 現在Spaceキーが押されているかを判定します。
IsPressEscKey(); // 現在ESCキーが押されているかを判定します。
IsPushUpKey(); // 前回から上キーが押されているかを判定します。
IsPushDownKey(); // 前回から下キーが押されているかを判定します。
IsPushLeftKey(); // 前回から左キーが押されているかを判定します。
IsPushRightKey(); // 前回から右キーが押されているかを判定します。
IsPushReturnKey(); // 前回からReturnキーが押されているかを判定します。
IsPushSpaceKey(); // 前回からSpaceキーが押されているかを判定します。
IsPushEscKey(); // 前回からESCキーが押されているかを判定します。
これらは、押されていれば非0,押されていなければ0が返ってきます。
IsPress系とIsPush系との違いは、前者がリアルタイム情報にあるのに
対して、後者は、前回のKeyInputを実行したときから、今回のKeyInputを
実行したまでの期間にキーが押し下げられたか(=すなわち前回時点では
押されていなくて、今回の時点で押されているか)という情報になります。
キーの同時押しも検出できます。
また、これらの関数は、最終、joystickにも対応させたいので、普通の文字キー
入力に対しては、非対応にしておきます。(必要ならば追加します)
KeyInputの呼出しは、haltを一回行なう間に1回実行するように
心がけてください。それ以上のタイミングで呼び出すと、正常に
キー入力がされない可能性があります。
上・下・左・右キーは、2・4・6・8キーでも代用可能です。
Z=スペース,X=リターンでも代用可能です。
// おまけ
IsPushKey(キーナンバー);
IsPressKey(キーナンバー);
キーボードの一般的なキーに対して入力を行ないます。キーナンバーは、
Dinput.hで定義されているコードです。以下に抜粋します。この右側の値を
使って、
if (IsPushKey(0x0C)) { ... // マイナスキーが押された
という風に判定します。
//////////////////////////////////////////////////////////////////////////////
#define DIK_ESCAPE 0x01
#define DIK_1 0x02
#define DIK_2 0x03
#define DIK_3 0x04
#define DIK_4 0x05
#define DIK_5 0x06
#define DIK_6 0x07
#define DIK_7 0x08
#define DIK_8 0x09
#define DIK_9 0x0A
#define DIK_0 0x0B
#define DIK_MINUS 0x0C /* - on main keyboard */
#define DIK_EQUALS 0x0D
#define DIK_BACK 0x0E /* backspace */
#define DIK_TAB 0x0F
#define DIK_Q 0x10
#define DIK_W 0x11
#define DIK_E 0x12
#define DIK_R 0x13
#define DIK_T 0x14
#define DIK_Y 0x15
#define DIK_U 0x16
#define DIK_I 0x17
#define DIK_O 0x18
#define DIK_P 0x19
#define DIK_LBRACKET 0x1A
#define DIK_RBRACKET 0x1B
#define DIK_RETURN 0x1C /* Enter on main keyboard */
#define DIK_LCONTROL 0x1D
#define DIK_A 0x1E
#define DIK_S 0x1F
#define DIK_D 0x20
#define DIK_F 0x21
#define DIK_G 0x22
#define DIK_H 0x23
#define DIK_J 0x24
#define DIK_K 0x25
#define DIK_L 0x26
#define DIK_SEMICOLON 0x27
#define DIK_APOSTROPHE 0x28
#define DIK_GRAVE 0x29 /* accent grave */
#define DIK_LSHIFT 0x2A
#define DIK_BACKSLASH 0x2B
#define DIK_Z 0x2C
#define DIK_X 0x2D
#define DIK_C 0x2E
#define DIK_V 0x2F
#define DIK_B 0x30
#define DIK_N 0x31
#define DIK_M 0x32
#define DIK_COMMA 0x33
#define DIK_PERIOD 0x34 /* . on main keyboard */
#define DIK_SLASH 0x35 /* / on main keyboard */
#define DIK_RSHIFT 0x36
#define DIK_MULTIPLY 0x37 /* * on numeric keypad */
#define DIK_LMENU 0x38 /* left Alt */
#define DIK_SPACE 0x39
#define DIK_CAPITAL 0x3A
#define DIK_F1 0x3B
#define DIK_F2 0x3C
#define DIK_F3 0x3D
#define DIK_F4 0x3E
#define DIK_F5 0x3F
#define DIK_F6 0x40
#define DIK_F7 0x41
#define DIK_F8 0x42
#define DIK_F9 0x43
#define DIK_F10 0x44
#define DIK_NUMLOCK 0x45
#define DIK_SCROLL 0x46 /* Scroll Lock */
#define DIK_NUMPAD7 0x47
#define DIK_NUMPAD8 0x48
#define DIK_NUMPAD9 0x49
#define DIK_SUBTRACT 0x4A /* - on numeric keypad */
#define DIK_NUMPAD4 0x4B
#define DIK_NUMPAD5 0x4C
#define DIK_NUMPAD6 0x4D
#define DIK_ADD 0x4E /* + on numeric keypad */
#define DIK_NUMPAD1 0x4F
#define DIK_NUMPAD2 0x50
#define DIK_NUMPAD3 0x51
#define DIK_NUMPAD0 0x52
#define DIK_DECIMAL 0x53 /* . on numeric keypad */
#define DIK_F11 0x57
#define DIK_F12 0x58
#define DIK_F13 0x64 /* (NEC PC98) */
#define DIK_F14 0x65 /* (NEC PC98) */
#define DIK_F15 0x66 /* (NEC PC98) */
#define DIK_KANA 0x70 /* (Japanese keyboard) */
#define DIK_CONVERT 0x79 /* (Japanese keyboard) */
#define DIK_NOCONVERT 0x7B /* (Japanese keyboard) */
#define DIK_YEN 0x7D /* (Japanese keyboard) */
#define DIK_NUMPADEQUALS 0x8D /* = on numeric keypad (NEC PC98) */
#define DIK_CIRCUMFLEX 0x90 /* (Japanese keyboard) */
#define DIK_AT 0x91 /* (NEC PC98) */
#define DIK_COLON 0x92 /* (NEC PC98) */
#define DIK_UNDERLINE 0x93 /* (NEC PC98) */
#define DIK_KANJI 0x94 /* (Japanese keyboard) */
#define DIK_STOP 0x95 /* (NEC PC98) */
#define DIK_AX 0x96 /* (Japan AX) */
#define DIK_UNLABELED 0x97 /* (J3100) */
#define DIK_NUMPADENTER 0x9C /* Enter on numeric keypad */
#define DIK_RCONTROL 0x9D
#define DIK_NUMPADCOMMA 0xB3 /* , on numeric keypad (NEC PC98) */
#define DIK_DIVIDE 0xB5 /* / on numeric keypad */
#define DIK_SYSRQ 0xB7
#define DIK_RMENU 0xB8 /* right Alt */
#define DIK_HOME 0xC7 /* Home on arrow keypad */
#define DIK_UP 0xC8 /* UpArrow on arrow keypad */
#define DIK_PRIOR 0xC9 /* PgUp on arrow keypad */
#define DIK_LEFT 0xCB /* LeftArrow on arrow keypad */
#define DIK_RIGHT 0xCD /* RightArrow on arrow keypad */
#define DIK_END 0xCF /* End on arrow keypad */
#define DIK_DOWN 0xD0 /* DownArrow on arrow keypad */
#define DIK_NEXT 0xD1 /* PgDn on arrow keypad */
#define DIK_INSERT 0xD2 /* Insert on arrow keypad */
#define DIK_DELETE 0xD3 /* Delete on arrow keypad */
#define DIK_LWIN 0xDB /* Left Windows key */
#define DIK_RWIN 0xDC /* Right Windows key */
#define DIK_APPS 0xDD /* AppMenu key */
//////////////////////////////////////////////////////////////////////////////
これらに関しては、同時押し入力可能なのですが、キーボードの特性により
いくつまで同時押しが保証されるかはわかりません。最悪、2つの同時押し
すら保証はされません。市場に出回っているキーボードを調べたところ、
質の悪いものでは、3キーでさえ、特定のキーの組み合わせだと同時押しが
判定出来ないことがあります。
/////////////////////////////////////////////////////////////////
§2-11-2 キー入力関連(ジョイスティック)
/////////////////////////////////////////////////////////////////
SetJoyButtonMax(ボタンの最大数); // 入力判定を行なうボタンの最大数を指定する。
// (初期値2。最大32)
IsPushJoyKey(キーナンバー);
IsPressJoyKey(キーナンバー);
使いかたは、キーボードのときと同じです。ジョイスティックなので、キーナンバーは、
それぞれ
0 : 上方向に入力があれば非0
1 : 下 〃
2 : 左 〃
3 : 右 〃
4 : ボタン1 〃
5 : ボタン2 〃
以下、SetJoyButtonMax()で指定した分だけ入力が返ってきます。
通常、KeyInputを行なうと、キースキャンと、ジョイスティックのスキャンと両方を
行ないます。そして、IsPushUpKey()ならば、キーとジョイスティックのどちらの上方向の
入力があれば非0が返ることに注意してください。
/////////////////////////////////////////////////////////////////
§2-11-3 キー入力関連(MIDI INPUT)
/////////////////////////////////////////////////////////////////
IsPushMIDIKey(キーナンバー);
IsPressMIDIKey(キーナンバー);
使いかたは、キーボードやジョイスティックとまったく同じ。関数名・パラメータも
同じにしてあるので、すんなり理解していただけることでしょう。
256個の入力状態バッファに対して、
253 (左ペダル)
254 (中央ペダル)
255 (右ペダル)
を割り当てています。
それ以外は、ノートナンバー(MIDI規格表を参考にすること)に対応する
部分に、入力ベロシティ(打鍵したときの強さ)が返ります。入力がないときは、
その部分は0です。
IsPushMIDIKey等を使うと、On/Offの検出しかできないので、
ベロシティを得るための関数が
long GetVelocityMIDIKey(long key);
ひとつ追加になっています。
ベロシティは0から256までの値で、入力が無い場合は0です。
MIDIキー入力は、KeyInputしたときに同時に行なわれます。
詳しくは、MIDIキー入力サンプルのほうをご覧ください。
/////////////////////////////////////////////////////////////////
§2-11-4 キー入力関連(MOUSE入力)
/////////////////////////////////////////////////////////////////
DirectDrawを使用するため、MOUSEカーソルは、自前で描画してやる必要があります。
(WindowsNTでは、自前で描画しなくともチラつかないのですが、Windows95/98では、
自前で描画しないと、チラつくため)
よって、MOUSE入力関連は、マウスカーソルの自前での描画機能を含みます。
自前で描画すると言っても、マウスカーソルにするプレーンを指定するだけですので
非常に簡単です。
MouseLayerOn(3,5,5);
// Mouseカーソルとして、3番プレーンの(5,5)の座標位置を
// カーソルの先端として描画を開始する
※ 以降、haltするごとに自動的にマウスカーソルが描画されます。
※ プレーンには、あらかじめビットマップを読み込んで、透過キーを
設定しておいてください。
MouseLayerOff(); // MouseLayerの使用を終了する
※ これで、MouseLayerの使用を終了します。MouseLayerOnとMouseLayerOffは、
一対一に対応している必要はありません。つまり、途中でマウスカーソルを
変えたくなったら、何度でもMouseLayerOnをして、マウスカーソルを変更す
ることが出来ます。そして、最後に、一度だけMouseLayerOffすれば良いの
です。
マウスのカーソル位置、ボタン情報を取得するには、GetMouseInfoを使います。
int x,y,b; // カーソル位置(x,y)とボタン情報
GetMouseInfo(&x,&y,&b);
// これでマウスカーソルの位置と、ボタンの入力情報がわかります。
SetMouseInfo(120,320); // マウスカーソルを強制移動
※ 座標は、ウィンドゥのクライアント座標系(左上が(0,0),右下が(639,479)と
する座標系)で返されます。
※ ボタン情報は、右クリックがビット0,左クリックがビット1に対応します。
また、右ダブルクリックがビット2。左ダブルクリックがビット3に対応します。
つまり、右クリックが押されていればbは1,左クリックが押されていれば、
bは2,両方が押されていれば、bは3、右ダブルクリックされていればbは4
という具合になります。
※ MouseLayerは、Layerですが、バックアッププレーンには反映しません。
※ また、あらゆるLayerより、手前に描画されることが保証されます。
/////////////////////////////////////////////////////////////////
§2-12 MIDIファイルの再生関連
/////////////////////////////////////////////////////////////////
LoadMIDI(ファイル名);
PlayMIDI();
StopMIDI();
PauseMIDI();
ReplayMIDI();
ReleaseMIDI();
IsPlayMIDI();
SetLoopModeMIDI(b);
使いかたは、CD系と同じなのです。
例)
LoadMIDI("resource/memory.mid");
PlayMIDI();
/////////////////////////////////////////////////////////////////
§2-13 ゲームデータの簡易ロード/セーブ関数
/////////////////////////////////////////////////////////////////
long LoadGameFlag(ファイル名); // gameflagを丸ごとファイルに書き出す
long SaveGameFlag(ファイル名); // gameflagを丸ごとファイルから読み込む
long LoadGameFlag2(ファイル名); // gameflag2を丸ごとファイルに書き出す
long SaveGameFlag2(ファイル名); // gameflag2を丸ごとファイルから読み込む
これらの関数の返し値は、成功すれば0,失敗すれば非0です。
gameflag,gameflag2が何であるかについては、ユーザー公開変数の説明を
ご覧になってください。
ResetGameFlag(); // gameflagを丸ごと0で埋める(初期化)
ResetGameFlag2(); // gameflag2を丸ごと0で埋める(初期化)
これもあれば便利だと思います。
また、現在、何番のユーザーデータが存在するかなどは、gameflag2のほうに
格納して管理すれば良いと思います。また、gameflag2を保存するファイルは
固定しておき、LoadGameFlag2を実行して返し値が非0であれば、ファイルが
存在しない、すなわち、第1回目のゲームということになりますから、
そのときにResetGameFlag2()としたあと、SaveGameFlag2();でゲームフラグ
ファイルを作成すれば良いでしょう。
SaveGameFlag関数で、ファイルは作られますが、新規にフォルダは作成され
ません。フォルダは、あらかじめ用意しておく必要があります。ご注意ください。
/////////////////////////////////////////////////////////////////
§2-14 簡易ファイル操作
/////////////////////////////////////////////////////////////////
LoadFile(ファイル名,読み込むデータアドレス,読み込む最大サイズ);
SaveFile(ファイル名,書き込むデータアドレス,書き込みサイズ);
まず、SaveFileから説明します。
long x[100]; // 4バイト×100=400バイト
// そして配列xの内容を適宜更新して、
SaveFile("xfile.bin",&x,400); // 配列xを400バイト分書き出し
どうですか?うまく行きましたか?
LoadFileの場合は、この逆です。
long x[100]; // 4バイト×100=400バイト
// LoadFileで読み込む場合、あらかじめデータエリアの確保が必要。
LoadFile("xfile.bin",&x,400); // 配列xに400バイト分読み込み
400バイト以上のファイルであった場合、そこ以降は読み込まれません。
非常にシンプルですが、とりあえず、フラグの保存等はこれで可能でしょう。
long型の変数は1つが4バイトであることに注意してください。
※ 備考
理解する必要はまったくありませんが、参考までに言うと、
配列x[]に対して、この配列名xは、配列へのポインタにはなっていません。
(C言語と違うのです)
ここで出てきた&xの&は、配列名に対して使うと、その配列の先頭アドレス、
変数に対して使うと、その変数の格納されているアドレスが入ります。
それ以外に&x[5]というような使い方も出来ます。(x[5]の格納されている
アドレスが入ります)
それと、関数内で宣言した変数は、スタック領域に確保されます。
スタックサイズは固定で64Kしかありませんから、関数内では
あまり大きな配列を宣言できません。そのへん、注意してください。
(グローバル変数は、コード領域に確保されます。コード領域は、
必要分だけコンパイルするときに確保されます)
/////////////////////////////////////////////////////////////////
§2-15 他のスクリプトを呼び出す機能
/////////////////////////////////////////////////////////////////
JumpScript(スクリプト名);
指定のスクリプトにジャンプします(返ってきません)
指定されたスクリプトは、この関数を実行後、main関数から脱出した時点で、
読み込まれ、コンパイルされ、そのスクリプトのmain関数から実行が開始されます。
JumpScriptは、returnとセットで使うと覚えておいてください。
CallScript(スクリプト名);
指定のスクリプトを呼び出します(そのスクリプトでの処理終了後に、また返って
きます)
指定されたスクリプトは、この関数を実行後、次のhaltのあとで、読み込まれ、
コンパイルされ、そのスクリプトのmain関数から実行が開始されます。
このときのhaltでは、画面描画は行ないません。
CallScriptはhaltとセットで使うと覚えておいてください。
使用例)
JumpScript("script/callscript.c"); // ジャンプする(戻ってこない)
return ;
使用例)
CallScript("script/callscript.c"); // Callする(戻ってくる)
halt;
☆ CallScriptにはエラーハンドラを書く機能があります。
コンパイルエラーが発生した場合、グローバル変数bErrorResultの値が非0になります。
例)
SetErrorRestrain(1); // エラー表示を抑制する。(引数が0ならば抑制しない)
CallScript("test.c"); halt;
if (bErrorResult) { // CallScriptにエラーがあるとbErrorResultが非0になる
// test.cのコンパイルエラー発生
// ここに、エラー処理を書く
}
/////////////////////////////////////////////////////////////////
§2-16 ゲーム終了関数
/////////////////////////////////////////////////////////////////
Quit();
本来ならば、main関数からreturnすれば、それで終了するのですが、
CallScriptしていると、呼出し元のスクリプトに戻ってしまいます。
そこで、どんな場合でも強制的に終了させるためには、この関数を
使います。
使いかたは、この関数を呼び出したあと、halt;すれば、OKです。
どれだけCallScriptしてようとも、その時点で終了します。
/////////////////////////////////////////////////////////////////
§2-17 乱数の発生
/////////////////////////////////////////////////////////////////
long Rand(最大); // 乱数が返ってきます。
例) x = Rand(10); とやれば、xに0~9までの乱数が入ります。
/////////////////////////////////////////////////////////////////
§2-18 シナリオの表示機能
/////////////////////////////////////////////////////////////////
シナリオファイルとは、
"Message"
とダブルコーテーションで括られたメッセージ(最大32×5行。途中で改行が入ることもあり)
をならべたものです。MessageがENDとなっているところで終了します。
このファイルからメッセージを読み込み、スペースキーが押されるごとに次々と
新しいメッセージを表示していく機能が、このシナリオの表示機能というわけです。
使う関数は、以下の2つだけです。
OpenSenario(filename,n); // n番のメッセージボックスにシナリオファイルを読み込む
ReadSenario(); // 必要に応じて、次のメッセージを読み込む
まずOpenSenarioで、読み込むシナリオファイルを指定します。メッセージは、TextLayerに
読み込まれるので、事前にTextLayerOnし、そのテキストレイヤーの文字色、位置等を設定して
おきましょう。
例)
TextLayerOn(0,50,300); // 0番のメッセージボックスを使用開始!
OpenSenario("txt/senario1.txt",0); // 0番のメッセージボックスにシナリオファイルを読み込む
loop { // 表示ループ
ClearSecondary();
// 必要ならば、この位置でメッセージの背景となるプレーンなどをBltで描画すると良い
// これを入れておくだけで、スペースが押されるごとに次々とメッセージが読み込まれる。
if (ReadSenario()) break;
halt;
}
TextLayerOff(0); // 0番のメッセージボックス使用終了!
これだけです。ReadSenario()は、スペースキーが押されていれば、自動的に
次のメッセージを読み込み、"END"が見つかった時点で非0を返します。(よって、上の
プログラムであればloopから抜けることになります)
たったこれだけです。
あと、マップ表示中にメッセージボックスを出すような場合は、バックアッププレーンを
利用すれば、簡単です。(シナリオ表示サンプルに、バックアッププレーンを利用して、
シナリオ表示を行なうサンプルがありますので、そちらをご覧ください。要は、
ClearSecondary();の代わりに、バックアッププレーンからの転送命令が入るだけです。
しかし、その瞬間に画面モードを切り替えられるとバックアッププレーン自体は死んで
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
しまいますので、あまり良くないような気がします。この場合ならば、Map表示ルーチンを
関数化しておき、シナリオ表示のときに、そのMap表示ルーチンを呼び出すようにするのが
ベストです)
順番に文字バッファにシナリオを読み込みたいときは、
OpenSenario2();と
ReadSenarioToString();を使います。使いかたは、いたって簡単!
OpenSenario2("txt/senario1.txt"); // シナリオファイルを読み込む
loop { // 表示ループ
if (ReadSenarioToString(string[0])) break;
// これで、次のメッセージが一回分読み込めたので、
// この部分でstring[0]を表示する。
... // なんとかして、string[0]を細切れに切ってゆっくり表示
... // するプログラムをここに書く
}
// ReadSenarioToStringは、シナリオ終了の部分で非0が返ってくる
// ので、breakでここに抜ける
注意:
OpenSenario2とReadSenario,OpenSenarioとReadSenarioToStringを
組み合わせて使用しないでください。
☆ 行単位に読む機能(簡易的ファイルI/O):β7での新機能
OpenSenario2();のあと
ReadSenarioToString();の代わりにReadLineToString();を使います。
そうすると、一行(改行まで)が入ってきます。
例)
OpenSenario2("txt/senario1.txt"); // シナリオファイルを読み込む
loop { // 表示ループ
if (ReadLineToString(string[0])) break;
// これで、一行分読み込めたので、
// この部分でstring[0]を表示する。
... // なんとかして、string[0]を細切れに切ってゆっくり表示
... // するプログラムをここに書く
}
/////////////////////////////////////////////////////////////////
§2-19 画面モードの切り替え
/////////////////////////////////////////////////////////////////
SetDisplayMode(ディスプレイモード1,ディスプレイモード2); // ディスプレイモードの設定
ChangeDisplayMode(n); // nが1ならば、ディスプレイモード1に
// 2ならばディスプレイモード2に変更します
まず、SetDisplayModeでディスプレイモードの設定をします。
仮に、ディスプレイモード1は、アクションシーン、ディスプレイモード2は、ビジュアルシーン
だとしましょう。ここで設定する値は、
0 : WindowMode(この場合、立ち上げられたときの解像度に依存し、色数は変更できない)
1 : FullScreenMode 256色
2 : FullScreenMode 65536色 (High Color)
3 : FullScreenMode 16777216色 (Full Color)
4 : FullScreenMode 4294967296色 (True Color)
です。アクションシーンは、フルスクリーン256色、ビジュアルシーンは、FullScreen65536色に
しようと思えば、
SetDisplayMode(1,2); // 256色&65536色
とまず設定し、アクションシーンの開始部分で、
ChangeDisplayMode(1); // SetDisplayModeの第1パラメータで指定した256色モードになる
とすればOKです。同様にビジュアルシーンの開始部分では、
ChangeDisplayMode(2); // SetDisplayModeの第2パラメータで指定した65536色モードになる
とやります。
備考:
ChangeDisplayModeで、そのモードをディスプレイカードがサポートしていない場合、
その一つ上の解像度をトライします。HighColorをサポートしていなければ、FullColorさらに、
FullColorをサポートしていなければTrueColorという具合にです。TrueColorをサポートして
いない場合、最終、WindowModeになります。
ゲームのメニュー選択で、ユーザーに、以下のような設定ができると良いでしょう。
設定1.常にウィンドゥモード SetDisplayMode(0,0)y;
設定2.常にフルスクリーン256 SetDisplayMode(1,1);
設定3.アクション256,ビジュアル65536 SetDisplayMode(1,2);
設定4.アクション256,ビジュアルフルカラー SetDisplayMode(1,3);
設定5.常に65536色 SetDisplayMode(2,2);
設定6.常にフルカラー SetDisplayMode(3,3);
/////////////////////////////////////////////////////////////////
§2-20 フォルダ関連
/////////////////////////////////////////////////////////////////
GetCurrentDirectory(str); // 起動フォルダを表す文字列を返す
SetCurrentDirectory(str); // 起動フォルダを設定する
// バッファは事前に確保しておくこと
→ファイル入出力を行なうDLLを作るときに必要なので追加しました。
また、駆け上がりパスをサポートしていますので、".."は、ひとつ上のフォルダを
意味します。
つまり、
"../../test/test.c"は、起動フォルダから二つ上のフォルダのtestというフォルダの
なかにあるtest.cというファイルを意味します。
→ その他、フォルダ検索関連につきましては、別途DLLを用意していますので、
そちらをご利用ください。
/////////////////////////////////////////////////////////////////
§2-21 各種定数を設定する機能
/////////////////////////////////////////////////////////////////
SetConstParam(パラメータ文字列,パラメータ); // パラメータを設定する
この関数は、各種パラメータを変更するのに使用します。
パラメータ文字列としては、"SoundMax"とか"PlaneMax"というように、""で囲まれた
文字列を指定し、それに対するパラメータを二つ目の引数で指定します。
※ 未知のパラメータ文字列や、設定に失敗した場合、返し値は非0になります。
例)
SetConstParam("PlaneMax",256); // プレーンの最大数は256に変更
※ これは、イニシャライザでなくとも使えるのですが、そのときに確保していたプレーンは
すべて初期状態に戻ってしまいます。なるべく、イニシャライザで設定したほうが
無難です。
※ パラメータ文字列は、大文字小文字の区別はしません。
他に、どんなパラメータ文字列が使えるのか、その一覧を以下に示します。
//////////////////////////////////////////////////////////////////
パラメータ文字列 意味
SoundMax 総Soundチャンネル数
PlaneMax 総プレーン数
GameTimeMax 総GameTime数
TextLayerMax 総テキストレイヤー数
StringMax string配列の数
StringLength string配列の大きさ
USE_XZ_FOR_BUTTON XとZキーをスペース、リターンに割り当てるのか?
※ 割り当てないがディフォルト
EnablePause ゲーム中、他アプリに制御が移ったらPauseを掛けるか?
※ Pauseを掛けるがディフォルト
EnableMultiApp このアプリの複数同時起動を許可するか?
※ 許可しないがディフォルト
UseFlip フルスクリーン描画でFlip描画を行なうか?
※ 行なうのがディフォルト
※ (これは評価用です。使う必要はありません)
※ これらはすべてパラメータに数字をとります。
※ 最後のは、1ならばYes, 0ならばNoです。
例)
SetConstParam("EnableMultiApp",1); // このアプリの複数同時起動を許可する。
※ DirectDrawを使用している関係上、256色モードだと他アプリに制御が移ったときに
パレットがうまく再現されませんので、
SetConstParam("EnablePause",0); // 他のアプリに制御が移ったときにPauseを掛けない
を指定するときは、気をつけてください。
※ StringMax,StringLengthを変更すると、そのスクリプトファイルから抜けるまで
string[]変数は無効になります。よって、この設定はイニシャライザで行なうのが
無難です。
WindowPos ウィンドゥの位置を設定します。
例)
SetConstParam("WindowPos",100,200); // (100,200)をウィンドゥ左上として表示します
※ この機能は、フルスクリーンモードでは意味がありません。
//////////////////////////////////////////////////////////////////
パラメータ文字列
※ これらは、パラメータに文字列をとります。
Caption Windowのキャプションを変更(キャプションは、いつでも変更可能です)
例)
SetConstParam("Caption","これが窓のキャプション");
MessageBox メッセージボックスを出す
YesNo メッセージボックスでYesNoを問う
例)
SetConstParam("MessageBox","タイトル","内容");
if (SetConstParam("YesNo","確認","本当ですか?")) {
// 本当らしい(笑)
}
※ この2つの機能は、簡易的なものです。これを実行しているときはGDI描画が
行なわれるため、ソフトウェアマウスカーソルは無効になります。また、フル
スクリーンモードではメッセージボックスをドラッグして移動させると画面
がおかしくなります。
よって、起動時に、フルスクリーンモードにするかをユーザーに確認するだとか、
256色モードで起動していると警告を出すだとか、そういった用途に適しています。
/////////////////////////////////////////////////////////////////
§2-22 各種定数を取得する機能
/////////////////////////////////////////////////////////////////
GetConstParam(パラメータ文字列,パラメータ); // パラメータを取得する
基本的にSetConstParamと同じような使いかたをします。
パラメータ文字列の一覧
ScreenSize 画面全体のサイズを取得します。
例)
GetConstParam("ScreenSize",&x,&y); // x,yに画面全体のサイズが入ります。
//////////////////////////////////////////////////////////////////////////////
§3.その他
§3-1 ゲーム上で利用できる内部変数
ここでは、ゲーム上で利用できる変数について書きます。
これらについては、いつでも使用することが可能です。
ゲーム上のフラグ等(アイテムの所持・ゲーム内時間等)も、すべてこの内部変数に
格納されており、これを利用することで、アイテムの所持・不所持のチェックを
行なったり、ゲーム内時間のチェックを行なったりすることが可能です。
////////////////////////////////////////////////////////////////////////////////
変数名
gameflag[512] : ゲーム内のフラグ(アイテムの所持・不所持・イベント
達成フラグ等)を入れるための配列です。
セーブコマンド、ロードコマンドを使用した場合、この
配列の内容がまるごとセーブ・ロードされるという仕掛け
です。0~511までを、御自由にご使用ください。
////////////////////////////////////////////////////////////////////////////////
例)
// gameflag[0]は仮にアイテムAの所有フラグだとする。
// 所有していれば非0。
gameflag[0] = 1; // アイテムAを獲得した。
例)
// gameflag[2]は仮にアイテムCの所有フラグだとする。
// 所有していれば非0。
if (gameflag[2] == 0) { // アイテムCを持っていないならば、
//
// ここの内容が起こる
//
}
////////////////////////////////////////////////////////////////////////////////
gameflag2[512] : グローバルゲームフラグ
こちらも、内容はgameflagと同様ですが、ゲーム全体でひとつしか持って
いないような達成フラグ等を管理するために使用します。
////////////////////////////////////////////////////////////////////////////////
※ 上のゲームフラグについては、フラグエディタ,グローバルフラグエディタのほうで
編集が出来ます。ゲームフラグエディタの使用説明も参考にしてください。
//////////////////////////////////////////////////////////////////////////////
§3-2 HALT命令について(重要)
//////////////////////////////////////////////////////////////////////////////
描画をすると、描画タイミングは、どこで得るのか?という問題が生じてきます。
というか、スクリプトを実行すると、ずっとスクリプトに制御が移ったままになって
しまい、ウィンドゥ右上の×印すら利かなくなってしまいます。
そこで、halt;命令を入れます。
これを入れたタイミングで、描画を行ない、同時にメッセージ処理(ウィンドゥの
右上の×印が押されたかだとか、そういった必要不可欠なもの)を行ないます。
そんなわけで、描画タイミング、そして、長い待ちループ中に、
適宜haltを入れるようにしてください。(→サンプル waveの再生等をご覧になって
ください)
メニュー選択枝3のScript Testでは、ESCキーを押すと強制終了するようになって
いますが、しかし、halt命令が入っていないことには、ESCを押してもキー入力の
チェックが行なえないため、終了しません。一度、確認してみてください。halt命令は
必要不可欠なのです。
描画タイミングのどの位置で入れるかについては、ビットマップの表示のところで
解説します。
//////////////////////////////////////////////////////////////////////////////
§3-3 イニシャライザについて
//////////////////////////////////////////////////////////////////////////////
gamestart.cが起動してしまうと、すでに画面は640*480であるなど設定されている
ので、それらは変更不可です。
そこで、gamestart.cが起動する前に各種設定するためのものが、イニシャライザです。
script/gameinit.cのmain関数が呼び出されます。(このファイルが存在しないときは
初期設定値が採用されます)
そのなかで、各種設定を行なうことが出来ます。(ただし、ウィンドウは構築されて
いない段階なのでhaltで描画することは出来ません)
// gameinit.c
void main(){
SetWindow(0,400,200,8); // ウィンドウモード400*200
}
☆ イニシャライザでのみ使える関数
SetWindow(mode,x,y,color);
// mode : 0ならフルスクリーンモード,1ならWindowモード
// x,y : サイズ
// color : 8なら256色,16なら65536色,24ならfull color,32ならtrue color
// (ただし、ウィンドウモードでは、色数は現在のディスプレイモードに依存で、
// このパラメータは無視されます)
※ フルスクリーンでは640×480以外の画面サイズは
ビデオカードでサポート外の可能性が高いです。
SetDebugMode(mode);
// mode 0 : デバッグ用エラー出力なし,中間ファイル無し(ディフォルト)
// 1 : デバッグ用エラー出力あり,中間ファイル無し
// 2 : デバッグ用エラー出力なし,中間ファイル有り
// 3 : デバッグ用エラー出力あり,中間ファイル有り
※ デバッグ用エラー出力をありにしておかないと、読み込むファイルがないだとかの
エラー出力がされず、またInnerLog,InnerLogMesが機能しません。
※ 中間ファイルとは、アセンブルされた仮想CPU用のコードで、コード生成の
研究用です。
//////////////////////////////////////////////////////////////////////////////
§4.サンプル
//////////////////////////////////////////////////////////////////////////////
サンプルが無いとやりづらいと思うので、ここでは、サンプルをいくつか書きます。
§4.1 デバッグ用出力
long main() {
long x,y; // 変数xとyを宣言します
x = 2; // 変数xに2を代入します
y = 3; // 変数yに3を代入します
InnerLogMes("x * y ="); // ErrorLog.txtというファイルに x * y = が出力されます
// 注意:InnerLogMesは、256文字までしか一度に表示できません。
InnerLog(x*y); // ErrorLog.txtというファイルに 6 が出力されます。
}
§4-2-1 WAVEの再生
void main() {
LoadWave("testwav/se01.wav",1);
// 起動ディレクトリにあるtestwavというフォルダにあるse01.wav
// という名前のwaveファイルをチャンネル1に読み込みます。
// この命令が実行された瞬間に読みに行きます。事前に読むわけではありません。
PlayWave(1); // 上で読み込んだチャンネル1のWaveを再生します
loop { // ループでまわります
if (!IsPlayWave(1)) break;
// チャンネル1のWaveの再生が終了していればloopから抜けます
// !は、否定演算子です
halt; // 長いループ中には、haltを入れるんでしたね。
}
ReleaseWave(1);
// チャンネル1のサウンドバッファを解放します
// 使用終了後は、サウンドバッファをメモリから解放することによって
// メモリの使用率を下げます。
// ReleaseWaveAll()で一気に行なうことが出来ます。
// スクリプトの終了ポイントで、使い終わったサウンドは必ず解放するようにしてください。
}
§4-2-2 WAVEのループ再生
void main() {
LoadWave("testwav/se01.wav",0);
SetLoopModeWave(0,1); // これでループモードに!
PlayWave(0);
loop {
KeyInput();
if (IsPushEscKey()) break;
halt;
}
ReleaseWave(0);
}
§4-3-1 CDの再生サンプル
long main() {
SetLoopModeCD(0); // CDは非ループモードに設定
OpenCD(); // CDの初期化(CDを回す)
PlayCD(1); // トラック1を再生
loop {
if (!IsPlayCD()) break; // CDの再生が停止していればloopから脱出
halt; // 長いループ中にはおまじないとしてhaltを入れます。
}
CloseCD(); // 不要になったので、CDの回転を停止させます。
}
§4-3-2 CDのカレントポジションについて
void main() {
OpenCD();
PlayCD(2);
TextLayerOn(0,0,0);
loop {
sprintf1(string[0],"CD Pos = %.8x",GetCurrentPosCD());
TextOut(0,string[0]);
ClearSecondary();
halt;
if (!IsPlayCD()) break;
}
TextLayerOff(0);
CloseCD();
}
画面の左上にカレントポジションを表示させています。16進8桁表示になっていますが、
下の2桁が分、その上2桁が秒になっていることがわかるはずです。
つまり、CD再生の秒数は、GetCurrentPosCD() & 0xff00 >> 8
ってな感じで取得できるわけですね。
§4-4-1 画面描画のサンプル
void main(){
LoadBitmap("tools/chara1.bmp",2,1);
// ビットマップファイルを2番プレーンに読み込む
SetFillColor(0xffffffff); // 背景は白に
loop {
ClearSecondary(); // 背景クリア
BltFast(2,10,20); // 2番プレーンを(10,20)に転送
halt; // 画面の描画
} // 永久ループなので、ウィンドゥ右肩の×を押して終了させてくださいね!
}
§4-4-2 左から右にスクロールさせる
void main(){
long x,y;
LoadBitmap("tools/chara1.bmp",2,1);
// ビットマップファイルを2番プレーンに読み込む
x = -300;
y = 50;
loop {
ClearSecondary(); // 背景クリア
BltFast(2,x,y); // 2番プレーンを(x,y)に転送
halt; // 画面の描画
if (x>=640) break ; // xが640以上になれば終了(画面サイズは640*480です)
x = x + 3; // xに3を加算
}
}
§4-4-3 画面全体に、32×32のビットマップを敷き詰める
void main(){
long x,y;
LoadBitmap("tools/mapchip2.bmp",0,1);
// 16*16のビットマップファイルを0番のプレーンに読み込む
loop { // 永久ループ
ClearSecondary(); // 背景クリア
// 画面を0番プレーンで埋める
y = 0;
loop {
x = 0;
loop {
BltFast(0,x,y); // 0番プレーンを(x,y)に転送
x = x + 32; // xに32を加算
if (x>=640) break ; // xが640以上になれば、内側のloopから抜ける
}
y = y + 32; // yに32を加算
if (y>=480) break ; // yが480以上になれば、このloopから抜ける
}
halt; // 画面の描画
}
}
§4-4-4 FPS設定機能、FPS表示機能のサンプル
void main(){
long x,y;
LoadBitmap("tools/chara1.bmp",2,1);
// ビットマップファイルを2番プレーンに読み込む
x = -300;
y = 50;
SetFPS(30); // FPSを30に設定
FPSLayerOn(500,10); // FPS表示機能の利用開始!
loop {
ClearSecondary(); // 背景クリア
BltFast(2,x,y); // 2番プレーンを(x,y)に転送
halt; // 画面の描画
if (x>=640) break ; // xが640以上になれば終了(画面サイズは640*480です)
x = x + 3; // xに3を加算
}
FPSLayerOff(); // FPS表示機能の利用終了!
loop {
ClearSecondary(); // 背景クリア
BltFast(2,x,y); // 2番プレーンを(x,y)に転送
halt; // 画面の描画
if (x<=-100) break ; // xが-100以下になれば終了(画面サイズは640*480です)
x = x - 3; // xに3を加算
}
}
§4-4-5 マシンスピードに依存しない移動速度で描画する
マシンスピードが遅いとSetFPSを設定していても、それより低い値になってしまうことが
あります。そのような場合、一定の移動速度が得られず、思っているような演出効果が
期待できないかも知れません。(フェードアウト等) そういう場合、タイマを見ながら
プレーンを動かすと良いでしょう。具体例は、以下のものです。
void main(){
long x,y;
LoadBitmap("tools/chara1.bmp",2,1);
// ビットマップファイルを2番プレーンに読み込む
y = 50;
SetFPS(50);
FPSLayerOn(500,10);
ResetTime(0); // タイマー0番をリセット
loop {
x = GetTime(0)/5; // x 座標は、タイマー0番の値を5で割ったものを利用
// これにより、マシンスピードとは無縁の移動速度が得られる
ClearSecondary(); // 背景クリア
BltFast(2,x,y); // 2番プレーンを(x,y)に転送
halt; // 画面の描画
if (x>=640) break ; // xが640以上になれば終了(画面サイズは640*480です)
}
}
注意1.
割り算するときは、整数演算であることに注意してください。
たとえば、
x = x / 5 * 3;
は、xを5で割って(整数。小数以下は切り捨てられる)、その後3を掛けることに
なるので、端数分だけ誤差が出ます。このような場合、
x = x * 3 / 5;
と、先に掛け算を行なうようにしましょう。
注意2.
また、演算は、優先順位があります。+,-より*,/のほうが優先順位が高いです。
優先順位の同じものは、原則的に左から評価(計算)されていくとお考えください。
優先順位に不安があるときは、( )カッコでくくると良いでしょう。
注意3.
関数のパラメータの数のチェックはしていません。
たとえば、GetTimeのパラメータをうっかり忘れたりしても、そのまま動いたり
することもあるので、注意してください。
§4-4-6 フェードアウトのサンプル
void main(){
long bright;
LoadBitmap("tools/chara1.bmp",0,1);
SetFPS(10);
FPSLayerOn(500,10);
bright = 256;
// フェードアウト
loop {
ClearSecondary(); // 背景クリア
SetBrightness(bright); // 画面の明るさの設定
BltFast(0,100,100); // 0番プレーンを(x,y)に転送
halt; // 画面の描画
bright = bright - 16; // 明るさ値から16引く
if (bright<0) break; // 明るさ値が0以下になれば終了
}
SetBrightness(256); // 画面の明るさをもとに戻す
// haltは行なっていないので、画面描画は行なわれない
}
§4-4-7 フェードアウト/フェードインのサンプル
ビットマップAをほんわかとフェードアウトさせ、その後、ビットマップBを
ほんわかとフェードインさせるサンプルです。
void main(){
long bright;
// あらかじめ別のプレーンに2つのビットマップを読み込んでおく
LoadBitmap("tools/chara1.bmp",0,1);
LoadBitmap("tools/chara2.bmp",1,1);
SetFPS(10);
FPSLayerOn(500,10);
bright = 256;
// フェードアウト
loop {
ClearSecondary(); // 背景クリア
SetBrightness(bright); // 画面の明るさの設定
BltFast(0,100,100); // 0番プレーンを(x,y)に転送
halt; // 画面の描画
bright = bright - 16; // 明るさ値から16引く
if (bright<0) break; // 明るさ値が0以下になれば終了
}
bright = 0;
// フェードイン
loop {
ClearSecondary(); // 背景クリア
SetBrightness(bright); // 画面の明るさの設定
BltFast(1,100,100); // 1番プレーンを(x,y)に転送
halt; // 画面の描画
bright = bright + 16; // 明るさ値から16足す
if (bright>256) break; // 明るさ値が256以上になれば終了
}
SetBrightness(256); // 画面の明るさをもとに戻す
}
FPSはどうでしたでしょうか?遅かったでしょうか?
今度は、SetFPSしている部分を、SetFPS(60);のようにしてみるとどうでしょうか?
この場合、実際のFPSは60出ないかも知れません。しかし、速いマシンでは、60出る
というのも困りものです。
解決策1.
SetSystemMemoryUse(1);を、LoadBitmapの前に入れることによって、
システムメモリを利用してフェードアウトを行ない、速度をかせぐ。
解決策2.
GetTime()を利用して、現在のタイマを見ながらフェードアウトをかける。
こうすれば、速いマシンであれば、なめらかな(描画枚数の多い)フェードアウトが、
期待でき、逆に遅いマシンでも、一定時間内で終了するフェードアウトが可能となります。
この2つの解決策をほどこしたものを以下に示します。
§4-4-8 理想的なフェードイン/フェードアウト
void main(){
long bright;
SetSystemMemoryUse(1); // システムメモリを使用する
// あらかじめ別のプレーンに2つのビットマップを読み込んでおく
LoadBitmap("tools/chara1.bmp",0,1);
LoadBitmap("tools/chara2.bmp",1,1);
RealizePalette(0); // 256色モードに対応させるためには、
// このビットマップのパレットをリアライズしておく必要がある!
SetFPS(30);
FPSLayerOn(500,10);
ResetTime(0);
// フェードアウト
loop {
bright = 256 - GetTime(0)/5; // 経過時間を5で割った速度でフェードアウト
if (bright<0) break; // 明るさ値が0以下になれば終了
ClearSecondary(); // 背景クリア
SetBrightness(bright); // 画面の明るさの設定
BltFast(0,100,100); // 0番プレーンを(x,y)に転送
halt; // 画面の描画
}
ResetTime(0);
// フェードイン
loop {
bright = GetTime(0)/3; // 経過時間を3で割った速度でフェードイン
if (bright>256) break; // 明るさ値が256以上になれば終了
ClearSecondary(); // 背景クリア
SetBrightness(bright); // 画面の明るさの設定
BltFast(1,100,100); // 1番プレーンを(x,y)に転送
halt; // 画面の描画
}
SetBrightness(256); // 画面の明るさをもとに戻す
}
※ 256色モードと非256色モードとで読み込むビットマップを変更する場合は、
LoadBitmapのところ、LoadBitmapWにします。
§4-4-9 クリップ機能つき転送
void main(){
long x,y;
LoadBitmap("tools/chara1.bmp",0,1);
// ビットマップファイルを0番プレーンに読み込む
x = 200;
y = 100;
loop {
ClearSecondary(); // 背景クリア
ClipBltFast(0,x,y,200,250,200,50);
// 0番プレーンを(x,y)に(200,250,200,50)の領域をクリップしながら転送
halt; // 画面の描画
y = y + 1; // yに1を加算
if (y>=250) break ; // yが250以上になれば終了
}
}
§4-4-10 2画面スクロールサンプル
void main(){
long x,y;
LoadBitmap("tools/chara1.bmp",0,1);
LoadBitmap("tools/chara2.bmp",1,1);
// 2の二つのビットマップを連ねて2画面スクロールさせる
// (さらに、転送先クリップしながら)
x = 200;
y = -400; // ここから
loop {
ClearSecondary(); // 背景クリア
ClipBltFast(0,x,y,100,100,400,300);
// 0番プレーンを(x,y)に(100,100,400,300)の領域をクリップしながら転送
ClipBltFast(1,x,y+480,100,100,400,300);
// 1番プレーンを(x,y+480)に(100,100,400,300)の領域をクリップしながら転送
// このClipBltFastをBltFastに書きかえれば、クリップなしの転送。
// また+480の部分は、プレーン0の画像高さに合わせて調整すること。
halt; // 画面の描画
y = y + 1; // yに1を加算
if (y>=250) break ; // yが250以上になれば終了
}
}
§4-4-11 αブレンドのサンプル
void main(){
long bright;
SetSystemMemoryUse(1); // システムメモリを使用する
LoadBitmap("tools/chara1.bmp",0,1);
LoadBitmap("tools/chara2.bmp",1,1);
SetFPS(30);
FPSLayerOn(500,10);
ResetTime(0);
// フェードアウト
loop {
bright = 256 - GetTime(0)/20; // 経過時間を20で割った速度でフェードアウト
if (bright<0) break; // ブレンド比率値が0以下になれば終了
ClearSecondary(); // 背景クリア
// 0番プレーンと1番プレーンとをブレンドしながら転送
BlendBlt(0,100,100,bright,bright,bright,256-bright,256-bright,256-bright);
BlendBlt(1,200,150,256-bright,256-bright,256-bright,bright,bright,bright);
// 少し転送先をずらしておけば、その効果がよくわかる。
halt; // 画面の描画
}
}
§4-5-1 メッセージ表示のサンプル
long main(){
TextLayerOn(1,100,200);
// 文字列ボックス1を(100,200)の位置に設定する。
TextOut(1,"このメッセージが表示されるのである。\nこちらが次の行である。");
// 文字列ボックス1にメッセージを設定する。
halt; // 画面表示
TextLayerOff(1);
// 文字列ボックス1は使い終わった
}
§4-5-2 長い長い文字列を表示する。
long main(){
TextLayerOn(1,100,200);
// 文字列ボックス1を(100,200)の位置に設定する。
TextSize(1,20); // テキストサイズ = 約20ドット(?)
TextHeight(1,25); // 改行幅 = 25ドット
TextColor(1,200,0,0); // テキスト色 = RGB(120,120,0);
TextBackColor(1,120,0,0); // 影の色 = RGB(64,64,0);
TextOut(1,"そのとき僕らはまだ少年だった。\n家の近くには" +
"駄菓子屋があって学校帰りには\nそこにたむろするのが常であった。\n\n" +
"だからと言って、他に何も娯楽がなかったわけではない。");
// 文字列ボックス1にメッセージを設定する。長い場合は、このように
// +記号を使って、いくらでも加算できる。
halt; // 画面表示
TextLayerOff(1);
// 文字列ボックス1は使い終わった
}
§4-5-3 文字列をフェードインさせる。
(ただし、256色モードでは、パレットの初期化を行なっていないので
このままではうまくいかない。何らかの画像をLoadBitmapして、
RealizePaletteしてある必要があるためである。詳しくは、フェードイン/
フェードアウトのサンプルを参照のこと)
long main(){
long bright;
TextLayerOn(1,100,200);
// 文字列ボックス1を(100,200)の位置に設定する。
TextSize(1,20); // テキストサイズ = 約20ドット(?)
TextHeight(1,25); // 改行幅 = 25ドット
TextColor(1,200,0,0); // テキスト色 = RGB(120,120,0);
TextBackColor(1,120,0,0); // 影の色 = RGB(64,64,0);
TextOut(1,"そのとき僕らはまだ少年だった。\n家の近くには" +
"駄菓子屋があって学校帰りには\nそこにたむろするのが常であった。\n\n" +
"だからと言って、他に何も娯楽がなかったわけではない。");
// 文字列ボックス1にメッセージを設定する。長い場合は、このように
// +記号を使って、いくらでも加算できる。
bright = 0;
SetFPS(30);
SetSystemMemoryUse(1); // システムメモリを使用する
loop {
SetBrightness(bright);
halt; // 画面表示
bright = bright + 4;
if (bright>256) break;
}
TextLayerOff(1);
// 文字列ボックス1は使い終わった
}
§4-5-4 文字列をフェードイン/フェードアウトさせる。
毎回、フェードイン/アウトのコードを書くのは面倒なので、関数化
してみる。
long main(){
SetFPS(30);
SetSystemMemoryUse(1); // システムメモリを使用する
TextLayerOn(1,100,200);
// 文字列ボックス1を(100,200)の位置に設定する。
TextSize(1,20); // テキストサイズ = 約20ドット(?)
TextHeight(1,25); // 改行幅 = 25ドット
TextColor(1,200,0,0); // テキスト色 = RGB(120,120,0);
TextBackColor(1,120,0,0); // 影の色 = RGB(64,64,0);
TextOut(1,"Tracing memories by writing like this,\n" +
"I'm sometimes over come with terrible doubts.");
fadein();
fadeout();
TextOut(1,"I find myself thinking,\nwhat if I've lost \nthe most essential part of "+
"these memories?");
fadein();
fadeout();
TextOut(1,"Suppose that somewhere in me,in some dark recess,\n"+
"all my most important recollections\n"+
"have become buried in the sludge of memory");
fadein();
fadeout();
TextLayerOff(1);
// 文字列ボックス1は使い終わった
}
void fadein(){
long bright;
bright = 0;
loop {
SetBrightness(bright);
halt; // 画面表示
bright = bright + 4;
if (bright>256) break;
}
}
void fadeout(){
long bright;
bright = 256;
loop {
SetBrightness(bright);
halt; // 画面表示
bright = bright - 4;
if (bright<0) break;
}
}
§4-6-1 文字列操作関数のサンプル
long main(){
TextLayerOn(0,100,50);
strcpy(string[0],"これを表示する"); // stringの0番に"これを表示する"を入れる
TextOut(0,string[0]); // stringの0番を表示してみる。
halt;
TextLayerOff(0);
}
§4-6-2 文字列の連結
long main(){
TextLayerOn(0,100,50);
strcpy(string[0],"これを表示する。");
strcat(string[0],"さらにこの文字列を追加してみる");
TextOut(0,string[0]);
halt;
TextLayerOff(0);
}
§4-6-3 stringにstringの連結
long main(){
TextLayerOn(0,100,50);
strcpy(string[0],"これを表示する。"); // stringの0番に代入
strcpy(string[1],"これも表示する?"); // stringの1番に代入
strcat(string[0],string[1]); // stringの0番にstringの1番を追加
TextOut(0,string[0]);
halt;
TextLayerOff(0);
}
§4-6-4 stringを利用して数字の埋め込み
long main(){
long item;
item = 10; // アイテム数が入っているとする。
TextLayerOn(0,100,50);
sprintf1(string[0],"アイテム残り %d 個しかありません!",item);
// %dの部分に数字が埋め込まれる
TextOut(0,string[0]);
halt;
TextLayerOff(0);
}
§4-6-5 stringを利用して2つの数字の埋め込み
long main(){
long item1,item2;
item1 = 10; // アイテム数が入っているとする。
item2 = 20;
TextLayerOn(0,100,50);
sprintf2(string[0],"アイテムAは %d 個、\nアイテムBは %d 個しかありません!",item1,item2);
TextOut(0,string[0]);
halt;
TextLayerOff(0);
}
§4-6-6 stringを利用して2つの数字と、stringの埋め込み
long main(){
long item1,item2;
item1 = 10; // アイテム数が入っているとする。
item2 = 20;
strcpy(string[1],"<これを埋め込む>");
TextLayerOn(0,100,50);
sprintf3(string[0],"アイテムAは %d 個、\nアイテムBは %d 個しかありません!\n %sのです!"
,item1,item2,string[1]);
TextOut(0,string[0]);
halt;
TextLayerOff(0);
}
§4-7-1 キー入力に応じて、上下左右にビットマップを移動
void main(){
long x,y;
LoadBitmap("tools/chara1.bmp",0,1);
x = 200;
y = 100; // ここから
loop {
ClearSecondary(); // 背景クリア
ClipBltFast(0,x,y,100,100,440,200);
// 0番プレーンを(x,y)に(100,100,440,200)の領域をクリップしながら転送
halt; // 画面の描画
KeyInput(); // キー入力
if (IsPushEscKey()) break; // ESCキーで終了
// 上下左右キーに応じて移動
if (IsPressDownKey()) y = y+1;
if (IsPressUpKey()) y = y-1;
if (IsPressRightKey()) x = x+1;
if (IsPressLeftKey()) x = x-1;
// スペースキーが押されると初期位置に戻す
if (IsPressSpaceKey()) { x = 200; y = 100; }
if (IsPressReturnKey()) { x = 300; y = 200; }
}
}
上のIsPushなんたらを、IsPressなんたらに変更してみてください。
一度キーを押しても一回分しか移動しないはずです。
メニュー選択等は、そちらのほうが向いていますね。
§4-7-2 MIDIキー入力サンプル
MIDIキー入力も、普通のキー入力同様の感覚で使用できます。
押されたキーのベロシティを表示する簡単なサンプルをご紹介します。
void main(){
long x;
TextLayerOn(0,0,0);
TextOut(0,"Now Waiting for MIDI KeyInput");
loop {
KeyInput();
if (IsPushEscKey()) break;
x = 0;
loop {
if (IsPushMIDIKey(x)){
sprintf2(string[0],"%d Key Velocity %d",x,GetVelocityMIDIKey(x));
TextOut(0,string[0]);
}
x = x +1;
if (x>255) break;
}
ClearSecondary();
halt;
}
TextLayerOff(0);
}
§4-8 バックアッププレーンを利用してフェードイン・フェードアウト関数を作成
void FadeIn(fadetime){
// fadetime : フェードインするまでの時間[ms]
long bright;
EnableBackupPlane(); // バックアッププレーンの使用開始
SetBrightness(256);
SnapToBackupPlane();
halt; // バックアッププレーンに格納
ResetTime(0);
loop {
bright = 256 * GetTime(0)/fadetime; // フェードイン
if (bright>256) break; // 明るさ値が256を超えていれば脱出
SetBrightness(bright); // 画面の明るさの設定
FlushPalette(); // 256色モードならばパレットをいますぐ反映
// (描画後では遅すぎるため)
BltFromBackupPlane(); // バックアッププレーンから転送しての描画
// 画面まるごと転送しているのでClearSecondary();は不要。
halt; // 画面の描画
}
// 最後にSetBrightness(256)の状態で、再度描画しておく。
SetBrightness(256);
ClearSecondary();
BltFromBackupPlane();
halt;
DisableBackupPlane(); // バックアッププレーンの使用終了
}
void FadeOut(fadetime){
// fadetime : フェードアウトするまでの時間[ms]
long bright;
EnableBackupPlane(); // バックアッププレーンの使用開始
SnapToBackupPlane();
SetBrightness(256);
halt; // バックアッププレーンに格納
ResetTime(0);
loop {
bright = 256 - (256 * GetTime(0)/fadetime); // フェードアウト
if (bright<0) break; // 明るさ値がマイナスになれば脱出
SetBrightness(bright); // 画面の明るさの設定
BltFromBackupPlane(); // バックアッププレーンから転送しての描画
// 画面まるごと転送しているのでClearSecondary();は不要。
halt; // 画面の描画
}
// 最後に画面をクリアしておく
SetBrightness(256);
ClearSecondary();
halt;
DisableBackupPlane(); // バックアッププレーンの使用終了
}
void main(){
SetSystemMemoryUse(1); // システムメモリを使用する
LoadBitmap("tools/chara3.bmp",0,1);
RealizePalette(0); // 256色モードに対応させるためには、
// このビットマップのパレットをリアライズしておく必要がある!
SetFPS(30);
// 画面を構築したあと...
ClearSecondary();
BltFast(0,100,100); // 0番プレーンを(x,y)に転送
// この命令を呼ぶだけで一発フェードイン!
FadeIn(3000); // 3000ms(3秒)かけてFadeIn
// FadeOut(3000); // 3000ms(3秒)かけてFadeOut
}
最後のFadeInのところ、FadeOutにしてみてください。
FadeOutされるはずです。
また、このFadeIn,FadeOut関数のように、頻繁に使うものは別ファイルにしておき、
includeして使用するようにすれば、一元管理できます。是非、そうされることを
お勧めします。
§4-9 ゲームフラグの読み込み/保存のサンプル
long main() {
if (LoadGameFlag2("userdata/grobal.dat")) { // 読み込んでみる
// ファイルが存在しない
ResetGameFlag2(); // フラグ2を丸ごとクリアして...
SaveGameFlag2("userdata/grobal.dat"); // ファイルを新規作成!
}
// これで、読み込み終了。gameflag2を書き込むときは、SaveGameFlag2を使用する。
ClearSecondary();
if (gameflag2[10]) { // GameFlag2の10番が立っていたら、
LoadBitmap("tools/chara1.bmp",0,1); // このビットマップを画面に表示
Blt(0,100,200);
}
halt;
}
§4-10 シナリオの表示サンプル
// 以下は、シナリオを表示する関数
// このまま別ファイルにしてincludeで読み込まれても構いません。
呼出し側は、
Senario("txt/senario1.txt");
のようにするだけでOKです。
void Senario(filename){
EnableBackupPlane(); // バックアッププレーンの使用開始
SnapToBackupPlane();
halt; // 現在画面をバックアッププレーンに格納
TextLayerOn(0,50,300); // 0番のメッセージボックスを使用開始!
TextSize(0,20); // (必要とあらば、テキストのサイズ・色等を設定すること)
OpenSenario(filename,0); // 0番のメッセージボックスにシナリオファイルを読み込む
loop { // 表示ループ
BltFromBackupPlane(); // バックアッププレーンから転送しての描画
// 必要ならば、この位置でメッセージの背景となるプレーンなどをBltで描画すると良い
// これを入れておくだけで、スペースが押されるごとに次々とメッセージが読み込まれる。
if (ReadSenario()) break;
halt;
}
TextLayerOff(0); // 0番のメッセージボックス使用終了!
DisableBackupPlane(); // バックアッププレーンの使用終了
}
§4-11 MIDI出力のサンプル
void main() {
LoadMIDI("script/myheart.mid"); // ファイルを読み込む
PlayMIDI(); // 再生開始
loop {
KeyInput();
if(IsPushSpaceKey()) PauseMIDI(); // SPACEキーでPause
if(IsPushReturnKey()) ReplayMIDI(); // RETURNキーで再開
if(IsPushEscKey()) break; // ESCキーで終了
halt;
}
ReleaseMIDI(); // MIDIファイルの解放
}
//////////////////////////////////////////////////////////////////////////////
§5.Q & A
//////////////////////////////////////////////////////////////////////////////
Q.
bitmapXX.bmp (XXは2桁の数字)というファイル名からビットマップファイルを
読み込むにはどうすれば良いでしょうか?
A.
stringを介して、
sprintf(string[0],"bitmap%.2d",BitmapNo);
LoadBitmap(0,string[0]);
のようにすれば良いでしょう。
//////////////////////////////////////////////////////////////////////////////
Q.
関数の引数に配列は、使えないのですか?
A.
使えません(笑)
ただし、ポインタを受け取って、そこから間接でアクセスは出来ます。
実例を示します。
void main(){
long x[5];
test(&x);
}
void test(*x){
x[0] = 123;
x[1] = 234;
x[2] = 345;
}
//////////////////////////////////////////////////////////////////////////////
Q.
二次元配列は使えませんか?
A.
使えません(笑) あまり必要性を感じません。
long p[20*10]; // long p[20][10];だと考える
p[x+y*10] = 123; // long p[x][y] = 123;の意味
}
//////////////////////////////////////////////////////////////////////////////
Q.
アイコンを置き換えることは出来ますか?
A.
そういうツールがあるようです。
|【ソ フ ト名】 アイコン書き換えツール「KH IconRewrite98」
|【ソフト紹介】
| KH IconRewrite98は、実行ファイルなど各種ファイル内のアイコンを
| 任意のアイコンに書き換えることのできるツールです。
| ファイルスキャン機能を使うと、実行ファイル形式だけではなく、
| 標準フォーマットでアイコンを格納しているどんなファイルにも
| 対応できます。
URLは
http://hp.vector.co.jp/authors/VA007769/software/index.html
です。
//////////////////////////////////////////////////////////////////////////////
§6.更新履歴
//////////////////////////////////////////////////////////////////////////////
次回予定
インポートライブラリ対応。
GDI制御系、BMS系インポートライブラリ公開。
点ヌキツール。
// 1.56 (WESTSIDE社刊 お楽しみCD26用特別version)
'00/05/20 変数名・関数名に漢字をサポート。
さらに全角スペースをスペースとみなす。
/* と */によるコメント文(ネスト可)のサポート
'00/05/19 関数呼び出しで不要なカンマが最後にあるとそのあとのローカル変数が
うまくコンパイルされないのでコンパイルエラーが出るようにした。
// 1.55
'00/05/16 JPEG,GIF画像対応。Susie Plug-in対応。
'00/04/02 プレーンはディフォルトで左上をカラーキーとする。
LoadBitmapしたときも、左上をカラーキーに再初期化する。
'00/03/29 BlendBltRのbug-fix。
'00/03/12 MIDI出力でエクスクルーシブが無いデータだと落ちるのを修正。
'00/03/11 SetMouseInfo()追加。
// 1.54
'00/03/07 圧縮WAVE,MP3に対応。(要CODEC→DirectShowをインストールすればOK)
'00/02/29 X ZキーがReturn/Spaceに割り当てたままになっていたのを修正。
// 1.53(small bug-fix)
'00/02/26 ローカル変数の代入のバグ(ver.1.50~) fix。
// 1.52(small bug-fix)
'00/02/20 24BitモードのBlendで白が抜き色にされていた。
'00/02/11 CallScriptがうまく動いていなかったbug-fix。
'00/02/07 TrueColorの抜き色、うまくいかないビデオカードがあるのを修正。
(ビデオカード側のバグ)
'00/02/05 マウス入力でダブルクリックを拾えるようにした。
'00/02/03 実行ファイルにアイコン追加。
'00/02/02 フォーカスを失ったときのMIDIのPause処理がおかしかった。
// 1.51(small bug-fix)
'00/02/01 !演算子が実行エラーになっていた。(thanks > A0k1_SAKATA)
// 1.50(ネイティブコンパイラバージョン)
'00/02/01 待望のネイティブコンパイラ化。
'00/01/31 グローバル変数の初期値は0とする。(そう仮定してプログラムしている人が
多かったため)
// 1.02(安定版/非公開)
'00/01/29 ソフトウェアマウスカーソルでフルスクリーンのとき、見えないウィンドゥ
キャプションによってソフトウェアカーソルにならないbug-fix。
(カイネさんあんがと!)
'00/01/28 他ウィンドゥにフォーカスが移ると、そのとき押していたキーが押しっ
ぱなしになるのを防いだ。
'00/01/27 補数演算子(~)をマニュアルに書き忘れていた。しかも、その動作がバグってた:p
// 1.01
'00/01/24 マウスを押し下げたままウィンドゥ外に持って行き、再度戻したときに
GetMouseInfoが嘘を返すBug-fix。
'00/01/20 SaveBitmap関数追加。(Thanks > questさん)
'00/01/12 配列で文字列を初期化子に使用した場合、うまく初期化されていないbug-fix。
'00/01/11 joystickで5ボタン以上のときのbug-fix。(カイネさんあんがと!)
'00/01/10 MIDI出力でGS,GM,GM2の初期化処理追加。細かなbug-fix。
'00/01/09 SetWaveFormatをSetFormatとマニュアルに誤記していたのを修正
TextBltの引数の数をマニュアルに誤記していたのを修正。
// 1.00
'00/01/06 ScriptSDKへのExport機能を完成。
'00/01/04 SetFillColorRGB追加。
'00/01/03 モノクロ,16色等のビットマップ読み込み対応。
256色ビットマップ読み込み強化。
'00/01/01 プライマリサウンドバッファの周波数設定のためSetWaveFormat追加。
'99/12/31 sprintf0~3をマニュアルから削除。sprintfに統一。
'99/12/30 MIDI DEVICEのopen/closeタイミングの処理変更。
*p = *p / 10;などがうまくコンパイルされないbug-fix。
(*,&,単項-の優先順位修正)
// Finalβ(WAFFLE制作/『懇願』に使用)
'99/12/05 Jump文でジャンプラベルの省略を可能に。
MIDIの初期化の不都合修正。
配列変数の添え字省略がエラーにならない等のbug-fix。
// Finalβpreview1
'99/12/02 if文で()をつけなくてもエラーにならなかったbug-fix。
'99/12/01 モザイクをかける機能MosaicBlt追加。
画面をフラッシュさせるFlushBlt追加。
セカンダリの転送オフセットの設定SetSecondaryOffset追加。
テーブル分岐命令(jump)追加。
'99/11/30 同一ファイル名のWaveを読み込んだときは、同一のバッファを共有する。
フォーカスを失ったときにサウンドのPauseがされないbug-fix。
'99/11/29 SwapToSecondary中にTextBltが動作しなかったbug-fix。
イニシャライザで定数設定が出来ていなかったbug-fix。
'99/11/28 フォーカスを失ったときにPauseTimeされていなかったbug-fix。
'99/11/25 MIDI出力改善。
'99/11/09 JoyStick2を認識していなかったbug-fix。
// β8
'99/11/08 §2-21,§2-22追加。
MessageBoxをSetConstParamで出せるようにした。
CD関数としてEjectCDを追加。
ScreenSizeの取得をGetConstParamに追加。
窓の移動をSetConstParamに追加。
'99/11/07 ClearSecondaryRect追加。
User関数呼び出しのあと;がなくてもコンパイルが通るのを修正。
イニシャライザのコンパイルエラーで停止しないバグ修正。
'99/11/06 TextBlt(),TextGetSize()追加。
'99/11/05 各種初期値をイニシャライザで変更可能にする。(SetConstParam)
'99/11/04 起動するまでのウィンドゥサイズがおかしかったのを修正。
BlendBltのFull Colorモードにおける透過キーのbug-fix。
'99/11/01 マニュアルのミス、数箇所修正。
// β7
'99/10/23 Mouse入力サポート(MouseLayer)
MIDIのループ制御が機能していなかったのを修正。
Waveのヴォリューム変更機能追加。
'99/10/22 ".."による駆け上がりパスをサポート。
'99/10/21 マニュアルまとめなおす。
'99/10/20 起動フォルダを得るGetCurrentDirectory,SetCurrentDirectory追加。
'99/10/19 →文字列操作は、yanestr.dllとして分離。
'99/10/17 セカンダリバッファを他のプレーンと入れ換える機能追加。
'99/10/16 x=a/b/c;とかの不都合修正。
簡単な文字列操作LeftStr,RightStr,MidStr,LenStr,CharAt追加。
'99/10/12 ファイルから一行読み出す機能追加(ReadLineToString)
文字列を数値化する関数追加(Val)
// β6
'99/10/11 EnableBlendColorKey追加。(ブレンド転送の透過カラーキー)
SetLoopModeMIDI()追加。
Key入力系のバッファ処理改善。
'99/10/10 文字のαブレンド機能追加(TextBlend)
'99/10/09 文字フォントが95とNTで異なる(ディフォルトフォントが異なるため、大きな文字に
していると横幅がかなり違ってくるようです)→MS ゴシックをディフォルトと変更しました。
TextLayerの章にあるTextFont()を参照してください。
'99/10/06 LoadLibrary,FreeLibrary,GetFunction追加。
変数()で、変数の示す関数を呼び出せるように拡張。
'99/10/05 起動パスに.が含まれていると、ファイルの読み込みに失敗するbug-fix。
位置指定の透過カラーキーを使っている場合、範囲外のチェックをしていなかったbug-fix
CallScript/JumpScriptのエラーハンドラを書く機能追加。
配列・変数の初期化子記述機能追加。(ただしグローバル配列変数のみ)
// β5
'99/09/15 a-(b*5) とかを評価すると、結果の符合が反転してしまうbug-fix。
'99/09/13 イニシャライザにデバッグオプション追加。
// β4
'99/09/12 planeのサイズを取得する関数追加。
配列の要素に対してアドレス演算子&が使えるようにする。例(&x[5]とか)
PauseTime/RestartTime/PauseTimeAll/RestartTimeAll追加。
new,delete追加。int追加(表記の上だけlongと意味は同じ)。
関数の引数に型指定を許す(型チェックはしていない)
initializer追加。
'99/09/11 while,do~while,++,--追加。
'99/09/09 for追加。
'99/09/08 &&,||,%%追加。
// β3
'99/09/07 圧縮ファイル対応。
'99/09/06 MIDIファイル対応。
'99/09/05 拡大縮小で透過キー有効になっていなかったのを修正。
'99/09/03 WindowsNTで描画のコマ落ちする不都合修正。
'99/09/02 SetColorKeyPosバグfix。
'99/09/01 前方参照型のローカルラベルのbug-fix。
'99/08/30 関数の引数としてポインタを使えるように(配列の受け渡しのため)
'99/08/29 LoadFile,SaveFile追加。
// β2(WAFFLE制作/『盗撮マニアact1.テレビ局』に使用)
'99/08/28 CD関連関数追加。CDPause処理変更。WaveのPause機能追加。
MIDIキー入力機能追加。
'99/08/27 スクリプトのプログラムサイズの上限を無くす。(必要サイズを読み込み
時に自動判別して、必要量だけ確保するように変更)
'99/08/26 Blt系の関数すべてに拡大縮小機能追加。
'99/08/25 CD情報取得機能追加
'99/08/24 CDループ再生の不都合修正
// β1
//////////////////////////////////////////////////////////////////////////////