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

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

ただいまの
回答率

88.92%

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

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 297

bump_of_pool

score 7

イメージ説明
イメージ説明
イメージ説明
イメージ説明
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();
}
}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • thkana

    2020/07/12 10:35

    いまさらの感もありますが、コード部分はそのままだと読みにくいので https://teratail.com/help/question-tips#questionTips3-5-1https://teratail.com/questions/238564 を参考に```で囲って下さい。

    キャンセル

回答 3

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等の名前を付けて以下を記述する必要があります。

//Framework.java
interface Framework{
  void setup();
  void draw();
  void mouseClicked();
}


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

import processing.sound.*;
enum Results {
  STAY, 
    GO, 
    CORRECT, 
    WRONG
}

class Control implements Framework {
  Screen active;//表示される画面
  Screen start, question, correct, wrong;//使われる各画面
  void setup() {
    start.setup();
    active.enter();
    question.setup();
    correct.setup();
    wrong.setup();
  }
  void draw() {
    active.draw();
    Results rc=active.result();
    switch(rc) {
    case STAY:
    default:
      break;
    case GO:
      if (active==start) {
        active.exit();
        active=question;
        active.enter();
      } else {
        active.exit();
        active=start;
        active.enter();
      }
      break;
    case CORRECT:
      active.exit();
      active=correct;
      active.enter();
      break;
    case WRONG:
      active.exit();
      active=wrong;
      active.enter();
      break;
    }
  }
  Control( Title start, Question question, Title correct, Title wrong ) {
    this.start=start;
    active=start;
    this.question=question;
    this.correct=correct;
    this.wrong=wrong;
  }
  void mouseClicked() {
    active.mouseClicked();
  }
}

class Screen implements Framework {
  String text;
  SoundFile bgm;
  color bgColor;
  boolean done=false;
  Screen( PApplet app, color bgColor, String text, String bgmFile) {
    this.bgColor=bgColor;
    this.text=text;
    bgm=new SoundFile(app, bgmFile);
  }
  void setup() {
  }
  void draw() {
    background(bgColor);
    textAlign(CENTER, CENTER);
    textSize(autoSize(text, width*0.8));
    fill(0);
    text(text, width/2, height*0.2);
  }
  void enter() { //画面に入る時に行う処理
    done=false;
    if (bgm!=null) {
      bgm.play();
    }
  }
  void exit() { //画面を終了するときに行う処理
    if (bgm!=null) {
      bgm.stop();
    }
  }
  Results result() { //画面内処理の結果を得る
    return Results.STAY;
  }
  void mouseClicked() {
  }
}

class Title extends Screen {
  String subText;
  Title( PApplet app, color bgColor, String text, String subText, String bgmFile) {
    super(app, bgColor, text, bgmFile);
    this.subText=subText;
  }
  @Override void draw() {
    super.draw();
    textAlign(CENTER, CENTER);
    textSize(autoSize(subText, width*0.7));
    fill(0);
    text(subText, width/2, height*0.7);
  }    
  @Override Results result() {
    return done? Results.GO : Results.STAY;
  }
  @Override void mouseClicked() {
    done=true;
  }
}

class Question extends Screen {
  int rightAns;
  int ansPos;
  class Button {
    float left;
    float top;
    float w;
    float h;
    String text;
    Button( float left, float top, float w, float h, String text) {
      this.left=left;
      this.top=top;
      this.w=w;
      this.h=h;
      this.text=text;
    }
    boolean isInside(float x, float y) {
      return left<=x && x<= left+w && top<=y && y<=top+h;
    }
    void draw() {
      fill(255);
      rectMode(CORNER);
      rect(left, top, w, h);
      fill(0);
      textSize(autoSize(text, w));
      textAlign(CENTER, CENTER);
      text(text, left+w/2, top+h/2);
    }
  }
  Button[] button;
  Question( PApplet app, color bgColor, String text, String choice1, String choice2, int right, String bgmFile) {
    super(app, bgColor, text, bgmFile);
    button=new Button[2];
    button[0]=new Button(width*0.1, height*0.7, width*0.3, height*0.2, choice1);
    button[1]=new Button(width*0.6, height*0.7, width*0.3, height*0.2, choice2);
    rightAns=right;
  }
  @Override void draw() {
    super.draw();
    for ( Button btn : button) {
      btn.draw();
    }
  }
  @Override void enter() {
    super.enter();
    ansPos=0;
  }
  @Override void mouseClicked() {
    for (int i=0; i<button.length; i++) {
      if (button[i].isInside(mouseX, mouseY)) {
        ansPos=i+1;
      }
    }
  }
  @Override Results result() {
    Results ret;
    if (ansPos==0) {
      ret=Results.STAY;
    } else {
      if (ansPos==rightAns) {
        ret=Results.CORRECT;
        done=true;
      } else {
        ret=Results.WRONG;
        done=true;
      }
    }
    return ret;
  }
}

int autoSize(String text, float width) {
  String[] lines=text.split("\n");
  int maxLen=0;
  for (String line : lines) {
    if (maxLen<line.length()) {
      maxLen=line.length();
    }
  }
  return (int)(width/maxLen);
}  


Control ctrl;
void setup() {
  size(460, 800);
  textFont(createFont("游明朝 Demibold", 24));
  ctrl=new Control(
    new Title(this, color(0, 255, 255), 
    "ルイザ・グロス・ホロウィッツ賞\n日本人受賞者を覚えよう!", 
    "ルイザ・グロス・ホロウィッツ賞\n日本人受賞者を全員答えられたらクリアだよ", 
    "https://taira-komori.jpn.org/quick/upl/fanfare2.mp3"), 
    new Question(this, color(245, 100, 170), 
    "生物学や生化学の研究者に贈られる\nルイザ・グロス・ホロウィッツ賞を\n現在、日本人で唯一受賞したのは誰?", 
    "利根川進", "木村資生", 1, "https://taira-komori.jpn.org/sound/anime01/hurry_up.mp3"), 
    new Title(this, color(255, 255, 0), 
    "クリア", 
    "1不可説不可説転点\n獲得", 
    "https://taira-komori.jpn.org/sound/game01/crrect_answer1.mp3"), 
    new Title(this, color(255, 255, 0), 
    "はずれ", 
    "あなたはルイザ・グロス・ホロウィッツ賞の\n日本人受賞者を1人も覚えていません", 
    "https://taira-komori.jpn.org/sound/game01/blip01.mp3")
    );
  ctrl.setup();
}

void draw() {
  ctrl.draw();
}

void mouseClicked() {
  ctrl.active.mouseClicked();
}

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/12 12:16

    いろんな考え方がありますね^^ 事前に設計してから書くのができないんで羨ましいです^^;
    画面サイズが変わっても破綻しないのは気が利いてますね。
    予想外のBGMが鳴ってちょっと笑いましたw

    > ツッコミ歓迎。
    とのことなので疑問&気になった点。
    * interfaceも中に書けちゃったのですが、何かまずい点ってあるんでしょうか?(クラスを外に書いた場合、見えなくなるのはわかります)
    * PAppletが見えてしまうのはあまり初心者向けに思えないので、SoundFileをScreenに渡せばいいんじゃないでしょうか。
    * switchがやっぱりイケてないですよねぇ^^;

    ---

    私は普段C#でMVVMとかなんで、modelとviewを分けたくなってしまいます。
    そういう意味では回答1の2つ目が理想に近いです(問題も増やし放題&3択や4択化も比較的簡単)
    このお題では意味ないですが^^;

    キャンセル

  • 2020/07/12 13:06

    TN8001さん
    あれ?確かに、interface、pdeに書けますね。どこかで勘違いしていたようです。
    > SoundFileをScreenに渡せばいいんじゃないでしょうか。
    確かに。
    思い込んでしまうとなかなか見えなくなるので他人の目(レビュー)がありがたいです。

    > switchがやっぱりイケてない
    日頃がCで組み込み屋ですからswitchとは割と仲良くしていてそんなに気にしていないです(笑)。各画面が終了したら次に何をする、という知識は各画面が知っていることではないよなぁ...と思ったらControlがあぁなっちゃいました。switchというか、前画面を終わらせて新画面に切り替えて入状処理...という似た作業が並んでるのが結構かっこわるいなぁ、とは思います。

    私も普段はそんなに設計資料とか書かないですけれどね(というか、最近は製品に入るコーディングからはちょっと離れてたり)。ただ、TN8001さんの回答への(無)反応から見てコードだけでは質問者さんがついていけていない感があったのに、しかしお題が「オブジェクトを活用」という実は結構な難題...どうしようかと思ってコード以前の「動作(ユースケース)シナリオを考える」「クラスを抽出する」「クラス図を描いてみる」あたりをざっとなぞってみました。コラボレーション図とかCRCカードとかもあるといいかなぁ、とは思いつつそこまでは手が回らず。

    質問者さん、多分課題かなにかだと思いますけど、「オブジェクトを活用」というお題が出るくらいならその辺やってませんかね。

    キャンセル

  • 2020/07/12 14:09

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

    キャンセル

0

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

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

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

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

int x1 = 20;
int y1 = 220;
int x2 = 210;
int y2 = 220;
int w = 170;
int h = 160;
int mode = 0; // 0:問題 1:正解 -1:はずれ

void setup() {
  size(400, 400);
  textFont(createFont("メイリオ", 24));
  textAlign(CENTER, CENTER);
}

void draw() {
  background(255);
  fill(0);

  if (mode == 1) {
    text("正解!", 20, 20, 360, 200);
    return;
  }
  if (mode == -1) {
    text("ざんねん", 20, 20, 360, 200);
    return;
  }

  text("史上初の家庭用ゲーム機とされるものは?", 20, 20, 360, 200);
  rect(x1, y1, w, h);
  rect(x2, y2, w, h);

  fill(255);
  text("オデッセイ\n(マグナボックス)", x1 + 10, y1 + 10, w - 20, h - 20);
  text("カラーテレビゲーム15\n(任天堂)", x2 + 10, y2 + 10, w - 20, h - 20);
}

void mouseClicked() {
  if (x1 < mouseX && mouseX < x1 + w && y1 < mouseY && mouseY < y1 + h) {
    mode = 1;
  }
  if (x2 < mouseX && mouseX < x2 + w && y2 < mouseY && mouseY < y2 + h) {
    mode = -1;
  }
}


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

  • 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)
    定番の処理とはいえくどい。標準でメソッドがあれば。。

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

活用したプログラム

import java.util.*;
import g4p_controls.*;

GLabel label;
GButton button1;
GButton button2;

final MondaiList mondaiList = new MondaiList(
  new Mondai("史上初の家庭用ゲーム機とされるものは?", "オデッセイ\n(マグナボックス)", "カラーテレビゲーム15\n(任天堂)"), 
  new Mondai("ファミコンのコントローラーにはマイクが付いている?", "○", "×"), 
  new Mondai("スーパーファミコンソフト「ドラゴンクエスト6 幻の大地」の定価(税抜)は?", "11,400円", "6,980円"), 
  new Mondai("PlayStationの同時発売ソフトは?", "リッジレーサー\n(ナムコ)", "チョロQ\n(タカラ)"), 
  new Mondai("PlayStation2で動くLinuxがあった?", "○", "×"));

void setup() {
  size(400, 400);
  surface.setTitle("おじさんゲーマークイズ");

  G4P.setDisplayFont("メイリオ", G4P.PLAIN, 24);

  label = new GLabel(this, 20, 20, 360, 200);
  label.setTextAlign(GAlign.CENTER, GAlign.MIDDLE);

  button1 = new GButton(this, 20, 220, 170, 160);
  button2 = new GButton(this, 210, 220, 170, 160);

  next();
}

void draw() {
  background(220);
}

void next() {
  Mondai mondai = mondaiList.get();

  label.setText(mondai.getQuestion());

  List<String> choices = mondai.getChoices();
  button1.setText(choices.get(0));
  button2.setText(choices.get(1));
}

void handleButtonEvents(GButton button, GEvent event) {
  if (event != GEvent.CLICKED) return;

  mondaiList.answer(button.getText());

  if (mondaiList.empty()) {
    int seikai = mondaiList.getSeikai();
    int count = mondaiList.getCount();
    float rate = (float) seikai / count;
    String s = count + "問中" + seikai + "問正解\n";
    s += rate == 1 ? "おじさんゲーマー度 100%" : rate >= 0.5 ? "意外とおじさん?" : "一般人です。";

    label.setText(s);
    button1.setVisible(false);
    button2.setVisible(false);
  } else {
    next();
  }
}

class MondaiList {
  private final List<Mondai> mondaiList;
  private int count;
  private int seikai;

  public MondaiList(Mondai... array) {
    mondaiList = new ArrayList<Mondai>(Arrays.asList(array));
    reset();
  }

  public void reset() {
    count = 0;
    seikai = 0;
    Collections.shuffle(mondaiList);
  }

  public void answer(String ans) {
    if (!empty() && mondaiList.get(count).isCorrect(ans)) {
      seikai++;
    }
    count++;
  }

  public Mondai get() {
    return mondaiList.get(count);
  }

  public boolean empty() {
    return mondaiList.size() <= count;
  }

  public int getSeikai() {
    return seikai;
  }

  public int getCount() {
    return count;
  }
}

class Mondai {
  private String question;
  private String answer;
  private List<String> choices;

  public Mondai(String question, String... choices) {
    this.question = question;
    answer = choices[0];
    this.choices = Arrays.asList(choices);
    Collections.shuffle(this.choices);
  }

  public String getQuestion() {    
    return question;
  }

  public List<String> getChoices() {
    return choices;
  }

  public boolean isCorrect(String ans) {
    return answer.equals(ans);
  }
}


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

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

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/11 22: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枚目の画像に戻るようにしたいです。

    キャンセル

  • 2020/07/11 23:01

    えーとそれなりに時間をかけて回答を書きましたので、何かしらの感想を聞きたいです。
    何もないと実行どころか読んでもいないんじゃないかと思ってしまいます。

    > 1枚目の画像に戻るようにしたい
    class Opening等がないので検証できませんが、

    if(mousePressed){ question.display(); }
    これがまずいんじゃないでしょうか。

    今どの画面にいるかを表す変数(私の回答コードの1個目のほうで言うとint modeに当たる)を用意するのがいいんじゃないでしょうか。


    質問は編集できます。
    ここにコードを書いても目につかないので、質問のほうに追記してください。

    キャンセル

  • 2020/07/12 00:42

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

    キャンセル

0

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

とにかく動けばいい場合

import ddf.minim.*;

Minim minim;
AudioPlayer player;
PFont font;

Opening opening;
Question question;
Correct correct;
Incorrect incorrect;

int x1 = 30;
int y1 = 500;
int x2 = 250;
int y2 = 500;
int w = 170;
int h = 170;

int mode; // 0:タイトル 1:問題 2:判定

void setup() {
  size(460, 800);
  //minim = new Minim(this);
  //player = minim.loadFile("QuizKnockのメインテーマ.mp3");
  //player.play();
  font = createFont("游明朝 Demibold", 24);
  textFont(font);

  opening = new Opening();
  correct = new Correct();
  incorrect = new Incorrect();
  question = new Question();
  opening.display();
}

void draw() {
}

void mouseClicked() {
  switch (mode) {
  case 0:
    mode = 1;
    question.display();
    break;
  case 1:
    if (x1 < mouseX && mouseX < x1 + w && y1 < mouseY && mouseY < y1 + h) {
      mode = 2;
      correct.display();
    }
    if (x2 < mouseX && mouseX < x2 + w && y2 < mouseY && mouseY < y2 + h) {
      mode = 2;
      incorrect.display();
    }
    break;
  case 2:
    mode = 0;
    opening.display();
    break;
  }
}


class Opening {
  void display() {
    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);
  }
}

class Question {
  void display() {
    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);
  }
}

class Correct {
  void display() {
    background(255, 255, 0);
    textAlign(CENTER);
    textSize(80);
    text("クリア", width / 2, 300);
    textSize(25);
    text("1不可説不可説転点", width / 2, 500);
    text("獲得", width / 2, 535);
  }
}

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

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

オブジェクトを活用した場合
import ddf.minim.*;

Minim minim;
AudioPlayer player;
PFont font;

Scene current; // 今の画像?を保持する変数

void setup() {
  size(460, 800);
  //minim = new Minim(this);
  //player = minim.loadFile("QuizKnockのメインテーマ.mp3");
  //player.play();
  font = createFont("游明朝 Demibold", 24);
  textFont(font);

  Opening opening = new Opening(); // *1でsetNextしたいのでOpening型変数に入れる
  //Scene opening = new Opening(); // としたいところだがScene型にはsetNextがない
  Scene correct = new Correct(opening); // CorrectはScene型に入れられる
  Scene incorrect = new Incorrect(opening);
  Scene question = new Question(correct, incorrect);

  opening.setNext(question); // *1
  current = opening; // 初めの画像?の設定
}

void draw() {
  current.display(); // 今の画像?を表示
}

void mouseClicked() {
  Scene next = current.getNext(mouseX, mouseY); // 今の画像?に次の画像?を要求する
  current = next; // 今の画像?変数の中身を次の画像?に入れ替える
}


interface Scene { // それぞれの画像?が共通して持っているべき機能
  void display(); // きっと何か表示するのかな?
  Scene getNext(int x, int y); // 座標を引数にSceneをかえす ふーむ?
}
// インターフェースからは実際の動作はわかりません クラスで「実装」して初めて意味を持ちます
// 長くなるので各自で調べてください^^;


class Opening implements Scene { // Openingは「Sceneのメソッドを必ず持っています」という約束(実装)
  Scene next; // 次の画像?

  void setNext(Scene next) { // 次の画像?設定(他と同じようにコンストラクタで渡したいが、循環してるのでどれかはこうするよりない)
    this.next = next;
  }

  void display() {
    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);
  }

  Scene getNext(int x, int y) {
    return next; // 次の画像?(question)を無条件でかえす
  }
}

class Question implements Scene {
  final Scene next1; // finalをつけると変更不可になる(初期化も強制される)
  final Scene next2;
  final int x1 = 30; // この辺の変数はほかで使わないのでクラスのメンバーに
  final int y1 = 500;
  final int x2 = 250;
  final int y2 = 500;
  final int w = 170;
  final int h = 170;

  Question(Scene next1, Scene next2) { // 分岐があるので2つもらう
    this.next1 = next1;
    this.next2 = next2;
  }

  void display() {
    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);
  }

  Scene getNext(int x, int y) {
    if (x1 < x && x < x1 + w && y1 < y && y < y1 + h) {
      return next1; // もし左の四角内ならcorrectをかえす
    }
    if (x2 < x && x < x2 + w && y2 < y && y < y2 + h) {
      return next2; // もし右の四角内ならincorrectをかえす
    }

    return this; // どちらでもなければ自身(question)をかえす(無駄というか意味のない動作だが、そういう設計にしたので仕方がない^^;
  }
}

class Correct implements Scene {
  final Scene next;

  Correct(Scene next) {
    this.next = next;
  }

  void display() {
    background(255, 255, 0);
    textAlign(CENTER);
    textSize(80);
    text("クリア", width / 2, 300);
    textSize(25);
    text("1不可説不可説転点", width / 2, 500);
    text("獲得", width / 2, 535);
  }

  Scene getNext(int x, int y) {
    return next;
  }
}

class Incorrect implements Scene {
  final Scene next;

  Incorrect(Scene next) {
    this.next = next;
  }

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

  Scene getNext(int x, int y) {
    return next;
  }
}

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


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

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

とタイトルにある以上、

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

等、回答について何かしらのアクションを期待しているのですが、これでは単なる作業依頼です。
もちろん「そういうつもりではなかった。」というのはわかっていますが。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る