質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

5212閲覧

Java Turtleアプレット「一匹の亀をドラッグすると、三匹の他の亀がそれぞれ1/2,1/3,2倍の距離を同時に動くようにしたい。」 

Rino-T_C

総合スコア95

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2015/06/02 05:57

編集2015/06/02 10:33

こんにちは、Java初心者です。
Turtleアプレットの作成を通じて、イベント処理とオブジェクト指向の学習をしています。
現在、亀に足跡を描かせるクラス。Turtleクラスをを用いて、4匹の亀を生成します。うち1匹をドラッグすると、それに伴って他の亀が同じ向きで距離だけ異なって移動し、図形を描画させたいです。
頑張って考えたのですが、実際に動かしてみると、全く描画されません。
急ぎなので、わかる方お願いします!

Turtle.java

lang

1import java.applet.Applet; 2import java.awt.*; 3import java.util.*; 4 5public class Turtle{ 6 7 //インスタンス変数の宣言 8 9 int x, y; 10 double angle = 0; 11 int pensize = 1; 12 Color pencolor = Color.black; 13 14 ArrayList<Point> points = new ArrayList<Point>(); 15 16 17 //コンストラクタの定義 18 19 Turtle(int i, int j){ 20 x = i; 21 y = j; 22 //亀さんの座標を決定 23 24 points.add(new Point(x, y)); 25 26 } 27 28 29 30 //各種メソッドの定義 31 32 //現在位置から進行方向に向かって距離lengthだけ移動する。 33 34 public void move(double length){ 35 int i = points.size()-1; 36 Point pt = points.get(i); 37 int x_l = (int)Math.round(length * Math.cos(angle)) + pt.x; 38 int y_l = (int)Math.round(length * Math.sin(angle)) + pt.y; 39 40 points.add(new Point(x_l, y_l)); 41 } 42 43 //進行方向をdegだけ左回転する。 44 public void turn(double deg){ 45 angle -= deg; 46 } 47 48 //ペンの太さを設定する。 49 50 public void PenSize(int size){ 51 pensize = size; 52 } 53 54 //ペンの色を設定する 55 56 public void penColor(Color c){ 57 pencolor = c; 58 } 59 60 //亀の軌跡の描画 61 62 public void paint(Graphics g){ 63 g.setColor(pencolor); 64 65 int i; 66 int px[] = new int[points.size()]; 67 int py[] = new int[points.size()]; 68 for( i = 0; i < points.size(); i++){ 69 Point p_i = points.get(i); 70 px[i] = p_i.x; 71 py[i] = p_i.y; 72 } 73 g.drawPolyline(px, py, points.size()); 74 } 75}

Turtle2.java

lang

1import java.applet.Applet; 2import java.awt.*; 3import java.util.*; 4 5public class Turtle2{ 6 7 Turtle kame[] = new Turtle[4]; 8 9 Turtle2(Turtle k[]){ 10 kame = k; 11 } 12 13 void move(double length){ 14 kame[0].move(length); 15 kame[1].move(length/2); 16 kame[2].move(length/3); 17 kame[3].move(length*2); 18 } 19 20 void turn(double deg){ 21 for(int i = 0; i < 4; i++){ 22 kame[i].turn(deg); 23 } 24 } 25 26 void paint(Graphics g){ 27 for(int i = 0; i < 4; i++){ 28 kame[i].paint(g); 29 } 30 } 31 32}

Rabbit.java

lang

1import java.applet.Applet; 2import java.awt.*; 3import java.util.*; 4import java.awt.event.*; 5 6 7public class Rabbit extends Applet implements MouseMotionListener{ 8 int current_x; //マウスの現在のx座標 9 int current_y; //マウスの現在のy座標 10 Turtle kame[] = new Turtle[4]; 11 Turtle2 Usagi = new Turtle2(kame); 12 double deg = 0; 13 double length = 0; 14 double pi = Math.PI; 15 Image imgs; 16 17 18 public void init(){ 19 setBackground(Color.white); 20 imgs= getImage(getDocumentBase(), "kame2.gif"); 21 22 kame[0] = new Turtle(100, 100); 23 kame[1] = new Turtle(300, 100); 24 kame[2] = new Turtle(100, 300); 25 kame[3] = new Turtle(300, 300); 26 27 //addMouseListener(this); 28 29 addMouseMotionListener(this); 30 31 } 32 33 public void mouseDragged(MouseEvent e){ 34 35 int size = kame[0].points.size() - 1; 36 Point p_0 = kame[0].points.get(size); 37 if(current_x >= p_0.x && current_x <= p_0.x+68 && current_y >= p_0.y && current_y <= p_0.y + 48){ 38 current_x = e.getX(); 39 current_y = e.getY(); 40 kame[0].points.add(new Point(current_x, current_y)); 41 } 42 repaint(); 43 } 44 45 public void mouseMoved(MouseEvent e){ 46 47 } 48 49 50 51 public void paint(Graphics g){ 52 int size = kame[0].points.size() - 1; 53 for(int i = 0; i < 4; i++){ 54 g.drawImage(imgs, kame[i].points.get(size).x, kame[i].points.get(size).y, this); 55 } 56 g.setColor(Color.black); 57 Point p_0 = kame[0].points.get(size - 1); 58 double dx = current_x - p_0.x; 59 double dy = current_y - p_0.y; 60 deg = Math.atan2(dy, dx); 61 if( deg != 0 || deg != pi || deg != -pi){ 62 length = dx; 63 } 64 else{ 65 length = dy/Math.sin(deg); 66 } 67 Usagi.turn(deg); 68 Usagi.move(length); 69 Usagi.paint(g); 70 } 71} 72 73

解決「現在は実行時エラーです。
また、実行時エラーにならずとも、足跡が描画されなかったり、右下にしか亀が動かなかったりします。」

現在、実行した段階でなぜか毎回決まった線が描画されてしまっています。

修正後
Turtle.java

lang

1public class Turtle{ 2 3 //インスタンス変数の宣言 4 5 int x, y; 6 double angle = 0; 7 8 ArrayList<Point> points = new ArrayList<Point>(); 9 10 11 //コンストラクタの定義 12 13 Turtle(int i, int j){ 14 x = i; 15 y = j; 16 points.add(new Point(x, y)); 17 18 } 19 //各種メソッドの定義 20 public void move(double x, double y){ 21 int i = points.size() - 1; 22 Point pt = points.get(i); 23 24 points.add(new Point( (int)x+pt.x, (int)y+pt.y)); 25 } 26 27 //亀の軌跡の描画 28 29 public void paint(Graphics g){ 30 31 g.setColor(pencolor); 32 33 int i; 34 int px[] = new int[points.size()]; 35 int py[] = new int[points.size()]; 36 for( i = 0; i < points.size(); i++){ 37 Point p_i = points.get(i); 38 px[i] = p_i.x; 39 py[i] = p_i.y; 40 } 41 g.drawPolyline(px, py, points.size()); 42 43 } 44}

Turtle2.java

lang

1public class Turtle2{ 2 3 Turtle kame[] = new Turtle[4]; 4 5 Turtle2(Turtle k[]){ 6 kame = k; 7 } 8 9 void move(double x, double y){ 10 kame[1].move(x/2, y/2); 11 kame[2].move(x/3, y/3); 12 kame[3].move(x*2, y*2); 13 14 15 void paint(Graphics g){ 16 for(int i = 0; i < 4; i++){ 17 kame[i].paint(g); 18 } 19 } 20 21}

Rabbit.java

lang

1public class Rabbit extends Applet implements MouseListener, MouseMotionListener{ 2 int current_x; //マウスの現在のx座標 3 int current_y; //マウスの現在のy座標 4 Turtle kame[] = new Turtle[4]; 5 Turtle2 Usagi = new Turtle2(kame); 6 Image imgs; 7 8 9 public void init(){ 10 setBackground(Color.white); 11 imgs= getImage(getDocumentBase(), "kame2.gif"); 12 13 kame[0] = new Turtle(100, 100); 14 kame[1] = new Turtle(300, 100); 15 kame[2] = new Turtle(100, 300); 16 kame[3] = new Turtle(300, 300); 17 18 addMouseListener(this); 19 20 addMouseMotionListener(this); 21 22 } 23 24 public void mouseDragged(MouseEvent e){ 25 26 int size = kame[0].points.size() - 1; 27 Point p_0 = kame[0].points.get(size); 28 if(current_x >= p_0.x && current_x <= p_0.x+68 && current_y >= p_0.y && current_y <= p_0.y + 48){ 29 current_x = e.getX(); 30 current_y = e.getY(); 31 kame[0].points.add(new Point(current_x, current_y)); 32 repaint(); 33 } 34 } 35 36 public void mouseMoved(MouseEvent e){ 37 38 } 39 40 public void mouseClicked(MouseEvent e){ 41 42 } 43 public void mouseEntered(MouseEvent e){ 44 45 } 46 public void mouseExited(MouseEvent e){ 47 48 } 49 50 public void mousePressed(MouseEvent e){ 51 52 } 53 54 public void mouseReleased(MouseEvent e){ 55 56 } 57 58 public void paint(Graphics g){ 59 for(int i = 0; i < 4; i++){ 60 61 int size = kame[i].points.size() - 1; 62 63 Point p_cur = kame[i].points.get(size - 1); 64 Point p_prev = kame[i].points.get(size - 1); 65 double dx = p_cur.x - p_prev.x; 66 double dy = p_cur.y - p_prev.y; 67 Usagi.move(dx, dy); 68 g.drawImage(imgs, kame[i].points.get(size).x, kame[i].points.get(size).y,this); 69 } 70 g.setColor(Color.black); 71 Usagi.paint(g); 72 } 73}

こんなかんじになりました。現在実行時エラーです(´;ω;`)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ドラッグするということは、マウスボタンを離した所まで移動するということになりますね。
ドラッグを始めた位置→ドラッグを終えた位置という2点の情報が得られるはずです。
この2点のx差分とy差分を調べます。左上の亀を左下へ50ずつ動かしたとしましょう。
右下座標系、右へ行けばxがプラス、下へ行けばyがプラスという前提で。
100,100から50,150へ移動したと思います。
ということはx差分は50-100で-50、y差分は150-100で+50ですね。
この差分値を他の亀の座標に加算してあげれば良いのです。
右上の亀は300,100なので250,150。左下の亀は100,300なので50,350。右下はの亀は250,350になります。

ドラッグ中もマウスの動きを監視して描画させたい場合も同じで、前回の位置と今回の位置の差分をとって、他の亀の位置へ加算すれば良いです。

あ、掲題に書いてある「二分の一、三分の一、二倍」については、その差分値を1/2, 1/3, 2倍してから加算すれば良いです。

投稿2015/06/02 08:44

編集2015/06/02 08:46
DAT

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

変更点は2つです。
描画と亀の動きを弄るところを分けました。

mouseDraggedで亀を移動させる時、他の亀の移動も処理しています。
paintメソッドでは描画のみを実行しています。

lang

1public class Rabbit extends Applet implements MouseListener, MouseMotionListener{ 2 public void mouseDragged(MouseEvent e){ 3 int size = kame[0].points.size() - 1; 4 Point p_0 = kame[0].points.get(size); 5 if(current_x >= p_0.x && current_x <= p_0.x+68 && current_y >= p_0.y && current_y <= p_0.y + 48){ 6 current_x = e.getX(); 7 current_y = e.getY(); 8 9 kame[0].points.add(new Point(current_x, current_y)); 10 // 他の亀はドラッグにあわせて動くので、ここで座標も弄りましょう 11 Point p_cur = kame[0].points.get(kame[0].points.size() - 1); 12 Point p_prev = kame[0].points.get(kame[0].points.size() - 2); 13 double dx = p_cur.x - p_prev.x; 14 double dy = p_cur.y - p_prev.y; 15 Usagi.move(dx, dy); // 他の亀の移動 16 17 repaint(); 18 } 19 } 20 21 public void paint(Graphics g){ 22 // 描画に関することだけやります 23 for(int i = 0; i < 4; i++){ 24 int size = kame[i].points.size() - 1; 25 g.drawImage(imgs, kame[i].points.get(size).x, kame[i].points.get(size).y,this); 26 } 27 g.setColor(Color.black); 28 Usagi.paint(g); 29 } 30}

先ほど見せていただいた修正後のコードを見たのですが、どこで実行時エラーがでているかまではちょっとわかりませんでした。
動きも予想で書いているのでチグハグなところがあるかもしれません。


旧回答

これは…まとめて質問に答えるのはたぶん難しいので気づいたところだけ。

右下にしか亀が動かなかったりします。

lang

1public void move(double length){ 2 int i = points.size()-1; 3 Point pt = points.get(i); 4 int x_l = (int)Math.round(length * Math.cos(angle)) + pt.x; 5 int y_l = (int)Math.round(length * Math.sin(angle)) + pt.y; 6 7 points.add(new Point(x_l, y_l)); 8}

これではMath.roundの結果分常に他の亀は右下に進み続けてしまいます。
移動距離だけ渡すなら、xとyを別々に計算してそれぞれの亀の現在位置に加算するようにしましょう。
(上に100移動していたらy=-100, 他の亀は-50, -33,-200 する、下に100移動なら+50,+30,+200)

実行時エラーについては…
ぱっと見ですがpublic void paint(Graphics g)の以下の部分は初期状態で長さ2以上あるのでしょうか?(points.size() - 2 の位置を参照しても大丈夫ですか?)

lang

1Point p_0 = kame[0].points.get(size - 1);

投稿2015/06/02 06:30

編集2015/06/02 11:01
haru666

総合スコア1591

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Rino-T_C

2015/06/02 07:03

回答ありがとうございます!! 実行時エラーの方はなくなりました! なのですが、右下に進んでしまう方の対処方がイマイチよくわかりません。 こちらの理解が浅いせいで、手を煩わせてしまい、申し訳ないのですが、具体的にどう計算すればいいか教えてもらってもよろしいですか?
Rino-T_C

2015/06/02 07:40

考えてみた結果、指摘のあったところを以下のように書き換えてみました。 public void move(double length){ x += (int)Math.round(length * Math.cos(angle)); y += (int)Math.round(length * Math.sin(angle)); points.add(new Point(x, y)); } x, yは亀の現在の座標になります。 ですが、実行した段階で、何かしらの値がArrayListに入ってしまっているらしく、 実行した段階で変な線が描かれてしまっています。 また、今度は左下に一瞬動いたあと、repaint()はされるものの、亀は動かず、線も描画されなくなってしまいます。
Rino-T_C

2015/06/02 07:45

亀の動きを見てみると、なんだかある一点に収束していくような動きを見せたあと、止まります。
haru666

2015/06/02 09:20

すみません、angleを設定してその距離分移動したい、という感じだったんですね。 最初ぱっと見た時にはそのあたりわかっていませんでした。 申し訳ないですが、私は三角関数は不得意なので、そこが正しく動いているかソースコードだけをみて判断することができません。 ただ、このプログラムならangle抜きでXとYを使うだけでも十分進行方向を定めることができると思います。 コードにすると以下みたいな感じですね。 public class Turtle { public void move(double x, double y){ int i = points.size()-1; Point pt = points.get(i); points.add(new Point(x + pt.x, y + pt.y)); } } public class Turtle2 { void move(double x, double y){ // kame[0].move(length); // これは必要なのかな…?いらない気がしますが… kame[1].move(x/2, y/2); kame[2].move(x/3, y/3); kame[3].move(x*2, y*3); } } public class Rabbit extends Applet implements MouseMotionListener{ public void paint(Graphics g){ int size = kame[0].points.size() - 1; Point p_cur = kame[0].points.get(size); Point p_prev = kame[0].points.get(size - 1); double dx = p_cur.x - p_prev.x; double dy = p_cur.y - p_prev.y; Usagi.move(dx, dy); // 描画は描画でまとめます for(int i = 0; i < 4; i++){ g.drawImage(imgs, kame[i].points.get(size).x, kame[i].points.get(size).y, this); } g.setColor(Color.black); Usagi.paint(g); } } これで動くようなら三角関数の使い方があっているか確認する必要があるでしょう。
haru666

2015/06/02 10:02

ふと思ったのですが、今のコードはkame[0].pointsとkame[1~3].pointsの長さが同じ保障が今現在無いので危険ですね…しかも描画頻度で勝手に亀が進んでしまう気もします…
Rino-T_C

2015/06/02 10:10

回答ありがとうございます! 今頑張って試してみています。 pointsの長さの保証は・・・確かにないかもですね・・・ とりあえず、試してみますね(^-^)
Rino-T_C

2015/06/02 10:20

試してみたのですが、今度はまた実行時エラーとなってしまいました・・・。
Rino-T_C

2015/06/02 10:35

参考にさせてもらったのですが、今度は実行時エラーがまた起こってしまい描画されません・・・。 実際に修正したプログラムを質問の方を修正して加えました。
haru666

2015/06/02 10:38

全部実行時対策をいれるとなると以下みたいな感じかな・・・ public class Rabbit extends Applet implements MouseMotionListener{ public void paint(Graphics g){ int size = kame[0].points.size() - 1; if (size > 0) { Point p_cur = kame[0].points.get(size); Point p_prev = kame[0].points.get(size - 1); double dx = p_cur.x - p_prev.x; double dy = p_cur.y - p_prev.y; Usagi.move(dx, dy); } // 描画は描画でまとめます for(int i = 0; i < 4; i++){ int last = kame[i].points.size() - 1; g.drawImage(imgs, kame[i].points.get(last).x, kame[i].points.get(last).y, this); } g.setColor(Color.black); Usagi.paint(g); } }
haru666

2015/06/02 10:44

質問の書き直しの方法だと Usagi.move(dx, dy);が4回よばれてしまうのでちょっと違いますね・・・ ちょっとこっちだとコードが見づらいので、投稿を編集して整理してみますね
Rino-T_C

2015/06/02 10:54

描画を言われたとおりに、MouseDraggedのところを public void mouseDragged(MouseEvent e){ for(int i = 0; i < 4; i++){ current_x = e.getX(); current_y = e.getY(); int size = kame[i].points.size() - 1; Point p_i = kame[i].points.get(size); if(current_x >= p_i.x && current_x <= p_i.x+68 && current_y >= p_i.y && current_y <= p_i.y + 48){ kame[i].points.add(new Point(current_x, current_y)); } repaint(); } } に書き換え MousePressedのところに public void mousePressed(MouseEvent e){ current_x = e.getX(); current_y = e.getY(); } を追加右方向と下方向(x, yともに正の向き)のみには同時に動いてくれるようになりました! しかし、負の方向には動いてくれません(´;ω;`)
Rino-T_C

2015/06/02 10:55

ありがとうございます!
haru666

2015/06/02 11:05

もう一つ気になったことが・・・ mouseDraggedで座標を処理していますが、これだと移動範囲がかなり狭められてしまいます。 下記はドラッグの開始位置を調整したいコードだと思いますが、ドラッグ中の座標移動でよばれるコードなのでこれでは右下にしか移動できません。 if(current_x >= p_i.x && current_x <= p_i.x+68 && current_y >= p_i.y && current_y <= p_i.y + 48){ } このソースコードを消してみてください。左上に移動できるようになりますが、一方でどこをクリックしても亀が移動できるようになると思います。 そこまで書いたら、mousePressed と mouseReleased の二つのイベントを使って 亀をドラッグ中か判定するフラグ処理を作ってみてください }
Rino-T_C

2015/06/02 11:39

できました! 長い時間私に付き合っていただき本当にありがとうございました!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問