#author("2019-06-05T13:45:11+09:00","default:qua","qua") #author("2019-06-05T14:12:44+09:00","default:qua","qua") #navi(Processing/4.クラスの利用) * 4-3 クラスの継承---Fisicaの図形の描き方 [#yd58001a] 次のスケッチを実行してみよう。 import fisica.*; FWorld world; FCircle ball1, ball2; void setup(){ size(600,300); Fisica.init(this); world = new FWorld(); world.setEdges(); world.setEdgesFriction( 0 ); ball1=new FCircle(40); ball1.setDamping( 0 ); ball1.setDensity( 2 ); ball1.setFriction( 0.1 ); ball1.setRestitution( 1 ); ball1.setPosition( 50, 274.5 ); ball1.setGrabbable( false ); ball1.setFill( 128, 255, 128 ); world.add( ball1 ); ball2=new FCircle(40); ball2.setDamping( 0 ); ball2.setDensity( 4 ); ball2.setFriction( 0.1 ); ball2.setRestitution( 1 ); ball2.setPosition( 200, 274.5 ); ball2.setGrabbable( false ); ball2.setFill( 255, 128, 128 ); world.bottom.setFill(128); world.top.setFill(128); world.left.setFill(192); world.right.setFill(192); world.bottom.setStroke(128); world.top.setStroke(128); world.left.setStroke(192); world.right.setStroke(192); world.add( ball2 ); } void mouseClicked(){ if( dist( mouseX, mouseY, ball1.getX(), ball1.getY()) < ball1.getSize() ){ ball1.addImpulse( ball1.getMass()*200, 0, mouseX-ball1.getX(), mouseY-ball1.getY() ); } } void draw(){ background(0); world.step(); world.draw(); } これを実行すると、左側の球をマウスでクリックすると、クリックした点に力積が加えられる。 #ref(http://www.ist.aichi-pu.ac.jp/lab/qua/~qua/pbl/processing/img/4-2-1.png,450x245) これだけでは、どこをクリックしてもあまり様子が変わらない。そこで、球のどこかに目印をつけて回転する様子を眺めてみよう。それには、球のクラスFCircleを元に自前のクラスMyBallを作成して、描き方だけを変えてみればよい。このようにあるクラスを元にそれと少し変更・拡張したクラスを作ることをクラスの継承という。 まず、クラスを定義する。 class MyBall extends FCircle{ MyBall( float r ){ super( r ); } public void draw(PGraphics applet) { preDraw(applet); if (m_image != null ) { drawImage(applet); } else { applet.ellipse(0, 0, getSize(), getSize()); applet.fill( 0 ); applet.ellipse( getSize()/3, 0, 3, 3 ); } postDraw(applet); } } 1行目の class MyBall extends FCircle では、FCircleクラスを継承して、MyBallクラスを定義することを宣言している。次の MyBall( float r ){ super( r ); } はnew MyBall( r )でインスタンスを作成するときに、拡張元であるFCircle( r )と同じ コンストラクタを利用することを書いている。 public void draw(PGraphics applet) が球を描画する部分である。もともとのFCircleのdraw()は次の通りである。 public void draw(PGraphics applet) { preDraw(applet); if (m_image != null ) { drawImage(applet); } else { applet.ellipse(0, 0, getSize(), getSize()); } postDraw(applet); } ここに applet.fill( 0 ); applet.ellipse( getSize()/3, 0, 3, 3 ); として、getSize()で得られる直径の1/3のところに半径3の黒い点を追加して描く。 あとは、FCircleをMyBallに置き換えればよい。その結果を下記に示す。 import fisica.*; FWorld world; MyBall ball1, ball2; class MyBall extends FCircle{ MyBall( float r ){ super( r ); } public void draw(PGraphics applet) { preDraw(applet); if (m_image != null ) { drawImage(applet); } else { applet.ellipse(0, 0, getSize(), getSize()); applet.fill( 0 ); applet.ellipse( getSize()/3, 0, 3, 3 ); } postDraw(applet); } } void setup(){ size(600,300); Fisica.init(this); world = new FWorld(); world.setEdges(); world.setEdgesFriction( 0 ); ball1=new MyBall(40); ball1.setDamping( 0 ); ball1.setDensity( 2 ); ball1.setFriction( 0.1 ); ball1.setRestitution( 1 ); ball1.setPosition( 50, 274.5 ); ball1.setGrabbable( false ); ball1.setFill( 128, 255, 128 ); world.add( ball1 ); ball2=new MyBall(40); ball2.setDamping( 0 ); ball2.setDensity( 4 ); ball2.setFriction( 0.1 ); ball2.setRestitution( 1 ); ball2.setPosition( 200, 274.5 ); ball2.setGrabbable( false ); ball2.setFill( 255, 128, 128 ); world.bottom.setFill(128); world.top.setFill(128); world.left.setFill(192); world.right.setFill(192); world.bottom.setStroke(128); world.top.setStroke(128); world.left.setStroke(192); world.right.setStroke(192); world.add( ball2 ); } void mouseClicked(){ if( dist( mouseX, mouseY, ball1.getX(), ball1.getY()) < ball1.getSize() ){ ball1.addImpulse( ball1.getMass()*200, 0, mouseX-ball1.getX(), mouseY-ball1.getY() ); } } void draw(){ background(0); world.step(); world.draw(); } #ref(http://www.ist.aichi-pu.ac.jp/lab/qua/~qua/pbl/processing/img/4-2-2.png,450x245) 調子に乗って、3次元的に描いてみる。上のプログラムとの違いは、 - MyBallクラスのdraw()で、ellipseではなく、sphereで立体的に描いていること - size(600,300,P3D)で3次元描画にしていること - setup内で壁(world.top, world.bottom, world.left, world.right)を描かないように設定し、その代わりに、drawEdges()関数を用いて立体的に描いていること - setup内で壁(world.top, world.bottom, world.left, world.right)を描かないように設定し、その代わりに、drawEdges()関数を作り、その中で立体的に描いていること - 計算が面倒なので、マウスのクリックの処理を手抜きしていること import fisica.*; FWorld world; MyBall ball1, ball2; FBox bottom; class MyBall extends FCircle{ MyBall( float r ){ super( r ); } public void draw(PGraphics applet) { preDraw(applet); if (m_image != null ) { drawImage(applet); } else { applet.sphere( getSize()/2 ); } postDraw(applet); } } void setup(){ size(600,300,P3D); Fisica.init(this); world = new FWorld(); world.setEdges(); world.setEdgesFriction( 0 ); ball1=new MyBall(60); ball1.setDamping( 0 ); ball1.setDensity( 2 ); ball1.setFriction( 0.1 ); ball1.setRestitution( 1 ); ball1.setPosition( 50, 264.5 ); ball1.setGrabbable( false ); ball1.setFill( 128, 255, 128 ); ball1.setNoStroke(); world.add( ball1 ); ball2=new MyBall(60); ball2.setDamping( 0 ); ball2.setDensity( 4 ); ball2.setFriction( 0.1 ); ball2.setRestitution( 1 ); ball2.setPosition( 200, 264.5 ); ball2.setGrabbable( false ); ball2.setFill( 255, 128, 128 ); ball2.setNoStroke(); world.add( ball2 ); world.bottom.setNoFill(); world.top.setNoFill(); world.left.setNoFill(); world.right.setNoFill(); world.bottom.setNoStroke(); world.top.setNoStroke(); world.left.setNoStroke(); world.right.setNoStroke(); println( world.bottom.getY() ); } void drawEdges(){ pushMatrix(); translate( world.bottom.getX(), world.bottom.getY(), 0 ); rotateX(radians(90)); fill( 128 ); rect( -500, -500, 1000, 1000 ); popMatrix(); pushMatrix(); translate( world.left.getX(), world.left.getY(), 0 ); rotateY(radians(90)); fill( 192 ); rect( -500, -500, 1000, 1000 ); popMatrix(); pushMatrix(); translate( world.right.getX(), world.right.getY(), 0 ); rotateY(radians(90)); fill( 192 ); rect( -500, -500, 1000, 1000 ); popMatrix(); } void mouseClicked(){ ball1.addImpulse( ball1.getMass()*200, 0 ); } void draw(){ background(0); lights(); drawEdges(); translate( 0, 0, -100 ); world.step(); world.draw(); } #ref(http://www.ist.aichi-pu.ac.jp/lab/qua/~qua/pbl/processing/img/4-2-3.png,450x245)