2018プログラミング講座14:サウンド

サウンドの再生

はじめに、サウンドの再生を実行します。サウンドを扱うためにminimというサウンドライブラリを用います。(ライブラリとは、processingなどプログラミング言語の開発環境に様々な機能を追加するプログラムの集まりのようなものだと理解するとよいでしょう。)また、今回はminimを使うためにprocessing バージョン2を使用しますので注意してください。

まず、processingを起動しておきます。次にフリーの音源データをインターネット上から探してデスクトップにダウンロードします。ダウンロードする音源データは必ずmp3形式を選んでください。ダウンロードした音源データの名称をtest.mp3と変更します。

次に、デスクトップにダウンロードした音源データをprocessingで扱えるように追加します。processingのメニューからSketchを選択し、Add File…を選びます。デスクトップから先ほどダウンロードした音源データを選択しopenボタンを押して追加します。

以下のコードを記述して実行ボタンを押すと音源データが再生されます。

import ddf.minim.*; //サウンドライブラリminimの読み込み
 
Minim sound; //minim型変数の宣言
AudioPlayer player;//サウンドデータ格納用変数の用意
 
void setup(){
  size(100, 100);
  sound = new Minim(this); //minim型変数の初期化
  player = sound.loadFile("test.mp3"); //サウンドデータの読み込み
  player.play(); //サウンドデータの再生
}
 
void draw(){
  background(0);
}
 
void stop(){ 
  player.close(); //サウンドデータの終了
  sound.stop(); //minimプログラムの停止
  super.stop(); //プログラムの停止
}

マウスクリックでサウンドを再生する

次にマウスをクリックすることでサウンドが再生されるプログラムを作成してみましょう。(新規でプログラムを作成する場合は、先ほどと同じようにあらかじめ音源データを追加しておきます。)

import ddf.minim.*;
 
Minim sound;
AudioPlayer player;
 
void setup(){
  size(100, 100);
  sound = new Minim(this);
  player = sound.loadFile("test.mp3");
}
 
void draw(){
  background(0);
}
 
void stop(){
  player.close();
  sound.stop();
  super.stop();
}
 
void mousePressed() { //マウスを押下したときに動作する関数
    player.play();
    player.rewind(); //サウンドデータの巻き戻し
}

音量の視覚化

サウンドの音量(ボリューム)とグラフィックスを関連づけてみましょう。

import ddf.minim.*;
 
Minim sound;
AudioPlayer player;
 
void setup(){
  size(400, 400);
  sound = new Minim(this);
  player = sound.loadFile("test.mp3");
}
 
void draw(){
  background(0);
  float d = player.mix.level() * 2000; //サウンドデータの音量を数値化して変数dに代入
  ellipse(width/2, height/2, d, d);
}
 
void stop(){
  player.close();
  sound.stop();
  super.stop();
}
 
void mousePressed() {
    player.play();
    player.rewind();
}

複数のサウンドを再生する

複数のサウンドをマウスクリックで再生するプログラムを作成します。2種類の音源(mp3データ)を用意して、それぞれ、test1.mp3、test2.mp3と名称変更します。2種類の音源データをprocessingに追加します。
準備ができたら、以下のコードを記述しましょう。

import ddf.minim.*;
 
Minim sound;
AudioPlayer player1, player2; //サウンドデータ格納用変数を2種類用意する
 
void setup(){
  size(800, 800);
  sound = new Minim(this);
 //下記で2種類のサウンドデータを読み込む
  player1 = sound.loadFile("test1.mp3"); 
  player2 = sound.loadFile("test2.mp3");
  fill(255); //オブジェクトの塗りの初期設定
}
 
void draw(){
  background(0);
  rect(50, 50, 100, 100);
  rect(200, 50, 100, 100);
  rect(350, 50, 100, 100);
  rect(500, 50, 100, 100);
  float d1 = player1.mix.level() * 2000;
  float d2 = player2.mix.level() * 2000;
  ellipse(width/2, height/2, d1, d1);
  ellipse(width/2, height/2, d2, d2);
}
 
void stop(){
  player1.close();
  player2.close();
  sound.stop();
  super.stop();
}

void mousePressed() {
 if (mouseX > 50 && mouseX < 150 && mouseY > 50 && mouseY < 150) { 
    player1.play(); 
    player1.rewind(); 
}
 if (mouseX > 200 && mouseX < 300 && mouseY > 50 && mouseY < 150) { 
    player1.pause(); 
    player1.rewind(); 
}
 if (mouseX > 350 && mouseX < 450 && mouseY > 50 && mouseY < 150) { 
    player2.play(); 
    player2.rewind(); 
}
 if (mouseX > 500 && mouseX < 600 && mouseY > 50 && mouseY < 150) {
    player2.pause();
    player2.rewind();
  }
}
 
void mouseReleased() {
  fill(255);
}
総合課題2:
上記のサウンド再生ソフトを改良し独自のデザインにする。
ただし以下の機能は全て必ず実装すること。
画面のサイズやボタンの配置は自由とする。
・サウンドデータを3種類以上用意し再生と停止ができるようにする。
・サウンドの音量で独自に用意した画像を変形させる。
・背景画像を用意し配置する。
・ボタンを画像に変更する。

2018プログラミング講座13:インターフェースデザイン

インターフェース(interface)とは英語で境界や界面を表す言葉です。この講座では、ユーザーインターフェースと呼ばれる、人間と機械の境界を取り扱います。お絵かきソフトのインターフェースデザインを通して、そのプログラミング手法を学んでいきましょう。

まず、はじめに作成するお絵かきソフトの画面サイズを決めます。ここでは800ピクセルx800ピクセルの画面で作成することにします。また背景色を白に設定します。

void setup(){
  size(800,800);//画面サイズ
 background(255);//背景色を白に設定
}

void draw(){
  
}

次に、幅20ピクセル・高さ20ピクセルの黒色の円がマウスの動きに付いてくるようにします。

int penX = 0;//円のX座標
int penY = 0;//円のY座標
int penSize = 20;//円の直径

void setup(){
  size(800,800);
  background(255);
}

void draw(){
  penX = mouseX;//円のX座標にマウスのX座標を代入
  penY = mouseY;//円のY座標にマウスのY座標を代入
  fill(0);//円の塗りを黒色にする
  noStroke();//円の輪郭線の描画を無効にする
  ellipse(penX,penY,penSize,penSize);//円の描画
}

円のサイズを変えるためのアイコンを配置します。アイコンが描線で隠れてしまわないようにアイコンの背景として長方形を配置します。

int penX = 0;
int penY = 0;
int penSize = 20;

void setup(){
  size(800,800);
  background(255);
}

void draw(){
  penX = mouseX;
  penY = mouseY;
  fill(0);
  noStroke();
  ellipse(penX,penY,penSize,penSize);
  fill(255);
  rect(0,700,800,100);//アイコンの背景
  fill(0);
  ellipse(50,750,20,20);//細い描線のアイコン
  ellipse(150,750,40,40);//太い描線のアイコン 
}

アイコンの上にマウスが重なると描線の太さが変わるように設定します。

int penX = 0;
int penY = 0;
int penSize = 20;

void setup(){
  size(800,800);
  background(255);
}

void draw(){
  penX = mouseX;
  penY = mouseY;
  fill(0);
  noStroke();
  ellipse(penX,penY,penSize,penSize);
  fill(255);
  rect(0,700,800,100);
  fill(0);
  ellipse(50,750,20,20);
  ellipse(150,750,40,40); 
  if(penX<60 && penY>740){ //小さい円のアイコンの座標にマウスが重なった場合
    penSize=20;
  }
  if(penX>60 && penX<170 && penY>740){ //太い円のアイコンの座標にマウスが重なった場合
    penSize=40;
  }
}

同じ手法を使って描線の色を変えてみましょう。

int penX = 0;
int penY = 0;
int penSize = 20;
int penR = 0;//描線の色・赤
int penG = 0;//描線の色・緑
int penB = 0;//描線の色・青


void setup(){
  size(800,800);
  background(255);
}

void draw(){
  penX = mouseX;
  penY = mouseY;
  fill(penR,penG,penB);
  noStroke();
  ellipse(penX,penY,penSize,penSize);
  fill(255);
  rect(0,700,800,100);
  fill(0);
  ellipse(50,750,20,20);
  ellipse(150,750,40,40);
  fill(255,0,0);
  ellipse(250,750,40,40);
  fill(0,255,0);
  ellipse(350,750,40,40);
  fill(0,0,255);
  ellipse(450,750,40,40);
  if(penX<60 && penY>740){
    penSize=20;
  }
  if(penX>60 && penX<170 && penY>740){
    penSize=40;
  }
  if(penX>230 && penX<270 && penY>740){ //アイコンに描線が重なったら描線の色を赤色に変更する
    penR = 255;
    penG = 0;
    penB = 0;
  }
  if(penX>330 && penX<370 && penY>740){ //アイコンに描線が重なったら描線の色を緑色に変更する
    penR = 0;
    penG = 255;
    penB = 0;
  }
  if(penX>430 && penX<470 && penY>740){ //アイコンに描線が重なったら描線の色を青色に変更する
    penR = 0;
    penG = 0;
    penB = 255;
  }
}

更に描線をline()関数を使用してスムーズにつなげてみましょう。1フレーム前のX座標、Y座標を格納するpmouseX、pmouseYという変数を使用します。

int penX = 0;
int penY = 0;
int penPX = 0;//pmouseXの値を格納する変数
int penPY = 0;//pmouseYの値を格納する変数
int penSize = 20;
int penR = 0;
int penG = 0;
int penB = 0;


void setup(){
  size(800,800);
  background(255);
}

void draw(){
  penX = mouseX;
  penY = mouseY;
  penPX = pmouseX; //1フレーム前のX座標を代入
  penPY = pmouseY; //1フレーム前のY座標を代入
  stroke(penR,penG,penB); //線の色を設定
  strokeWeight(penSize); //線の太さを設定
  line(penX,penY,penPX,penPY); //線を描画
  noStroke(); //以下のオブジェには線を描画しないよう設定
  fill(255);
  rect(0,700,800,100);
  fill(0);
  ellipse(50,750,20,20);
  ellipse(150,750,40,40);
  fill(255,0,0);
  ellipse(250,750,40,40);
  fill(0,255,0);
  ellipse(350,750,40,40);
  fill(0,0,255);
  ellipse(450,750,40,40);
  if(penX<60 && penY>740){
    penSize=20;
  }
  if(penX>60 && penX<170 && penY>740){
    penSize=40;
  }
  if(penX>230 && penX<270 && penY>740){
    penR = 255;
    penG = 0;
    penB = 0;
  }
  if(penX>330 && penX<370 && penY>740){
    penR = 0;
    penG = 255;
    penB = 0;
  }
  if(penX>430 && penX<470 && penY>740){
    penR = 0;
    penG = 0;
    penB = 255;
  }
}

次にマウスボタンが押されているときだけ、描線が描画されるように改良しましょう。

int penX = 0;
int penY = 0;
int penPX = 0;
int penPY = 0;
int penSize = 20;
int penR = 0;
int penG = 0;
int penB = 0;


void setup(){
  size(800,800);
  background(255);
}

void draw(){
  penX = mouseX;
  penY = mouseY;
  penPX = pmouseX;
  penPY = pmouseY;
  stroke(penR,penG,penB);
  strokeWeight(penSize);
  if(mousePressed){ //マウスボタンが押されている間だけコードが実行される
    line(penX,penY,penPX,penPY);
  }
  noStroke();
  fill(255);
  rect(0,700,800,100);
  fill(0);
  ellipse(50,750,20,20);
  ellipse(150,750,40,40);
  fill(255,0,0);
  ellipse(250,750,40,40);
  fill(0,255,0);
  ellipse(350,750,40,40);
  fill(0,0,255);
  ellipse(450,750,40,40);
  if(penX<60 && penY>740){
    penSize=20;
  }
  if(penX>60 && penX<170 && penY>740){
    penSize=40;
  }
  if(penX>230 && penX<270 && penY>740){
    penR = 255;
    penG = 0;
    penB = 0;
  }
  if(penX>330 && penX<370 && penY>740){
    penR = 0;
    penG = 255;
    penB = 0;
  }
  if(penX>430 && penX<470 && penY>740){
    penR = 0;
    penG = 0;
    penB = 255;
  }
}

最後に、キーボードの特定のボタンを押すと描線がリセットされるようにしましょう。keyPressedおよびkeyという関数を用いることで、キーボードが押されているかどうか、また、どのキーが押されているかをif文で判定するコードを書き加えます。

int penX = 0;
int penY = 0;
int penPX = 0;
int penPY = 0;
int penSize = 20;
int penR = 0;
int penG = 0;
int penB = 0;

void setup(){
  size(800,800);
  background(255);
}

void draw(){
  penX = mouseX;
  penY = mouseY;
  penPX = pmouseX;
  penPY = pmouseY;
  stroke(penR,penG,penB);
  strokeWeight(penSize);
  if(mousePressed){
    line(penX,penY,penPX,penPY);
  }
  noStroke();
  fill(255);
  rect(0,700,800,100);
  fill(0);
  ellipse(50,750,20,20);
  ellipse(150,750,40,40);
  fill(255,0,0);
  ellipse(250,750,40,40);
  fill(0,255,0);
  ellipse(350,750,40,40);
  fill(0,0,255);
  ellipse(450,750,40,40);
  if(penX<60 && penY>740){
    penSize=20;
  }
  if(penX>60 && penX<170 && penY>740){
    penSize=40;
  }
  if(penX>230 && penX<270 && penY>740){
    penR = 255;
    penG = 0;
    penB = 0;
  }
  if(penX>330 && penX<370 && penY>740){
    penR = 0;
    penG = 255;
    penB = 0;
  }
  if(penX>430 && penX<470 && penY>740){
    penR = 0;
    penG = 0;
    penB = 255;
  }
  if ((keyPressed == true) && ((key == 'd') ||  (key == 'D'))) {
    fill(255);
    noStroke();
    rect(0,0,800,700);
  }
}
総合課題1:
上記のお絵かきソフトを改良し独自のインターフェースデザインにリデザインする。
ただし以下の機能は全て必ず実装すること。
画面のサイズやアイコンの配置は自由とする。
・描画色を黒色に戻せるようにする。
・3段階以上の太さの描線で描画できるようにする。
・4色以上の色で描画できるようにする。
・消しゴム機能を追加する。

2018プログラミング講座 スケジュール

発表および提出までのスケジュールを記載します。

まず練習課題02〜12の制作をすすめてください。中間発表および疑問点や不明点解消のための制作日を設けますので、理解できていない点などをまとめておいてください。尚、練習課題4と5は連続した課題になっています(課題番号は練習課題04-05)。

11月12日以降は総合課題として、より複雑な制作に挑んでもらいます。練習課題で取り上げた技術がベースになりますので、ここまでの内容について理解を深めておくようにしてください。

05: 10/22 〜練習と練習課題
06: 11/05 練習課題確認(中間発表と制作)
07: 11/12 総合課題1:お絵かきソフトのインターフェースデザイン
08: 11/19 制作
09: 11/26 総合課題2:サウンドのビジュアライズ
10: 12/03 制作
11: 12/10 総合課題3:パーティクル
12: 12/17 制作
13: 12/24 総合課題4:ジェネラティブデザイン
14: 01/07 制作
15: 01/21 発表(練習課題02〜12、総合課題1〜4)

課題提出:1月30日(水)まで

提出方法:共有フォルダに提出(詳細は授業内で告知します)

評価:
練習課題02〜12 各2点(04-05は10点)計22点(提出された作品の動作が確認できることが条件)
総合課題01〜04 各5点 計20点(提出された作品の動作が確認できることが条件)
発表点 18点(疾病や怪我、交通機関の遅延などの場合は証明書類の提出をもって試験期間内などに発表日を変更できる)
提出点(各課題の完成度や創意工夫などを評価)40点
合計100点

2018プログラミング講座12:移動、回転、伸縮

Processingで描画することができるオブジェクトにはそれぞれ座標が存在します。Processingの実行ウィンドウの座標(グローバル座標)は常に左上が座標の原点になりますが、個々のオブジェクトの座標(ローカル座標)は移動、回転、伸縮することができます。

座標の移動
それでは、まず座標の移動について解説します。はじめに座標の移動を実行せずに図形を描画します。

void setup(){
  size(400,400);
}

void draw(){
  rect(0,0,50,50);
}

このプログラムでは図形(正方形)の原点(図形の左上)をX座標=0,Y座標=0(以下(0,0)と記述)としているため、実行ウィンドウの左上から描画されています。

次に図形(正方形)のローカル座標をtranslate()関数を使って移動させてみましょう。

void setup(){
  size(400,400);
}

void draw(){
  translate(200,200);
  rect(0,0,50,50);
}

上のコードでは図形(正方形)の座標は(0,0)であるにも関わらず、実際に図形が描画される位置はtranslate()関数によって実行ウィンドウ上の(200,200)の位置に移動しています。

更に、複数のtranslate()関数を使った例を見てみましょう。

void setup(){
  size(400,400);
}

void draw(){
  background(0);
  translate(mouseX,mouseY);
  rect(0,0,50,50);
  translate(50,50);
  rect(0,0,25,25);
}

上のコードでは、複数のtranslate()関数の効果が合成されることが確かめられます。

座標の回転
図形のローカル座標を回転させるためにはrotate()関数を使用します。rotate()関数のパラメータは1つだけで、回転角(ラジアン)を指定します。
それでは、図形の座標を回転させてみましょう。

void setup(){
  size(160,160);
}

void draw(){
  background(0);
  rotate(mouseX/100.0);
  rect(0,0,160,20);
}

上のコードではrotate()関数を使って図形を回転しています。回転角(ラジアン)は0〜360度までを0〜約6.28の数値で表します。このコードではX座標を100.0で割ることで回転角(ラジアン)に変換しています。

座標の伸縮
座標を伸縮させるには、scale()関数を使用します。scale(2)とすると画面内の図形はすべて2倍の大きさになります。scale(0.5)とすると、図形はすべて半分の大きさになります。
それでは、以下のコードで確認してみましょう。

void setup(){
  size(400,400);
}

void draw(){
  rect(0,0,100,100);
  scale(0.5);
  rect(0,200,100,100);
  scale(4);
  rect(0,100,100,100);
}

座標の復元
座標系の変換(移動、回転、伸縮)は、変換後のすべてのコードに影響を及ぼしますが、その影響の範囲を限定し、変換以前の状態に復元することができます。pushMatrix()関数とpopMatrix()関数を使うことで変換した座標の復元ができます。pushMatrix()関数を実行すると、それ以降に記述した座標系変換の情報が記録され、popMatrix()が使われると変換前の座標系に戻ります。pushMatrix()関数とpopMatrix()関数は常にペアで使う必要があります。
それでは、以下のコードを使って確認してみましょう。

void setup(){
  size(400,400);
}

void draw(){
  background(0);
  pushMatrix();
  translate(mouseX,mouseY);
  ellipse(0,0,50,50);
  popMatrix();
  ellipse(200,200,200,200);
}

上のコードでは1つめの図形(円)の座標系の移動をマウスの座標に合わせていますが、pushMatrix()関数とpopMatrix()関数を使って、座標系の移動が復元されるため、2つめの円は座標系の移動の影響を受けません。

練習課題12:
以下の条件を全て満たす作品を作成してください。
・固定された座標を持つ図形が表示されていること。
・マウスの動きによって変化する図形が表示されること。
・マウスの動きによって色(背景色や図形の色)が変化すること。

2018プログラミング講座11:動き

Processingを使った動きの表現を学んで行きましょう。

図形の水平移動
図形を水平移動させます。以下のコードを記述してみましょう。

float speed = 0.5;
float x = 0;

void setup(){
  size(400,200);
}

void draw(){
  background(0);
  x += speed;
  ellipse(x,100,40,40);
}

このコードで変数宣言に使ったデータ型である float 型は小数点を持つ数値を扱うことができるため細かな動きが表現できます。

フレーム
Processingはdraw()関数内に記述されたコードを毎秒60回実行しています。Processingのコードを実行すると表示されるウィンドウの画面は毎秒60回、更新されているということになります。この更新される画面の1枚(1コマ)をフレームと呼びます。
また1秒間に何回フレームを更新するかはフレームレートで表します。標準(デフォルト)のフレームレートが毎秒60回となります。

それでは、以下のコードでフレームレートを変更してみましょう。

float speed = 0.5;
float x = 0;

void setup(){
  size(400,200);
  frameRate(30);//フレームレート関数
}

void draw(){
  background(0);
  x += speed;
  ellipse(x,100,40,40);
}

上記のコードのframeRate()関数の数値を色々と変更してみましょう。

画面から出ていった図形が反対から入ってくる
上のコードでは画面の右端から図形が出て行ったら、それっきり戻ってくることはありません。コードを改良して右端から出ていった図形が左端から入ってくるように変更してみましょう。

float speed = 0.5;
float x = 0;

void setup(){
  size(400,200);
}

void draw(){
  background(0);
  x += speed;
  if(x>400){
    x = 0;
  }
  ellipse(x,100,40,40);
}

このコードでは、先ほどのコードに加えてif文を使ってxの値が画面サイズの幅(この例では400)より大きくなった場合に、xの座標を0に戻すことで、右端から出ていった図形が左端から入ってくるように処理しています。

図形の跳ね返り1
次のコードでは図形が右端まで行ったら、まるで壁に当たって跳ね返ったかのように左に戻るというように変更してみましょう。

float speed = 0.5;
float x = 100;
int direction = 1;

void setup(){
  size(400,200);
}

void draw(){
  background(0);
  x += speed*direction;
  if((x>400-20)||(x<0+20)){
    direction = -direction;
  }
  ellipse(x,100,40,40);
}

上のコードでは direction という変数を使って、図形のx座標の位置が画面の幅より大きい場合と小さい場合に direction の符号を反転させて図形の進行方向を変えています。

図形の跳ね返り2
次のコードでは斜め方向に図形が移動し、壁に跳ね返って戻るという表現を実装してみましょう。

float xpos = 100;
float ypos = 100; 
float xspeed = 0.5;
float yspeed = 1;
int xdirection = 1;
int ydirection = 1;

void setup() 
{
 size(400, 400);
}

void draw() 
{
 background(0);
 xpos = xpos + ( xspeed * xdirection );
 ypos = ypos + ( yspeed * ydirection );
 if ((xpos > 400-20) || (xpos < 0+20)) {
 xdirection *= -1;
 }
 if ((ypos > 400-20) || (ypos < 0+20)) {
 ydirection *= -1;
 }
 ellipse(xpos, ypos, 40, 40);
}

上のコードでは、先ほどのコードに加え、x座標、y座標それぞれの進行方向に対して壁に当たると符号が反転し逆方向に進行する表現を実装しています。

練習課題11:
図形の跳ね返り2のコードをもとに以下の変更を加えて作品を完成させましょう。
・移動するオブジェのスピードや角度を変更する。
・移動するオブジェを円から画像に変更する。

2018プログラミング講座10:フォント

Processingでは各種フォントを読み込んで扱うことができます。

フォントを使う
TrueTypeフォントをdataフォルダに格納して使用する方法を学びましょう。はじめにProcessingの新規スケッチ(sketch_)を開きます。「ツール(Tools)」メニューより「フォントを作成…(Create Font…)」を選択すると、下のようなウィンドウが開きます。

フォント作成ウィンドウの中のフォント一覧から使用したいフォントを選択し、サイズを選び(48ポイントより大きい場合に設定すると良い)、プレビューで確認したら「OK」ボタンを押します。「スケッチ(Sketch)」メニューの「スケッチフォルダーを開く(Show Sketch Folder)」を実行し、dataフォルダの中に作成したフォントデータが格納されているか確認しておきましょう。以下のプログラムでは Helvetica-Bold-48.vlw という名称のフォントを使用します。

それではProcessingでフォントを表示するプログラムを記述してみましょう。

PFont font;

void setup(){
  size(800,400);
  font = loadFont("Helvetica-Bold-48.vlw");
}

void draw(){
  background(0);
  textFont(font,32);
  text("Good!",20,200);
}

まず、PFont変数を作成します。この例では font という変数名にしました。loadFont()関数を使用して、変数 font に作成したフォント Helvetica-Bold-48.vlw を格納します。textFont()関数を使用してフォントの表示サイズを決めます。text() 関数を使用して表示するテキスト(文書)と座標を指示します。

それでは、フォントを使った別のプログラムを記述してみましょう。新たにフォント作成ウィンドウでHelveticaNeue-Bold-48.vlwというフォントを作成してから以下のプログラミングを記述しましょう。

float x1,x2,x3,x4,x5;
float y1,y2,y3,y4,y5;
float easing1 = 0.1;
float easing2 = 0.2;
float easing3 = 0.3;
float easing4 = 0.4;
float easing5 = 0.5;

PFont font;

void setup(){
size(800,400);
font = loadFont("HelveticaNeue-Bold-48.vlw");
}

void draw(){
background(0);
float targetX = mouseX;
float targetY = mouseY;
x1 += (targetX - x1)*easing1;
x2 += (targetX - x2)*easing2;
x3 += (targetX - x3)*easing3;
x4 += (targetX - x4)*easing4;
x5 += (targetX - x5)*easing5;
y1 += (targetY - y1)*easing1;
y2 += (targetY - y2)*easing2;
y3 += (targetY - y3)*easing3;
y4 += (targetY - y4)*easing4;
y5 += (targetY - y5)*easing5;
textFont(font,32);
text("G",x1,y1);
text("o",x2+40,y2);
text("o",x3+80,y3);
text("d",x4+120,y4);
text("!",x5+160,y5);
}
練習課題10:
画像とフォントを組み合わせたプログラムを作成してください。
これまでに学んだ内容を自由に組み合わせて作成してください。

2018プログラミング講座9:画像

Processingでは他のソフトウェアなどで作成した画像を扱うことができます。

画像ファイルの読み込み
まず始めにProcessingで使用したい画像ファイルを用意します。次にProcessingを開き、新しいスケッチ(sketch_)を表示します。Processingの「スケッチ(Sketch)」メニューから「ファイルを追加…(Add File…)」を選び実行します。使用したい画像ファイルを選択し「開く(Open)」ボタンを押して読み込みます。
追加した画像ファイルは「スケッチ(Sketch)」メニューの「スケッチフォルダーを開く(Show Sketch Folder)」を実行し、dataフォルダの内容を確認すると見つかります。このdataフォルダに格納された画像ファイルをProcessingのプログラムで使用します。Processingでは、ひとつのdataフォルダに複数の画像ファイルを格納して使用します。

画像ファイルの表示
画像ファイルをProcessingのプログラムで使用してみましょう。画像ファイルは、ここでは仮に XXXX.jpg という名称のJPEGデータとします。

PImage img;

void setup(){
  size(800,800);
  img = loadImage("XXXX.jpg");
}

void draw(){
  image(img,0,0);
}

上記のプログラムでは、始めにPImage変数を作成し、img と名付けます。変数 img にloadImage()関数を使って画像ファイル XXXX.jpg(XXXXは任意の名称を各自で入力してください)を格納します。画像ファイル XXXX.jpg を格納した変数 img をimage()関数を使って表示します。image(img,0,0) 内の数値は画像ファイルの座標を表します。

複数の画像ファイルを表示する
複数の画像ファイルを表示する際のプログラム例を以下に記述します。画像ファイルは、ここでは仮に XXXX_1.jpg, XXXX_2.jpg という名称の2種類のJPEGデータとします。

PImage img1;
PImage img2;

void setup(){
  size(800,800);
  img1 = loadImage("XXXX_1.jpg");
  img2 = loadImage("XXXX_2.jpg");
}

void draw(){
  image(img1,0,0,800,800);
  image(img2,mouseX,mouseY,40,40);
}

上記のプログラムでは、image(img1,0,0,800,800) のように記述することで画像ファイルの表示サイズをプログラムで変更しています。image()関数の各パラメータは以下のようになります。

image(画像を格納した変数, x座標, y座標, 幅, 高さ)

扱える画像フォーマット
Processingで扱うことのできるラスタ画像のファイルフォーマットは、JPEG、PNG、GIF になります。
ラスタ画像とは色のついた点(ドット)の集合として画像を表現するデータ形式のことです。もとの画像サイズより拡大するとジャギー(ギザギザ)が目立つようになるなど、拡大、縮小、変形には適さない形式ですが、写真などの複雑な画像の表現に適しています。

練習課題:
PNGデータを使用し背景を透明化した画像データを作成する。
作成した画像データを使用して、画像データがマウスカーソルの動きに追従する作品を作成してください。

2018プログラミング講座8:繰り返し構造

繰り返し構造について
プログラムでは繰り返しの構造を使うことで、ひとまとまりのコードを繰り返し実行することができます。繰り返しの構造を使うことで複雑な構造のプログラムを短いコードにできたり、プログラムにパターンを生み出すことなどができます。

forループ文
繰り返し構造を記述するコードとしてforループ文を使ったプログラムを作成してみましょう。
forループ文は以下のように記述します。

for(初期値; 条件式; 更新){
繰り返し実行されるコード
}

例)
for(i = 0; i < 100; i+=10){  繰り返し実行されるコード } ・「初期値」で最初の値を設定します。  forループ文では慣例的に変数 i が使われることが多い。 ・「条件式」で変数 i を評価します。  変数 i の値を比べて条件にあわなくなるまで「繰り返し実行されるコード」を実行する。  i > A Aより大きい
i < A Aより小さい  i >= A A以上
i <= A A以下
i == A Aと等しい
i != A Aと等しくない
・「更新」で変数 i の値をどのように変化させるかを設定します。
i+=10ならコードが実行されるごとに変数 i に10加算
i-=10なら10減算
i++は1加算
i–は1減算。

それでは、forループ文を使った繰り返し構造のプログラムを記述してみましょう。

void setup(){
  size(400,200);
}

void draw(){
  for(int i = 20; i < 400; i += 20){
    ellipse(i,100,20,20);
  }
}

 

二重の繰り返し構造
forループ文のなかにforループ文を記述することができます。
それでは、二重の繰り返し構造のプログラムを記述してみましょう。

void setup(){
  size(400,400);
  background(0);
  noStroke();
}

void draw(){
  for(int i = 0; i <= 400; i += 20){
    for(int j = 0; j <= 400; j += 20){
      fill(255,48,203);
      ellipse(i,j,15,15);
   }
  }
}

 

二重の繰り返し構造を使った別のプログラムを記述してみましょう。

void setup(){
  size(400,400);
}

void draw(){
  background(0);
  fill(252,145,3);
  stroke(250,240,48);
  for(int i = 0; i <= 400; i += 20){
    for(int j = 0; j <= 400; j += 20){
      ellipse(i,j,10,10);
      line(i,j,mouseX,mouseY);
   }
  }
}

 

練習課題08:これまでに学んだ、点、線、面および色のコードと繰り返しの構造を組み合わせてグラフィック作品を作成してください。

2018プログラミング講座7:ストラクチャー(構造)

Processingにおいて時間の経過とともに変化するグラフィックスを作成する場合には、Processingのストラクチャーを学び、効果的に利用することが必要になります。

それでは、まず以下のコードを記述してみましょう。

int x = 10;
int y = 10;
int w = 20;
int h = 20;

void setup(){
  size(400,400);
}

void draw(){
  ellipse(x+frameCount, y+frameCount, 20, 20);
}

記述したコードを実行してみましょう。
以下のように円が対角線上を移動するグラフィックスが表示されます。

このコードをもとにprocessingのストラクチャーについて学んでいきましょう。

このプログラムは以下の3つの部位で成り立っています。

1)グローバル変数の宣言と初期化
グローバル変数とは以下に説明する関数(setup関数とdraw関数)などから参照することができる変数の一種です。

int x = 10;
int y = 10;
int w = 20;
int h = 20;

2)setup関数
各種初期化で行う処理部分。アプリケーションが実行され、ウィンドウが開いたとき、最初に1度だけ実行されます。
setup関数では、画面(ウィンドウ)のサイズを決定するsize関数などの記述を行います。

void setup() {

// 一度だけ実行される処理

}

3)draw関数
アプリケーションが実行中に繰り返し実行し続ける処理部分。draw関数内に記述されたコードが終了するたびに新しいフレームがディスプレイ・ウィンドウに描画されコードが実行され続ける。
デフォルトの描画速度は1秒あたり60フレーム( 1秒あたりのフレーム数はframeRate関数を使って変更することができる)。

void draw() {

// 繰り返し実行される処理

}

練習課題07:
上のコードの記述を変更して、様々なプログラムを作ってみましょう。
例)
・円が水平または垂直に移動するプログラム。
・円の大きさが変化するプログラム。

2018プログラミング講座6:変数

変数について
変数とは、ある値をコンピュータのメモリに保存しておき、プログラムのなかで再利用できるようにするための仕組みです。

変数の作成
変数を作成するには、データ型、変数の名前、変数の値を考えて設定します。
変数を使う前には必ず変数の宣言をします。宣言とは、コンピュータのメモリにデータの値を格納する領域を確保することです。
変数の宣言をするためには格納する値にあったデータ型を定義し、名前を決めて値を設定します。

変数の宣言は以下のように記述します。

データ型 変数の名前 = 値;

例)
int x = 10;

上の例は以下のように記述することができます。

int x;
x = 10;

ある変数に格納できる値や種類はデータ型で指定します。データ型には以下のようなものがあります。
・整数(小数点以下のない数値を扱うデータ型 マイナスの値をとることができる)
・浮動小数点(小数点を扱えるデータ型)
・文字
・単語
・画像
・フォント など

変数には任意の名前を付けて設定をします。データの内容がわかりやすい名前を選んで設定しましょう。

変数を使った描画
それでは、変数を使って基本図形を描画してみましょう。

int d = 100; //変数の宣言
size(400,400);
ellipse(100,200,d,d);
ellipse(200,200,d,d);
ellipse(300,200,d,d);

上の例では1行目の int d = 100; にて変数の宣言が行われています。
int で整数のデータ型を定義し、変数の名前を d とし、変数 d に 100 という整数の値を代入しています。
変数を使うことで3つの円が同じ値を受け取ることができます。

練習課題06:変数を2つ作成し、x座標とy座標に変数を使用した4つの方形を描いてみましょう。