MAUプログラミング講習資料(2019/08/21 10:00 – 17:00)
MAUプログラミング講習の資料コードを載せています。詰まることがなければ、このページのみで1日目の内容を独習することができます。分からないことがあれば遠慮なく周りに質問してください。
また、内容が確認できたらすぐ次へ行ってしまうことをオススメします。
その前に!
- Teamsに参加していない方は、アンケートの回答をお願いします。
- 8/23-25 10:00-17:00:2日目より本格的な電子工作講習およびCAD講習
- 8/27-8/30:ハッカソン(グループでの開発会)
質問について
-
直接の質問ももちろん受け付けておりますが、匿名での質問をご希望の方はSlidoというサイトを利用して質問することができます。
https://app.sli.do/event/suxhhvjr/live/questions
本日の講習スライド
本日の講習スライドは3パートに分かれています。クリックすると各パートのスライドが見られます。
- Part1:プログラミングで図形を描く
- Part2:アニメーションへ
- Part3:お絵かきツール・幾何学模様
目次
- <コードを書く前の注意点>
- 簡単に絵を描いてみよう
- 休憩(予定)
- アニメーションへの誘い(その1)
- アニメーションへの誘い(その2)
- 休憩(予定)
- 条件分岐でお絵かきツール
- 繰り返しで幾何学模様
- 1日目終了
<コードを書く前の注意点>
-
以降に載せるコードをコピー&貼り付けして、再生ボタンを押せばすぐに実行できます。
コピーしたい箇所を囲んでCtrlキー+Cキーでコピー、貼り付けたい箇所を選んでCtrlキー+Vキーで貼り付けられます。
内容を理解したら、コピー貼り付けして実行して確認。この流れが良いかと思います。
キーボードを打つのが苦手な人はこれを積極的に利用していきましょう。 - Ctrlキー+Sキーで書いたプログラムを保存できます。基本的にコードはこのページにすべて書いてありますが、もし自分で作ったものを保存したい、ということがあれば活用してください。
- 書いた命令は上から下へ実行(=逐次(ちくじ)実行)されていきます。実行順によるミスにご注意ください。
- セミコロン(;)を忘れるとエラーになります。注意しましょう。エンターキーの近くにあります。
- 命令は基本的に、頭文字が小文字です。大文字にしてしまうとエラーが起きます。
2語以上でできている命令(noFill)などは2語目の頭文字だけ大文字になります。 - プログラミングで扱うX, Y座標は高校などで習った数学のX,Y座標と決め方が少し違います。分からない方はプレゼン資料23-25ページを確認してください。
簡単に絵を描いてみよう
コード①:プログラムを書いてみよう
size命令とrect命令
- size命令は、ウインドウのサイズを設定する命令です。
size(w, h);は「幅w,高さhのウインドウにせよ」という命令になります。
size(800, 600);は「幅800,高さ600のウインドウにせよ」という命令になります。 -
rect命令は、四角形を描く命令です。
rect(x, y, w, h);は「(x,y)に幅w,高さhの四角形を作れ」という命令になります。
rect(100, 150, 300, 400);は「(100,150)に幅300,高さ400の四角形を作れ」という命令になります。
size(800, 600);
rect(100, 150, 300, 400);
コードを見やすく・書きやすくしよう
最初の設定のままだと、コードが見にくいかもしれません。もし字が小さいとか、フォントが気にくわない、ということがあれば、フォントの設定をすることができますのでやってみてください。
- メニューの「ファイル」→「設定」をクリックして、
- フォントを変えたければ、「エディターとコンソールのフォント」
- 文字の大きさを変えたければ「エディタフォントサイズ」の数値を変えてみてください
- メニューの「ファイル」→「設定」をクリックして、「コード補完 Ctrl-space」にチェックを入れる
コード②:命令を増やしてみよう
関数と引数、コメント
- size(800,600)や、rect(100,150,300,400)のうち、「rect」「size」の部分を関数,()内の数字を引数と呼びます。
size関数は引数を2つ持ち、rect関数は引数を4つ持つことになります。 -
ellipse関数は、円を描く関数です。
ellipse(x, y, w, h);は「(x,y)に横幅w,縦幅hの円を作れ」という命令になります。
rect(200, 300, 300, 400);は「(200,300)に横幅300,縦幅400の円を作れ」という命令になります。 - コードの中にある「//追加」の部分は、
コメントと呼ばれ、この部分をコンピュータ側が読むことはありません。
他の人が書いたコードや、自分が書いたコードを後で見たときなど、分かりやすいようにコメントを入れておくことができます。今回は「ここに追加した」という意味で「//追加」と記述しています。
また、「//」は、それ以降の文字がすべてコメントになりますが、有効範囲は1行だけです。「/* (コメント) */」のように「/*」と「*/」で囲むことにより、複数行でコメントを書けます。エラーが起きたとき、どこでエラーが起こったかを調べるのにも役立ちます。 - 先にも述べましたが、プログラムは上から下へと逐次実行されます。ですから、四角形を描いた後、円を描く。という風になるので、四角形の上に円が重なって表示されます。
size(800, 600);
rect(100, 150, 300, 400);
ellipse(200, 300, 300, 400);//追加 有効範囲1行
/* こう書くと
複数行にわたってコメントできる */
課題(無視してもよい):
今までの内容で何かお絵かきをしてみてください。
上に載せた他にも、絵を描く関数には次のようなものがあります。
- point(x,y):(x,y)に点を打つ
- line(x1,y1,x2,y2):(x1,y1)と(x2,y2)を結んで線を描く
- triangle(x1,y1,x2,y2,x3,y3):(x1,y1)と(x2,y2)、(x3,y3)の3点を結んで三角形を描く
- quad(x1,y1,x2,y2,x3,y3,x4,y4):4点を結んで四角形を描く
- stroke(r,g,b):輪郭線の色を赤(red)、緑(green)、青(blue)、光の三原色で指定して変えられる
- strokeWeight(weight):輪郭線の太さを変えられる
- noStroke:輪郭線が表示されなくなる
- fill(r,g,b):この命令より下の命令で作られる図形を、指定した(r,g,b)の色で塗りつぶす
- noFill():塗りつぶししなくなる。
とりあえず全て数値を入れておいたコードを載せます。好きにいじってみてください。
//キャンバスの大きさ(x,y);
size(800, 600);
//四角(始点x,始点y,長さx,長さy);
rect(100, 150, 300, 400);
//塗りつぶし(R,G,B);
fill(0, 255, 0);
//楕円(始点x,始点y,x半径,y半径);
ellipse(600, 300, 300, 400);
//塗りつぶし(R,G,B);
fill(255, 255, 255);
//線塗りつぶし(R,G,B);
stroke(255, 0, 0);
//線太さ
strokeWeight(20);
//点(始点x,始点y);
point(400, 50);
//線(始点x,始点y,終点x,終点y);
line(200, 450, 350, 450);
//四角(始点x,始点y,点2x,点2y,点3x,点3y,点4x,点4y);
quad(50, 150, 200, 200, 150, 300, 400, 400);
//線なし
noStroke();
//三角(始点x,始点y,点2x,点2y,点3x,点3y);
triangle(600, 200, 700, 200, 650, 300);
少し休憩
アニメーションへの誘い(その1)
コード③:波かっこ「{}」の中に書こう
- setup関数について。美大生のみなさんは、絵を描くことと思います。実際に絵を描くときは、画用紙のサイズなどから決めていくと思います。
そのように、最初の決め事を書いておく場所がsetup関数になります。size関数などはここに入ります。1回だけ実行します。 - draw関数は、1秒間に60回、中身の命令を次々に上から下へと実行し続ける関数になります。
ですから、下のコードで言えばrect命令とellipse命令を1秒間に60回ずつ実行し続けることになります。
ここではまだありがたみが分からないと思いますが、アニメーションを扱うときや、後に行う電子工作(関数の名前はdrawではなくloopですが、)においても便利な関数です。 - 「{」「}」で囲むことによって「ここからここまでは、setupで、ここからここまではdrawが実行する命令だよ」ということを表しています。これは境界のようなものなので、「{}」を抜くとエラーが起こってしまいますから抜かないでください。
- また、setupの”中に入っている”、drawの”中に入っている”ということを分かりやすくするために、「{」「}」の中身をインデントします。インデントとは、「Tabキー」を押して命令の前に空白を入れることです。した場合としなかった場合でコードの見やすさが大きく変わるので、意識できるとよいです。
- インデントを楽に行う方法もあります。Ctrlキー+Tキーを押すと、自動で整形(オートフォーマット)してくれます。割と便利なコマンドなので、覚えておくと良いかもしれません。
void setup(){
size(800, 600);
}
void draw(){
rect(100, 150, 300, 400);
ellipse(200, 300, 300, 400);
}
コード④:プログラムを変えてみよう(その1)
- background(r,g,b)は、赤、緑、青それぞれ0~255の数値で色を決めて、その色で背景を染める命令になります。
background(255,255,255)は白色で染める、ということになります。 - mouseX,mouseYは、現在のマウスの位置の座標を自動で取得して変化する数です。
以下に書かれたコードを実行すると、マウスの動きに合わせて円が動くと思います。
1/60秒が経過する度にmouseX,mouseYが更新され、全部白く染まった後に新しく円を描きます。
これが繰り返されることで、パラパラ漫画のように円が動いているように見えるわけです。 - mouseX,mouseYのほかに、width,height,pmouseX,pmouseYというものがあります。それぞれ次のような数値が入っています。
width:size関数で決めたウインドウの幅
height:size関数で決めたウインドウの高さ
pmouseX:1フレーム前のマウスのX座標
pmouseY:1フレーム前のマウスのY座標
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
ellipse(mouseX, mouseY, 400, 400);//変更
}
コード⑤:プログラムを変えてみよう(その2)
frameRate関数
- frameRate関数は、1秒間に何回drawの中身を実行するのかを決める関数です。これを書かなかった場合は60回になります。
frameRate(30)は1秒間に30回実行するという指定を意味します。 - 1秒間の実行回数が減るので、先ほどよりカクカクした動きになると思います。
void setup(){
size(800, 600);
frameRate(30);//追加
}
void draw(){
background(255, 255, 255);
ellipse(mouseX, mouseY, 400, 400);
}
コード⑥:数値の変化を文字で見てみよう
println関数と文字列
- println関数は中の数値や文字を出力する関数です。
- ここでは使っていませんが、print関数というものもあります。printとprintlnの違いは、実行するごとに改行するかどうかの違いです。
print関数は改行せずに出力し、println(=print line)関数は実行するごとに改行が入ります。
void setup(){
size(800, 600);
frameRate(30);
}
void draw(){
background(255, 255, 255);
ellipse(mouseX, mouseY, 400, 400);
println(mouseX);//追加
}
- 複数の文字が並んだものは文字列と呼ばれ、プログラム上では「”」で囲うことによって文字列と認識されます。(「Shift」キー+「2」キーで打てます)
println(mouseX)の部分を、println(“Hello!”)のように書き換えれば、「Hello!」と何行も表示します。
println(Hello!)ではエラーが起こります。
void setup(){
size(800, 600);
frameRate(30);
}
void draw(){
background(255, 255, 255);
ellipse(mouseX, mouseY, 400, 400);
println("Hello!");//変更
}
コード⑦:プログラムを変えてみよう(その3)
文字列の結合
- 文字列は結合することができます。”Hello!”+”World”とすれば、”Hello!World”とつなげることができます。
また、「”文字列”+数値」という書き方をすれば、文字列と数値を同時に出力でき、
「”文字列”+数値+”文字列”+数値」という風に結合しまくることもできます。 - 以下のコードを実行すると、ウインドウサイズが出力できます。確認してみてください。
void setup(){
size(800, 600);
println("ウインドウサイズは");
println("幅:" + width + " 高さ:" + height);
}
void draw(){
}
アニメーションへの誘い(その2)
コード⑧:変数が絡んだプログラム
変数について
ここが少し難しくなるのでご注意ください。すぐに理解できなくても大丈夫です。
- 数値や、文字列などを記憶してとっておくための箱を変数と呼びます。値を記憶させながら変化させることで、アニメーションを実現させることができます。
- 前に述べた「width,height,mouseX,mouseY」などは全て、processing側が予め用意&管理している変数なのです。
- 変数の使う流れは、宣言、代入、読み出しです。
変数の宣言
- まず、変数を宣言(「私はこういう変数を使いますよ」と宣言)します。宣言の仕方にはルールがあり、
「変数の型 変数の名前;」という順に書く必要があります。 - 変数の型とは、箱に何を入れるのか(数値なのか文字なのか)を区別させるのに用いるものです。型というものを使います。整数ならint、
小数点付きの数値(=より細かい値が欲しいときに使う)ならfloat、文字列ならString(これは頭文字が大文字)、真偽判定ならboolean(後述)などに分かれます。
int x; と書けば、int型の変数xを宣言した(=整数を扱う箱を用意した)ということになります。 - 変数の名前はほぼ自由に決められます。(頭文字に数字を入れられない、記号は「_」「$」のみなどのルールはある)ただ、自分にとって分かりやすい名前をつけることをオススメします。
変数への代入
- 次に、変数に値を代入します。「変数の名前 = 代入したい値;」という風に書きます
- x = 100;と書けば、「変数xに100を代入する」という意味になります。(何も代入しなければ0が入っています)
- この「=」は数学の左辺が右辺に等しい、という意味ではなく、左の変数に対して右の値を代入するという意味になります
- また、足し算・引き算・掛け算・割り算に用いる記号はそれぞれ「 +(プラス)、-(マイナス)、 *(アスタリスク)、 /(スラッシュ) 」です
掛け算と割り算が少し特殊なので注意してください - 変数そのものを代入することもでき、x = 100;の後に、x = x + 1;が命令された場合、xには101が代入されることになります
- x = x + 1; は x += 1;と書くこともできます。
- x = x – 1;(または x -= 1;)すれば元の値から1を引くことができます
- 宣言すると同時に代入することもできます。その場合は「int x = 100;」のように書きます
- 先ほど述べたfloat型の変数に対しては、「float x = 100.0f;」というように、後ろにfを入れる必要があります。(これはより精度の高い小数を扱う変数の型である「double」型と区別するためです。)
- 文字列に対しては「String s = “Hello!”;」というようにして宣言と代入ができます
変数の読み出し
- 値を代入した変数は、他の命令で読み出すことができます。下のコードではellipseの中でxを使っています
x = 100;の後のellipse(x, height / 2, 50, 50);では、ellipse(100, height / 2, 50, 50);
x = 200;の後のellipse(x, height / 2, 50, 50);では、ellipse(200, height / 2, 50, 50);が実行されます
int x = 0;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
x = 100;
ellipse(x, height / 2, 50, 50);
x = 200;
ellipse(x, height / 2, 50, 50);
}
ここで、先ほどのコードを再掲します。
void setup(){
size(800, 600);
frameRate(30);
}
void draw(){
background(255, 255, 255);
ellipse(mouseX, mouseY, 400, 400);
println("Hello!");
}
文字列、String型の変数に入れることで次のように書き換えることもできます。このとき、最後のprintln()の中身に「”」を必要としないところに注意してください。
String s = "Hello!";
void setup(){
size(800, 600);
frameRate(30);
}
void draw(){
background(255, 255, 255);
ellipse(mouseX, mouseY, 400, 400);
println(s);
}
コード⑨:変数を連続的に変化させてみよう
- 先ほど解説したx = x + 1;のパターンの代入です。プログラムは1秒間に60回、上から下へ実行されますから、 xは0からスタートして1秒間に60ずつ刻々と増えていくので、円は徐々に右側へと動いていきます。
int x;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
x = x + 1;
ellipse(x, height / 2, 50, 50);
}
- println(“x = ” + x);で、刻々とxの値が増えていく様子を確認できます。
int x;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
x = x + 1;
println("x = " + x );//追加
ellipse(x, height / 2, 50, 50);
}
- 以下のように書けば、斜めに(右下に向かって)動きます。
int x;
int y;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
x = x + 2;
y = y + 3;
ellipse(x, y, 50, 50);
}
- 以下のように書くと、今度は左上に向かって動きます。int x; int y;のままだとすぐに画面外に行ってしまい、様子を確認できないので
int x = width; int y = height;と書き換えています。
int x = width;//変更
int y = height;//変更
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
x = x - 5;//変更
y = y - 8;//変更
ellipse(x, y, 50, 50);
}
コード⑩:どう動くだろうか?
- 下のコードを見ると、変数が2つ使われています。 vが刻々と増えながら、それがxに足され続け、xは急速に増えます。
最後にそれが円の描画に使われているので、 結果、徐々に早くなっていく運動(=等加速度運動)になります。
ellipse(width / 2, x, 50, 50);と書き換えれば、物体の落下を再現することもできます。
int x;
int v;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
v = v + 1;
x = x + v;
ellipse(x, height / 2, 50, 50);
}
課題(無視してもよい):
アニメーションを作ろう!
今まで習ったものを使ってアニメーションを作ってみましょう。
少し休憩
条件分岐でお絵かきツール
ある条件を満たすかどうかによって実行する命令を変えること(=条件分岐)ができれば、より多様なプログラムを書けます。条件分岐を使えば、簡単なお絵かきツールが作れます。そのために、if文とboolean型の変数、条件の扱い方について理解していただきます。
コード⑪:簡単なif文
if文
- 「if文」は、条件分岐を可能にする文の1つです。下のコードを実行してみてください。 マウスが押されたときだけ、押した場所を中心に円が表示されるはずです。
- if(条件){命令;}という形で、「ある条件を満たしたときだけ中の命令を実行せよ」という内容の指示をすることができます。
条件は、true(真、正しい、数字で言うと1)か、false(偽、間違っている、数字で言うと0)かで判定し、true(真)なら中身の命令を実行する、false(偽)なら実行しないという形式です。 - mousePressedというのは、マウスが押されているのかどうかを判定しているboolean型の変数です。
- boolean型の変数には、trueまたはfalseが入っており、mousePressedは、マウスボタンが押されればtrue,離されていればfalseが入ります。
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
if (mousePressed){
ellipse(mouseX, mouseY, 300, 300);
}
}
- if(条件){命令;}においては、さらに命令が{}に囲まれることになるので、条件分岐しているということが分かりやすくなるようにさらにインデントします。
- if文の中身の命令は、いくつあっても問題ありません。以下のコードは、上のコードと同じ結果になります。
int x, y;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
if(mousePressed){
x = mouseX;
y = mouseY;
}
ellipse(x, y, 400, 400);
}
boolean型の変数を少し扱ってみましょう。下のコードではboolean型の変数valueを宣言するとともにtrueを代入し、 最後にif文の条件で「value」を使っています。valueにはtrueが入っているので、当然中身の命令であるellipse関数が実行されます。ここでもし仮にvalueにfalseを代入すると、中身の命令は実行されません。
boolean value = true;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
if (value){
ellipse(mouseX, mouseY, 300, 300);
}
}
else文
以下に示すコードには、elseというものが使われています。「else」とは「そうでなければ」の意味を表し、 これを使うときは、ifとセットで使います。下のコードでは、mousePressedがtrueでない場合(マウスボタンが押されてない場合)に中身の命令が実行されます。 つまり、マウスを押している間は四角形が描かれ、離している間は円が書かれることになります。
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
if ( mousePressed ){
rect(100, 100, 200, 200);
}else{
ellipse(200, 200, 300, 300);
}
}
コード⑫:お絵かきツール
まず、下のコードをコピー&貼り付けして実行してみてください。解説はまず読まないで結構です。マウスを押しながら動かすと紙にペンで描いているような動作をすると思います。また、適当に何かキーを押すと全消しされてまっさらな状態に戻ると思います。
解説
- if文にはさらにつなげて「else if」という書き方ができます。
- if(条件1){命令;}else if(条件2){命令;}という書き方です。
- 再掲しますが「mousePressed」というのはマウスのボタンが押されたかどうかという判定で、もし押されたならその中身を実行する(line関数を実行してマウスの位置に線を引く)ということになります。
- 「else if」というのは、「そうでなくてもし」の意味で、この場合は「マウスのボタンが押されてなくて、もし」という意味になります。そのあとにkeyPressedとありますが、これはキーが押されたかどうかの判定になります。つまりその中にある「background(255,255,255)」(←画面をすべて白く塗りつぶす)命令は、「マウスのボタンが押されてなくて、キーが押されたときだけ」に実行されます。このようにして、変なタイミングで全部消したりしないように制御することができるのがif文のメリットです。
void setup(){
size(800, 600);
background(255,255,255);
}
void draw(){
if(mousePressed){
line(pmouseX,pmouseY,mouseX,mouseY);
}else if(keyPressed){
background(255,255,255);
}
}
以下のコードは実行してもエラーが起きます。内容を確認するだけにしてください。
- 以下のコードのように、else ifはいくらでもつなげられて、elseは最後につけることもできます。 この場合、「条件1なら命令1、そうでなくて条件2なら命令2、そうでもなくて条件3なら命令3と命令4、さらにそれ以外なら命令5を実行せよ」という指示になります。これでわがままな指示が出せますね。
if(条件1){
命令1;
}else if(条件2){
命令2;
}else if(条件3){
命令3;
命令4;
}else{
命令5;
}
補足:ボールの跳ね返り
条件の中に書けるものはmousePressedやkeyPressed以外にもあります。以下のコードを実行してみてください。
ボールが右端まで行った後、跳ね返ったと思います。
- if文の条件の中に、x > widthというものが入っていますね。これは、xがwidth(=800)よりも大きいかどうか、という条件を表します。
- そのif文の中身v = -v;は、速度の反転を表します。 今まで速度4(右向き)だったものが、速度ー4(左向き)になるわけです。 「=」は代入を意味していることに注意してください。
- ですから、ボールが右端に行ったタイミングで xはwidthより大きくなるので、条件がtrueになり、v = -v;によって速度が反転します。これが、跳ね返る動作の正体です。
- このように、変数の大小関係を条件にすることもできます。
int x;
int v = 15;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
x = x + v;
if(x > width){
v = -v;
}
ellipse(x, height / 2, 50, 50);
}
他にも以下のような条件式の書き方があります。
- A == B:AはBと等しいかどうか(代入と区別するため、「=」を2つ使う!)
- A != B:AはBと等しくないかどうか
- A <= B:AはB以下か
- A >= B:AはB以上か
- A > B:AはBより大きいか
- A < B:AはBより小さいか
補足:ボールの往復
先ほどのコードを使って、ボールが左側でも跳ね返るようにしてみましょう。少し挑戦してみてください。下に解答を載せます。
int x;
int v = 15;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
x = x + v;
if(x > width){
v = -v;
}
if(x < 0){
v = -v;
}
ellipse(x, height / 2, 50, 50);
}
このコードは、よく見てみると2つの条件で同じ命令v = -v;を実行していることが分かります。 このようなとき、省略して書くことができます。下のコードはその条件を省略形で書いたものです。
int x;
int v = 15;
void setup(){
size(800, 600);
}
void draw(){
background(255, 255, 255);
x = x + v;
if(x > width || x < 0){
v = -v;
}
ellipse(x, height / 2, 50, 50);
}
- 2つ以上の条件式を、演算子を使ってまとめることができます。「||」をOR(オア)演算子と呼び、 「x > width または x < 0」という意味になります。どちらかを満たしていれば、中身の命令は実行されます。
- この他に「&&」というものがあります。「&&」をAND(アンド)演算子と呼び、 「x > width && x < 0」と書かれた場合は「x > width かつ x < 0」という意味になり、 両方満たしていなければ中身の命令は実行されません。
繰り返しで幾何学模様
while文・for文
条件を満たすまで命令を繰り返すこと(=繰り返し)ができれば、規則的な図形の描画などができます。ここでは、繰り返しを使って幾何学模様を描くことに挑戦します。そのために、while文とfor文の扱い方について理解していただきます。
setupとdrawを書いていないコードがありますが、これらは説明用のため、割愛してあります。ご了承ください。
コード⑬:while文
ますは実行してみてください。while文とは、繰り返し回数が決まってないときに用いられる構文です。もちろん決まっているときにも使えます。 while(条件){命令;}という形で書き、条件を満たし続ける限り命令を実行します。
解説
- 以下のコードを実行すると、0,1,2,...,9まで出力するのが分かると思います。while文の中にある命令が、条件を満たすまでずっと繰り返されているのです。
- counter++;という見慣れないものがあります。これはcounter = counter + 1;を省略して書いた形で、
++をインクリメント演算子と呼びます。(名前を覚える必要はありません)
ほかに、counter = counter - 1;を意味する、counter--;というものもあります。これはデクリメント演算子と呼ばれます。 - まず、命令① println(counter);が実行され、はじめに0が出力されます。そのあと、次のcounter++;によってcounterに1という値が入り、また上に戻って条件を確認します。counterは10未満なので再び中身の命令が実行され、counter,1を出力します。そのあと、 次のcounter++;でcounterに2という値が入り、また上に戻って条件を確認...という流れで0~9までの数字が出力されます。
int counter = 0;
while (counter < 10){
println(counter);
counter++;
}
以下のコードは、何も実行されずに終了します。
int counter = 0;
while (counter > 10){
println(counter);
counter++;
}
というのも、はじめにcounterに入っている値は0なわけですが、それは条件式counter > 10を満たしません(条件式:counterが10より大きいか? に対して counterは10未満)。ですから、このwhile文の中身の命令を実行することなくスキップします。
以下のコードでは、counter++;をコメントにしてしまうことで、counter++;という命令を無効化しています。 これをコメントアウトと呼び、エラーを確認するときによく用います。コメントアウトしたい範囲を囲ってCtrlキー+ / キーを押すとコメントアウトすることができます。
今回はcounter++;が実行されないので、ずっと0が出力され続けることになります。無限に出力し続けるため、processingが動かなくなると思うので実行非推奨です。もし実行したら、停止ボタン(〇の中に■があるマーク)を押して終了してください。
int counter = 0;
while (counter < 10){
println(counter);
//counter++;
}
補足①:ループの途中で次に行ってしまいたい場合は「continue;」を使います。下のコードは、counterが8のときは次(counterが9)になるようにしたものです。 0から9までが出力されますが、8だけ消えた形になります。
int counter = 0;
while (counter < 10){
if(counter == 8){
counter++;
continue;
}
println(counter);
counter++;
}
補足②:ループの途中でそのループを抜けたい場合は「break;」を使います。下のコードは、counterが6のときにループを抜けるようにしたものです。 0から5まで出力されますが、6でループを抜けるのでそれ以降は出力されません。
int counter = 0;
while (counter < 10){
if(counter == 6){
break;
}
println(counter);
counter++;
}
少し幾何学模様に触れてみよう
さて、while文が理解できれば、幾何学模様は記述できるようになります。以下のコードを実行してみてください。
size(800, 600);
translate(width / 2, height / 2);
scale(20.0f);
int i = 0;
while (i < 1000){
fill(i, 255, i / 2);
rotate(0.1f);
scale(0.99f);
rect(0, 0, 50, 50);
i++;
}
吸い込まれそうな絵が出たかと思います。これは、1つの大きい正方形を、少しずつ縮小&回転させたものを1000回描いたプログラムです。 これをwhile文を使わずに書くのは至難の業ですよね。このような人間にとって恐ろしい回数の繰り返しを、while文はやってのけるわけです。
解説
ここらで解説しましょう。特に重要なのはtranslate,rotate,scaleという関数たちです。
- translate(x,y):これから描く図形を指定した座標(x,y)分だけ移動する
- rotate(r):これから描く図形を指定した角度r(ラジアン)だけ回転させる(参考:π(パイ)ラジアン=180°)
- πラジアン回転させたいときはrotate(PI);と書けばOK
- ラジアンが面倒で180°回転させたいときはrotate(radians(180.0f));と書けばOK
- scale(s):これから描く図形を指定した倍率sだけ拡大・縮小する
- 上の関数は一度呼び出すと、そのあとの命令全てに実行される
- そのため、もし戻したい場合は次のように変えていく必要がある。
translate(100,200);→translate(-100,-200);
rotate(0.1f); → rotate(-0.1f);
scale(2.0f); → scale(0.5f);
最初のtranslate(width/2,height/2);は、四角形を描く位置を修正するものです。これによってrect(0,0,50,50); は、rect(width/2, height/2, 50 + width/2, 50 + height/2);となり、真ん中あたりに描かれるようになります。 わざわざこのように書くと大変なので、初めにtranslateで書いておくことでrectの中身をきれいに書くことができます。
それぞれの関数がループごとに、図形にどういう影響を与えていくのか説明していきます。
まず、fill(i, 255, i/2);というのは、回数を重ねるごとに四角形を染める色が変わっていくというような具合です。
はじめfill(0,255,0);(緑)から始まって、途中(255回目あたり)で(255,255,127);(黄)になります。
そして後半(510回以降)ではfill(255,255,255);(白)となって、白く塗りつぶされることになります。
次のrotate(0.1f)は、実行されるたびに0.1ラジアン回転していくので、最終的に100ラジアンほど回転します。
0以上の値なら反時計回りなので、四角形は少しずつ反時計回りしていきます。
最後のscale(0.99f)は、元の図形の99%の大きさに縮小していく関数です。これを1000回繰り返すと、最終的に
元の図形の0.0004%程度になります。ほとんど無いに等しいですね。模様の真ん中あたりには本来、正方形があるはずなのですが、あまりに小さいので見えなくなっているわけです。
さらに上のコードを、マウスと連携させ、キーを押すと次々に図形が変化していく、幾何学模様+アニメーションを融合させたものも作ることができます。それが次のコードです。
基本的には、上のコードと変わらないのですが、translate(mouseX,mouseY)で、マウスと一緒に幾何学模様も動き、 if(keyPressed)、もしキーが押されると、angleValueを大きくなる→回転する角度を増える、ということで図形が次々と回転していきます。 これが足され続けて2πラジアンまでいくと、ちょうど1周するので完全に元の模様に戻る、つまりキーを押し続けていると周期的に模様が変わっていくプログラムができるわけです。
float angleValue = 0.1f;
void setup(){
size(800, 600);
}
void draw(){
background(255);
translate(mouseX, mouseY);
scale(20.0f);
if(keyPressed){
angleValue = angleValue + 0.01f;
}
int i = 0;
while ( i < 1000 ){
fill(i, 255, i / 2);
rotate( angleValue );
scale(0.99f);
rect(0, 0, 50, 50);
i++;
}
}
コード⑭:for文
もう1つ、よく使われる繰り返しの構文があります。以下に示したコードには、for文が使われています。for文は、繰り返しの回数が明確なときによく用いられます。 さきほど、0から9までカウントするプログラムをwhile文で書きましたが、for文で書くこともできます。それが下のコードです。
for (int i = 0; i < 10; i++){
println(i);
}
- for文にも書き方のルールがあり、for(初期化文;条件;再初期化文){命令;}という書き方をします。
- 初期化とは、新たな変数を宣言して初期値を代入することです。変数名は本来なんでもいいですが、一般的にiが使われます。 while文での、int counter = 0;に対応し、今回は、int i = 0;となります。
- 条件にはwhileで扱ったcount < 10と同じように、i < 10のようにして設定します。
- 再初期化文には、いくつ増やすかの指定を行います。while文のcounter++;にあたる部分で、今回はi++です。最後にセミコロンを必要としないことに注意してください。
- while文で補足した「continue;」や「break;」はfor文でも使えます。
また、このfor文を使って幾何学模様のプログラムを変えたものも念のため載せておきます。for文は本当によく使いますので感覚を掴んでおいて損はありません。
size(800, 600);
translate(width / 2, height / 2);
scale(20.0f);
for(int i = 0; i < 1000; i++){
fill(i, 255, i / 2);
rotate(0.1f);
scale(0.99f);
rect(0, 0, 50, 50);
i++;
}
float angleValue = 0.1f;
void setup(){
size(800, 600);
}
void draw(){
background(255);
translate(mouseX, mouseY);
scale(20.0f);
if(keyPressed){
angleValue = angleValue + 0.01f;
}
for(int i = 0; i < 1000; i++ ){
fill(i, 255, i / 2);
rotate( angleValue );
scale(0.99f);
rect(0, 0, 50, 50);
i++;
}
}
以上でMAUプログラミング資料は終了です。1日目お疲れさまでした。
本日の講習の参加アンケート(ここをクリック)を実施しています。今後のために是非ともご回答をよろしくお願いします。
- 文責:佐々木(電通大2年Ⅱ類)
- 協力:IML教育班