RealBasic University

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

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

REALbasic アニメーション:スプライト入門

私が最初にコンピュータを使い始めた1980年代中頃は、グラフィックスのプログラムは非常に複雑でした。簡単なアニメーション -- スクリーンを横切る動きの無い宇宙船のような -- さえも容易ではありませんでした。グラフィックをある場所に描いて、それを消し、そして別の場所にもう一度描くということをしていました。もし、宇宙船の後ろに背景画像がある場合には、宇宙船を消すということは背景をも消すことになるので、そのような方法は新たな問題を引き起こしました。

別の問題はタイミングでした:もし、複数の物体を同時に移動させようとすると、すべての同期をとるための太鼓手のようなものが必要になります。私はその鼓動がコンピュータの速度に依存しない骨の折れる方法を見つけました。私の作ったアニメーションゲームは、2倍速のアクセラレータをコンピュータに付けるまでは上手く動きました:なんと私のアニメーションは以前の2倍の速さで動き、ゲームが出来なくなりました!

それ以上にやっかいなのは2つのアニメーション物体が衝突するのを検出する方法です。衝突の検出はそれをプログラムしようとするまではそれほど難しいとは思われないでしょう。、しかし、全体がその問題を扱っている本があるくらいなのです!扱う物体の形状が正方形か長方形であれば、それほど困難ではありません。しかし、奇妙な形の物体である場合には、それは本当に厄介なものになります。例えば、町並みの超高層ビルの屋上につきたっているアンテナに宇宙船がいつ衝突するかを知りたいときなど。(あなたが数学愛好者でないかぎり、3次元の衝突検出については考えたくもないでしょう。)

もちろん、ゲーム開発の専門家はアニメーションの作成を容易にするソフトウェアを使っています。幸い、現在の REALbasic はそのような機能を持っています。まず、スプライト sprite と呼ばれる特別なオブジェクトが追加されました。スプライトとはどんなものなのでしょうか?スプライトはアニメーション画像です。通常、それは宇宙船のようなアイコンです。スプライトが素晴らしいのは、実際のスプライトの描画、消去そして移動という全ての技術的なことを REALbasic が処理してくれることです:あなたは自分のプログラムの内容、すなわちスプライトが行なうことについてのみ考えればいいのです。

例えば、スプライトはそれがスクリーン上に置かれる位置を制御する x および y 属性を持っています。スプライトを移送させるには、ただ x および y 属性を変更すればいいのです!

さらに素晴らしいことは、REALbasic が同期の問題を同様に処理してくれます。スプライトは スプライトサーフェイスspritesurfaceと呼ばれる別の特別な RB のオブジェクト上に描画されます。スプライトサーフェイスはスプライトのための描画領域のようなものです。スプライトサーフェイスオブジェクトは、アニメーションの次のフレームを描画しなければならない時にいつも呼ばれる NextFrame というイベントを持っています。これは、あなたが NextFrame イベント内ですべてのスプライトを更新すれば、すべてのあなたのオブジェクトが同期して動くということを意味します。

あの有名な Space Invaders(スペースインベーダ)のようなゲームを考えましょう。憶えていますか?そこにはスクリーン上で格子状に並んで素早く前後に移動し、徐々にあなたの宇宙船に向かっておりてくる邪悪な宇宙船の大群があります。それを REALbasic で実現するには、スプライト(邪悪な船)の配列を作ります、そしてそれらの位置を初期化します(ゲームが始まったときにそれらが現れる場所を設定します)、それから、それぞれの NextFrame イベントで船を適切に移動させます。異なる種類の船にはことなるふるまいをさせるというように複雑にすることも可能です。その場合には、あなたのスプライト配列は船の種類などの特別な属性を含むことになり、そして移動のコードは異なる船を異なるように移動させることができるでしょう。

最後に、REALbasic は衝突の問題をもまた非常にスマートな方法で処理してくれます。あなたが作成したそれぞれのスプライトに対して、グループコードを割当てることができます。このグループコードは整数(数値)です。もし、整数が値であれば、そのオブジェクトは他のどのような正のグループのオブジェクトと衝突します。もし、オブジェクトがグループゼロに設定されれば、それはどれとも衝突しません。もし、オブジェクトがグループのグループ値を持っていれば、それは負のグループオブジェクトとのみ衝突します。

あなたのスプライトサーフェイスオブジェクトは collision(衝突)イベントを持っています:任意の2つのオブジェクトが衝突すると、その collisionイベントが起ります。お互いに衝突した2つのスプライトは collisionイベントに引数として渡されますので、あなたはどの2つのオブジェクトが衝突したのかが判ります、そしてプログラムがどのような動作をすべきかを決定することが可能です。例えば、次週から始める射撃場ゲーム(Shooting Gallery)では、標的ににかって打ち出されるミサイル(弾丸)スプライトがあります。もし、それが標的に命中すれば -- 衝突があれば -- 標的は爆発します。

射撃場ゲームは私がスプライトについて勉強しようとして数年前に書いたデモ用プログラムです。それは単純で、絵は大笑いを誘うほどに実にひどいものです。しかし、それは RB で射撃系のゲームをつくるのがいかに容易かを示しています。

私は射撃場ゲームを今週から始めよう思いましたが、プログラムを完成するところで泥沼にはまり込みました。REAL Software 社は REALbasic 3.x でスプライトに関して大幅に変更したようで、私の古いプログラムは以前のようにはうまく動作しませんでした。多くの読者は多分 RB 3.x を使用しているので、RB 3.x 用の射撃場ゲームが重要だと決断しました。運悪く、RB 3.x のスプライトのコードは完全には古いものには対応していません。このため、RB 2.x を使用している読者はアップグレードが必要となるでしょう(あるいは RB 3.x のデモ版を使用する)、または希望があれば元の RB 2.x のコードを提供することが可能です。

Walker(歩行者)

射撃場ゲームはまだ準備が十分ではありませんので、スプライトの紹介としては歩行者と呼ぶ簡単なプログラムがいいと考えました。これはスクリーンを横切る棒切れの人影を作ることです。これはまさに基本的なことです -- 現実的なアニメーションを作ろうとはしていません、そして棒切れの人形の基準からみても、これは貧弱です -- しかし、考え方はつかめると思います。

Walker in action:

動いているWalker

では、まず最初にWalkerと呼ぶ新しい REALbasic のプロジェクトを作りましょう。それから、次の3つの画像をダウンロードしてきて、それらをwalker1.gifwalker2.gifおよびwhite.gif(これは何もない白い箱です)として保存しましょう。(多くのブラウザでは、それらをハードディスクにそのままドラッグできるでしょう、あるいはそれらをcontrolを押してクリックして、現れるメニューから「画像をダウンロード」を選びます。)

   

walker1.gifwalker2.gif、および white.gif をあなたの REALbasic プロジェクトウィンドウにドラッグしましょう。それらは名前がイタリックのピクチャーオブジェクトとして現れるでしょう(これは REALbasic がオリジナルにリンクしていることを意味しています:オリジナルを削除してはいけません、さもないとWalkerを実行することができなくなります)。

では、Window1 を開きましょう。spriteSurface () をそこへドラッグします:それをウィンドウの下に半インチの空間を残してほとんどを満たすようにサイズを調節します。その半インチ空間に pushButton をドラッグします。そして、その caption を "Start" と設定します。

SpriteSurface1 については2つの重要な属性を設定する必要があります。1つは FrameSpeed と呼ばれるものです。そのデフォルト値はゼロです。それはスプライトがあなたの Mac がそれらを移動させる最高の速度(それは通常速すぎますが)でアニメ化されることを意味します。それをもっと程よい2または3(あるいは、さらに5)に設定しましょう。アニメーションをもっと速くしたいときには、その値は何時でも変更することが可能です。

他の重要な属性は backDrop 属性です。あなたはポップアップメニューから、それを white(先程インポートしたグラフィック)に設定したいでしょう。 white グラフィックはただ余白の画像です。REALbasic はそれを自動的に張りつめて、アニメーションのための白い背景とします(そうしないと、我々の棒切れの人形はデフォルトの黒い背景上に現れます)。

Walkerはこれから定義する2つの属性を持っています。Window1 のコードエディタを開きましょう(Window1 をダブルクリックします)、そして Edit メニューから "New Property" を選び、それからダイアログで "dir as integer" と入力します。同じことをもう一度行ない、 "walkerSprite as sprite" と設定します。

次に、pushButton1 を開き、Action イベントに次のコードを入力します:

   walkerSprite = new sprite 
walkerSprite = spriteSurface1.newSprite(walker1, 0, spriteSurface1.height - walker1.height)
dir = 1
spriteSurface1.run

ここで行なったことは新しいスプライトとスプライトサーフェイスオブジェクトを初期化することです。我々はスプライトを walkerSprite に割当てるために、スプライトサーフェイスの newSprite メソッドを使っています。その最初のパラメータはスプライトが使用する画像(walker1)です。2番目と3番目のパラメータはスプライトの最初の位置を示すxとy座標(水平と垂直)です。ここでは水平位置をゼロ(最も左端)で、spriteSurface1 の下端(スプライトサーフェイスの高さからスプライトの高さを引いたもの)に設定しています。このようにすれば、スプライトはウィンドウの下端にそって歩くようになるでしょう。

最後の行は spriteSurface1 に動作さを指示するための run コマンドです。REALbasic の以前のバージョンでは、スプライトサーフェイスはスクリーン全体を使用して、メニューとか他のコントロールが使えませんでした。RB 3.x では、スプライトサーフェイスをアニメーションが表示される指定した領域に限定することが可能です:ずいぶんよくなりました。しまし、スプライトサーフェイスが実行されると、まだ多少コンピュータ全体を占有します。マウスをクリックしたときのデフォルトの動作はスプライトサーフェイスを終了させます。(RB 3.x にはCPU を占有しないで スプライトサーフェイスをアニメ化させる新しいメソッドがあります;それは後で考察されるでしょう。)

次に我々のすることのすべては SpriteSurface1 の NextFrame イベントに幾らかのコードを追加することです。それで完了です!

SpriteSurface1.NextFrame のコード

   if walkerSprite.image = walker1 then 
walkerSprite.image = walker2
else
walkerSprite.image = walker1
end if

if walkerSprite.x >= me.width - walker1.width then
dir = 0
elseif walkerSprite.x <=0 then
dir = 1
end if

select case dir
case 0
walkerSprite.x = walkerSprite.x - 1
case 1
walkerSprite.x = walkerSprite.x + 1
end select

あなたが信じようと信じまいと、これで終わりです!これが全プログラムです。上のコードは何をしているのでしょうか?

最初の部分は本質的にスプライトを2つの画像、walker1walker2 の間で切換えます。2つの画像は歩行の異なる状態ですので、これは歩いている効果を作り出します。

次の部分はスプライトがスクリーンをはみ出さしたか(右左のどちらの方向にも)を調べて、もしそうであれば、方向を切換え (dir) を変更します。

最後の部分はスプライトを移動させます:もし、dir が 0 ならば左へ(マイナス)、dir が 1 ならば右へ(プラス)行かせます。簡単でしょう!

Walkerを起動させると、空の白いウィンドウが示されるでしょう。アニメーションを始めるには "Start" ボタンをクリックします。アニメーションを終了するにはマウスをクリックします。あなたが開始ボタンをクリックするたびに、新しいアニメーションが始まることに気が付きましたか:古いものはもちろん動きを止めています(それらは事実上「死んで」います)、しかし新しいものは古いものの上を右へと歩いていきます!

次に、2人の歩行者があるときのWalkerがどのように見えるかを示しています、一方が他方の上を歩いています:

Walkerは非常に単純ですが、考え方は判ったと思います:一連の画像を繋げることによって、スプライトをスクリーンを横切って移動させるだけでなく、スプライトそのものも移動させることが出来ます!これを使ってどのようなことができるか想像してみて下さい:移動する方向にしたがって変化する人物、揺れ動くロウソク、しっぽを振る子犬など。

もし、完成した Walker プロジェクト(ソースコードとグラフィック)が必要であれば、ここにあります。

:このスプライトの入門を継続し、簡単なスプライトを使ったゲームである射撃場ゲームの説明とソースを示します。

Letters

次の週かそのあたりで、REALbasicの使用状況の調査結果についてお知らせしたいと思います。多種多様な解答を受けましたので、他のプログラマーがRBを使って何をしようとしているのかが判っておもしろいでしょう。もし解答がまだであれば、今週中にここまで送って下さい。

今週の手紙はすべて最初のRBUのプロジェクトであるGenderChangerに関してです。Glen FosterさんはGenderChangerを作ってみることは役にたったといっています。

こんにちはMarcsさん

私はつい最近、Realbasic University Archivesを偶然見つけました。私は冬の間の雪の季節の退屈しのぎにRealbasicを買ったのですが、しかしプログラムのなかでどんなことがどのように成し遂げられるのかを理解することができませんでした。私はあなたのGenderChangerの記述にしたがい、ただ指示にしたがって、良く理解もせずにGenderChangerを完成しました。それから、何度もそれを投げ捨てて、その理由を少しづつ理解しまがら、最初から作り直しました。そして今は、五回目を完成しました、そして毎回違った光がさし、また少しだけ多くのことが理解できます。70才をゆうに越えた者には幾つかの専門用語は理解できませんのでスクリーンショットが有用でした、そして一見は百聞にしかずです。素晴らしいコラムを続けてください。

それは素晴らしい、Glenさん。私は同じプロジェクトを2回以上しようと思ったことはありませんが、素晴らしい考えです。それはそんなに大変な仕事ではありませんが、もちろんやる度に簡単になり、その後やっているうちに一回目や2回目には見逃していた事に気づき、そして理解するでしょう。もし読者の中でGenderChangerがすこし難しいと感じておられる方は、Glenさんの方法でそのコラムをもう一度やってみて下さい。今よりももっと良く理解できることは間違いないでしょう。

次に、Philip Mobleyさんは先週のリストボックスの色のついた文字の問題に対して、おもしろい解答を提供してくれました。そして、GenderChangerを作ったことは彼が最初に思っていた以上に役に立ったという発見を披露してくれています。

あなたの読者の一人の質問(リストボックスの色付き文字に関する)に対する可能な答えはリストボックスコントロールのRowPictureメソッドでしょう。もし文字が変化しないのであれば、実際の文章の代わりに絵を使うことができるでしょう。

私はリストボックスには文字の色のためのコントルールがあると考えていましたが、それは間違っていました。

RBUについて...

私はあなたのGenderChangerのコラムを読み直し、そこからかなりたくさんのことを利用しました。最初にそのコラムを読んだとき、「これは基本的すぎる」と思いました。そしてRealBasic for Dummiesの書評を読んだときは、「その本を買う事はないだろう」と思いました。

さて、私はGift Certificate Generatingプログラム(無作為に数値を生成する)を現在85%終えました。私はProfessional版をまだもっていないので、データベースを使うことができません(それが一番良い方法なのでしょうが)。私は配列を使わなければならないので、GenderChangerプログラムは、私自身のプログラムのロードマップとして、とても役に立ちました。

私はそれぞれの段階やあなたがそのコードを使ったわけを理解しようとGenderChangerを詳しく勉強しました

私は今、あなたのコラムがどれだけ深いものであるかに気づき、プログラミングの多くの基本的な事をコラムでどのように扱っているかが分かりました。コラムを続けてください。次のコラムが待ち遠しいです。

それから、Dummiesの本を買いにいくつもりです。

プログラミングの本の良い点のひとつは、Philipさん、他の読者にその本をいつでも渡すことが出来ることです。あなたがRBUは役に立つと気づいてくれて嬉しいです。それは一般的なものです。私はひとつかみのコラムだけで全員の問題を解決することはできませんが、一年かそのぐらい後に、このコラムが驚くようなリソースになっていることを思い描いています。

リストボックスの中で文字の代わりに絵を使うというあなたの考えは素晴らしい!実際に、newPictureコマンドを使うことで、その絵を動的につくりだすことさえできます。必要なのはpicture変数で、canvasコントロールにするのと同じように、その変数に絵に書きこむことができます。

次に示すのは私の試した簡単なデモで、うまく動きました!(数百の項目でリストボックスを試すということはしませんでしたが、文字を追加するよりも遅いこともありませんでした。)

   dim p as picture 
dim s as string

// Make a new picture 200 pixels wide, 20 tall, and 8-bits deep
p = newPicture(200, 12, 8)

// Make sure newPicture call worked
if p <> nil then
// random color
p.graphics.foreColor = rgb(rnd * 255, rnd * 255, rnd * 255)
p.graphics.textFont = "Geneva"
p.graphics.bold = true
p.graphics.textSize = 10
s = "This is line " + str(listBox1.listCount + 1)
p.graphics.DrawString s, 92, 10
listBox1.addRow ""
listBox1.rowPicture(listBox1.lastIndex) = p
end if

ひとつ奇妙だったことは、drawstringコマンドではゼロでは無く 92ピクセルずらして描画を始めなければ文字がカットされるという事でした。これがRBバッグなのかRowPicturesの実装の問題なのかわかりません。または、私が何かそれ以外のことを見逃しているのかもしれません。(この挙動にたいする説明が解ったひとは、気がねせず私に教えてください。私はあることの機能しない理由が解らないのが嫌なのです。)

次は、幾らかの行を追加して、リストボックスをスクロールしたときに、プログラムの動いている様子です:

もし完全なデモプロジェクトが必要なら、ここをクリックしてください。

最後はMartin Jeanさんからで、GenderChangerを強化することについて質問してきています。

Marcさん、

最初に、私はあなたのコラムに感謝したいと思います。私はThink PascalとHyperCardの幾らかの経験のあるRBの初心者です。本当にRealbasic Universityを毎週楽しく勉強しています。是非、この素晴らしいコラムを続けてください。

コラム13を終えて、GenderChangerを楽しんだ後、いくつかの考えを思い付きました。その一つは、FinderからGenderChangerのアイコンへ書類をドラッグできるようにプログラムを修正することです(プログラムが作動しているときもそうでないときも)。私の目標はそのエリアスをFinder 上(あるいはFinderpop フォルダ内)に置いて、ただファイルをドロップすることで素早く身元を変更できるように強化することです。

これをすることはどれぐらい大変でしょうか。私はMarkの本(これはマットの本を意味していると思います:編者)の中で、これはAppクラスのOpenDocumentイベントが関係ということを読みました。しかし、助けなしにはそのレベルの修正をする自信がありません!

これはいつ働くのでしょうか、その内容を処理するためにフォルダー(またはディスク)全体をドロップするのはどうでしょうか?

感謝をもう一度!

Martinさん、あなたの考えは正しいです。しかし、それを機能させるためには、あまり正確には記述されていない設定を行わなければなりません。もしそのうちの一つでもかけていたら、それはうまく機能しません。その過程は混乱するものだと思います。(問題の一部はOpenDocumentをRealbasic IDEのなかではテストすることが出来ないということです:あなたはそのプログラムをディスクにコンパイルし、それを実行しなくてはなりません。)

まず、あなたのアプリケーションはクリエイターコードをもたせなくてはなりません。GenderChangerのクリエーターコードは"GdCh"です−−それはEdit メニューのProject Settings メニュー項目で設定します(もしまだ設定していなければ)。

次に、それぞれのFile Type 設定の中のアイコンのチェックボックスにチェックを付けなければなりません(これもEdit メニューにあります)。

もしこの種類のファイルをあなたのアプリケーションにドロップしたければ、アイコンのチェックボックスにチェックを付けなければなりません。

ファイルタイプのダイアログが現れているときに、そのまま進んでフォルダーのファイルタイプを加えてください。これによりフォルダーがGenderChangerにドロップできるようになります(それはポップアップメニューの"supecial/folder"として準備されているはずです。)

(もしディスク全部をGenderChangrにドロップできるようにしたければ、"special/disk"のファイルタイプを加えて、アイコンチェックボックスをチェックします。しかし、本当はこれはお勧めしません:全てのディスクの全てのファイルを変えようとするとは思えないからです。)

それがすめば、GenderChangerのAppクラスのOpenDocumentイベントへいってください。そこに、とても簡単なコードを加えます:

   if item.directory then 
handleFolder(item)
else
handleFile(item)
end if

ここでItemはプログラムにドロップされたものです。GenderChangerの一部として以前に扱ったdropObjectのイベントとは違って、OpenDocumentのイベントは複数のファイルを一度に取り入れることが出来ません。そのかわりに、ドロップされたそれぞれのオブジェクトに対して一度ずつ呼び出されます。それによって、プログラミングすることがずっと簡単になります。(我々はobj.nextItemをよぶ必要はありません):ユーザーがフォルダー又はファイルをドロップしたかをチェックし、その結果を適切なメソッドに渡すだけです。

メソッドに関しては、我々は handleFolder handleFile の2つがあります。どちらも"f as folderItem"のパラメーターをもっています。そのまま進んで、それらをAppオブジェクトに加えましょう。

以下はhandleFileのコードです。とても簡単です。これはlistBox1dropObjectイベントと同じ事をします(それはfolderitemのパスおよびcreator と typeコードをlistboxに追加しました)。

   window1.listBox1.addRow f.absolutePath 
window1.listBox1.cell(window1.listBox1.lastIndex, 1) = f.macCreator
window1.listBox1.cell(window1.listBox1.lastIndex, 2) = f.macType

HandleFolderのコードはもう少し複雑です。それがフォルダーを含んでいることがわかっていますので、いくつの項目がフォルダーの中にあるかを数えて、それぞれをループします。それそれの項目に対して、それがフォルダーなのかファイルなのかを調べ、そして適切なメソッドにそれを渡します。

   dim i, n as integer 

n = f.count
for i = 1 to n
if f.item(i).directory then
handleFolder(f.item(i))
else
handleFile(f.item(i))
end if
next

もしそれがフォルダーであれば、我々は既にその中にいるメソッドを呼んでいることに注意して下さい。これは再帰呼出し recursion (自分自身を呼ぶこと)と言われるのもです。再帰呼出しは強力ですが危険でもあります:再帰呼出しが多すぎると、プログラムはメモリーを使い果たしてクラッシュします。また、再帰呼出しルーチンは出口を必ず持たなければなりません:いいかえれば、ある点で自分自身の呼び出しを止めて、巻き戻すことが出来なければなりません。それぞれのメソッドの呼出しは終了し、そしてそれ以前のものに制御を返して、呼び出しを始めたところまで戻る必要が有ります、そうしてプログラムの継続が可能になります。我々の場合には、GenderChangerにドロップされるファイルやフォルダの数は有限ですので、呼び出しの数は有限です(しかし、大きなフォルダやディスクがドロップされれば、GenderChangerは メモリーを使い果たしてしまうでしょう)。

これで十分でしょう:上のコードを追加して、File Typesに上の変更をすれば、Finder上のGenderChangerのアイコンに多数のファイルをドロップできるようになるでしょう。


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

INDEXに戻る