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

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

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

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

Q&A

解決済

2回答

567閲覧

目の向きを変えるオブジェクトが表示できない

likuson

総合スコア34

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

0グッド

0クリップ

投稿2019/07/12 22:35

前提・実現したいこと

数式を用いてマウスの方向に白目の中で黒目が向くオブジェクトをプログラムしています。エラーは起きていませんが。黒目が白目に収まらず、暴走してしまいます。

発生している問題・エラーメッセージ

エラーメッセージはありません。

該当のソースコード

processing

1Eye eye; 2 3void setup(){ 4 size(200,200); 5 eye=new Eye(100,100,50,20); 6} 7 8void draw(){ 9 background(255); 10 eye.display(); 11} 12class Eye{//classname 13 int x;//feild 14 int y; 15 int w;//white width 16 int b;//black width 17 Eye(int tempX,int tempY,int tempW,int tempB){ 18 x=tempX; 19 y=tempY; 20 w=tempW; 21 b=tempB; 22 } 23 void display(){ 24 fill(255);//white 25 ellipse(x,y,w,w); 26 int dx; 27 int dy; 28 dx=mouseX-x; 29 dy=mouseY-y; 30 float l; 31 l=sqrt(sq(dx)+sq(dy));//sqrt=rute2 sq=^2 32 float ex; 33 float ey; 34 ex=x+(((w-b)*dx)/2*l); 35 ey=y+(((w-b)*dy)/2*l); 36 fill(0);//black 37 ellipse(ex,ey,b,b); 38 } 39} 40 41 42 43

試したこと

数式を見直しました。

補足情報(FW/ツールのバージョンなど)

⽩⽬の直径が w,⽩⽬の中⼼の座標が(x, y),⿊⽬の直径が b,マウスの座標が(mouseX,mouseY)、⿊⽬の中⼼の座標(ex, ey)、マウスの座標と白目の座標の距離をlとしています。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2019/07/13 00:15

分類:【Processing】オブジェクトを操作できない で3つ質問立ってますが、これは一つ解決したら全部解決するか、解決の足掛かりになります。 質問するときは オブジェクトの色(→状態)を変更できない。 オブジェクトの向き(→状態)を変更できない。 等別の言い方に変えて同じ質問じゃないか判断してから質問しましょう
thkana

2019/07/13 01:38

通常、プログラムにおいて「暴走」というは制御不能になることであって、今回のように異常に動きが大きいだけのものは暴走とはいいません。 「試したこと」の欄は「自分はなにかやった、頑張っているんだ」というアピールのためにあるのではありません。問題解決につながるかも知れないと考えてあなたがやったこと、そして起きたこと(あるいは起こらなかったこと)を結果まで書いて下さい。それが解決への手がかりになる...かも知れません。
guest

回答2

0

ベストアンサー

質問者さんご自身の課題

プログラマーは期待通りに動かないとき、コードのどこに問題があるかをデバッグします。

デバッグする方法にはいろいろありますが

(A) ソースコードを見直して正しいかどうか「考える」
(B) 実際に動かし変数の値などが本当に期待通りかの「事実を確認する」

質問者さんは(A)のみで原因を探ろうとしているわけですが、原因に到達できるためには以下を論理的かつ正確に行える必要があります。

  • (1)そのコードの入力となるデータの範囲がどうかを正確に認識し、

本件で言えばmouseX, mouseYが入力と言えましょう。

  • (2)そのコードの計算によりどのような出力情報の範囲になるか正確に認識し、

本件で言えばex, eyが出力と言えましょう。

  • (3)上記を正確に認識するために、計算機言語の仕様を充分に把握する

ex, eyがどのような範囲となるかは途中の計算式の意味を正しく捉えればよいです。

数式を見直したにもかかわらず間違いを見つけられなかったとのことですが、実際にex, eyは期待通りの範囲にはなりません。

つまり(1)~(3)を正しく推論できてないのが「問題の原因を見つけられない原因」すなわち「質問者さんの課題」です。

どうすれば問題の原因に近づけるか

こういう場合の最も有効と思えるアプローチは「自分の推論を裏付ける事実の確認」であり、それは前項で述べた(B)にあたります。ex, eyが期待通りの範囲かどうかはその値を表示するコードを追加し、実際にプログラムを動かして確認してみればわかります。例えばtextを使うなら、displayメソッドの最終行付近を以下のようにすればよいでしょう。

processing

1... 2 void display() { 3 ... 4 ellipse(ex,ey,b,b); 5 text(dx, 100, 12); 6 text(dy, 100, 24); 7 text(ex, 2, 12); 8 text(ey, 2, 24); 9 } 10}

動かしてみると「ex, eyが期待外の値になっている」ことが確認できるでしょう。

プログラミングで重要なのは、コードが正しいと**「思う」ことではなく、実際に正しいことを「確認する」**ことです。確認は事実に基づいて行うのが最も分かり易いのでex, eyの値を表示することが有力な方法となります。表示してみて「それが期待外になっている」ことが確認できれば「そういう値になるのは自分が書いたコードにバグがあるからだ」とはっきり認識できバグの本当に原因に近づくことができます。逆に事実を掴まないまま曖昧な推測「Processingのバグかなにかで暴走したのではないか」なんてことをしてしまうとデバッグは迷走することでしょう。

プログラミングで最も大事なのは「正しくない方向に進まないよう、事実に基づき理詰めに推論を進めること」と言えましょう。それを原則としてコードを書いたりデバッグしたりすることを覚えてください。

蛇足かも知れないこと1(バグの原因)

バグの原因へのアプローチ方法を上記でコメントしましたが、それだけだと質問者さんが「原因に到達できない」かも知れませんので具体的なバグの箇所を言いますと

processin

1 ex = x + (((w - b) * dx) / 2 * l); 2 ^

ここです。*ではなく/とすべきでしょう。蛇足を言えば数式が充分整理されない気がします。同じ内容を表す式でもしかるべき順番で項を並べれば正しい式かどうか分かり易くなると思います。

processin

1 ex = x + (w - b) / 2 * dx / l; 2 <---------> これが白目と黒目の半径の差 3 <----> これがx座標の方向成分

蛇足かも知れないこと2

このコードはUnixのウィンドウシステムX11ウィンドウシステムに付属しているおなじみのサンプルアプリケーションxeyesに似ています。それと似た振る舞いにするなら「表示しようとしている目」に対してマウスの位置が近いなら黒目を白目の中心近くに、遠いなら中心から離れたところへ表示するようにしたいところ。そうするには例えば次のようなコードにすればよいと思います。

processing

1 ... 2 int dx = mouseX - x; 3 int dy = mouseY - y; 4 float l = sqrt(sq(dx) + sq(dy)); 5 float distFactor = (w - b) / 2 * constrain(l, 0, width / 2) / 100; 6 float ex = x + distFactor * dx / l; 7 float ey = y + distFactor * dy / l; 8 ...

投稿2019/07/13 02:35

編集2019/07/13 02:36
KSwordOfHaste

総合スコア18394

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

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

thkana

2019/07/13 03:14

ツッコミ失礼。 float l = sqrt(sq(dx) + sq(dy)); でlが0になると、lで割る計算はちょっとマズいのでは。
likuson

2019/07/13 15:29

丁寧な回答ありがとうございました。具体的に何をやればいいか明確に説明してくださり、正解までたどり着くことができました。違うプログラムを書き、数式だけをプログラムし、確かめたところ思ったような数値は出ませんでした。数式を書き換え、この数式が事実であることを確認してから、今回の該当するプログラムに書き換えたところうまくオブジェクトが動いてくれました。自分はプログラム初心者なので今回のような丁寧で具体的な回答をもらえると、とても助かります。ありがとうございました。
KSwordOfHaste

2019/07/13 20:46

thkanaさんご指摘ありがとうございます。 おっしゃるとおり単純に'/'にしてしまうとまずいですね。ゼロ割が発生しないよう例えば割り算をする前に、「l = l == 0 ? 1 : l」のようにして回避するなどの配慮が必要ですね。
guest

0

この質問に関しては、プログラム言語の扱いの問題ではなくて、あなたが与えた数式が間違っているから期待する動作をしていません。そこを「ちゃんと」見直せば動くはずで、動かないのなら見直しが足りないとしか言いようがないです。

あなたの数式の意図が私には読み切れないので、今の式のまま「白目の外に出ない」ように制限だけするならば

Processing

1//他は変更なし 2 void display() { 3 fill(255);//white 4 ellipse(x, y, w, w); 5 int dx; 6 int dy; 7 dx=mouseX-x; 8 dy=mouseY-y; 9 float l; 10 l=sqrt(sq(dx)+sq(dy));//sqrt=rute2 sq=^2 11 float ex=(w-b)*dx/2*l;//まずは黒目の変位量だけを扱う 12 float ey=(w-b)*dy/2*l; 13 float d=dist(0, 0, ex, ey);//ex,eyのベクトルの長さを求める 14 if (d>(w-b)/2) { //白目の外に出る条件 15 ex=ex/d*(w-b)/2; //白目の中に収める 16 ey=ey/d*(w-b)/2; 17 } 18 ex+=x;//黒目の最終的な位置 19 ey+=y; 20 fill(0);//black 21 ellipse(ex, ey, b, b); 22 } 23

投稿2019/07/13 01:36

thkana

総合スコア7629

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

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

likuson

2019/07/13 15:30 編集

if関数を使わずにできました。ありがとうございます。
thkana

2019/07/13 22:26 編集

よくある勘違いではありますが、ifは関数じゃありません。 関数ってのは、カッコ内に書かれた引数を受け取って、定義された処理をして、返り値を返す(返さない場合もあるけれど)もの、です。 if文は、カッコ内の値によってプログラムの流れを切り替える働きをする文法要素です。 ついでに言えば、https://teratail.com/questions/200261 はローカル'変数'の話題ですね。なんでもかんでも「関数」じゃありません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問