質問するログイン新規登録

回答編集履歴

2

音源素材について追記

2020/07/12 01:32

投稿

thkana
thkana

スコア7739

answer CHANGED
@@ -276,4 +276,6 @@
276
276
  ```
277
277
 
278
278
  「画面」というか、結局状態マシンになった気がしますがさて。
279
- 「オブジェクトの活用」は、クラス図を描いたときにクラス間に何らかの関連が引ければまぁいいんじゃないでしょうか。
279
+ 「オブジェクトの活用」は、クラス図を描いたときにクラス間に何らかの関連が引ければまぁいいんじゃないでしょうか。
280
+
281
+ (音源は、'効果音 サンプル 無料'で検索して上位に引っかかった[サイト](https://taira-komori.jpn.org/index.html)の素材URLを貼っています。昔だと直リンとか嫌われたけど、最近はどうなんでしょう。ただ、ローカルの素材を使っちゃうと他人のソースの試行が面倒なんですよね)

1

追記

2020/07/12 01:31

投稿

thkana
thkana

スコア7739

answer CHANGED
@@ -12,4 +12,268 @@
12
12
 
13
13
  どうしてもクラスを使いたいというなら、まずはプログラムの動作の概略を日本語で記述して、その中に登場する「名詞」をピックアップしてそれをクラスに置くことがどうだろうかと検討するのがとっかかりになるかと思います。「n枚目の画像」とか。
14
14
 
15
- (Javaモードで作れば、内部的にはクラスは生成されていますが...)
15
+ (Javaモードで作れば、内部的にはクラスは生成されていますが...)
16
+
17
+ ---
18
+ [追記]結構真面目にやってみました。
19
+ Processingでオブジェクト指向っぽくってあまりやったことなかったので出来は保証しません。ツッコミ歓迎。
20
+
21
+ 重視すること:
22
+ オブジェクトの「活用」をオブジェクト間の協調動作と捉える。
23
+
24
+ ストーリー:
25
+ プログラムを起動すると、タイトル画面を表示する。
26
+ タイトル画面をクリックすると、質問画面を表示する。
27
+ 質問画面の選択肢のいずれかをクリックすると、正解画面または不正解画面を表示する
28
+ 正解/不正解画面でクリックすると、タイトル画面に戻る
29
+ 各画面ではBGMを流す(質問者のプログラムを見ると全編で一つのBGMを流せばよかったみたいですが、作り込んでしまったのでそのまま。変更は難しくはないでしょう)。
30
+
31
+ さて、このストーリーからクラス候補(名詞)は...これだけのモノしか登場しないと、「画面」をクラスにするぐらいしかなさそうですね。その路線でざっくりのクラス構成を考えましょうか。
32
+ ![クラス図案](03cabb2d709d017c809d2ba839313c3d.jpeg)
33
+ Processingの構造(setup()-draw()とmouseClicked())に当てはめるため、これをinterfaceにしてみました。Processingでinterfacaを使うには、ProcessingのIDEでは、新規タブを作成し、例えばFramework.java等の名前を付けて以下を記述する必要があります。
34
+ ```Processing
35
+ //Framework.java
36
+ interface Framework{
37
+ void setup();
38
+ void draw();
39
+ void mouseClicked();
40
+ }
41
+ ```
42
+ で、プログラム本体というか。自分に余裕が無かったのでコメントとか付いてません。継承の使い方がイケてない気がしますが...
43
+ ```Processing
44
+ import processing.sound.*;
45
+ enum Results {
46
+ STAY,
47
+ GO,
48
+ CORRECT,
49
+ WRONG
50
+ }
51
+
52
+ class Control implements Framework {
53
+ Screen active;//表示される画面
54
+ Screen start, question, correct, wrong;//使われる各画面
55
+ void setup() {
56
+ start.setup();
57
+ active.enter();
58
+ question.setup();
59
+ correct.setup();
60
+ wrong.setup();
61
+ }
62
+ void draw() {
63
+ active.draw();
64
+ Results rc=active.result();
65
+ switch(rc) {
66
+ case STAY:
67
+ default:
68
+ break;
69
+ case GO:
70
+ if (active==start) {
71
+ active.exit();
72
+ active=question;
73
+ active.enter();
74
+ } else {
75
+ active.exit();
76
+ active=start;
77
+ active.enter();
78
+ }
79
+ break;
80
+ case CORRECT:
81
+ active.exit();
82
+ active=correct;
83
+ active.enter();
84
+ break;
85
+ case WRONG:
86
+ active.exit();
87
+ active=wrong;
88
+ active.enter();
89
+ break;
90
+ }
91
+ }
92
+ Control( Title start, Question question, Title correct, Title wrong ) {
93
+ this.start=start;
94
+ active=start;
95
+ this.question=question;
96
+ this.correct=correct;
97
+ this.wrong=wrong;
98
+ }
99
+ void mouseClicked() {
100
+ active.mouseClicked();
101
+ }
102
+ }
103
+
104
+ class Screen implements Framework {
105
+ String text;
106
+ SoundFile bgm;
107
+ color bgColor;
108
+ boolean done=false;
109
+ Screen( PApplet app, color bgColor, String text, String bgmFile) {
110
+ this.bgColor=bgColor;
111
+ this.text=text;
112
+ bgm=new SoundFile(app, bgmFile);
113
+ }
114
+ void setup() {
115
+ }
116
+ void draw() {
117
+ background(bgColor);
118
+ textAlign(CENTER, CENTER);
119
+ textSize(autoSize(text, width*0.8));
120
+ fill(0);
121
+ text(text, width/2, height*0.2);
122
+ }
123
+ void enter() { //画面に入る時に行う処理
124
+ done=false;
125
+ if (bgm!=null) {
126
+ bgm.play();
127
+ }
128
+ }
129
+ void exit() { //画面を終了するときに行う処理
130
+ if (bgm!=null) {
131
+ bgm.stop();
132
+ }
133
+ }
134
+ Results result() { //画面内処理の結果を得る
135
+ return Results.STAY;
136
+ }
137
+ void mouseClicked() {
138
+ }
139
+ }
140
+
141
+ class Title extends Screen {
142
+ String subText;
143
+ Title( PApplet app, color bgColor, String text, String subText, String bgmFile) {
144
+ super(app, bgColor, text, bgmFile);
145
+ this.subText=subText;
146
+ }
147
+ @Override void draw() {
148
+ super.draw();
149
+ textAlign(CENTER, CENTER);
150
+ textSize(autoSize(subText, width*0.7));
151
+ fill(0);
152
+ text(subText, width/2, height*0.7);
153
+ }
154
+ @Override Results result() {
155
+ return done? Results.GO : Results.STAY;
156
+ }
157
+ @Override void mouseClicked() {
158
+ done=true;
159
+ }
160
+ }
161
+
162
+ class Question extends Screen {
163
+ int rightAns;
164
+ int ansPos;
165
+ class Button {
166
+ float left;
167
+ float top;
168
+ float w;
169
+ float h;
170
+ String text;
171
+ Button( float left, float top, float w, float h, String text) {
172
+ this.left=left;
173
+ this.top=top;
174
+ this.w=w;
175
+ this.h=h;
176
+ this.text=text;
177
+ }
178
+ boolean isInside(float x, float y) {
179
+ return left<=x && x<= left+w && top<=y && y<=top+h;
180
+ }
181
+ void draw() {
182
+ fill(255);
183
+ rectMode(CORNER);
184
+ rect(left, top, w, h);
185
+ fill(0);
186
+ textSize(autoSize(text, w));
187
+ textAlign(CENTER, CENTER);
188
+ text(text, left+w/2, top+h/2);
189
+ }
190
+ }
191
+ Button[] button;
192
+ Question( PApplet app, color bgColor, String text, String choice1, String choice2, int right, String bgmFile) {
193
+ super(app, bgColor, text, bgmFile);
194
+ button=new Button[2];
195
+ button[0]=new Button(width*0.1, height*0.7, width*0.3, height*0.2, choice1);
196
+ button[1]=new Button(width*0.6, height*0.7, width*0.3, height*0.2, choice2);
197
+ rightAns=right;
198
+ }
199
+ @Override void draw() {
200
+ super.draw();
201
+ for ( Button btn : button) {
202
+ btn.draw();
203
+ }
204
+ }
205
+ @Override void enter() {
206
+ super.enter();
207
+ ansPos=0;
208
+ }
209
+ @Override void mouseClicked() {
210
+ for (int i=0; i<button.length; i++) {
211
+ if (button[i].isInside(mouseX, mouseY)) {
212
+ ansPos=i+1;
213
+ }
214
+ }
215
+ }
216
+ @Override Results result() {
217
+ Results ret;
218
+ if (ansPos==0) {
219
+ ret=Results.STAY;
220
+ } else {
221
+ if (ansPos==rightAns) {
222
+ ret=Results.CORRECT;
223
+ done=true;
224
+ } else {
225
+ ret=Results.WRONG;
226
+ done=true;
227
+ }
228
+ }
229
+ return ret;
230
+ }
231
+ }
232
+
233
+ int autoSize(String text, float width) {
234
+ String[] lines=text.split("\n");
235
+ int maxLen=0;
236
+ for (String line : lines) {
237
+ if (maxLen<line.length()) {
238
+ maxLen=line.length();
239
+ }
240
+ }
241
+ return (int)(width/maxLen);
242
+ }
243
+
244
+
245
+ Control ctrl;
246
+ void setup() {
247
+ size(460, 800);
248
+ textFont(createFont("游明朝 Demibold", 24));
249
+ ctrl=new Control(
250
+ new Title(this, color(0, 255, 255),
251
+ "ルイザ・グロス・ホロウィッツ賞\n日本人受賞者を覚えよう!",
252
+ "ルイザ・グロス・ホロウィッツ賞\n日本人受賞者を全員答えられたらクリアだよ",
253
+ "https://taira-komori.jpn.org/quick/upl/fanfare2.mp3"),
254
+ new Question(this, color(245, 100, 170),
255
+ "生物学や生化学の研究者に贈られる\nルイザ・グロス・ホロウィッツ賞を\n現在、日本人で唯一受賞したのは誰?",
256
+ "利根川進", "木村資生", 1, "https://taira-komori.jpn.org/sound/anime01/hurry_up.mp3"),
257
+ new Title(this, color(255, 255, 0),
258
+ "クリア",
259
+ "1不可説不可説転点\n獲得",
260
+ "https://taira-komori.jpn.org/sound/game01/crrect_answer1.mp3"),
261
+ new Title(this, color(255, 255, 0),
262
+ "はずれ",
263
+ "あなたはルイザ・グロス・ホロウィッツ賞の\n日本人受賞者を1人も覚えていません",
264
+ "https://taira-komori.jpn.org/sound/game01/blip01.mp3")
265
+ );
266
+ ctrl.setup();
267
+ }
268
+
269
+ void draw() {
270
+ ctrl.draw();
271
+ }
272
+
273
+ void mouseClicked() {
274
+ ctrl.active.mouseClicked();
275
+ }
276
+ ```
277
+
278
+ 「画面」というか、結局状態マシンになった気がしますがさて。
279
+ 「オブジェクトの活用」は、クラス図を描いたときにクラス間に何らかの関連が引ければまぁいいんじゃないでしょうか。