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

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

新規登録して質問してみよう
ただいま回答率
85.35%
オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Processing

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

Q&A

3回答

2634閲覧

processingのオブジェクトの考え方

bump_of_pool

総合スコア7

オブジェクト

オブジェクト指向において、データとメソッドの集合をオブジェクト(Object)と呼びます。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Processing

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

0グッド

0クリップ

投稿2020/07/07 15:51

編集2020/07/11 15:37

イメージ説明
イメージ説明
イメージ説明
イメージ説明
processingで画像のようなプログラムをつくりたいです。
1枚目の画像をクリックすると、2枚目の画像が出てきて、利根川進をクリックするとクリア、木村資生を押すと残念がでるようなプログラムを作成したいです。画像を表示するのではなく、プログラムでテキストなどを表示したいです。これにBGMをつけたいです。クラスを定義し,オブジェクトを生成し,オブジェクトを活用するプログラムという条件では、どのようにすればよいのかわからないです。

class Opening{//画像1
int x;
int y;
Opening(int tempX,int tempY){
x = tempX;
y = tempY;
}
void display(){
pushMatrix();
translate(x,y);
background(0,255,255);
textAlign(CENTER);
fill(0);
textSize(25);
text("ルイザ・グロス・ホロウィッツ賞",width/2, 250);
text("日本人受賞者を覚えよう!",width/2, 285);
textSize(18);
text("ルイザ・グロス・ホロウィッツ賞",width/2, 500);
text("日本人受賞者を全員答えられたらクリアだよ",width/2, 530);
popMatrix();
}
}

class Question{//画像2
int x;
int y;
Question(int tempX,int tempY){
x = tempX;
y = tempY;
}
void display(){
pushMatrix();
translate(x,y);
background(245,100,170);
textAlign(CENTER);
fill(0);
textSize(25);
text("生物学や生化学の研究者に贈られる",width/2, 250);
text("ルイザ・グロス・ホロウィッツ賞を",width/2, 285);
text("現在、日本人で唯一受賞したのは誰?",width/2, 320);
fill(255);
noStroke();
rect(x1,y1,w,h);
fill(0);
textAlign(CENTER);
textSize(30);
text("利根川進",115,600);
fill(255);
rect(x2,y2,w,h);
fill(0);
text("木村資生",335,600);
popMatrix();
}
}

class Correct{//画像3
int x;
int y;
Correct(int tempX,int tempY){
x = tempX;
y = tempY;
}
void display(){
pushMatrix();
translate(x,y);
background(255,255,0);
textAlign(CENTER);
textSize(80);
text("クリア",width/2,300);
textSize(25);
text("1不可説不可説転点",width/2,500);
text("獲得",width/2,535);
popMatrix();
}
}

class Incorrect{//画像4
int x;
int y;
Incorrect(int tempX,int tempY){
x = tempX;
y = tempY;
}
void display(){
pushMatrix();
translate(x,y);
background(255,255,0);
textAlign(CENTER);
textSize(80);
text("残念",width/2,300);
textSize(20);
text("あなたはルイザ・グロス・ホロウィッツ賞の",width/2,500);
text("日本人受賞者を1人も覚えていません",width/2,535);
popMatrix();
}
}

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

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

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

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

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

guest

回答3

0

どちらも残したいので回答を分けさせていただきます。

とにかく動けばいい場合

Processing

1import ddf.minim.*; 2 3Minim minim; 4AudioPlayer player; 5PFont font; 6 7Opening opening; 8Question question; 9Correct correct; 10Incorrect incorrect; 11 12int x1 = 30; 13int y1 = 500; 14int x2 = 250; 15int y2 = 500; 16int w = 170; 17int h = 170; 18 19int mode; // 0:タイトル 1:問題 2:判定 20 21void setup() { 22 size(460, 800); 23 //minim = new Minim(this); 24 //player = minim.loadFile("QuizKnockのメインテーマ.mp3"); 25 //player.play(); 26 font = createFont("游明朝 Demibold", 24); 27 textFont(font); 28 29 opening = new Opening(); 30 correct = new Correct(); 31 incorrect = new Incorrect(); 32 question = new Question(); 33 opening.display(); 34} 35 36void draw() { 37} 38 39void mouseClicked() { 40 switch (mode) { 41 case 0: 42 mode = 1; 43 question.display(); 44 break; 45 case 1: 46 if (x1 < mouseX && mouseX < x1 + w && y1 < mouseY && mouseY < y1 + h) { 47 mode = 2; 48 correct.display(); 49 } 50 if (x2 < mouseX && mouseX < x2 + w && y2 < mouseY && mouseY < y2 + h) { 51 mode = 2; 52 incorrect.display(); 53 } 54 break; 55 case 2: 56 mode = 0; 57 opening.display(); 58 break; 59 } 60} 61 62 63class Opening { 64 void display() { 65 background(0, 255, 255); 66 textAlign(CENTER); 67 fill(0); 68 textSize(25); 69 text("ルイザ・グロス・ホロウィッツ賞", width / 2, 250); 70 text("日本人受賞者を覚えよう!", width / 2, 285); 71 textSize(18); 72 text("ルイザ・グロス・ホロウィッツ賞", width / 2, 500); 73 text("日本人受賞者を全員答えられたらクリアだよ", width / 2, 530); 74 } 75} 76 77class Question { 78 void display() { 79 background(245, 100, 170); 80 textAlign(CENTER); 81 fill(0); 82 textSize(25); 83 text("生物学や生化学の研究者に贈られる", width / 2, 250); 84 text("ルイザ・グロス・ホロウィッツ賞を", width / 2, 285); 85 text("現在、日本人で唯一受賞したのは誰?", width / 2, 320); 86 fill(255); 87 noStroke(); 88 rect(x1, y1, w, h); 89 fill(0); 90 textAlign(CENTER); 91 textSize(30); 92 text("利根川進", 115, 600); 93 fill(255); 94 rect(x2, y2, w, h); 95 fill(0); 96 text("木村資生", 335, 600); 97 } 98} 99 100class Correct { 101 void display() { 102 background(255, 255, 0); 103 textAlign(CENTER); 104 textSize(80); 105 text("クリア", width / 2, 300); 106 textSize(25); 107 text("1不可説不可説転点", width / 2, 500); 108 text("獲得", width / 2, 535); 109 } 110} 111 112class Incorrect { 113 void display() { 114 background(255, 255, 0); 115 textAlign(CENTER); 116 textSize(80); 117 text("残念", width / 2, 300); 118 textSize(20); 119 text("あなたはルイザ・グロス・ホロウィッツ賞の", width / 2, 500); 120 text("日本人受賞者を1人も覚えていません", width / 2, 535); 121 } 122}

しかしこれでは「クラスを定義し,オブジェクトを生成」はしましたが、とても「オブジェクトを活用」しているとは言えません。
クラスのdisplay()openingDisplay()等で関数にしたのと大差ありません。

オブジェクトを活用した場合

Processing

1import ddf.minim.*; 2 3Minim minim; 4AudioPlayer player; 5PFont font; 6 7Scene current; // 今の画像?を保持する変数 8 9void setup() { 10 size(460, 800); 11 //minim = new Minim(this); 12 //player = minim.loadFile("QuizKnockのメインテーマ.mp3"); 13 //player.play(); 14 font = createFont("游明朝 Demibold", 24); 15 textFont(font); 16 17 Opening opening = new Opening(); // *1でsetNextしたいのでOpening型変数に入れる 18 //Scene opening = new Opening(); // としたいところだがScene型にはsetNextがない 19 Scene correct = new Correct(opening); // CorrectはScene型に入れられる 20 Scene incorrect = new Incorrect(opening); 21 Scene question = new Question(correct, incorrect); 22 23 opening.setNext(question); // *1 24 current = opening; // 初めの画像?の設定 25} 26 27void draw() { 28 current.display(); // 今の画像?を表示 29} 30 31void mouseClicked() { 32 Scene next = current.getNext(mouseX, mouseY); // 今の画像?に次の画像?を要求する 33 current = next; // 今の画像?変数の中身を次の画像?に入れ替える 34} 35 36 37interface Scene { // それぞれの画像?が共通して持っているべき機能 38 void display(); // きっと何か表示するのかな? 39 Scene getNext(int x, int y); // 座標を引数にSceneをかえす ふーむ? 40} 41// インターフェースからは実際の動作はわかりません クラスで「実装」して初めて意味を持ちます 42// 長くなるので各自で調べてください^^; 43 44 45class Opening implements Scene { // Openingは「Sceneのメソッドを必ず持っています」という約束(実装) 46 Scene next; // 次の画像? 47 48 void setNext(Scene next) { // 次の画像?設定(他と同じようにコンストラクタで渡したいが、循環してるのでどれかはこうするよりない) 49 this.next = next; 50 } 51 52 void display() { 53 background(0, 255, 255); 54 textAlign(CENTER); 55 fill(0); 56 textSize(25); 57 text("ルイザ・グロス・ホロウィッツ賞", width / 2, 250); 58 text("日本人受賞者を覚えよう!", width / 2, 285); 59 textSize(18); 60 text("ルイザ・グロス・ホロウィッツ賞", width / 2, 500); 61 text("日本人受賞者を全員答えられたらクリアだよ", width / 2, 530); 62 } 63 64 Scene getNext(int x, int y) { 65 return next; // 次の画像?(question)を無条件でかえす 66 } 67} 68 69class Question implements Scene { 70 final Scene next1; // finalをつけると変更不可になる(初期化も強制される) 71 final Scene next2; 72 final int x1 = 30; // この辺の変数はほかで使わないのでクラスのメンバーに 73 final int y1 = 500; 74 final int x2 = 250; 75 final int y2 = 500; 76 final int w = 170; 77 final int h = 170; 78 79 Question(Scene next1, Scene next2) { // 分岐があるので2つもらう 80 this.next1 = next1; 81 this.next2 = next2; 82 } 83 84 void display() { 85 background(245, 100, 170); 86 textAlign(CENTER); 87 fill(0); 88 textSize(25); 89 text("生物学や生化学の研究者に贈られる", width / 2, 250); 90 text("ルイザ・グロス・ホロウィッツ賞を", width / 2, 285); 91 text("現在、日本人で唯一受賞したのは誰?", width / 2, 320); 92 fill(255); 93 noStroke(); 94 rect(x1, y1, w, h); 95 fill(0); 96 textAlign(CENTER); 97 textSize(30); 98 text("利根川進", 115, 600); 99 fill(255); 100 rect(x2, y2, w, h); 101 fill(0); 102 text("木村資生", 335, 600); 103 } 104 105 Scene getNext(int x, int y) { 106 if (x1 < x && x < x1 + w && y1 < y && y < y1 + h) { 107 return next1; // もし左の四角内ならcorrectをかえす 108 } 109 if (x2 < x && x < x2 + w && y2 < y && y < y2 + h) { 110 return next2; // もし右の四角内ならincorrectをかえす 111 } 112 113 return this; // どちらでもなければ自身(question)をかえす(無駄というか意味のない動作だが、そういう設計にしたので仕方がない^^; 114 } 115} 116 117class Correct implements Scene { 118 final Scene next; 119 120 Correct(Scene next) { 121 this.next = next; 122 } 123 124 void display() { 125 background(255, 255, 0); 126 textAlign(CENTER); 127 textSize(80); 128 text("クリア", width / 2, 300); 129 textSize(25); 130 text("1不可説不可説転点", width / 2, 500); 131 text("獲得", width / 2, 535); 132 } 133 134 Scene getNext(int x, int y) { 135 return next; 136 } 137} 138 139class Incorrect implements Scene { 140 final Scene next; 141 142 Incorrect(Scene next) { 143 this.next = next; 144 } 145 146 void display() { 147 background(255, 255, 0); 148 textAlign(CENTER); 149 textSize(80); 150 text("残念", width / 2, 300); 151 textSize(20); 152 text("あなたはルイザ・グロス・ホロウィッツ賞の", width / 2, 500); 153 text("日本人受賞者を1人も覚えていません", width / 2, 535); 154 } 155 156 Scene getNext(int x, int y) { 157 return next; 158 } 159}

元のテイストをできるだけ残したので不自然なところもありますが、それなりに「オブジェクトを活用」できたかなと思います。
もちろんこれが「答え」というものではありません。人それぞれいろいろな作りが考えられます。
その辺が面白いところでもあり、難しいところでもありますね。


乗りかかった船なので回答しましたが、

processingのオブジェクトの考え方

とタイトルにある以上、

  • 難しすぎて全くわからない
  • 理解するのに時間が欲しい
  • 実行できない
  • ここの意味がよくわからない
  • 参考になった

等、回答について何かしらのアクションを期待しているのですが、これでは単なる作業依頼です。

投稿2020/07/11 21:33

編集2023/07/22 08:51
TN8001

総合スコア9862

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

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

0

意外とProcessingでクイズゲームの記事ってないですね。。。(Javaはたくさんありますが)

クラスを定義し,オブジェクトを生成し,オブジェクトを活用するプログラム

個人的には慣れの問題だと思っています(たくさん書いたり見たりする)が、活用していないプログラムと活用しているプログラムを、見比べるのも面白いと思いました。
(ネタに深い意味はありません。過去に書いたものを再利用しただけ)

活用していないプログラム

Processing

1int x1 = 20; 2int y1 = 220; 3int x2 = 210; 4int y2 = 220; 5int w = 170; 6int h = 160; 7int mode = 0; // 0:問題 1:正解 -1:はずれ 8 9void setup() { 10 size(400, 400); 11 textFont(createFont("メイリオ", 24)); 12 textAlign(CENTER, CENTER); 13} 14 15void draw() { 16 background(255); 17 fill(0); 18 19 if (mode == 1) { 20 text("正解!", 20, 20, 360, 200); 21 return; 22 } 23 if (mode == -1) { 24 text("ざんねん", 20, 20, 360, 200); 25 return; 26 } 27 28 text("史上初の家庭用ゲーム機とされるものは?", 20, 20, 360, 200); 29 rect(x1, y1, w, h); 30 rect(x2, y2, w, h); 31 32 fill(255); 33 text("オデッセイ\n(マグナボックス)", x1 + 10, y1 + 10, w - 20, h - 20); 34 text("カラーテレビゲーム15\n(任天堂)", x2 + 10, y2 + 10, w - 20, h - 20); 35} 36 37void mouseClicked() { 38 if (x1 < mouseX && mouseX < x1 + w && y1 < mouseY && mouseY < y1 + h) { 39 mode = 1; 40 } 41 if (x2 < mouseX && mouseX < x2 + w && y2 < mouseY && mouseY < y2 + h) { 42 mode = -1; 43 } 44}

自分で書いておいてなんですが、もうすでにげんなりしています。

  • int x1, y1, x2, y2, w, h
    なんだかわかりにくい。かといって長い名前だと後の計算部分でくどくなる。
  • text("", 20, 20, 360, 200)
    同じ数字の繰り返し(これはメソッドにすればいい)
  • rect(x1, y1, w, h)
    主語がないのでボタンだとわからない。
  • x1 + 10, y1 + 10, w - 20, h - 20
    謎の計算。
  • if (x1 < mouseX && mouseX < x1 + w && y1 < mouseY && mouseY < y1 + h)
    定番の処理とはいえくどい。標準でメソッドがあれば。。

このままの流れでボタンのマウスオーバーで色を変えたり、問題数を増やしたりするとさらにゴチャゴチャしてくるでしょう。

活用したプログラム

Processing

1import java.util.*; 2import g4p_controls.*; 3 4GLabel label; 5GButton button1; 6GButton button2; 7 8final MondaiList mondaiList = new MondaiList( 9 new Mondai("史上初の家庭用ゲーム機とされるものは?", "オデッセイ\n(マグナボックス)", "カラーテレビゲーム15\n(任天堂)"), 10 new Mondai("ファミコンのコントローラーにはマイクが付いている?", "○", "×"), 11 new Mondai("スーパーファミコンソフト「ドラゴンクエスト6 幻の大地」の定価(税抜)は?", "11,400円", "6,980円"), 12 new Mondai("PlayStationの同時発売ソフトは?", "リッジレーサー\n(ナムコ)", "チョロQ\n(タカラ)"), 13 new Mondai("PlayStation2で動くLinuxがあった?", "○", "×")); 14 15void setup() { 16 size(400, 400); 17 surface.setTitle("おじさんゲーマークイズ"); 18 19 G4P.setDisplayFont("メイリオ", G4P.PLAIN, 24); 20 21 label = new GLabel(this, 20, 20, 360, 200); 22 label.setTextAlign(GAlign.CENTER, GAlign.MIDDLE); 23 24 button1 = new GButton(this, 20, 220, 170, 160); 25 button2 = new GButton(this, 210, 220, 170, 160); 26 27 next(); 28} 29 30void draw() { 31 background(220); 32} 33 34void next() { 35 Mondai mondai = mondaiList.get(); 36 37 label.setText(mondai.getQuestion()); 38 39 List<String> choices = mondai.getChoices(); 40 button1.setText(choices.get(0)); 41 button2.setText(choices.get(1)); 42} 43 44void handleButtonEvents(GButton button, GEvent event) { 45 if (event != GEvent.CLICKED) return; 46 47 mondaiList.answer(button.getText()); 48 49 if (mondaiList.empty()) { 50 int seikai = mondaiList.getSeikai(); 51 int count = mondaiList.getCount(); 52 float rate = (float) seikai / count; 53 String s = count + "問中" + seikai + "問正解\n"; 54 s += rate == 1 ? "おじさんゲーマー度 100%" : rate >= 0.5 ? "意外とおじさん?" : "一般人です。"; 55 56 label.setText(s); 57 button1.setVisible(false); 58 button2.setVisible(false); 59 } else { 60 next(); 61 } 62} 63 64class MondaiList { 65 private final List<Mondai> mondaiList; 66 private int count; 67 private int seikai; 68 69 public MondaiList(Mondai... array) { 70 mondaiList = new ArrayList<Mondai>(Arrays.asList(array)); 71 reset(); 72 } 73 74 public void reset() { 75 count = 0; 76 seikai = 0; 77 Collections.shuffle(mondaiList); 78 } 79 80 public void answer(String ans) { 81 if (!empty() && mondaiList.get(count).isCorrect(ans)) { 82 seikai++; 83 } 84 count++; 85 } 86 87 public Mondai get() { 88 return mondaiList.get(count); 89 } 90 91 public boolean empty() { 92 return mondaiList.size() <= count; 93 } 94 95 public int getSeikai() { 96 return seikai; 97 } 98 99 public int getCount() { 100 return count; 101 } 102} 103 104class Mondai { 105 private String question; 106 private String answer; 107 private List<String> choices; 108 109 public Mondai(String question, String... choices) { 110 this.question = question; 111 answer = choices[0]; 112 this.choices = Arrays.asList(choices); 113 Collections.shuffle(this.choices); 114 } 115 116 public String getQuestion() { 117 return question; 118 } 119 120 public List<String> getChoices() { 121 return choices; 122 } 123 124 public boolean isCorrect(String ans) { 125 return answer.equals(ans); 126 } 127}

まずボタン等のUIはライブラリ(G4P)を使いました。ずるい気がしますが便利なものがあるなら活用します(再利用
おかげで上で箇条書きした点がすべて解消されています。
もちろんGButtonクラスの中では似たような処理があるはずです。しかしクイズゲーム作成中は、ボタンがどう作られているかを気にする必要はありません(カプセル化

機能が増えたにもかかわらず、グローバル変数(不正確)が7個から4個に減っています(だいぶ恣意的です^^;

変数名やメソッド名が長めなので、文字の密度が上がって圧迫感はあります。
しかし主語(変数名)と操作(メソッド名)に、適切な名前がついていればそのまま読めます。

行数は約3倍になりました。
各メソッドや1行1行は非常に単純で「どういうことだろう?」という点は減りました。
クラスを書いている間はそのクラスの責任だけに集中できるので、規模が大きくなるほどメリットを感じます。

投稿2020/07/08 12:33

TN8001

総合スコア9862

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

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

bump_of_pool

2020/07/11 13:06

import ddf.minim.*; //minimライブラリのインポート Minim minim; //Minim型変数であるminimの宣言 AudioPlayer player; PFont font; Opening opening;//1枚目の画像  Question question;//2枚目の画像 Correct correct;//クリア Incorrect incorrect;//残念 int x1 = 30; int y1 = 500; int x2 = 250; int y2 = 500; int w = 170; int h = 170; void setup(){ size(460,800); minim = new Minim(this); //初期化 player = minim.loadFile("QuizKnockのメインテーマ.mp3"); //sample.mp3をロードする player.play(); //再生 font = createFont("游明朝 Demibold", 24); textFont(font); opening = new Opening(CENTER,CENTER); correct = new Correct(CENTER,CENTER); incorrect = new Incorrect(CENTER,CENTER); question = new Question(CENTER,CENTER); opening.display(); } void draw(){ if(mousePressed){ question.display(); } } void mouseClicked(){ if (x1 < mouseX && mouseX < x1 + w && y1 < mouseY && mouseY < y1 + h) { correct.display(); } if (x2 < mouseX && mouseX < x2 + w && y2 < mouseY && mouseY < y2 + h) { incorrect.display(); } } 回答いただきありがとうございます。 一応こんな感じで作りましたが、最後の画面で問題の選択肢をクリックすると一瞬問題の画面に切り替わり、正解または、残念の画面になります。これを1枚目の画像に戻るようにしたいです。
TN8001

2020/07/11 14:01

えーとそれなりに時間をかけて回答を書きましたので、何かしらの感想を聞きたいです。 何もないと実行どころか読んでもいないんじゃないかと思ってしまいます。 > 1枚目の画像に戻るようにしたい class Opening等がないので検証できませんが、 if(mousePressed){ question.display(); } これがまずいんじゃないでしょうか。 今どの画面にいるかを表す変数(私の回答コードの1個目のほうで言うとint modeに当たる)を用意するのがいいんじゃないでしょうか。 質問は編集できます。 ここにコードを書いても目につかないので、質問のほうに追記してください。
bump_of_pool

2020/07/11 15:42

質問のほうに追記しておきました。よろしくお願いします。
guest

0

それだけならクラスを使う必要はありません。

公式ページのリファレンスから使いそうな部品を拾うと、

四角を描画するのはrect()
文字を描画するのはtext()/文字サイズを変えるのはtextSize()/フォントを変えるのはtextFont()
mouseのクリックを知るのはmousePressed/mousePressed()/マウス位置を知るのはmouseX,mouserY
グラデーションを描くならlerpColor()/line()
BGMはSoundライブラリのSoundFileクラス

あたりで出来るのではないでしょうか。

どうしてもクラスを使いたいというなら、まずはプログラムの動作の概略を日本語で記述して、その中に登場する「名詞」をピックアップしてそれをクラスに置くことがどうだろうかと検討するのがとっかかりになるかと思います。「n枚目の画像」とか。

(Javaモードで作れば、内部的にはクラスは生成されていますが...)


[追記]結構真面目にやってみました。
Processingでオブジェクト指向っぽくってあまりやったことなかったので出来は保証しません。ツッコミ歓迎。

重視すること:
オブジェクトの「活用」をオブジェクト間の協調動作と捉える。

ストーリー:
プログラムを起動すると、タイトル画面を表示する。
タイトル画面をクリックすると、質問画面を表示する。
質問画面の選択肢のいずれかをクリックすると、正解画面または不正解画面を表示する
正解/不正解画面でクリックすると、タイトル画面に戻る
各画面ではBGMを流す(質問者のプログラムを見ると全編で一つのBGMを流せばよかったみたいですが、作り込んでしまったのでそのまま。変更は難しくはないでしょう)。

さて、このストーリーからクラス候補(名詞)は...これだけのモノしか登場しないと、「画面」をクラスにするぐらいしかなさそうですね。その路線でざっくりのクラス構成を考えましょうか。
クラス図案
Processingの構造(setup()-draw()とmouseClicked())に当てはめるため、これをinterfaceにしてみました。Processingでinterfacaを使うには、ProcessingのIDEでは、新規タブを作成し、例えばFramework.java等の名前を付けて以下を記述する必要があります。

Processing

1//Framework.java 2interface Framework{ 3 void setup(); 4 void draw(); 5 void mouseClicked(); 6}

で、プログラム本体というか。自分に余裕が無かったのでコメントとか付いてません。継承の使い方がイケてない気がしますが...

Processing

1import processing.sound.*; 2enum Results { 3 STAY, 4 GO, 5 CORRECT, 6 WRONG 7} 8 9class Control implements Framework { 10 Screen active;//表示される画面 11 Screen start, question, correct, wrong;//使われる各画面 12 void setup() { 13 start.setup(); 14 active.enter(); 15 question.setup(); 16 correct.setup(); 17 wrong.setup(); 18 } 19 void draw() { 20 active.draw(); 21 Results rc=active.result(); 22 switch(rc) { 23 case STAY: 24 default: 25 break; 26 case GO: 27 if (active==start) { 28 active.exit(); 29 active=question; 30 active.enter(); 31 } else { 32 active.exit(); 33 active=start; 34 active.enter(); 35 } 36 break; 37 case CORRECT: 38 active.exit(); 39 active=correct; 40 active.enter(); 41 break; 42 case WRONG: 43 active.exit(); 44 active=wrong; 45 active.enter(); 46 break; 47 } 48 } 49 Control( Title start, Question question, Title correct, Title wrong ) { 50 this.start=start; 51 active=start; 52 this.question=question; 53 this.correct=correct; 54 this.wrong=wrong; 55 } 56 void mouseClicked() { 57 active.mouseClicked(); 58 } 59} 60 61class Screen implements Framework { 62 String text; 63 SoundFile bgm; 64 color bgColor; 65 boolean done=false; 66 Screen( PApplet app, color bgColor, String text, String bgmFile) { 67 this.bgColor=bgColor; 68 this.text=text; 69 bgm=new SoundFile(app, bgmFile); 70 } 71 void setup() { 72 } 73 void draw() { 74 background(bgColor); 75 textAlign(CENTER, CENTER); 76 textSize(autoSize(text, width*0.8)); 77 fill(0); 78 text(text, width/2, height*0.2); 79 } 80 void enter() { //画面に入る時に行う処理 81 done=false; 82 if (bgm!=null) { 83 bgm.play(); 84 } 85 } 86 void exit() { //画面を終了するときに行う処理 87 if (bgm!=null) { 88 bgm.stop(); 89 } 90 } 91 Results result() { //画面内処理の結果を得る 92 return Results.STAY; 93 } 94 void mouseClicked() { 95 } 96} 97 98class Title extends Screen { 99 String subText; 100 Title( PApplet app, color bgColor, String text, String subText, String bgmFile) { 101 super(app, bgColor, text, bgmFile); 102 this.subText=subText; 103 } 104 @Override void draw() { 105 super.draw(); 106 textAlign(CENTER, CENTER); 107 textSize(autoSize(subText, width*0.7)); 108 fill(0); 109 text(subText, width/2, height*0.7); 110 } 111 @Override Results result() { 112 return done? Results.GO : Results.STAY; 113 } 114 @Override void mouseClicked() { 115 done=true; 116 } 117} 118 119class Question extends Screen { 120 int rightAns; 121 int ansPos; 122 class Button { 123 float left; 124 float top; 125 float w; 126 float h; 127 String text; 128 Button( float left, float top, float w, float h, String text) { 129 this.left=left; 130 this.top=top; 131 this.w=w; 132 this.h=h; 133 this.text=text; 134 } 135 boolean isInside(float x, float y) { 136 return left<=x && x<= left+w && top<=y && y<=top+h; 137 } 138 void draw() { 139 fill(255); 140 rectMode(CORNER); 141 rect(left, top, w, h); 142 fill(0); 143 textSize(autoSize(text, w)); 144 textAlign(CENTER, CENTER); 145 text(text, left+w/2, top+h/2); 146 } 147 } 148 Button[] button; 149 Question( PApplet app, color bgColor, String text, String choice1, String choice2, int right, String bgmFile) { 150 super(app, bgColor, text, bgmFile); 151 button=new Button[2]; 152 button[0]=new Button(width*0.1, height*0.7, width*0.3, height*0.2, choice1); 153 button[1]=new Button(width*0.6, height*0.7, width*0.3, height*0.2, choice2); 154 rightAns=right; 155 } 156 @Override void draw() { 157 super.draw(); 158 for ( Button btn : button) { 159 btn.draw(); 160 } 161 } 162 @Override void enter() { 163 super.enter(); 164 ansPos=0; 165 } 166 @Override void mouseClicked() { 167 for (int i=0; i<button.length; i++) { 168 if (button[i].isInside(mouseX, mouseY)) { 169 ansPos=i+1; 170 } 171 } 172 } 173 @Override Results result() { 174 Results ret; 175 if (ansPos==0) { 176 ret=Results.STAY; 177 } else { 178 if (ansPos==rightAns) { 179 ret=Results.CORRECT; 180 done=true; 181 } else { 182 ret=Results.WRONG; 183 done=true; 184 } 185 } 186 return ret; 187 } 188} 189 190int autoSize(String text, float width) { 191 String[] lines=text.split("\n"); 192 int maxLen=0; 193 for (String line : lines) { 194 if (maxLen<line.length()) { 195 maxLen=line.length(); 196 } 197 } 198 return (int)(width/maxLen); 199} 200 201 202Control ctrl; 203void setup() { 204 size(460, 800); 205 textFont(createFont("游明朝 Demibold", 24)); 206 ctrl=new Control( 207 new Title(this, color(0, 255, 255), 208 "ルイザ・グロス・ホロウィッツ賞\n日本人受賞者を覚えよう!", 209 "ルイザ・グロス・ホロウィッツ賞\n日本人受賞者を全員答えられたらクリアだよ", 210 "https://taira-komori.jpn.org/quick/upl/fanfare2.mp3"), 211 new Question(this, color(245, 100, 170), 212 "生物学や生化学の研究者に贈られる\nルイザ・グロス・ホロウィッツ賞を\n現在、日本人で唯一受賞したのは誰?", 213 "利根川進", "木村資生", 1, "https://taira-komori.jpn.org/sound/anime01/hurry_up.mp3"), 214 new Title(this, color(255, 255, 0), 215 "クリア", 216 "1不可説不可説転点\n獲得", 217 "https://taira-komori.jpn.org/sound/game01/crrect_answer1.mp3"), 218 new Title(this, color(255, 255, 0), 219 "はずれ", 220 "あなたはルイザ・グロス・ホロウィッツ賞の\n日本人受賞者を1人も覚えていません", 221 "https://taira-komori.jpn.org/sound/game01/blip01.mp3") 222 ); 223 ctrl.setup(); 224} 225 226void draw() { 227 ctrl.draw(); 228} 229 230void mouseClicked() { 231 ctrl.active.mouseClicked(); 232}

「画面」というか、結局状態マシンになった気がしますがさて。
「オブジェクトの活用」は、クラス図を描いたときにクラス間に何らかの関連が引ければまぁいいんじゃないでしょうか。

(音源は、'効果音 サンプル 無料'で検索して上位に引っかかったサイトの素材URLを貼っています。昔だと直リンとか嫌われたけど、最近はどうなんでしょう。ただ、ローカルの素材を使っちゃうと他人のソースの試行が面倒なんですよね)

投稿2020/07/07 23:58

編集2020/07/12 01:32
thkana

総合スコア7703

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

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

bump_of_pool

2020/07/08 07:16

回答していただきありがとうございました。 クラスを使う必要はないですか。。クラスを使ったものを作りたかったので。
thkana

2020/07/08 11:37

ですから、まずは「何をクラスにするのか」というところから考えて下さい。
bump_of_pool

2020/07/09 06:24

画像1枚1枚をクラスとしてやってみようと思ってやってみましたが、クリックしたら次の画像に映る動作がうまくいきません。。mouseClicked()など使ってみましたが駄目でした。。
thkana

2020/07/09 13:45

どこから書こうかといろいろ迷ってますけど。 それはともかく、 > 画像1枚1枚をクラス それはおかしいでしょう。オブジェクト、あるいはインスタンス、ならありだと思いますが。
bump_of_pool

2020/07/10 07:34

import ddf.minim.*; //minimライブラリのインポート Minim minim; //Minim型変数であるminimの宣言 AudioPlayer player; PFont font; Opening opening;//1枚目の画像  Question question;//2枚目の画像 Correct correct;//クリア Incorrect incorrect;//残念 int x1 = 30; int y1 = 500; int x2 = 250; int y2 = 500; int w = 170; int h = 170; void setup(){ size(460,800); minim = new Minim(this); //初期化 player = minim.loadFile("QuizKnockのメインテーマ.mp3"); //sample.mp3をロードする player.play(); //再生 font = createFont("游明朝 Demibold", 24); textFont(font); opening = new Opening(CENTER,CENTER); correct = new Correct(CENTER,CENTER); incorrect = new Incorrect(CENTER,CENTER); question = new Question(CENTER,CENTER); opening.display(); } void draw(){ if(mousePressed){ question.display(); } } void mouseClicked(){ if (x1 < mouseX && mouseX < x1 + w && y1 < mouseY && mouseY < y1 + h) { correct.display(); } if (x2 < mouseX && mouseX < x2 + w && y2 < mouseY && mouseY < y2 + h) { incorrect.display(); } } 一応こんな感じで作りましたが、最後の画面で問題の選択肢をクリックすると一瞬問題の画面に切り替わり、正解または、残念の画面になります。これを1枚目の画像に戻るようにしたいです。
thkana

2020/07/12 00:59

「オブジェクトを活用」というのをどう捉えるかですが、少なくとも「クラスを使いました」だけでは「活用」というには無理があるように思います。
TN8001

2020/07/12 03:16

いろんな考え方がありますね^^ 事前に設計してから書くのができないんで羨ましいです^^; 画面サイズが変わっても破綻しないのは気が利いてますね。 予想外のBGMが鳴ってちょっと笑いましたw > ツッコミ歓迎。 とのことなので疑問&気になった点。 * interfaceも中に書けちゃったのですが、何かまずい点ってあるんでしょうか?(クラスを外に書いた場合、見えなくなるのはわかります) * PAppletが見えてしまうのはあまり初心者向けに思えないので、SoundFileをScreenに渡せばいいんじゃないでしょうか。 * switchがやっぱりイケてないですよねぇ^^; --- 私は普段C#でMVVMとかなんで、modelとviewを分けたくなってしまいます。 そういう意味では回答1の2つ目が理想に近いです(問題も増やし放題&3択や4択化も比較的簡単) このお題では意味ないですが^^;
thkana

2020/07/12 04:06

TN8001さん あれ?確かに、interface、pdeに書けますね。どこかで勘違いしていたようです。 > SoundFileをScreenに渡せばいいんじゃないでしょうか。 確かに。 思い込んでしまうとなかなか見えなくなるので他人の目(レビュー)がありがたいです。 > switchがやっぱりイケてない 日頃がCで組み込み屋ですからswitchとは割と仲良くしていてそんなに気にしていないです(笑)。各画面が終了したら次に何をする、という知識は各画面が知っていることではないよなぁ...と思ったらControlがあぁなっちゃいました。switchというか、前画面を終わらせて新画面に切り替えて入状処理...という似た作業が並んでるのが結構かっこわるいなぁ、とは思います。 私も普段はそんなに設計資料とか書かないですけれどね(というか、最近は製品に入るコーディングからはちょっと離れてたり)。ただ、TN8001さんの回答への(無)反応から見てコードだけでは質問者さんがついていけていない感があったのに、しかしお題が「オブジェクトを活用」という実は結構な難題...どうしようかと思ってコード以前の「動作(ユースケース)シナリオを考える」「クラスを抽出する」「クラス図を描いてみる」あたりをざっとなぞってみました。コラボレーション図とかCRCカードとかもあるといいかなぁ、とは思いつつそこまでは手が回らず。 質問者さん、多分課題かなにかだと思いますけど、「オブジェクトを活用」というお題が出るくらいならその辺やってませんかね。
TN8001

2020/07/12 05:09

interface了解です。 普段何がメインかによってだいぶ変わってきそうですね。 良し悪しにかかわらず、質問者回答者のいろんなコードを見るのは楽しいです^^
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問