Home >> Lecture 10
タートル・グラフィックスでは、現在タートルがどちらを向いているかを getAngleメソッドで、 現在タートルの中心がどこにいるかの位置を getXメソッドと getYメソッドで 求めることができます。これらは実数で返してくれます。 getIntegerXメソッドと getIntegerYメソッドは、 整数で返してくれます。 これらのメソッドは戻り値がありますので、次のように変数に代入したりして値を得ます。
double angle = turtle.getAngle( ); double x = turtle.getX( ); double y = turtle.getY( ); int x = turtle.getIntegerX( ); int y = turtle.getIntegerY( );
これらのメソッドは、タートルの状態を知るために非常に有用です。 なお、タートルの方向はマイナスで表されることもあります。以下の図を参照にして、現在タートルが どちらを向いているのかを把握してプログラムしてください。
図10-1 タートルの方向
以下のプログラムでは、タートルが現在どちらを向いているかを、それぞれの頂点にきたときに、 getAngleメソッドで求めて、それを文字端末(ターミナル)に表示するものです。 このようなタイミングで必要な情報を文字端末に表示させることをデバッグプリント(Debug Print)と 呼びます。 デバッガでいちいちプログラムを止めるよりも、必要な時点での変数やタートルの状態がわかり、 それが表示として残こっていきます。 そのため、多くのプログラマはデバッガを使うときは、よほど根拠が掴めない特殊な場合だけに限る ようにしています。 熟練プログラマは、デバッガを殆ど使わずに、デバッグプリント、つまりプログラム上のある地点に おける変数の値の移り変わりをトレースするだけで問題点を掴み、プログラムを修正していきます。
import sfc.turtle.TurtleFrame; import sfc.turtle.Turtle; public class SeaUrchin extends TurtleFrame{ public static void main(String [ ] args) { new SeaUrchin( ); } public void start( ) { Turtle turtle = new Turtle( this ); turtle.rotate( 6 ); for ( int i=1; i <= 18 ; i++ ) { turtle.forward( 30 ); printLine( i + "番目の外頂点での角度" + turtle.getAngle( ) ); turtle.rotate( 168 ); turtle.forward( 30 ); printLine( i + "番目の内頂点での角度" + turtle.getAngle( ) ); turtle.rotate( -168 + 360 / 18 ); } } }
上記の「うに」のような図形を動かしてみなさい。クラス名はPractice1001とします。
上記の「うに」のような図形は、棘が18本でしたが、これをユーザが入力できるようにしてみなさい。 値としては、3〜60までの整数値の範囲で受け取るように入力をガードしなさい。 クラス名はSeaUrchinDrawerとします。
あまり意味がありませんが、タートルは、次のようなメソッドで大きさを変えることができます。
setSize( 幅, 高さ )
setScale( 比率 ) // 1.0はそのままの比率になります
setScale( x方向の比率, y方向の比率 ) // 1.0はそのままの比率になります
resetScale( x方向の比率, y方向の比率 ) // 元の大きさに戻ります
タートルは、次のような2つのメソッドで直接ウィンドウの特定の座標に置くことができます。
setLocation( x座標, y座標 )
moveTo( x座標, y座標 )
両者の違いは、setLocationがアニメーションを伴わないで、一瞬その位置に置かれるのに対して、 moveToは、タートルが目的地にまず回転して、それから歩いて移動するアニメーションを伴います。 ただし、ペンを上げていないと、初期の位置から、その座標まで軌跡が引かれることになります。 ウィンドウの座標は、左上の端がx座標0, y座標0で、x座標は右側にプラスになるのですが、 「y座標は下方向がプラスになる」という特性を持っています。 ほとんどのウィンドウのプログラミングができるライブラリにおいて、同じような座標系を 持っています。y座標の方向が違うことに注意して下さい。
次のプログラムは、配列の初期値を代入して、タートルを目的の座標に向かわせるものです。 x座標の配列とy座標の配列を持っています。ただし、x座標の配列の要素の値が -10ならばpendown、-20ならばpenupをさせるようにしています。 startメソッドの中だけを記述します。
public void start( ) { int tx [ ] = { 100, -10, 300, 300, 220, 220, 180, 180, 100, 100, -20, 320, -10, 360, 360, 440, 480, 390, 480, 440, 360, 360, 320, 320 }; int ty [ ] = { 100, -10, 100, 140, 140, 300, 300, 140, 140, 100, -20, 100, -10, 100, 180, 100, 100, 200, 300, 300, 220, 300, 300, 100 }; Turtle turtle = new Turtle( this ); turtle.setPenColor( Blue ); turtle.penup( ); // 最初はペンを上げた状態にしておきます turtle.moveTo( tx[ 0 ], ty[ 0 ] ); // 最初の位置に移動します。 for ( int i=1; i < tx.length ; i++ ) { if ( tx[ i ] == -10 ) { turtle.pendown( ) ; } //-10だったら、ペンを下ろす else if ( tx[ i ] == -20 ) { turtle.penup( ) ; } //-20だったら、ペンを上げる else{ turtle.moveTo( tx[ i ], ty[ i ] ); } // それ以外は要素の示す座標へ移動する } }
上記のプログラムは、下記の図のようにTKと描くようにしました。 余裕があれば、他にも直線的なアルファベット (AEFHILMNVWXYZ)を描くように配列の初期値を修正してみてください。 クラス名はPractice1002とします。
タートルグラフィックスでは、4角形や角の取れた4角形を描くのに非常に苦労します。そこで、 使い捨てのタートルを使って(軌跡を残すためだけにしか使われない)、矩形(4角形のこと)を描く 便利なメソッドを定義してみましょう。左上のx, y座標と、幅(width)と高さ(height)の4つの引数を 渡すようにします。 下記のメソッドの記述で、hideTurtle は、軌跡は残して、タートルだけは表示しないという機能を実行するメソッドです。
void drawRectangle( int x, int y, int width, int height ) { Turtle turtle = new Turtle( this ); turtle.penup( ); turtle.setLocation( x, y ); turtle.pendown( ); int i=1; while ( i <= 4 ) { turtle.rotate( 90 ); if ( i % 2 == 1 ) { turtle.forward( width ) ; } // 奇数だったら幅分だけ移動 else{ turtle.forward( height ); } // 偶数だったら高さ分だけ移動 i = i + 1; } turtle.hideTurtle( ); }
これでは、黒の矩形しか描きませんので、java.awt.Colorクラスを使って、色の指定ができるように します。そうすると、上記のメソッドは次のように記述することができます。Javaでは同じ名前のメソッドでも、 引数の数が違えば、シグネチャが異なりますので、違うメソッドとして認識してくれます。
void drawRectangle( int x, int y, int width, int height, java.awt.Color c ) { Turtle turtle = new Turtle( this ); turtle.penup( ); turtle.setLocation( x, y ); turtle.setPenColor( c ); turtle.pendown( ); int i=1; while ( i <= 4 ) { turtle.rotate( 90 ); if ( i % 2 == 1 ) { turtle.forward( width ) ; } // 奇数だったら幅分だけ移動 else{ turtle.forward( height ); } // 偶数だったら高さ分だけ移動 i = i + 1; } turtle.hideTurtle( ); }
上記のプログラムは枠だけですが、前のように、塗りつぶすメソッドを記述してみましょう。
void fillRectangle( int x, int y, int width, int height, java.awt.Color c ) { Turtle turtle = new Turtle( this ); turtle.penup( ); turtle.setLocation( x, y ); turtle.setPenColor( c ); turtle.rotate( 90 ); turtle.pendown( ); int i=1; while ( i <= height ) { // 高さ分だけ繰返しを実行 turtle.forward( width ); // 横線で描画していきますので、幅分だけ移動 if ( i % 2 == 1 ) { turtle.rotate( 90 ); } // 奇数回は時計回り、偶数回は半時計回り else{ turtle.rotate( - 90 ); } if ( i < height ) { turtle.forward( 1 ); // 1ドット下に降ります if ( i % 2 == 1 ) { turtle.rotate( 90 ); } else{ turtle.rotate( - 90 ); } } i = i + 1; } turtle.hideTurtle( ); }
さて、次はボタンなどに使われるちょっと角の取れた矩形を描くようにします。角の丸みをどれくらいに するかを併せて指定できるようにします。丸みを帯びた角は、10度ずつ9回、90度分の円弧を描くようにしています。
void drawRoundRectangle( int x, int y, int width, int height, int r, java.awt.Color c ) { Turtle turtle = new Turtle( this ); turtle.penup( ); turtle.setLocation( x, y ); turtle.setPenColor( c ); turtle.rotate( 90 ); turtle.forward( r ); turtle.pendown( ); int i=1; while ( i <= 4 ) { if ( i % 2 == 1 ) { turtle.forward( width - 2 * r ); } // 左右の丸み分だけ移動距離は少なくなります else { turtle.forward( height - 2 * r ); } // 上下の丸み分だけ移動距離は少なくなります int j=1; while ( j <= 9 ) { // 角の丸みを描いています turtle.rotate( 10 ); turtle.forward( 0.5 * r * Math.PI / 9 ); j = j + 1; } i = i + 1; } turtle.hideTurtle( ); }
これらのメソッドをstartメソッドから呼び出して使ってみます。
public void start( ) { drawRectangle( 10, 10, 80, 40 ); drawRectangle( 100, 10, 80, 40, Red ); fillRectangle( 190, 10, 80, 40, Magenta ); drawRoundRectangle( 280, 10, 80, 40, 6, Blue ); }
上記のメソッドをもつプログラムを完成させて、実行しなさい。 クラス名はPractice1003とします。
矩形を塗り潰すときは、同じ色で塗りつぶしましたが、これを、白から赤へのグラデーション (Colorオブジェクトを作るときに赤色成分だけを変化させる)で塗りつぶすようなメソッドを作ってみなさい。 1つの横線を描くたびに色を変えていきます。余裕がある人だけがやってください。 クラス名はGradationDrawerとします。
矩形(四角形)領域を軌跡で塗りつぶすプログラムを利用して、緑色は0で構いませんから、青色、赤色をそれぞれ、 0から240まで16ずつ変化させながら、格子を描くプログラムを記述して見なさい。格子を描く開始位置を指定するのには、 setLocation( ) メソッドを使っても良いでしょう。クラス名は、ColorTableとします。 以下の記述を参照しなさい。
turtle.setPenColor( new java.awt.Color( red, 0, blue ) ); // 軌跡の色をred, 0, blueの3原色で混色される色にする。
次は中心のx, y座標と半径、および色を指定して、円(正確には正60角形)を描画するメソッドを 定義してみましょう。
public void drawCircle( int x, int y, int r, java.awt.Color c ) { Turtle turtle = new Turtle( this ); turtle.penup( ); turtle.setLocation( x, y ); // まず中心座標に行って turtle.forward( r ); // 半径分だけ上に登ります turtle.rotate( 90 ); // そこで右に向いて turtle.setPenColor( c ); // ペンの色を設定して turtle.pendown( ); // 描き始めです int i=1; while ( i <= 60 ) { turtle.forward( 2 * Math.PI * r / 60 ); // 1回分の進む距離を求めています turtle.rotate( 6 ); i = i + 1; } turtle.hideTurtle( ); }
円は、必ず中心を指定するだけはなく、矩形と同じように左上の座標を指定する場合があります。 正方形に内接する円(円弧がちょうど正方形の各辺のどこかに触れる円)は一意に指定できます。 このことを利用して、左上のx, y座標と直径、および色を指定して、円を描画するメソッドを定義して みましょう。半径が直径になった以外は、単に最初に行く場所の記述の式が違うだけです。はい。
public void drawCircleSquare( int x, int y, int size, java.awt.Color c ) { Turtle turtle = new Turtle( this ); turtle.penup( ); turtle.setLocation( x+size/2, y+size/2 ); // 左上の座標から、中心の位置に行きます。 turtle.forward( size/2 ); // 直径の半分、すなわち半径分だけ上に登ります。 turtle.rotate( 90 ); turtle.setPenColor( c ); turtle.pendown( ); int i=1; while ( i <= 60 ) { turtle.forward( Math.PI * size / 60 ); turtle.rotate( 6 ); i = i + 1; } turtle.hideTurtle( ); }
円を塗りつぶしてみましょう。これは、中心から、1ドットずつ移動して、同心円を描いていきます。 うまく塗りつぶせるでしょうか。
public void concentricCircle( int x, int y, int r, java.awt.Color c ) { Turtle turtle = new Turtle( this ); turtle.penup( ); turtle.setLocation( x, y ); // まずは中心座標に行き turtle.setPenColor( c ); turtle.pendown( ); int i=1; while ( i <= r ) { // 1ドット登らせます turtle.forward( 1 ); turtle.rotate( 90 ); int j=1; while ( j <= 60 ) { // 円(同心円)を描かせます turtle.forward( 2 * Math.PI * i / 60 ); // 1回に進む距離は中心からの離れぐらいで異なります turtle.rotate( 6 ); j = j + 1; } turtle.rotate( -90 ); i = i + 1; } turtle.hideTurtle( ); }
塗りつぶしをするものがいま一つな感じがあります。やはり、三角関数と逆三角関数を用いて横の長さを計算して、 矩形のときのように横に線を引いて塗りつぶしていきましょうか。そうしたものが以下のメソッドになっています。
public void fillCircle( int x, int y, int r, java.awt.Color c ) { Turtle turtle = new Turtle( this ); turtle.penup( ); turtle.setLocation( x, y ); // まずは中心座標に行き turtle.forward( r ); // 半径分だけ縦に登らせます turtle.setPenColor( c ); turtle.rotate( 90 ); int i=1; while ( i <= 2 * r ) { double size = Math.sin( Math.acos( (r-i) / (double)r ) ) * r ; // この式は横の長さを求めています turtle.forward( size ); // 右側に移動しておき turtle.rotate( 180 ); // くるりときびすを返します turtle.pendown( ); turtle.forward( size * 2); // この左側への移動で横線を描画します turtle.penup( ); turtle.rotate( 180 ); turtle.forward( size ); // 左端から、また真ん中に戻ってきます turtle.rotate( 90 ); turtle.forward( 1 ); // 1ドット分下に降ります turtle.rotate( -90 ); i = i + 1; } turtle.hideTurtle( ); }
上記の4つの円を描くメソッドをstartメソッドから呼び出して使ってみます。
public void start( ) { drawCircle( 60, 60, 40, Red ); drawCircleSquare( 120, 20, 80, Magenta ); concentricCircle( 260, 60, 40, Orange ); fillCircle( 360, 60, 40, Blue ); }
上記のメソッドをもつプログラムを完成させて、実行しなさい。 クラス名はPractice1004とします。
円を塗り潰すときは、同じ色で塗りつぶしましたが、これも、中心が白で外側に行くに従って赤へ変化するグラデーション (Colorオブジェクトを作るときに赤色成分だけを変化させる)で塗りつぶすようなメソッドを作ってみなさい。 1つの同心円を描くたびに、色を変えながら描画していきます。余裕がある人だけがやってください。 クラス名はGradationCircleとします。
int width = getWidth( ); // ウィンドウの幅を得る setWidth( width * 2 ); // 現在の幅の2倍の幅にする setHeight( 400 ); // ウィンドウの高さを400に固定する
setBackgroundColor( Red ); // 赤に設定する setBackgroundColor( new java.awt.Color( 244, 20, 128 ) ); // 3原色を指定して
setWaitTurtle( false ); // タートルを待たないようにする fillRectangle( 10, 100, 200, 40 ); // Lecture 8で作った矩形塗りつぶしメソッドを呼ぶ setWaitTurtle( true ); // この後は通常の速度で
import sfc.turtle.TurtleFrame; import sfc.turtle.Turtle; public class SkyAndGround extends TurtleFrame { public static void main(String [ ] args) { new SkyAndGround( ); } public void start( ) { setWidth( 800 ); setHeight( 400 ); setWaitTurtle( false ); setBackgroundColor( new java.awt.Color( 200, 128, 80 ) ); Turtle turtle = new Turtle( this ); int halfheight = getHeight( ) / 2; turtle.penup( ); turtle.setLocation( 0, halfheight ); turtle.rotate( 90 ); turtle.pendown( ); for ( int i=0; i <= halfheight ; i++ ) { turtle.setPenColor( new java.awt.Color( 0, 255-(255*i/halfheight), 255 ) ); turtle.forward( getWidth( ) ); turtle.rotate( (i % 2 == 0) ? -90 : 90 ); turtle.forward( 1 ); turtle.rotate( (i % 2 == 0) ? -90 : 90 ); } turtle.hideTurtle( ); } }
ImageTurtle 変数名= new ImageTurtle( 画像ファイルの文字列, this );ImageTurtleは、Turtleクラスのサブクラスになっていますので、Turtleクラスでできたことは、何でも できます。ただ、setTurtleColorは効かないと思います。 なお、ImageTurtleでは、画像を読み込むのに少し時間が掛かりますので注意して下さい。 読み込めるビットマップ画像(専門的にはラスター画像と呼びます)形式の種類は以下の通りです。
JPEG形式の画像:一般的な画像形式です。圧縮率を変化させて、データサイズを小さくすることができます。注意して欲しいのは、Windows標準のBMP形式の画像は読み込めないという点です。 Windowsの「ペイント」などのプログラムは、標準ではBMP形式で保存するので注意して下さい。 画像ファイルが、プログラム(クラスファイル)のあるフォルダにあるときは、次のようにして、 画像を表示させることができます。次のプログラムは、startメソッドだけ、記述しています。
GIF形式の画像:背景に透明色を指定できます。ただし、256色までしか、使えません。
PNG形式の画像:背景に透明色を指定できます。フルカラー1677万色も使えますし、透明度も256段階で指定できます。
public void start( ) { ImageTurtle turtle = new ImageTurtle( "sample.png", this ); for ( int i=0; i<=60; i++ ) { turtle.rotate( 6 ); } }
以下はイメージの例です。このファイルを、Safariなどではドラッグアウト(ウィンドウの外にドラッグして デスクトップ上で離す)などをすると、デスクトップに保存されます。あるいは、右クリックして、コンテンツ・ メニューから「イメージを別名で保存」などを選んで、目的のフォルダに保存して下さい。
上記の画像を、プロジェクトのあるフォルダにコピーして実行してみてください。 PNG形式の画像で、背景を透明にして作ります。やってみましょう。クラス名は、Practice1006とします。
タートル変数名.rescale( 拡縮率 );拡縮率は、1.0が元のサイズです。 画像は最初は100×100の大きさで表示されてしまうので、rescale( 1.0 )をしておくと無難だと思います。 なお、resetScale( ) で、元の大きさにすることができます。 タートルのサイズを変えるのに、 setWidth( )や setHeight( )も使えます。 同時に、幅と高さを変える setSize( ) もあります。 また、タートルの幅や高さを得るためには、 getWidth( )や getHeight( )メソッドがあります。 これらは、実数で指定したり、実数で大きさを受け取ります。 なお、何もない、getWidth( ), getHeight( )は、ウィンドウの幅や高さを得るもので、整数で受け取ることになります。 次のプログラムは、startメソッドだけ、記述しています。
タートル変数名.setScale( 拡縮率 );
public void start( ) { setBackgroundColor( Blue ); ImageTurtle turtle = new ImageTurtle( "star.png", this ); turtle.rescale( 0.5 ); // 半分の大きさで for ( int i=0; i<=60; i++ ) { turtle.rotate( 6 ); turtle.setScale( 1.01 ); } }
画像を、Illustratorで作り、「ファイル」メニューの「Webやデバイス用に保存」を選んで、 PNG形式の画像で、背景を透明にして作ります。クラス名はPractice1007として、上記のプログラムを完成させて、 実行してみましょう。
変数名.setDirection( 方向 );たとえば、右方向を向いている画像のときは-90、左方向を向いている画像のときは90を指定します。
public void start( ) { ImageTurtle turtle, back; back = new ImageTurtle( "back.jpg", this ); back.setLocation( getWidth()/2, getHeight( )/2 ); // ウィンドウ中央に配置 turtle = new ImageTurtle( "airplane.png", this ); turtle.rescale( 0.5 ); // 半分の大きさで turtle.setDirection( -90 ); // 画像にあわせて左方向を0度とする for ( int i=0; i<=60; i++ ) { turtle.forward( 5 ); turtle.rotate( 6 ); } }
背景はPhotoshopで作ります。「フィルタ」メニューの「描画」サブメニューから「雲模様1」を選びます。 保存は同じく「ファイル」メニューの「Webまたはデバイス用に保存」で、今度はJPEG形式で高画質を選びます。 「back.jpg」という名前で保存してみて下さい。上のプログラムにある「airplane.png」は下の画像を 保存(ドラッグアウトか右クリックで「イメージを別名で保存」)して、使ってみて下さい。
これを雲模様の中で空中回転させてみます。クラス名はPractice1008として、プログラムを作成、実行してみなさい。
TextTurtle 変数名= new TextTurtle( 文字列, this );なお、TextTurtleの場合は、指定された文字列から構成される画像を作ります。 画像を作るのに少し時間が掛かりますので注意して下さい。 ちなみに、ImageTurtleでは効かなかった、 setTurtleColorによって文字の色を変えることができます。 なお、以下はstartメソッドの中だけを記述しています。
public void start( ) { TextTurtle turtle = new TextTurtle( "Sample", this ); turtle.setTurtleColor( Blue ); for ( int i=0; i< 60; i++ ) { turtle.rotate( 6 ); } }
やってみましょう。クラス名はPractice1009とします。
setTypeface( フォントの名前 );
setFontSize( ポイント数 );
テキストタートルが既に作成されて、回転されていたり、拡大縮小されている場合があると思いますが、 この2つのメソッドを呼び出しますと、テキストの画像を作り直しますので、回転や拡大縮小が元に戻って しまいます。注意してください。
import java.awt.*; public class SystemFontList { public static void main(String [ ] args) { GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment( ); Font allfonts [ ] = env.getAllFonts( ); for ( int i=0; i < allfonts.length; i++ ) { System.out.println( allfonts[ i ].getName( ) ); } } }なお、プログラム開発環境に置かれているフォントが、実行環境に必ずしも置かれていないことに注意して下さい。 Javaで、標準的に使われるのは、次のような名前のフォントです。
"Serif":装飾のあるフォント、英字の紙面に使われているTimesフォントなどが代表的です。
"SansSerif":装飾のないフォント、Helveticaフォントなどが代表的です。
"Dialog":これは、"SansSerif"と同じ場合が多いようです。
"MonoSpaced":すべての字の幅が同じフォント、Courierフォントなどが代表的です。
上記のシステムフォントの名前を全部表示するプログラムを動かしてみましょう。 なお、ターミナルの設定で、「バッファを制限しない」にチェックをいれておいて下さい。
TextTurtle 変数名= new TextTurtle( 整数, this );ただし、文字列の場合は、生成するときに次のようにサイズ、フォント名、色を指定することができます フォント名を指定するときは、システムにあるフォントかどうか確かめるか、標準のフォント名を使いましょう。
TextTurtle 変数名= new TextTurtle( 長桁整数, this );
TextTurtle 変数名= new TextTurtle( 実数, this );
TextTurtle 変数名= new TextTurtle( 文字列, サイズ, this );
TextTurtle 変数名= new TextTurtle( 文字列, 色, サイズ, this );
TextTurtle 変数名= new TextTurtle( 文字列, フォント名, サイズ, this );
TextTurtle 変数名= new TextTurtle( 文字列, 色, フォント名, サイズ, this );
上記の指定で、サイズは整数(の式)で、色はColorオブジェクト、フォント名は文字列で指定します。
生成時に色とサイズを指定できるテキストタートルを使って、 カレンダー的に配列の数をそのまま表示してみましょう。横に8個ずつ並べます。 1つの数を表示するのに、幅30ドット、高さ15ドットを確保しています。 y座標は20の位置から表示を始めることとします。 startメソッドだけを記述します。
public void start( ) { int a [ ] = { 10, 34, 82, 95, 3, 4 ,5 ,1,32, -32, 1, 3, 12, 45, 11, 32, 19, -6, 23, 21, 33 }; int width = 60, height = 30; for ( int i =0; i < a.length; i++ ) { TextTurtle t = new TextTurtle( a[ i ], Blue, 18, this ); t.penup( ); t.setLocation( i % 8 * width + 40 , i / 8 * height + 20 ); } }要素の値を表示するx座標とy座標を技巧的に計算しています。剰余演算はこのように周期的にサイクルさせたいときに使います。また整数除算は、周期毎に1つ値を増やすような場合に使います。次の周期のときには、割り算の結果が1つ大きな値になりますから、表示されるy座標は次の段になります。
やってみましょう。クラス名はPractice1011とします。
Javaでは音声ファイルの再生は、標準では16ビットのステレオで、22kHzの周波数で行なわれます。 ただし、実行されるコンピュータで、この品質で再生できないときは、8ビットのモノラル、 8kHzでの再生になってしまいます。 MIDIファイルに関しては、内蔵のデジタルシンセサイザー音源を使って再生されます。
音声ファイルの形式: MP3, WAVE, AU 音声ファイルのコーディング方法: PCM(リニア), μ-law,その他 音声ファイルの標本周波数: 8kHz 〜 48kHz 音声ファイルの 量子化ビット数: 8bitまたは16 bit 音声ファイルのチャンネル数: Mono (=1)または Stereo(=2)
MIDI形式(楽譜形式)ファイル: MIDI Type 0, MIDI Type 1, RMF
サウンドファイルをロードする:アプレットで、音声ファイルをロードしてAudioClipクラスのオブジェクトを用意してくれるものです。 実行ファイルのあるフォルダに置かれている音声ファイルを指定することができます。 たとえば、次のように記述します。
java.applet.AudioClip <変数名> = getAudioClip( <ファイル名の文字列> );
java.applet.AudioClip au = getAudioClip( "spacemusic.au" );AudioClipクラスのオブジェクトには次の3つのメソッドが用意されています。
サウンドファイルの再生・停止のためのメソッド:たとえば、上記の変数auが指し示すAudioClipクラスのオブジェクトを使った場合は、次のように記述します。
play( ) 1回だけ再生する
loop( ) 繰り返し何回も再生する(stopメソッドが呼ばれるまで)
stop( ) 再生を止める
au.play( ); au.loop( ); au.stop( );
次のファイルをダウンロードしてみて下さい(音声ファイルへのリンク)。 やってみましょう。リンク先の音声ファイルは、QuickTimePlayer Proのプラグインがインストールされていれば、 鳴らしてみてから、右端の▼メニューから「ファイルを保存」で保存できる筈です。 実習教室ではQuickTime Proが導入されていないので、Safariなどでは、上記のリンクを リンクを右クリックして、コンテンツ・メニューを出して「リンク先のファイルを別名で保存」などを 使ってダウンロードしてみてください。プログラム(.classファイル)のある フォルダに置かれていれば、次のようなプログラムで鳴らすことができます。
import java.applet.*; // AudioClipクラスは、java.appletパッケージに入っています。 import sfc.turtle.TurtleFrame; // クラス名を指定するときに「PlayOnce」という名前は、「Practice1012」でも構いません。 public class PlayOnce extends TurtleFrame { public static void main(String [ ] args) { new PlayOnce( ) ; } public void start( ) { AudioClip au = getAudioClip( "spacemusic.au" ); au.play( ); // au.loop( ); にすると鳴り続けますので要注意。 } }
なお、音声に関しては、λ21教室ではイヤホンで聴くことなります。 Macintoshでは、鳴らすための設定をする必要があります(以下の記述は、実習室で調整します)。 通常の実習室のMacintoshでは、システム環境設定を出して、「サウンド」を選び「出力」のタブで「内蔵スピーカー」を選びます。 ただし、教卓にあるMacintoshでは、これではうまくいかない場合もあります(OnyxのFirewireを選ぶなど)ので、注意して下さい。 録音・再生については、Audacityを用います。 これは、Mac OS X版(1.3.6版でないと実習室では動きません)も、Windows版もあるソフトウェアです。 Audacityを使った音声の録音や音声ファイルの変換については、 外部リンクですが、Clan Pohwa メンバーのYOUさんが書かれた(Windows版で書かれていますが、Mac OS Xでもだいたい同じです) 「Audacityの初心者お助け講座」 を参照して下さい。
public void start( ) {
// 最初にしておきたいことを記述しておく
while( true ) { //無限の繰返し
// アニメーションの中での変更点を記述する
update( ); //変更を描画させる
sleep( 秒数 ); // 何秒か休む(たとえば、0.5秒など)
}
}
public void start( ) { TextTurtle turtle = new TextTurtle( getDateString( ), "Optima-Bold", 24, this ); int angle = 0; while ( true ) { turtle.setText( getDateString( ) ); //現在時刻の文字列でタートルを作り直します。 turtle.setAngle( angle ); // タートルを作り直すと0度に戻るので、setAngleで変更させます。 turtle.forward( 0 ); // 描画に画像の角度変更を反映させるために、forwardを入れています。 angle = (angle + 6) % 360; // 360度になったら、0度に戻るようにさせています。 update( ); sleep( 1 ); } }
上記のサンプルを実行して見なさい。クラス名は、Practice1013とします。
public void start( ) { setWaitTurtle( false ); ImageTurtle turtle, back; back = new ImageTurtle( "back.jpg", this ); back.setLocation( getWidth()/2, getHeight( )/2 ); // ウィンドウ中央に配置 turtle = new ImageTurtle( "airplane.png", this ); turtle.setDirection( -90 ); turtle.rescale( 0.3 ); while ( true ) { turtle.forward( 5 ); turtle.rotate( 6 ); update( ); sleep( 0.5 ); } }
上記のサンプルを実行して見なさい。クラス名はPractice1014とします。
タートルを示す変数.intersects( 他のタートルを示す変数 )このメソッドは、衝突していれば、論理値のtrue、衝突していなければ、 論理値のfalseを返してきてくれます。 以下のプログラムの記述は、2つの画像ファイルを読み込んで、動かして、衝突したかどうかをアニメーションの中で判定しています。 衝突していれば、45度回転させながら移動させいます。 startメソッドの中だけを記述しています。
public void start( ) { ImageTurtle turtle1, turtle2, back; back = new ImageTurtle( "back.jpg", this ); back.setLocation( getWidth()/2, getHeight( )/2 ); // ウィンドウ中央に配置 back.rescale( 1.0 ); turtle1 = new ImageTurtle( "airplane1.png", this ); turtle2 = new ImageTurtle( "airplane2.png", this ); turtle1.rescale( 0.5 ); turtle2.rescale( 0.5 ); turtle1.penup( ); turtle2.penup( ); turtle1.setLocation( 10, getHeight( ) /2 ); turtle2.setLocation( getWidth( )-10, getHeight( ) / 2); turtle1.setDirection( 90 ); turtle2.setDirection( -90 ); turtle1.setPenColor( Red ); turtle2.setPenColor( Green ); turtle1.pendown( ); turtle2.pendown( ); while ( true ) { turtle1.forward( 5 ); turtle2.forward( 5 ); if ( turtle1.intersects( turtle2 ) ) { // 衝突したかどうか turtle1.rotate( 45 ); turtle2.rotate( 45 ); // それぞれ45度回転させる // 触れ続けている間は、両機とも5ドットずつ前に移動させる while ( turtle1.intersects( turtle2 ) ) { turtle1.forward( 5 ); turtle2.forward( 5 ); } } // 壁にぶつかったら180度回転させる if ( turtle1.getX( ) < 0 || turtle1.getX( ) > getWidth( ) || turtle1.getY( ) < 0 || turtle1.getY( ) > getHeight( ) ) { turtle1.rotate( 180 ); } if ( turtle2.getX( ) < 0 || turtle2.getX( ) > getWidth( ) || turtle2.getY( ) < 0 || turtle2.getY( ) > getHeight( ) ) { turtle2.rotate( 180 ); } update( ); sleep( 0.1 ); } } }
上記のサンプルを実行して見なさい。それから、斜め30度や60度で動く形に拡張しても良いでしょう。 airplane2.pngは、Photoshopなどで、airplane.pngなどを左右反転させて作ってみて下さい。 クラス名はPractice1015とします。
下記のプログラムで、背景画は左右反転した画像で作っておくのもいいでしょう。 2つの背景画像のサイズは同じにしておきます。2つの背景画像で、back1の左側がback2の右側と連続している ような状態で作っておきます。
public void start( ) { ImageTurtle turtle, back1, back2; back1 = new ImageTurtle( "back1.jpg", this ); back2 = new ImageTurtle( "back2.jpg", this ); back1.penup( ); back2.penup( ); setWidth( (int)( back1.getWidth( ) ) -10 ); // 背景画像のサイズでウィンドウのサイズを設定 -10はスクロールバー分 setHeight( (int)( back1.setHeight( ) ) ); double x1 = back1.getWidth( )/2; double x2 = -back2.getWidth( )/2; double y = getHeight( )/2; back1.setLocation( x1, y ); // ウィンドウ中央に配置 back2.setLocation( x2, y ); // ウィンドウから左側にはみ出て配置 turtle = new ImageTurtle( "airplane.png", this ); while ( true ) { x1 += 10; x2 += 10; if ( x1 >= getWidth( ) + back1.getWidth( ) / 2 ) { x1 = -back1.getWidth( ) / 2; } // 右側にはみ出したら左側に if ( x2 >= getWidth( ) + back2.getWidth( ) / 2) { x2 = -back2.getWidth( ) / 2; } // 同上 back1.setLocation( x1, y ); back2.setLocation( x2, y ); turtle.forward( 0 ); // アニメーションのメソッドを入れないと反映されない update( ); sleep( 0.5 ); } }
上記のサンプルプログラムをクラス名をPractice1016で作成し、実行して見なさい。 可能であれば、斜め45度とかに動かしてみるようにしてみてください(その場合は4つ反転された背景が必要かも)。
java.utilパッケージにあるCalendarクラスのオブジェクトには、 1970年の1月1日0時0分0秒からの経過時間を求めるgetTimeInMillisメソッドがあり、 タートル・グラフィックスでも、 getTotalMilliSecondでこの値を求めることができます。 経過時間の型はlongの整数型でミリ秒単位で求められます。下の代入文では、その経過時間を求めています。 2つの時刻に対して、この方法を使って経過時間を求め、その差分を出せば、どの程度時刻が過ぎたかわかります。 また、求められた時間差に対して、1000で割ると秒数が、更にその結果を60で割ると 分数(更にその結果を60で割ると時間)を得ることができます。
long millisecond = getTotalMilliSecond( ); printLine( millisecond );
次のプログラムは、1/10秒ごとに時間差を表示をするものです。プログラムが開始されたら計測を開始します。 開始時間に対する経過ミリ秒を変数starttimeに求めています。 また、刻々と変わる時間の経過ミリ秒を変数currentに求めています。 この2つの変数の差を1000で割った時間差が経過秒で変数secondに計算しています。 また、同じ差を1000で剰余を求めて、100で割ったものは、1/10秒の部分になります。 テキストタートルは使わずに、文字端末に表示をさせています(テキストタートルは作るのに時間が掛かるので)。 startメソッドと、printDifferenceメソッドを記述しています。
public void start( ) { long starttime = getTotalMilliSecond( ); long current = getTotalMilliSecond( ); printLine( makeDifference( starttime, current ) ); while ( current-starttime < 30000 ) { current = getTotalMilliSecond( ); printDifference( starttime, current ); sleep( 0.05 ); } } void printDifference( long first, long current ) { long minute = (current-first)/1000/60; long second = (current-first)/1000%60; long decisecond = (current-first)%1000/100; printLine( formatInteger( 2, 5, minute )+":"+ formatInteger( 2, 2, second ) +":"+ formatInteger( 2, 2, decisecond*10 ) ); }
上記のサンプルを実行して見なさい。アプリケーションで作成します。 Practice1017というクラス名にしなさい。
public void start( ) { int count=30; TextTurtle turtle = new TextTurtle( count, this ); turtle.setTypeface( "Lucida Grande" ); turtle.setFontSize( 64 ); while ( count > 0 ) { if ( count < 10 ) { turtle.setTurtleColor( Red ); } turtle.setText( count ); count--; update( ); sleep( 1 ); } turtle.setTurtleColor( Black ); turtle.setText( 0 ); turtle.rescale( 2 ); turtle.rotate( 360 ); }
上記のサンプルプログラムをクラス名Practice1018という名前で作成し、実行してみなさい。
時間計測のプログラムを参考にして、2分間だけ、1秒ずつカウントアップ(あるいはカウントダウン)する プログラムを作りなさい。 プログラムが実行されたらカウントアップ(あるいはカウントダウン)を開始します。 テキストタートルを使って表示させてみて下さい。テキストタートルが遅ければ、ターミナルに表示させなさい。 60秒から始めて、0秒になったら、プログラムを停止させます。また、1/10秒ではなくて、 1/100秒まで表示するプログラムを作りなさい。クラス名は、StopWatchにて。
何らかのメッセージを表示するプログラムを作ります。1つのテキストタートルを用いて、5秒に1回、 別の色でそのメッセージを表示させます。また、2秒に10ドットの割合で、左に移動して表示させます。 表示が左の端から消えたら、右側からまた表示させるようにします。クラス名は、MessageBoardにて。
ヒント:2つの動きの最小公約数の1秒単位で繰返しを構成するようにします。 繰返しの中で、5回に1回の割合で色を変えるようにします。 また、2回に1回の割合で左に移動させるようにします。
<<Previous Lecture | >>Next Lecture |