Getting Started
筆者: RayDunakin@aol.com
1995/11/26 改訂
注:これらの文書は複数のフォントとスタイルを使えるSimpleTextで書かれました。これで読みやすくなります。この文書の見出しが太字に見えない場合、終了してSimpleTextで開いてください。TeachTextをハードディスクから削除してSimpleTextに置き換えたいと思われることでしょう。
World Builderについて
World Builderは最初1986年に発売されました。二、三年後に発売は中止され、このプログラムは数年間絶版状態で入手不可能でした。1995年8月7日になって、World Builderの創造者であるBill Appletonはこれをパブリック・ドメインにしました。私がこれらのファイルと一緒に送ったバージョンは32ビットに対応すべく私の手によって変換されたものです。つまり、これはどんなマックでも動くということで、あなたがこれで作ったゲームも同様でしょう。ただし、サウンドを担当するハードウェアの変化のために、サウンド機能はAVマックとPowerMacでは働きません。
このファイルはWorld Builderアプリケーション、World Template、Sound Converterそしてサンプルのsound libraryを含んでいます。私はみなさんがWBを十分に使うのに役立つテキストファイルもいくつか書いておきました。これらのファイルを配布するときは、それらを一まとめにしてください。
始め方
元来、ゲーム作りは最初にWorld Templateのコピーを作ることから、でした。しかし、私が新しいテンプレートを作り、それにサイズ変更済みのテキスト・ウインドウ、いくつかの特別なグローバル・コード、一組の有用なオブジェクトが含まれています。便宜上どちらのテンプレートもこのファイルに入っていますが、私のテンプレートの方が助けになると思います。
World Builderでゲームを作り始めるには、最初にRay's World Templateを複製してください。その複製に自分のゲームにつけたい好きな名前をなんでもいいのでつけてください。それからそれをWorld Builderで開いてください。
空のシーンがすでに一つ作られています。このシーンのシーン/テキスト・ウインドウはサイズと位置が標準よりも大きく、見やすいように変更されています。シーンを増やす際に"Create"ボタンを使わないでください! その代わり、この空のシーンをコピーして必要なだけそのコピーをペーストしてください。
内蔵されているドローイング・ツールを使ってシーン・ウインドウの中にシーンの絵を描いてください。ほとんどの場合、場面の説明はシーンのテキストウインドウに書かれるのですが、場面の説明をシーン・コードの一部にした方が良い場合もあります。例えば、場面の中に変化するものがあって、ゲームの経過の中で場面の説明を変えなくてはならないときがそうです。その他に、テキストウインドウに書かれた説明と特別な状況でそれを覆えすシーンコードの両方必要である場合もあるでしょう。
シーンデータを使って東西南北方向の進行を阻みます。ある方向がブロックされていると、シーンの四角のその側が太い線になります。ブロックされている方向への進行、あるいは上下移動はシーンコードを使って実現します。例えば:
IF{TEXT$=UP}THEN
MOVE{PLAYER@}TO{UPPER ROOM}
EXIT
キャラクター
キャラクターもあらかじめ一人作られています。あなたのゲームに合うようにキャラクターの名前を変えなくてはいけません。プレーヤーキャラクターには絵が必要ありません。ゲーム中に出てくることはないからです。キャラクターデータを注意深く点検してください。そこに、クリックすることによってゲームに対し、そのキャラクターがプレーヤーキャラクターなのかどうか、それが「彼」なのか「彼女」なのか「それ」なのか、そして、名前は適切な名詞かどうかということを教えるためのボタンがあることに注意してください。
プレーヤーキャラクターのデータに最初のシーンの名前を記入することを忘れないでください。この作業によりゲームがそのシーンから始まるのです。非プレーヤーキャラクター(NPC)は、コードによってゲームの中に呼び出されるまではSTORAGE@で控えています。または、あなたが彼らのデータへシーンの名前を入れれば、彼らは最初にそのシーンに登場します。
データの残りはキャラクターの強さ、スピード等を決定します。あなたはそれらを変えたいと思われるかもしれませんね。
キャラクターメニューを使ってあなたが作った他のキャラクターはすべてプレーヤーの敵だとみなされます。プレーヤーが彼らに出会うと、彼らは攻撃してきたり、逃げ出したり、何かをプレーヤーに差し出そうとしたりします。こうした非プレーヤーキャラクターについて行える唯一のコントロールは彼らのデータの調整により行われます。非常に制限されているのです! 私はこの理由で、みなさんが「正真正銘の」キャラクターはマイナーな動物、コウモリ、ねずみの類にだけ使用することを強く推奨するのです。真のアドベンチャーゲームにとって、ほとんどのNPCを表現するためにオブジェクトを使い、必要な反応をすべてコードでまかなう方がずっと望ましいのです。この点についてさらにまた後で...
オブジェクト
オブジェクトには動くものと動かないものがあります。動かないオブジェクトでクリックできるオブジェクト、簡単なアニメーションなどを作成できます。それらはシーン/グローバルコード通りにしか動かすことができません。動くオブジェクトはプレーヤーがその上でクリックするだけで取ることができ、自動的にプレーヤーの持ち物になるものです。オブジェクトデータの中で、それがどういう種類のオブジェクトなのか、どのシーンで登場するのか、どのキャラクターが運ぶのか指定できます。使用回数、発生するサウンド、それが武器なら与えるダメージ、「使い切った」ときに何が起こるのか特定できます。これらの事柄の多くはシーンまたはグローバルコードでまかないます。
コード
ゲーム中のほとんどすべての行動はコードが扱います。World Builderゲームで使われるコードは二種類あります:シーン・コードとグローバル・コードです。シーンコードはゲーム中の大抵のコードが該当します。そのシーン内の行動だけを扱います。といっても、シーンコードを使って、ゲームの残りの部分へ持ち越す変数を設定したり変化させたりすることもできます。
グローバルコードはゲーム中いかなる場所でも起こりうること、そして標準プレーヤーコマンドに対する「あらかじめ用意された」反応のためにあります。たとえば、「Search」は共通のコマンドです。プレーヤーはあらゆる場所でsearchしなければいけません。ほとんどのシーンにおいて特に見つけるものはないでしょう。そして、標準的な応答はコード中に次のように書かれるのです。
IF{TEXT$=SEARCH}THEN
PRINT{You find nothing of interest.}
EXIT
しかし、すべてのシーンにこれを書くのは時間と領域の浪費ですので、代わりにグローバルコードに書く方がいいのです。プレーヤーが探索中に何かを発見するときは必ずシーンコードに書きます。
重要:"Ray's World Template"にはあなたが自分のゲームに取りかかりやすいように仕立てたグローバルコードがいくつか入っています。そのうちのいくつかはあなたには不要かもしれません。もっと詳しく理解するには、 "Global Code Info"テキストファイルを読んでください。
残念なことに、各シーンコードとグローバルコードにはテキストが10,240文字までという厳格な制限が存在します。これは十分に思えるかもしれませんが、そうではないのです! 私は自分の複雑なアドベンチャーについていつもこの制限にぶち当たってしまいます。ですから、グローバルコードに収める事について十分慎重になってください。いくつかのケースで、私はスペースを節約するためにグローバルコードに収めるような事柄を代わりにシーンコードに書いたことがありました。たとえば、プレーヤーがある地域で謎を解くために必要な特定のオブジェクトがあったとしたら、私はプレーヤーがそれをその地域外に持ち出す能力を制限する論理的な方法を考え、そのオブジェクトに対応したコードをそれらのシーンにのみ書くようにします。
この書類とともに含まれているものはWorld Builderの利用とコードの書き方についてさらに説明したテキストです。それらをじっくり学んでください!
World Builderで他のWorld Builderゲームを開いて、そのコードがどうなっているか確認してください。私は"A Mess O'Trouble"のコードを学ぶことを強く勧めます。それが現時点で最もきれいで進んだコードだからです。"Ray's World Builder Demo"もいいですよ。これは短くて簡単なゲームで、基本的なWBプログラミング技術に加えてすべてのシーンおよびグローバルコードの詳しい説明を見せるようデザインされています。Syntax TutorialとVariables Tutorialという書類を必ず読んでください。
書き方
優れたアドベンチャーゲームを作り出すというのは単にコードの書き方を知ること以上のことです。話がうまくないといけないし、面白い謎を物語に取り入れなくてはいけません。もしもあなたが怪物と闘う以外なにもないゲームを作るなら、それは全然見込みなしです。ただキャラクターメニューに化け物の群れを作って、プレーヤーに彼らと闘わせるというのはアドベンチャーゲームを作る道ではありません。それがほんとにあなたの作りたいゲームであるなら、別のプログラムを探してください。
World Builderを使ってDOOM 3!を作ることはできませんよ! プログラムの限界のためにDoomみたいなゲーム、それどころかたいていのRPGにも向いていません。動くものすべてを爆発させながら回廊を走り抜けるのはDoomのようなフル・アニメーションの環境ではすばらしいです。しかし同じことがWorld Builderゲームではこのようになります:あるシーンから別のシーンに移動する、化け物の静止画と出くわしたので、ウェポン・メニューをプル・ダウンし、化け物がそのシーンからいなくなるまで"Fire pistol"を何度も何度も選択する、そいつがあなたを真っ先に殺さない限りです。しかも普通はそうなってしまうのです。まちがいなくそんなのぜんぜん楽しくないです!
良質のWBゲームは良質のストーリー、良質の謎、そして最小限の死がなければいけません。あなたのゲームにたとえ怪物やその他の化け物が用意されていたとしても、ゲームを彼らをやっつけるための謎にしなくてはいけないのです。言い換えると、プレーヤーはただウェポン・メニューを繰り返し使うのではなく、自分の頭を使わなくてはなりません。そういうものは本当に落ち着いた、本当に色褪せないものになります。
あなたの手助けのため、私はアドベンチャーゲームのデザインと記述の創作過程を扱ったいくつかの書類を同封しました。
WBプログラミングとアドベンチャーゲームの作成についてのより詳しい情報はシェアウェア・レビューの中の私のコラムをご覧ください。
WB プログラミング・コード
テキスト変数:
CLICK$=(オブジェクトまたはプレーヤーがクリックした登場人物の名前)
TEXT$=(プレーヤーがタイプした、またはコマンドメニューから選んだコマンド)
数値変数:
LOOP# (現在の場面でプレーヤーが与えたコマンドの数)
RANDOM# (1と100の間の無作為に決まる数)
VICTORY# (殺された登場人物の数)
VISITS# (プレーヤーが訪れたシーンの数。繰り返し訪れた分を含む)
PHYS.ACC.BAS# (プレーヤーの元々の体の具合)
PHYS.ACC.CUR# (プレーヤーの現在の体の具合)
PHYS.ARM.BAS# (プレーヤーの元々の体の防御力)
PHYS.ARM.CUR# (プレーヤーの現在の体の防御力)
PHYS.HIT.BAS# (プレーヤーの元々の体のヒットポイント)
PHYS.HIT.CUR# (プレーヤーの現在の体のヒットポイント)
PHYS.SPE.BAS# (プレーヤーが元々持つ体の速さ)
PHYS.SPE.CUR# (プレーヤーが現在持つ体の速さ)
PHYS.STR.BAS# (プレーヤーの元々の体の強さ)
PHYS.STR.CUR# (プレーヤーの現在の体の強さ)
SPIR.ACC.BAS# (プレーヤーの元々の精神的確かさ)
SPIR.ACC.CUR# (プレーヤーの現在の精神的確かさ)
SPIR.ARM.BAS# (プレーヤーの元々の精神的防御力)
SPIR.ARM.CUR# (プレーヤーの現在の精神的防御力)
SPIR.HIT.BAS# (プレーヤーの元々の精神的ヒットポイント)
SPIR.HIT.CUR# (プレーヤーの現在の精神的ヒットポイント)
SPIR.SPE.BAS# (プレーヤーの元々の精神的速さ)
SPIR.SPE.CUR# (プレーヤーの現在の精神的速さ)
SPIR.STR.BAS# (プレーヤーの元々の精神的強さ)
SPIR.STR.CUR# (プレーヤーの現在の精神的強さ)
ワールド変数:
PLAYER@ (プレーヤーキャラクター)
MONSTER@ (いる場合、現在のシーンのプレーヤー以外の人物)
RANDOMCHR@ (不作為に選ばれる人物) <これは使い道がない
RANDOMOBJ@ (不作為に選ばれるオブジェクト) <これも使い道がない
RANDOMSCN@ (不作為に選ばれるシーン) <これによりプレーヤーを不特定のシーンに移動させられる。
STORAGE@ (使用されないときはオブジェクトと人物が格納されている見えない部屋のようなところ。プレーヤーを死なせたり、ゲームを終わらせたりするときはプレーヤーをSTORAGE@に移す。)
条件文:
IF/THENを使った記述で何が起こるのか、どんな反応があるのか決定できます。次のように記述します:
IF{TEXT$=UP}OR{TEXT$=CLIMB}THEN
MOVE{PLAYER@}TO{UPPER ROOM}
EXIT
次のように複数の文章を入れ子にすることもできます:
IF{TEXT$=UP}OR{TEXT$=CLIMB}THEN
IF{CLIFF.ROPE=SCENE@}THEN
MOVE{PLAYER@}TO{LEDGE}
EXIT
PRINT{The cliff is too steep to climb.}
EXIT
プレーヤーがコマンドを打ち込んだりマウスをクリックしたりするたびに、プログラムは行わなければいけないものがなにかないかとシーンコードを物色します。満たされる条件文に出会えば、コードのその部分で必要とされることをなんでもします。各構文はEXITかENDが後ろになければいけません。ENDはこの特定の文が終わること、しかし、実行されるべき他のことがないかどうか確かめるためにプログラムがシーンコードの残りを続行することを許すことを示します。シーンコードを一通り見た後、それまでにEXITによって停止されていなければ、プログラムはグローバルコードで調べを続け、実行されなければいけない他の条件を検査します。
次の例のように、必要なところではどこでもEXITかENDを使えます:
IF{TEXT$=UP}OR{TEXT$=CLIMB}THEN
IF{SECRET.LADDER=SCENE@}THEN
MOVE{PLAYER@}TO{HIDEOUT}
EXIT
END
この例では、プレーヤーが上に上がろうとしたときに秘密の梯子がすでに見つけられていないと、プログラムはこの文を無視してグローバルコードへ進みます。グローバルコードで標準的な反応を記述します。
IF{TEXT$=UP}OR{TEXT$=CLIMB}THEN
PRINT{You can't go up here.}
EXIT
ANDやORで複数の条件を一文の中で結合できることに注意してください。ただし、同一の文中でANDとORの両方を使うことはできません。例えば次のようにはできます:
IF{TEXT$=SHOOT}AND{PISTOL=PLAYER@}THEN
IF{THING.1=SCENE@}OR{THING.2=SCENE@}THEN
SOUND{GUNSHOT}
PRINT{Your bullets bounce off the creature without harming it!}
EXIT
END
しかし次のようにはできません:
IF{TEXT$=SHOOT}AND{PISTOL=PLAYER@}OR{TOMMYGUN=PLAYER@}THEN
上のいくつかの例において、テキストウインドウにテキストを表示させる方法を理解できます。サウンドを鳴らしたり人物やオブジェクトを移動させたりするのも同じように扱われます:
SOUND{BOOM.1} ("BOOM.1"は単なる例です。鳴らしたいサウンドの名前を自由に記入できます。)
MOVE{OPENDOOR.1}TO{SCENE@}
MOVE{BLANKET}TO{BEDROOM}
MOVE{GARGOYLE}TO{DUNGEON}
MOVE{PLAYER@}TO{STORAGE@}
ユーザー変数:
ユーザー変数は234個あります。これらはプログラマがイベントなどを追跡するために使う数字です。A1からA9、B1からB9といった具合にアルファベットだけあります。自分のゲームの中でどういう変数を使っているのかしっかり把握してください! もしも誤って同じ変数を二つの異なる事柄に使ったりしたら、ゲーム中にまずいことが起きるでしょう。そして、この手の問題を突き止めて解決するのは大変な苦痛にもなりえるのです。私はみなさんが変数を管理しやすいようにプリントアウトが可能なユーザー変数表を同封しました。あなたが使う各変数の隣にメモしてください。それがなんのために使われるのか、どういうシーンで使われるのかを。
それから、B4#は不良です。これはプログラムのバグです。使ってはいけません!
変数の設定はこうします:
LET{A1#=1} (各変数はどんな数も取りえます。1は単なる例に過ぎません。)
IF/THEN構文の一部にもなります:
IF{TEXT$=DRINK}THEN
LET{W1#=95}
PRINT{The water quenches your thirst.}
EXIT
ゲームの開始時点で、すべてのユーザー変数は0ではなく、1未満になっています。ですから、プレーヤーがある行動をとったかどうか知りたいときは、コードを次のように書いてください。:
IF{M4#<1}THEN
次のようにしないでください:
IF{M4#=0}THEN
変数を設定する別の方法がいくつかあります:
LET{A1#=A1#=1} (これはカウンタです。プレーヤーがある特定の行動をするたびに増えるようこれを記述の一部にすることができます。またはそれ自身で使えば、プレーヤーがあるシーンで何をしようとポイントを増加させられます。)
LET{A1#=A1#-1} (上と同様ですが、増加ではなく減少させます)
LET{A1#=H4#} (ある変数の総計を他の変数に渡します。)
LET{A1#=B1#+B2#} (別の二つの変数の合計を代入します。)
LET{A1#=RANDOM#} (1から100までの不作為に選ばれる数を変数に入れます。)
これらの問題の詳細な説明についてSyntax TutorialとVariables Tutorialを必ず読んでください。
WBプログラミングについて何か質問があれば、電子メールのRayDunakin@aol.comを通じて私と連絡がとれます。