REALbasic かってに連載します(第15回)


 SpriteSurfaceの画面ではStaticTextは使えません。文字や数字を表示させるには、表示させたい文字が、全て入る大きさの「newpicture」を定義します。その中に「Graphics.drawstring」で文字を書き込んだpictureを用意し、Spriteに登録します。
 第15回 - 太陽系の惑星運動(The SolarSystem) -

 万有引力による天体の運動を表現してみます。SpriteSurface Controlを利用してみました。描画速度はさすがに速く、惑星の数を15にしてみましたが、十分な表示速度です。G3等のようにCPUのパワーがあれば、それぞれ相互の引力も計算して、銀河の誕生過程のシミュレーションも可能です。


  1. REALbasicのアイコンをダブルクリックすると、初期画面が出ます。 まずEditメニューのEditor Settingsを選びます。ここでDefault Control FontのFontを「System」に変更しておきます。これで表示に日本語が使えるようになります。

  2.  Window1に、ToolBoxから次のものを持ち込む。

     説明を書くためListBox1、SpriteSurface1を開くためのPushButton1、それとSpriteSurface1です。

  3.  変数の定義 

     EditメニューのNewPropertyで配列変数を定義します。後から増やすことを考えて配列要素の数は50としておきます。「Picture型」の配列変数ball(50)、「Sprite型」の配列変数Sprite(50)、を定義します。また、位置、速度、加速度などの「Double型」の配列変数も用意します。x(50)、y(50)、vx(50)、vY(50)、ax(50)、ay(50)、r(50)などです。さらに、「Picture型」で背景用にback01、テキスト表示用にtext01、「Sprite型」でSpritetext01、惑星の数変更用に「integer型」でnobを定義します。

  4.  太陽の図形を用意する。

     Macに付属の、スクラップブックにある太陽を使います。まず、スクラップブックより太陽を選びこれをクラリスにペーストして、サイズを1.5cm程度に縮小したものを、PICT形式で保存したものをつかいます。ファイル名は「sun.pict」としました。これを、projectウィンドウにドラッグします。

  5.  Window1.Paint(Events:Paint) にSpriteSurface1で使用する、惑星となる図形を用意します。

    Sub Paint(g As Graphics)
      dim n as integer
     //「nob」は惑星の数
      for n=1 to nob
        ball(n)=newpicture(10,10,8)
      next
     //表示する文字の表示領域を考えてサイズを決めます。
     //ここでは、縦横のサイズが200*15の表示領域で
     //カラー深度は16ビットとしています。0,1,2,4,8,16,32
     //が使えます。大きい領域でカラー深度を上げると、
     //メモリーを消費します、適当にします。
      text01=newpicture(200,15,16)
      back01=newpicture(600,450,8)
      ball(0)=newpicture(35,35,16)
      //
      //「sun」はPICT形式の図形です。
      //ball(0)を太陽とします。
      ball(0)=sun
      //白の部分を透明にします
      ball(0).transparent=1
      //Window1に描いて確認します
      graphics.drawpicture ball(0),20,10
      //惑星の色付けと確認表示です。
      for n=1 to nob
        ball(n).graphics.forecolor=rgb(250-n*(250/nob),n*(250/nob),100)
        ball(n).graphics.filloval 0,0,ball(n).width,ball(n).height
        ball(n).transparent=1
        graphics.drawpicture ball(n),0,n*11
      next
      //文字もpictureとして用意します。
      text01.graphics.drawstring "SolarSystem <  koko@ask.or.jp >",0,10
      text01.transparent=1
      //確認用
      graphics.drawpicture text01,100,10
      //
      //背景1
      back01.graphics.forecolor=rgb(50,100,100)
      back01.graphics.fillrect 0,0,back01.width,back01.height
      back01.graphics.forecolor=rgb(50,50,200)
      back01.graphics.filloval 0,0,back01.width,back01.height
      back01.transparent=1
      
    End Sub

  6.  PushButton:Action にSpriteSurface1を開くためのプログラムを書く。

    Sub Action()
      dim n as integer
      //Spriteの初期条件をSpriteのOpenではなく
      //ここに書き込む
      for n =1 to nob
        vx(n)=0
        vy(n)=-10
        x(n)=300+n*(120 /nob) 
        y(n)=250
      next
      //SpriteSurface1に新しいパーツを登録する。
      //「NewSprite(ball01,100,200)」の各パラメータは
      //(picture型変数名、表示位置X、表示位置Y)
      Spritetext01=SpriteSurface1.NewSprite(text01,300,10)
      for n=1 to nob
        Sprite(n)=SpriteSurface1.NewSprite(ball(n),10,10+10*n)
      next
      Sprite(0)=SpriteSurface1.NewSprite(ball(0),250,250)
      x(0)=250-20
      y(0)=250-20
      //
      spriteSurface1.backdrop=back01
      SpriteSurface1.Run
      //SpriteSurface1がCloseされると
      //ここ「SpriteSurface1.Run」直後に処理が戻って来る。
      if SpriteSurface1<>nil then
        SpriteSurface1.close
      end if
      for n =0 to nob
        if Sprite(n).image<>nil then
          Sprite(n).image=nil
        end if
      next
    End Sub

     「SpriteSurface1.close」だけでは、SpriteSurface1に配置した、パーツは残ったままですので、再度「SpriteSurface1.Run」を実行すると、2重に表示されてしまいます。「SpriteSurface1.Run」以下は、これらのパーツを消去するためのものです。

     文字の表示は、「SpriteSurface1」という名前の掲示ボードに、文字を描いた「text01」という名前のメモ紙を張り付ける感じで理解できます。
     ですから、はじめに、自分が書きたいだけの文字がかける大きさのメモ紙を、用意しておく必要があります。使いたい文字のフォントやサイズで、必要な領域が変わってきますので、試してみて下さい。
    「text01=newpicture(200,15,16)」であれば、200*15の横長のメモ紙ですから、一行くらいしか入りません。
    「text01=newpicture(150,30,16)」として、
    text01.graphics.drawstring "一行目の表示",0,10
    text01.graphics.drawstring "二行目の表示",0,25
    のようにすれば、何列でもOKです。
     もちろん、文字の色や修飾もこのときに指定すれば好みの文字が、表示できます。
     結局、ststictextでは、文字を一回の操作で変更、表示できます。
     statictext1.text="一行目の表示"
     のように、
     「SpriteSurface1」での変更は、一旦pictureに書き直したり書き加えたりした後、「SpriteSurface1」の画面に、登録表示することになり、手順が少し複雑になりますが、コンピュータは、すばやいので結果的には、ststictextと同様に使えます。

  7.  SpriteSurface1:NextFrameに惑星運動を計算する、万有引力のメインプログラムを書く。

     NextFrameイベントでは、1秒間当たりSprite Surface1のProperties画面のFrame Speedで決められた枚数だけ、SpriteSurfaceを書き直します。つまり、リフレッシュも行ってくれるわけです。
     また、Sprite Surfaceでは、キーボードからのキー入力を監視していますので、キーの操作でパーツを動かすプログラムが簡単に書けます。ここでは、太陽を動かすことができるようにしました。

    Sub NextFrame()
      dim n ,i ,sh,sw as integer
      dim dt as double
      //刻み値
      dt=.2
      //
      sh=me.surfaceheight
      sw=me.surfacewidth
      for n=1 to nob
        //ここが心臓部分です、物体の動きをシミュレート
        //する場合の基本ルーチンと思って下さい。
        //vxはx方向の速度、vyはy方向の速度、
        //dtは微少時間です。
        
        r(n)=(1/50)*sqrt((x(0)-x(n))*(x(0)-x(n))+(y(0)-y(n))*(y(0)-y(n)))
        //接近しすぎると、計算誤差が大きくなるため制限しています。
      if r(n)<1.5 then
          r(n)=1.5
        end if
        //万有引力による加速度です
        ax(n)=-(x(n)-x(0))/(r(n)*r(n)*r(n))
        ay(n)=-(y(n)-y(0))/(r(n)*r(n)*r(n))
        vx(n)=vx(n)+ax(n)*dt
        vy(n)=vy(n)+ay(n)*dt
        x(n)=x(n)+vx(n)*dt
        y(n)=y(n)+vy(n)*dt
        //
        //
        Sprite(n).x=x(n)
        Sprite(n).y=y(n)
        Sprite(0).x=x(0)-20
        Sprite(0).y=y(0)-20
        //
        //キーボードで太陽をコントロールします。
        ////////////////////////////////////////
        //この部分は省略します。Sampleを御覧ください。
        ///////////////////////////////////////
      next
      
      If Me.KeyTest(&h24) Then
        Me.Close
      End if
      
    End Sub


  8.  - 次回は銀河系を作ってみます -

     今回は、太陽系の惑星運動を取り上げてみました。いかがでしたか。数式や数値だけではイメージしにくい万有引力ですが、画面にそれらしい動きが結果として表示されると病みつきになります。ここで使用しているオイラー法は、数値演算法としては、一番幼稚な方法ですので、刻み値を小さくしないと誤差が大きくなります。このため、正確に計算するためにはそれなりの計算時間が必要となり、表示時間が遅くなります。あまりゆっくりした動きでは面白くありませんので、誤差は承知で表示速度優先にしました。実際の惑星運動とは異なり、閉じた楕円軌道になりませんが、それなりに楽しめます。また、太陽の位置をキーボードからコントロールできるようにしました。次回は、「星と星の相互の万有引力を計算して、銀河系の形成、さらに銀河と銀河の衝突シミュレーション」を試みてみましょう。さて、どうなることやら。お楽しみに。 



 今回の「SolarSystem」の ソースプログラムです
  
  プロジェクトファイルのみです。REALbasicの最新バージョンが必要です。30 kバイト  

  ソースコードについての質問やご意見がありましたら以下のアドレスまでご連絡下さい。
          koko-@mx2.tiki.ne.jp

このホームページのホストは です。 無料ホームページをどうぞ!