RealBasic University

このコラムはStone Table Softwareのオーナーであり、またREALbasic Developerの編集者でもあるMarc Zeedar氏により書かれたものを、著者の許可を得て翻訳したものです。この翻訳はHREM Researchにより提供されています。この日本語版へのご意見はRBU-Jまでご連絡下さい。

URL: http://www.applelinks.com/rbu/052/
INDEXに戻る

Zoomer:パート I

「あなたはどうしてこんなにREALbasicに詳しいんですか?」私はよくこう聞かれます。しかし私の答えは簡単です――独学しました。

あなたはどのようにプログラミングを独学しますか?実験して、楽しんで、いろいろと試すでしょう。おそらくその中には、忍耐が必要となり、時には誰かの助けが必要になるものもあるかもしれません。しかし最終的には、プログラムを理解し、動かすことができます。

ある時は、このような実験はあなたの必要なやりたい実際のプログラムであり、またある時は私がスプライトについて勉強するために書いた簡単なShooting Galleryゲームのように、単に勉強のための場合もあります。このような場合は、ただ特定の技術について勉強する助けになるだけで、それ自身はあまり役に立つものではありません。

事実、私はそのようなREALbasicプログラムを何百も書きました。そうやって私は学んできたのです。特定の現象をテストしたり、何かをするときにはREALbasicを試してきました。そういうわけで、ここで忠告があります――今回私たちがやろうとしているものはあまり役に立ちません。しかし、なにかの勉強になると思います。

DrawInto

REALbasicには独特のコマンドdrawIntoがあります。初期バージョンのREALbasicではよく機能しませんでしたが、バージョン4では大部分のバグが改善されたようです。

オンラインヘルプには次のような説明があります。

初めてこれに気がついた時は好奇心をそそられました。どうもこれはウィンドウの内容をgraphicsオブジェクトに書き出すようです。これで何ができるのでしょうか?pictureオブジェクトはgraphicsオブジェクトを含むので、ウィンドウをpictureとして描けるのです!

しかし、それのどこがいいのでしょう?私の考えた一つ目の利点は、一度pictureとしてウィンドウを取り入れれば、大きく描く、つまりウィンドウをズームするような使い方ができることです。これはすごい事だと思います。私はテキスト・フィールドを拡大して使うためのフローティング・ウィンドウを用意しました。それによって、ちょうど良いテキストサイズ(10または12ポイント)で表示しながら、別ウィンドウでズームしながら読むことが可能になりました。

これをテストするために私は簡単な実験としてZoomerを書きました。これはプログラムとしてどれほど実用的であるかは分かりませんが、とてもうまく動作します。しかも学習にも適しています。

Zoomerの作成

新しいプロジェクトを始めてください。それからeditFieldSliderコントロール、そしていくつかのstaticTextオブジェクトをデフォルト・ウィンドウの上にドラッグしてください。そして次のようになるように調整してみてください。

editField1の属性を次のように設定します。

editFieldにデフォルト・テキストを入力しておきましょう。それでテストがしやすくなります。だって空欄の editFieldをズームして見るのは無駄ですからね!

zoomSliderを次のように設定します。

ここでちょっとした小技を紹介します。StaticTextはコントロールとしては役に立ちません。結局それはただ情報を表示するにすぎません。しかし個別のコントロールとしてstaticTextを加えれば、コード・エディタ(Code Editor)ウィンドウはこのように散らかって表示されます。

しかしすべてのStaticTextに同じ名前を与え、コントロール配列(control array)にすれば、より見やすく単一のオブジェクトだけがコントロール・リストに表示されます。

だから私はすべてのStaticTextに"Label"と命名し、コントロール配列として番号を振らせました。これらのstaticTextオブジェクトには何も入力されていないので、実際の番号には関連がありません。しかし一番下(デフォルト・テキストの"4")は、ユーザがzoomSliderをドラッグすると動的に変化するので、その例外です。このstaticTextは次の属性が必要になります。(特に配列インデックスは3である必要があることに注意してください)

次に、ズーム用のウィンドウを作成する必要があります。ファイルメニューに行き、"New Window"を選択してください。そこに次のような設定をします。

何だと思いますか?これがzoomWindowに必要なものすべてです!いかなるコードも含んでません!

どうしてそんなことが可能なのでしょうか?それはすべてがwindow1の中で行われているからです。そこから私たちは何がzoomWindowによって表示されるかを制御します。この欠点は、zoomWindow自身がどのように自身を描画したらよいか知らないので、適切に再描画できないことです。(実際のプログラムでは、あなたはこれと違った方法を採りたいかも知れませんが、今はただ実験しているだけなのでこれで良しとしましょう。)

コードを加える

window1に2つのメソッドを加えることから始めましょう。最初にzoomAmountと呼ばれるメソッドを作成します。このメソッドは現在のズーム・レベル(zoomSliderコントロール経由の設定)を返すだけです。

エディット・メニューに行って"New Method"を選択し、zoomAmountと命名します。リターン・タイプ(return type)はDoubleとします。それから次のコードを入力してください。

   label(3).text = str(zoomSlider.value / 2) + "x" 
return zoomSlider.value / 2

ここではzoomSliderの値を調整しています。sliderコントロールには小数値はなく整数値でしか動かせないので、このようにする必要があります。zoomSliderの最小値と最大値を欲しい値の2倍に設定し、それから現在の値を2で割ります。そうすれば、望む範囲内の値で1.5×、3.5×等のような値までも設定できるようになります。

第1行目は、現在の倍率を表示するためのstaticTextディスプレイを設定します。第2行目は、計算後の現在の倍率を返します。簡単ですね。

さて今から、プログラムの中心となる部分を作る必要があります。このメソッドは拡大された領域を描画するものです。今のところ、空のメソッドを用意しておきましょう。エディット・メニューから"New Method"を選択し、パラメータをx as integer, y as integerとしてdrawZoomと命名します。

今のところはメソッドは空にしておいて、それは次のレッスンでやりましょう。ひとまずwindow1コード・エディタ内のEventリストに行ってください。mouseMoveと呼ばれるeventを探して、次の1行を入力してください。

 drawZoom(x, y) 

これで、window1内のマウスが動くたびに、拡大されたウィンドウを再描画するようプログラムに伝えました!

しかし、editFieldでユーザが文字を入力している時、マウスは動かないですよね?だからControlsエリアへ行き、editField1タブを拡張し、selChangeイベントに行きます。そこで次を入力します。

 drawZoom(system.mouseX - window1.left, system.mouseY - window1.top)

ひゃあっ!何ですかこれは?

よろしい、では始めに座標についてのミニ講座をしましょう。座標はスクリーン上で個々のピクセルを表す水平成分(x)と垂直成分(y)の値です。しかし、中には異なった座標系もあります。複数のモニターを含むスクリーン全体における座標系であるグローバル座標系と呼ばれるもの、ひとつのウィンドウやオブジェクトを表す座標系であるローカル座標系と呼ばれるものがあります。

例えば、次の図では黄色の領域はスクリーンを表します(見て分かるようにとても小さなスクリーンですね)。

すべてのxyの値はグローバル座標です。しかし、ウィンドウ内のcanvasオブジェクトを表す白い四角の部分では、lxlyの値はローカル座標です。このような場合、それらはウィンドウに対して局所的です。(これはウィンドウの描画領域(drawing area)だけであることに注意してください。すなわち、 ウィンドウのタイトル部は座標領域には含まれません。)

canvas内で赤い円を描きたい場合は、canvasに関連するローカル座標で描きます。つまり、g.drawOval(10,10,30,30)canvasの左上端から内側に10ピクセル下、10ピクセル右にある30ピクセルの正方形中に円を描きます。

これは、どこで座標の情報を入手したか、またどんな座標系を使おうとしているのかに注意しなくてはならないことを示しています。場合によっては、ある座標系から別の座標系に変換させなければならないかもしれません。

それこそいま私たちの直面している問題です。2つの座標を要求するdrawZoomルーチンにはウィンドウ座標が必要です。しかしmouseMoveではそれは問題にはなりません。つまり、mouseMoveイベントを通るxyの値は、ウィンドウにおける座標なので、それをそのまま渡せば良いのです。

しかし今はselChangeイベントでは使えるウィンドウ座標がありません。その代わりに、グローバル座標を返すsystem.mouseX関数とsystem.mouseY関数を使用します。そして、これらをウィンドウ座標に変換しなければなりません。

変換は簡単です。グローバルのxy座標からウィンドウのlefttop属性を差し引くだけです。図を振り返って見てください。ウィンドウの左上部は42,77ですね?ウィンドウ幅の240からグローバル座標を引いてみてください。240-42=198ですね。だから、198は(ウィンドウ座標中における)ウィンドウ右端のピクセルになるでしょう!

詳細

私の図中の数字は近似値になっています。REALbasicの計算は正確ですが、私の計算はウィンドウの境界のようなものを考慮していません。しかし伝えようとしている一般的な理念は正確です。

座標系についてもっと詳しく知りたい場合は、私の書いた簡単なテストプログラムtestcoords.rbで遊んでみてください。マウスを動かすと、次のようにローカル座標とグローバル座標を表示します:

ですから、selChangeイベントで行っていることはグローバル座標をウィンドウ座標に変換し、それをdrawZoomルーチンに受け渡すことです。

ふうっ!今日のレッスンはこれでおしまいです。来週から実際に拡大した領域を描画することにしましょう(これはちょっと複雑です)。どんな感じだかお伝えするために、プログラムの動いている様子を次にお見せします。

今週のREALbasicチュートリアルの完全なプロジェクト・ファイル(リソースを含む)を入手したい場合は、ここからダウンロードしてください。

次週

Zoomerを仕上げます。

REALbasic Developer Magazine 最新情報

数週間前、私は今夏〔2002年夏〕に立ち上げを予定している新しい雑誌REALbasic Developerを公式にアナウンスしました。何人かの方が、チャーター購読者〔先着500名の定期購読申込み者は半額になるサービス〕になることを選んでくれました。あなた方の援助に感謝するとともに、非常にうれしく思います。チャーター購読は私が予想したよりも多く、すばらしいことです。

チャーターメンバーの提供は終了しましたが、25%割引の早期予約購読を始めました。定期購読に興味があるならば、今すぐ〔2002年4月時点〕に定期購読を申し込むことによってお金を節約することもできるし、この雑誌の支援にもなります。7月になって雑誌を正式に出版し始めると、定期購読価格は通常価格になります。

その他のニュースは、私たちはこの巨大ベンチャーの中でとても大きな進歩を遂げているということです。著者たちはいくつものすばらしい記事を書き、これを最良のREALbasicの出版物としてだけでなく、歴史に残るような雑誌とするために日夜忙しく働いています。さらなる最新情報は、進展に応じてこのコラムでお知らせしましょう

Letters

先週は、Ribnik医師からお問い合わせいただいたMac OS Xのコラム・ビューに似た情報を表示できるRBクラスについての質問に、私は分からないと答えました。しかし私が予想したように、そのようなものが存在することをOwenさんが知らせてくれました。

OS Xのコラム・ビューのRBクラスに関する質問のメールに対してのあなたの返事を読んだときに、私はちょうどそのようなものを以前に見たことがあることを思い出しました。確かOpenBroserか何かと呼ばれていたと思います。とても優れた外観でしたが、残念ながらGoogleで検索しても見つかりませんでした。しかしながら、私はAmar Sagoo氏によるColumnBrowserを見つけました。それは、この初期の頃のバージョンで、高度な機能(例えばファイルやフォルダーのファインダ・アイコンがない、ファイルが選択されたときに前回のコラムについてのファイル情報がない等)は一切ついていません。けれどこれは基礎的な導入には向いているので、お知らせしておこうと思いました。次はそのリンクです。

http://www.realbasic.com/learn/programmers/Class/ListBox/Premier.html

-- Owen

「初めに、宇宙は創造された。これは多くの人の怒りを買い、悪い動向だと広く見なされていました。」―宇宙の果てのレストラン、Douglas Adams著(1952-2001)

Owen、どうもありがとう。Douglas Adamsを署名の中で引用する人に悪人はいませんよ!;-)

次に、Svenからのいくつかの難題が届いています。

いかがお過ごしですか?私はつい最近REALbasicを始めました。私はバージョン4.02をMac OS X (10.1.3)の上で走らせています。今までのところ、スプライト・アニメーションが機能しなかったり、その他の複雑な問題に直面していますが、RBUは非常に役に立つものだと思っています。しかし、私の質問はそれとは別のところにあります。

私はPhoenix芸術学校でゲームアートとゲームデザインを学んでいます。だからゲーム・コンセプトについては豊富なアイデアがあります。私にはやりたいプロジェクトがあり、しばらく前から開発を進めてきました。私はいくらかのBASICの知識はあります。しかし、BASICでコーディングしてからもだいぶ時間がたっているので、OOP〔オブジェクト指向プログラム〕に移行するのに手を焼いています。

私は次のようなことを行うためのヒントが必要です:私はREALbasicプロジェクト・ファイル内のフォルダーをスキャンし、そこにあるアイテムの数を数え、名前を検索し、その使用に先立ってすべてをロードすることのできるスプライトのためにあらかじめバッファーを作成する必要があります。私はプログレス・バー(progress bar)にそれを実装しようとしましたが、やりたい様にはうまくいきませんでした。私は外部のフォルダーからコンテンツを引き出し、いくつのファイルがあるかカウントし、その名前を検索することはできますが、それらをどのようにバッファーすればよいのか分かりません。

それからスプライト・アニメーションについて助けて欲しいことがあります。私は、例として3〜6フレームの左に歩くセット、あるいは3フレームの飛び上がるセットといったマルチフレーム・オブジェクトを使いますが、これを実行する際にまたいくつかが必要になります。さらにスプライトやスプライト・フレームにマスクを適用しなければなりません。

別の質問ですが、たとえばゲームのオプション・ウィンドウのようにユーザーのモニター設定をどのように変更するのか教えてください。また2つの絵を重ねてフェイドさせるクイックタイム処理ではなく、デスクトップの黒い画面からプログラムのオープニングまで次第にフェイドさせ、さらにゲーム画面に移るまでその効果をまた使えるようにさせるにはどうしたらいいか知りたいです。これを行うために、画像の明るさを落としたりするような他のモニター設定を同様に利用することは可能ですか?それとも他にもっとよい方法があるのでしょうか。

私はすでにたくさんのものを描き上げましたが、まだ何百ものグラフィックスが必要です。私は、ゲーム動作、統計的設定、キャラクター作成に苦心してきましたが、まだまだ先は長いです。そのたびに勉強し、その知識を頼りに応用しようとするのですが、特にそれがうまくいかないときはイライラします。いまのところは3歩進んで2歩下がるといった具合です…

いろいろと助けていただきどうもありがとうございます。このゲームは全体の一部分に過ぎませんが、小さなところから一つ一つ積み上げていこうと思います。

(今後、その多くがピクセル同士が触れた時の判定に基くことはできないので、ワールドマップと衝突検知の相互作用について尋ねたいです。さらにカーソルによってアイコンを選択し、それを備品棚(手、胴、頭など)にドラッグ&ドロップし、その統計情報や修正データを読み出すことのできる在庫システムについてもお尋ねしたいと思います。)

あなたの支援に心から感謝します。

-Sev Gerk

私が教えたスプライトがうまく機能しない問題は、Mac OS Xのスプライトはいくつかの問題が報告されているので、おそらくそのためでしょう。さらに最近のバージョンのRBでは、私の古いコードでは問題がおきるような変更がスプライトになされたかもしれません。近々、スプライトに再び立ち返り、そのプロジェクトがうまく実行できるようにするでしょう。

あなたの質問に関して:まず始めにあらかじめバッファーし、画像に持ち込むことについては、外部ソースからの画像に関する似たような質問に対しての詳しい回答を最近行いました。それはスプライトに関してではありませんが、原理的には同じことです(なぜならスプライトはそれがどう見えるかを決定するためのpictureオブジェクトが必要なだけです)。私のCharlesさんへの返答を読んでみて下さい。Lesson 043にあるので、それが応用できるかどうか試してみてください。

次に、スプライトにマスクを適用できるかという質問:白を透明色として設定するか、または画像にマスクを設定し、その画像をスプライトに割り当てます。(マスクについての詳細はオンラインヘルプのpicture.maskを参照してください。)

最後に、ユーザーのスクリーン設定をコントロールする質問:これは宣言(Declare)によってできますが、おそらくプラグ・インを使用した方がよいでしょう。すぐにはどこにあったか思い出せませんが、以前に見たことがあるので、それが使えると思います。Googleで検索してみて、あなたが使えそうなものを探してみます。(読者の中でこのプラグ・インをご存知の方はお知らせください。来週ここで公表しましょう。)

それから将来の衝突検知のような質問に関してですが、その頃にはあなたはREALbasic Universityの範疇に及ばないほど十分に知識を兼ね備えていることでしょう。ここでは伝えられないもっと高度な情報を提供するREALbasic Developerマガジンを購読することをお勧めします。RBDにはQ&Aコラムがあり、この様な質問にも完全に対応できるでしょう。


RBU-Jの通知サービス!コラムが発表されるたびに日本語版REALbasic Universityのお知らせの emailがあなたに届きます。登録・削除は ここ から。

INDEXに戻る