Home> 2010-bアーカイブ
2010-bの最近のブログ記事
b-14 課題提出、プレゼンテーションについて
- 2011年1月17日 14:40
- 2010-b
課題の提出方法
前期とほぼ同様にして2つのファイルを提出する。
提出ファイルその1: ソースコード(プログラム)
前期と全く同じ。
提出ファイルその2: 作品の画像ファイル
画像の保存法が前期と異なるので注意。
ソースコードの最終行に
void keyPressed() {
save("学籍番号.png");
}
を追加する(ただし、keyPressed関数をすでに用いている場合は、keyPressed関数の最終行にsave関数を記述する)。
実行後、何かキーボードを押すと画像が作成されるので、ベストショットを保存する。以降、前期と同じ。
プレゼンテーション
- 持ち時間は2分間(長すぎず短すぎず適切に収まるようリハーサルをすること)
- 発表内容は「時計/時間をどのように解釈したか」「それを表現するために自分なりに工夫した点」など
- プレゼンテーションも評価の対象となる
- Comments (Close): 0
- TrackBack (Close): 0
b-10 音を出す
- 2010年11月29日 14:40
- 2010-b
Processing で音を扱う場合は、ライブラリを利用する。今回は標準で用意されている Minim を利用する。
※そのほかのサウンド系ライブラリ: SoundCipher
一般的な音楽ファイルを再生する
ミュージシャンの楽曲のような、一般的な音楽ファイル(再生時間が長い→ファイル容量が大きい)ものは AudioPlayer クラスを利用する。
利用した音楽ファイル: ccMixter - Wataridori 2 - Cornelius
import ddf.minim.*;
Minim minim;
AudioPlayer player;
void setup() {
minim = new Minim(this);
player = minim.loadFile("http://ccmixter.org/contests/freestylemix/Cornelius%20-%20Wataridori%202.mp3", 2048);
player.play(); //再生
}
void draw() {
}
void stop() {
player.close();
minim.stop();
super.stop();
}
mp3ファイルのメタ情報を表示する
import ddf.minim.*;
Minim minim;
AudioPlayer player;
AudioMetaData meta;
void setup() {
minim = new Minim(this);
player = minim.loadFile("http://ccmixter.org/contests/freestylemix/Cornelius%20-%20Wataridori%202.mp3", 2048);
player.play(); //再生
meta = player.getMetaData();
//コンソールに音声データのメタ情報を表示
println("アルバム名: " + meta.album());
println("曲名: " + meta.title());
println("アーティスト名: " + meta.author());
}
void draw() {
}
void stop() {
player.close();
minim.stop();
super.stop();
}
※そのほかAudioPlayer にできることはリファレンスを参照 → AudioPlayer
練習
- マウスをクリックすると一時停止する
サンプルファイルを再生する
各種ドラム音のような、サンプルファイルは AudioSample クラスを利用する。
import ddf.minim.*;
Minim minim;
AudioSample kick;
AudioSample snare;
void setup() {
minim = new Minim(this);
kick = minim.loadSample("kick.wav", 2048);
snare = minim.loadSample("snare.wav", 2048);
}
void draw() {
}
void keyPressed() {
if (key == 'k') kick.trigger();
if (key == 's') snare.trigger();
}
void stop() {
kick.close();
snare.close();
minim.stop();
super.stop();
}
サイン波を生成し、マウス位置に応じて音程・パンを調整する
import ddf.minim.*;
import ddf.minim.signals.*;
Minim minim;
AudioOutput out;
SineWave sine;
void setup() {
minim = new Minim(this);
out = minim.getLineOut(Minim.STEREO);
sine = new SineWave(440, 0.5, out.sampleRate());
sine.portamento(200);
out.addSignal(sine);
}
void draw() {
}
void mouseMoved() {
float freq = map(mouseY, 0, height, 1500, 60);
sine.setFreq(freq);
float pan = map(mouseX, 0, width, -1, 1);
sine.setPan(pan);
}
void stop() {
out.close();
minim.stop();
super.stop();
}
Gainer を利用し、赤外線センサーで測定した距離を音程に変換する
上記のコードを改変し、Gainer を利用したテルミンのような楽器をつくる。
import ddf.minim.*;
import ddf.minim.signals.*;
import processing.gainer.*;
Minim minim;
AudioOutput out;
SineWave sine;
Gainer gainer;
void setup() {
minim = new Minim(this);
out = minim.getLineOut(Minim.STEREO);
sine = new SineWave(440, 0.5, out.sampleRate());
sine.portamento(200);
out.addSignal(sine);
gainer = new Gainer(this);
gainer.beginAnalogInput();
}
void draw() {
int analogInput = gainer.analogInput[0];
println(analogInput);
background(204);
ellipse(width/2, height/2, analogInput, analogInput);
float freq = map(analogInput, 0, 180, 0, 3600);
sine.setFreq(freq);
}
void stop() {
out.close();
minim.stop();
super.stop();
}
- Comments (Close): 0
- TrackBack (Close): 0
b-09 オブジェクト指向プログラミング (OOP)
- 2010年11月22日 14:40
- 2010-b
オブジェクト指向プログラミングとは? → オブジェクト指向プログラミング - Wikipedia
オブジェクト指向プログラミングでプログラムを書く
円を描くプログラムを、オブジェクト指向プログラミングで書いてみる。
step. 0 これまでの書き方
float x, y, diameter; // x座標, y座標, 直径
void setup() {
x = 25;
y = 50;
diameter = 30;
}
void draw() {
ellipse(x, y, diameter, diameter);
}
step. 1 クラスを定義する
Spot sp; //オブジェクトを宣言
void setup() {
sp = new Spot(); //オブジェクトを生成(構築)
sp.x = 25; //属性(プロパティ)に値を代入。以下同様
sp.y = 50;
sp.diameter = 30;
}
void draw() {
ellipse(sp.x, sp.y, sp.diameter, sp.diameter);
}
//Spotクラスを定義
class Spot {
//属性を定義
float x, y, diameter; // x座標, y座標, 直径
}
※「Spot」は、関数を自分で定義したときのように、適切な名前を考えて付ける。その属性も同様。
step. 2 クラスにメソッド(method)の定義を追加する
Spot sp; //オブジェクトを宣言
void setup() {
sp = new Spot(); //オブジェクトを生成(構築)
sp.x = 25; //属性(プロパティ)に値を代入。以下同様
sp.y = 50;
sp.diameter = 30;
}
void draw() {
sp.display();
}
//Spotクラスを定義
class Spot {
//属性を定義
float x, y, diameter; // x座標, y座標, 直径
//表示するメソッドを定義
void display() {
ellipse(x, y, diameter, diameter);
}
}
step. 3 クラスにコンストラクタ(constructor)の定義を追加する
Spot sp; //オブジェクトを宣言
void setup() {
sp = new Spot(25, 50, 30); //オブジェクトを生成(構築)
}
void draw() {
sp.display();
}
//Spotクラスを定義
class Spot {
//属性を定義
float x, y, diameter; // x座標, y座標, 直径
//コンストラクタを定義
Spot(float _x, float _y, float _diameter) {
x = _x;
y = _y;
diameter = _diameter;
}
//表示するメソッドを定義
void display() {
ellipse(x, y, diameter, diameter);
}
}
step. 4 クラスに移動のメソッドを追加し、アニメーションにする
Spot sp; //オブジェクトを宣言
void setup() {
sp = new Spot(25, 50, 30, 1); //オブジェクトを生成(構築)
}
void draw() {
background(204);
sp.move();
sp.display();
}
//Spotクラスを定義
class Spot {
//属性を定義
float x, y, diameter, speed; // x座標, y座標, 直径, 速さ
//コンストラクタを定義
Spot(float _x, float _y, float _diameter, float _speed) {
x = _x;
y = _y;
diameter = _diameter;
speed = _speed;
}
//移動するメソッドを定義
void move() {
x += speed;
if (x > width + diameter/2) x = -diameter/2;
}
//表示するメソッドを定義
void display() {
ellipse(x, y, diameter, diameter);
}
}
クラス定義を別ファイルで管理する
※以降、Spot.pde ファイルの内容は同じなので省略する
異なる属性を持つ複数のオブジェクトを生成(インスタンス化)する
2個
Spot sp1, sp2; //オブジェクトを宣言
void setup() {
sp1 = new Spot(25, 50, 30, 1); //sp1 を生成
sp2 = new Spot(75, 80, 10, 2); //sp2 を生成
}
void draw() {
background(204);
sp1.move();
sp2.move();
sp1.display();
sp2.display();
}
60個(配列を使って)
Spot[] sp = new Spot[60];
void setup() {
for (int i = 0; i < sp.length; i++) {
sp[i] = new Spot(random(width), random(height), random(5,30), random(0.5,3));
}
}
void draw() {
background(204);
for (int i = 0; i < sp.length; i++) {
sp[i].move();
sp[i].display();
}
}
クラスを継承し、拡張された属性または機能を拡張した子クラスを定義する
Spot クラスを継承し、色を指定できる ColorSpot クラスを定義する
ColorSpot[] sp = new ColorSpot[60];
void setup() {
colorMode(HSB);
for (int i = 0; i < sp.length; i++) {
sp[i] = new ColorSpot(
random(width),
random(height),
random(5,30),
random(0.5,3),
color(random(255), 255, 255)
);
}
}
void draw() {
background(204);
for (int i = 0; i < sp.length; i++) {
sp[i].move();
sp[i].display();
}
}
ColorSpot.pde
//Spotクラスを継承し、ColorSpotクラスを定義
class ColorSpot extends Spot {
//属性を定義
color col; // 色
//コンストラクタを定義
ColorSpot(float _x, float _y, float _diameter, float _speed, color _col) {
super(_x, _y, _diameter, _speed); //親クラス(Spot)のコンストラクタを呼びだす
col = _col;
}
//移動するメソッドを定義
void move() {
super.move(); //親クラス(Spot)のメソッドを呼びだす
}
//表示するメソッドを定義
void display() {
fill(col);
super.display();
}
}
Spot.pde
//Spotクラスを定義
class Spot {
//属性を定義
float x, y, diameter, speed; // x座標, y座標, 直径, 速さ
//コンストラクタを定義
Spot(float _x, float _y, float _diameter, float _speed) {
x = _x;
y = _y;
diameter = _diameter;
speed = _speed;
}
//移動するメソッドを定義
void move() {
x += speed;
if (x > width + diameter/2) x = -diameter/2;
}
//表示するメソッドを定義
void display() {
ellipse(x, y, diameter, diameter);
}
}
シンプルな時計をOOPでつくる
- Comments (Close): 0
- TrackBack (Close): 0
b-08 ライブカメラを使う
- 2010年11月15日 14:40
- 2010-b
Processing でビデオ映像を扱う場合は、ライブラリを利用する。今回は標準で用意されている Video ライブラリを利用する。
ライブカメラの映像を表示する
そのまま表示する
import processing.video.*; // Videoを扱うライブラリをインポート
Capture camera; // ライブカメラの映像をあつかうCaptureの変数
void setup() {
size(480, 320);
camera = new Capture(this, width, height, 12); // Captureオブジェクトを生成
}
void draw() {
image(camera, 0, 0); // 画面に表示
}
//カメラの映像が更新されるたびに、最新の映像を読み込む
void captureEvent(Capture camera) {
camera.read();
}
同じ映像を4分割で表示する
import processing.video.*;
Capture camera;
void setup() {
size(480, 320);
camera = new Capture(this, width/2, height/2, 12); // 1/2サイズでCaptureオブジェクトを生成
}
void draw() {
image(camera, 0, 0); // 画面に表示
image(camera, width/2, 0); // 画面に表示
image(camera, 0, height/2); // 画面に表示
image(camera, width/2, height/2); // 画面に表示
}
void captureEvent(Capture camera) {
camera.read();
}
以下のようにしても同じ結果を得るが、計算の負荷が高くなる
import processing.video.*;
Capture camera;
void setup() {
size(480, 320);
camera = new Capture(this, width, height, 12);
}
void draw() {
image(camera, 0, 0, width/2, height/2); // 画面に表示 左上に1/2サイズで
image(camera, width/2, 0, width/2, height/2); // 画面に表示 右上に1/2サイズで
image(camera, 0, height/2, width/2, height/2); // 画面に表示 左下に1/2サイズで
image(camera, width/2, height/2, width/2, height/2); // 画面に表示 右下に1/2サイズで
}
void captureEvent(Capture camera) {
camera.read();
}
一般化して n*n 分割で表示する
import processing.video.*;
Capture camera;
int d = 4; //画面を4*4で分割する
void setup() {
size(480, 320);
camera = new Capture(this, width/d, height/d, 12);
}
void draw() {
for (int j = 0; j < d ; j++) {
for (int i = 0; i < d ; i++) {
image(camera, i*width/d, j*height/d);
}
}
}
void captureEvent(Capture camera) {
camera.read();
}
色情報を取得して再描画する
import processing.video.*;
Capture camera;
void setup() {
size(480, 320);
camera = new Capture(this, width, height, 12);
smooth();
noStroke();
}
void draw() {
background(0);
camera.loadPixels(); //カメラ画像のpixel情報を読み込み
int d = 10; //円の直径を定義
// ライブカメラの映像から、円の直径の間隔ごとに、色情報を取得し、その色で円を描く
for(int y = d / 2 ; y < height ; y += d) {
for(int x = d / 2 ; x < width ; x += d) {
fill(camera.pixels[y * width + x]);
ellipse(x, y, d, d);
}
}
}
void captureEvent(Capture camera) {
camera.read();
}
練習
- 円の大きさをランダムにしてみる
- 色情報を加工してみる
参考:OpenCV(画像処理ライブラリ)を使う
準備:OpenCVのインストール
- OPENCV \ library
- OpenCVのインストール
- OpenCVの Processing ライブラリを、書類 > Processing > libraries 内に配置
※Mac室では、インストールの権限制限があり、みなさん自身ではインストールができません。利用したい場合は事前に相談ください。
そのまま表示する
import hypermedia.video.*; //OpenCVライブラリをインポート
OpenCV opencv; //OpenCV型の変数
void setup() {
size(480, 320);
opencv = new OpenCV(this);
opencv.capture(width, height); ////映像読み込みの初期化
}
void draw() {
opencv.read(); //映像を読み込む
image(opencv.image(), 0, 0); //映像を表示
}
- videoライブラリを使用するときよりも、コードがシンプルになる
加工して表示する
import hypermedia.video.*;
OpenCV opencv;
void setup() {
size(480, 320);
opencv = new OpenCV(this);
opencv.capture(width/2, height/2);
}
void draw() {
opencv.read();
//左上
opencv.convert(OpenCV.GRAY); //グレースケールに変換
image(opencv.image(), 0, 0); //画面に表示 左上
//右上
opencv.invert(); //色を反転
image(opencv.image(), width/2, 0); // 画面に表示 右上
//左下
opencv.restore(); //オリジナルの映像に戻す
opencv.flip(OpenCV.FLIP_HORIZONTAL); //映像を水平方向に反転する
image(opencv.image(), 0, height/2); // 画面に表示 左下
//右下
image(opencv.image(OpenCV.SOURCE), width/2, height/2); // 画面に表示 オリジナルの映像 右下
}
そのほかOpenCVでできること
- Comments (Close): 0
- TrackBack (Close): 0
b-07 ピクセルを操作する
- 2010年11月 8日 14:40
- 2010-b
pixels[] pixels 配列
- 画面全体またはPImageオブジェクトを1次元の配列として表したもの
- color型の配列
- (x, y)の情報は pixels[y*width + x] で得られる ※下で具体的に解説
- loadPixels() pixelsを読み込み
- updatePixels() pixelsの更新
- 幅10ピクセル、高さ4ピクセルの画面には、40個の点がある。
- 左上から図のように、0から39の番号を割り振りふる。これらが pixels 配列のインデックス(番号)と一致する。
- 幅7ピクエル、高さ4ピクセルの画面には、28個の点がある。
- 点(5, 2) の情報は pixels[19] で得ることができる。この19という数は2*7+5(y座標*幅+x座標)で得られる。
- 幅100ピクセル、高さ100ピクセルの画面には、10,000個の点がある。
- 幅480ピクセル、高さ320ピクセルの画面には、153,600個の点がある。
- これらの膨大な数の点の色情報を扱えるようにするのが pixels 配列である。
例1 カラーピッカー(画面の色を調べる)
PImage myPhoto;
void setup() {
size(480, 320);
myPhoto = loadImage("http://farm3.static.flickr.com/2590/4180018215_c756b6b601.jpg"); // 画像を読み込む
}
void draw() {
image(myPhoto, 0, 0);
loadPixels(); //画面全体の画像を pixels を読み込む
int x = mouseX;
int y = mouseY;
fill(pixels[y*width + x]); //画面の点(x,y)の色情報を取得し、塗り色に設定
rect(20, 20, 60, 60);
}
例2 画像の色を調べて、その一部を画面に表示する
PImage myPhoto;
int myPhotoWidth, myPhotoHeight;
void setup() {
size(480, 320);
myPhoto = loadImage("http://farm3.static.flickr.com/2590/4180018215_c756b6b601.jpg"); // 画像を読み込む
myPhotoWidth = myPhoto.width; //画像サイズ(幅)を取得
myPhotoHeight = myPhoto.height; //画像サイズ(高さ)を取得
noStroke();
smooth();
background(255);
noLoop();
}
void draw() {
myPhoto.loadPixels(); //myPhoto の pixels を読み込む
loadPixels();//画面全体の pixels を読み込む
// 画像の色情報を調べ、画面全体のpixelsに代入する。インデックスが偶数のみ
for (int i = 0; i < myPhotoWidth*myPhotoHeight; i+=2) {
pixels[i] = myPhoto.pixels[i];
}
updatePixels(); //画面の更新
}
例3 モザイク(画像の色を調べて、ellipseなどで再描画する)
PImage myPhoto;
int myPhotoWidth, myPhotoHeight;
void setup() {
size(480, 320);
myPhoto = loadImage("http://farm3.static.flickr.com/2590/4180018215_c756b6b601.jpg"); // 画像を読み込む
myPhotoWidth = myPhoto.width; //画像サイズ(幅)を取得
myPhotoHeight = myPhoto.height; //画像サイズ(高さ)を取得
noStroke();
smooth();
background(255);
frameRate(60);
}
void draw() {
myPhoto.loadPixels(); //myPhoto の pixels を読み込む
int x = int(random(myPhotoWidth));
int y = int(random(myPhotoHeight));
fill(myPhoto.pixels[y*width+x]); //myPhoto の点(x,y)の色情報を取得し、塗り色に設定
ellipse(x, y, 10, 10);
}
現在のマウス位置に描画するようフォークしたもの
PImage myPhoto;
int myPhotoWidth, myPhotoHeight;
void setup() {
size(480, 320);
myPhoto = loadImage("http://farm3.static.flickr.com/2590/4180018215_c756b6b601.jpg"); // 画像を読み込む
myPhotoWidth = myPhoto.width; //画像サイズ(幅)を取得
myPhotoHeight = myPhoto.height; //画像サイズ(高さ)を取得
noStroke();
smooth();
background(255);
frameRate(60);
}
void draw() {
myPhoto.loadPixels(); //myPhoto の pixels を読み込む
int x = constrain(mouseX, 0, myPhotoWidth-1); //mouseXの値を画像サイズ(幅)未満にしておく
int y = constrain(mouseY, 0, myPhotoHeight-1); //mouseYの値を画像サイズ(高さ)未満にしておく
fill(myPhoto.pixels[y*width+x]); //現在のマウス位置の myPhoto の色情報を取得し、塗り色に設定
ellipse(x, y, 10, 10);
}
pixels のカラーデータ
これらを利用すると、さらに詳細な色設定が可能になる。
- red() 赤成分の値
- green() 緑成分の値
- blue() 青成分の値
- hue () 色相の値
- saturation() 彩度の値
- brightness() 色相の値
- alpha() アルファ値
PImage myPhoto;
int myPhotoWidth, myPhotoHeight;
void setup() {
size(480, 320);
myPhoto = loadImage("http://farm3.static.flickr.com/2590/4180018215_c756b6b601.jpg"); // 画像を読み込む
myPhotoWidth = myPhoto.width; //画像サイズ(幅)を取得
myPhotoHeight = myPhoto.height; //画像サイズ(高さ)を取得
noStroke();
smooth();
colorMode(HSB);
background(255);
frameRate(60);
}
void draw() {
myPhoto.loadPixels(); //myPhoto の pixels を読み込む
int x = int(random(myPhotoWidth));
int y = int(random(myPhotoHeight));
color myPhotoColor = myPhoto.pixels[y*width+x];
fill(hue(myPhotoColor), 0, brightness(myPhotoColor)); //色相と明度は変更なし、彩度は0に設定(モノクロになる)
ellipse(x, y, 10, 10);
}
- Comments (Close): 0
- TrackBack (Close): 0
b-06 時間を使う
- 2010年11月 1日 14:40
- 2010-b
hour, minute, second 時、分、秒
コンソールに日時を表示する
void setup() {
frameRate(1); //フレームレートを1に設定(毎秒1回draw関数を実行)
}
void draw() {
int s = second(); //秒
int m = minute(); //分
int h = hour(); //時
println(h + ":" + m + ":" + s); //コンソールに日時を表示
}
コンソールに日時を表示する(分と秒は2ケタで表示)
void setup() {
frameRate(1);
}
void draw() {
int s = second();
int m = minute();
int h = hour();
String t = h + ":" + nf(m, 2) + ":" + nf(s, 2);
println(t);
}
ウィンドウに日時を表示する
void setup() {
textSize(18);
textAlign(CENTER);
frameRate(1);
}
void draw() {
background(0);
int s = second();
int m = minute();
int h = hour();
String t = h + ":" + nf(m, 2) + ":" + nf(s, 2);
//println(t);
text (t, 50, 55);
}
時間を視覚化する
長方形の長さで、時計を表現する
19:45:06
void setup() {
size(240, 240);
frameRate(1);
}
void draw() {
background(204);
int s = second();
int m = minute();
int h = hour();
//長方形の長さで時計を表現する
rect(0, 0, h*10, height/3);
rect(0, height/3, m*4, height/3);
rect(0, height*2/3, s*4, height/3);
}
三針時計をつくる
このプログラムでは、三角関数を利用して針の描画している。12時の位置に線を描き rotate() で回転することにより描画することも可能。
void setup() {
size(240, 240);
frameRate(1);
smooth();
}
void draw() {
background(204);
noStroke();
ellipse (120, 120, 200, 200);
int s = second();
int m = minute();
int h = hour();
stroke(0);
strokeWeight(4);
line(120, 120 , 60 * cos(h % 12 * TWO_PI / 12 - HALF_PI) + 120, 60 * sin(h % 12 * TWO_PI / 12 - HALF_PI) + 120); //時針の描画
strokeWeight(2);
line(120, 120 , 80 * cos(m * TWO_PI / 60 - HALF_PI) + 120, 80 * sin(m * TWO_PI / 60 - HALF_PI) + 120); //分針の描画
strokeWeight(1);
line(120, 120 , 90 * cos(s * TWO_PI / 60 - HALF_PI) + 120, 90 * sin(s * TWO_PI / 60 - HALF_PI) + 120); //秒針の描画
}
より正確にシミュレートする
分針と時針を滑らかな動きにする。例えば、11時30分なら11時と12時のちょうど中間地点に時針が描画されるようにする。
void setup() {
size(240, 240);
frameRate(1);
smooth();
}
void draw() {
background(204);
noStroke();
ellipse (120, 120, 200, 200);
int s = second();
int m = minute();
int h = hour();
stroke(0);
strokeWeight(4);
line(120, 120 , 60 * cos((h + m/60.0) % 12 * TWO_PI / 12 - HALF_PI) + 120, 60 * sin((h + m/60.0) % 12 * TWO_PI / 12 - HALF_PI) + 120); //時針の描画
strokeWeight(2);
line(120, 120 , 80 * cos((m + s/60.0) * TWO_PI / 60 - HALF_PI) + 120, 80 * sin((m + s/60.0) * TWO_PI / 60 - HALF_PI) + 120); //分針の描画
strokeWeight(1);
line(120, 120 , 90 * cos(s * TWO_PI / 60 - HALF_PI) + 120, 90 * sin(s * TWO_PI / 60 - HALF_PI) + 120); //秒針の描画
}
練習
- second関数を利用し、時間(秒)に反応したアニメーションを作成する
参考資料:時計を用いたビジュアル・インタラクティブ表現
- Comments (Close): 0
- TrackBack (Close): 0
b-05 アニメーション
- 2010年10月25日 14:40
- 2010-b
画像シーケンスでアニメーションをつくる
- 下記プログラムを実行する前に、画像データをsketchのdataフォルダ内に読み込んでおく
- ここをクリックして素材をダウンロード
for文をつかわずに、画像を読み込む
int numFrames = 12; //アニメーションのフレーム数
int frame = 0; // 表示するフレーム番号
PImage[] images = new PImage[numFrames]; //アニメーション画像の配列
void setup() {
size(320, 240);
frameRate(6);
// 画像の読み込み
images[0] = loadImage("animation-000.jpg");
images[1] = loadImage("animation-005.jpg");
images[2] = loadImage("animation-010.jpg");
images[3] = loadImage("animation-015.jpg");
images[4] = loadImage("animation-020.jpg");
images[5] = loadImage("animation-025.jpg");
images[6] = loadImage("animation-030.jpg");
images[7] = loadImage("animation-035.jpg");
images[8] = loadImage("animation-040.jpg");
images[9] = loadImage("animation-045.jpg");
images[10] = loadImage("animation-050.jpg");
images[11] = loadImage("animation-055.jpg");
}
void draw() {
frame++;
// ループ処理
if (frame == numFrames) {
frame = 0;
}
image(images[frame], 0, 0); //画像を表示
}
for文を使ってたくさんの画像を読み込む
int numFrames = 60; //アニメーションのフレーム数
PImage[] images = new PImage[numFrames]; //アニメーション画像の配列
void setup() {
size(320, 240);
frameRate(30);
// 画像の読み込み
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("animation-" + nf(i, 3) + ".jpg");
}
}
void draw() {
int frame = frameCount % numFrames; //現在のフレームをアニメーションのフレーム数で割った余りを代入
image(images[frame], 0, 0); //画像を表示
}
練習:動きを加える
- 表示の際、画像をほんの少しランダムに配置する
- 表示の際、画像を1pxずつ下げて表示する
- 表示の際、不透明度を設定し、残像のように見せる
マウスの動きで、アニメーションをコントロールする
int numFrames = 60; //アニメーションのフレーム数
PImage[] images = new PImage[numFrames]; //アニメーション画像の配列
void setup() {
size(320, 240);
frameRate(30);
// 画像の読み込み
for (int i = 0; i < images.length; i++) {
images[i] = loadImage("animation-" + nf(i, 3) + ".jpg");
}
}
void draw() {
}
void mouseMoved() {
int frame = int(map(mouseX, 0, width, 0, numFrames)); //マウスポインタのx座標を0以上60未満の値へマッピング
image(images[frame], 0, 0);
}
- Comments (Close): 0
- TrackBack (Close): 0
b-04 配列を使う
- 2010年10月18日 14:40
- 2010-b
配列を使わないプログラムと配列を使ったプログラムの比較
5つの点A,B,C,D,Eを順に直線で結ぶ
配列を使わないプログラム(変数を使わない)
// 5つの点A,B,C,D,Eを順に直線で結ぶ
beginShape();
vertex(50, 18); //点Aの座標を指定
vertex(29, 82); //点Bの座標を指定
vertex(83, 43); //点Cの座標を指定
vertex(17, 43); //点Dの座標を指定
vertex(71, 82); //点Eの座標を指定
endShape(CLOSE);
配列を使わないプログラム(変数を使う)
int x0 = 50, y0 = 18; //点Aのx座標, y座標
int x1 = 29, y1 = 82; //点Bのx座標, y座標
int x2 = 83, y2 = 43; //点Cのx座標, y座標
int x3 = 17, y3 = 43; //点Dのx座標, y座標
int x4 = 71, y4 = 82; //点Eのx座標, y座標
// 5つの点A,B,C,D,Eを順に直線で結ぶ
beginShape();
vertex(x0, y0);
vertex(x1, y1);
vertex(x2, y2);
vertex(x3, y3);
vertex(x4, y4);
endShape(CLOSE);
配列を使ったプログラム
int[] x = {50, 29, 83, 17, 71}; //点A,B,C,D,Eのx座標
int[] y = {18, 82, 43, 43, 82}; //点A,B,C,D,Eのy座標
// 5つの点A,B,C,D,Eを順に直線で結ぶ
beginShape();
for (int i = 0; i < x.length; i++) {
vertex(x[i], y[i]);
}
endShape(CLOSE);
- プログラムが短くシンプルに
- 点の数を増やしたいとき、プログラムの書き換えが簡単
配列宣言
- 《配列データ型》[] 《配列の名前》 例)int[] x
- 《配列データ型》[] 《配列の名前》 = new 《配列の設定》 例)int[] x = new int[5]
配列への代入
- 一度にまとめて 例)x = {50, 29, 83, 17, 71}
- 個別に: x[0] = 50, x[1] = 29, x[2] = 83, x[3] = 17, x[4] = 71 ※0番目から始まることに注意
length 配列の長さ
- 上記サンプルでは、x.length は 5 となる
二次元配列を使ったプログラム
int[][] p = { {50, 18}, {29, 82}, {83, 43}, {17, 43}, {71, 82} }; //点A,B,C,D,Eのx,y座標
// 5つの点A,B,C,D,Eを順に直線で結ぶ
beginShape();
for (int i = 0; i < p.length; i++) {
vertex(p[i][0], p[i][1]);
}
endShape(CLOSE);
配列の使い方1 「過去のデータを記憶する」
int length = 50; //配列の個数
int[] x = new int[length]; //x座標を記録する配列
int[] y = new int[length]; //y座標を記録する配列
void setup() {
size(800, 600);
smooth();
frameRate(60);
}
void draw() {
background(204); //画面をリセット
//配列を参照して円を描画する
for(int i=0 ; i < length ; i++) {
fill(i * 3);
ellipse(x[i], y[i], i, i);
}
}
//マウスが動いたときの処理:マウスの座標を記録する
void mouseMoved() {
//配列の値をひとつ後ろへ移動する
for(int i = length - 1 ; i >= 1 ; i--) {
x[i] = x[i-1];
y[i] = y[i-1];
}
x[0] = mouseX;
y[0] = mouseY;
}
配列の使い方2 「複数の動きを処理する」
int length = 20;
float[] x = new float[length];
float[] speed = new float[length];
void setup() {
size(400, 400);
for (int i = 0; i < length; i++){
x[i] = width / 2;
speed[i] = random(-1, 1);
}
}
void draw() {
background(204);
for (int i = 0; i < length; i++){
x[i] = x[i] + speed[i];
rect(x[i], (height / length) * i, 10, 10);
}
}
※ 上のプログラムは、以下のプログラムを応用したもの
float x;
float speed;
void setup() {
size(400, 400);
x = width / 2;
speed = 1;
}
void draw() {
background(204);
x = x + speed;
rect(x, height/2, 10, 10);
}
配列の使い方3 「用意したデータを選ぶ」
String[] message = {"how","are","you?","I","am","fine","thank","you!"};
int count = 0;
void setup(){
size(400, 400);
colorMode(HSB, 100);
background(99);
textSize(28);
textAlign(CENTER);
frameRate(3);
}
void draw() {
background(99);
fill(random(100), 99, 99);
text(message[count], width/2, height/2);
count++;
count %= message.length;
}
練習「おみくじ」を作る
- 大吉、中吉、小吉、吉の4つとする
- ウィンドウサイズは自由とする
作り方のヒント
- どのタイミングでおみじくを表示するか?
- ユーザーがアクションを起こしたとき
- どうやってユーザーにアクションを起こしてもらうか?
- マウスやキーボードからの入力
- おみくじデータの用意方法は?
- 配列を利用する
- おみくじをランダムに選ぶには?
- random関数を利用する
- 大吉が出にくく、吉が出やすくするには?
- 100本のくじのうち、大吉は10本、中吉は20本、小吉は30本、吉は40本、と考える
- if(...){...}else if(...){...}else if(...){...}else{}
手順のヒント
- 基本的な機能が動作するシンプルな「プロトタイプ」を作る
- プロトタイプが出来てから、細部を作り込んでいく
評価のポイント
- おみくじとして成立しているか
- シンプルでわかりやすいプログラムを書いているか
- Comments (Close): 0
- TrackBack (Close): 0
b-03 文字を使う
- 2010年10月11日 14:40
- 2010-b
text() 文字を描く関数
text("あいうえお愛", 10, 35); // 表示するテキスト, x座標, y座標
text("あいうえお愛", 10, 35, 40, 40); // 表示するテキスト, x座標, y座標, 表示領域の幅, 表示領域の高さ
fill(0); //塗色を設定する
text("あいうえお愛", 10, 35, 40, 40);
textSize() 文字サイズを指定する
fill(0);
textSize(16);
text("あいうえお愛", 10, 35);
textAlign() 文字揃えを指定する
fill(0);
textAlign(CENTER);
text("あいうえお愛", 50, 35);
String 文字列のデータ型
String s = "あいうえお愛";
text(s, 10, 35);
指定したフォントで文字を描く
準備
以下のようにフォントデータを生成しておく
PFont 変数でフォントデータを扱う場合のデータ型 , textFont 使用するフォントを指定
size(500, 200);
PFont myFont = loadFont("HelveticaNeue-Bold-24.vlw");
textFont(myFont);
text("I Love Processing!", 0, 100);
キーボードからの入力に反応する「押されたキーの文字を表示する」
※事前に「Tools」の「Create Font...」でフォントデータを生成しておく。
int x = 0, y = 50;
PFont font;
void setup() {
size(400, 400);
background(0);
fill(255, 128);
font = loadFont("Serif-48.vlw");
textFont(font, 48);
//textAlign(CENTER);
}
void draw() {
}
void keyPressed() {
text(key, x, y);
}
void keyReleased() {
x += 10;
if (x > width) {
x = 0;
y += 50;
}
}
練習
- 文字の出現位置をランダムにしてみる
- 文字の色をランダムにしてみる
- スペースキーを押すと、画面がリセットされる
- Comments (Close): 0
- TrackBack (Close): 0
b-02 反応させる(マウス、キーボードからの入力に)
- 2010年10月 4日 14:40
- 2010-b
mouseX, mouseY マウスポインタの位置(座標)
現在のマウスポインタの位置に円が描かれる。
void setup() {
size(400, 400);
}
void draw() {
ellipse(mouseX, mouseY, 60, 60);
}
練習
- マウスポインタの位置に円がくっついて動く
- マウスポインタの位置に「10pxの黒い円」を描く
- マウスのy座標に合わせて円の大きさを変える
- マウスのx座標に合わせて円の塗り色を変える
pmouseX, pmouseY 前フレームのマウスポインタの位置(座標)
前フレームのマウスポインタの位置から現フレームのマウスポインタの位置に線が描かれる。(マウスを動かすと、線が描かれるように見える)
void setup() {
size(400, 400);
}
void draw() {
line(mouseX, mouseY, pmouseX, pmouseY);
}
練習
- マウスポインタの位置が、画面の左側のときは線の太さを5, 画面の右側のときは線の太さを10にする
mousePressed マウスボタンが押されている(== true)、押されていない(== false)
マウスボタンを押している間、線が描かれる。
void setup() {
size(400, 400);
strokeWeight(10);
}
void draw() {
if (mousePressed == true){
line(mouseX, mouseY, pmouseX, pmouseY);
}
}
mousePressed() {...} マウスボタンが押されたときに1回だけ {...} の中を実行する
マウスボタンを押すと、円が描かれる。
void setup() {
size(400, 400);
}
void draw() {
}
void mousePressed() {
ellipse(mouseX, mouseY, 60, 60);
}
mouseReleased() {...} マウスボタンが離されたときに1回だけ {...} の中を実行する
マウスボタンを押している間、線が描かれる。ボタンが離されると線が消える。
void setup() {
size(400, 400);
strokeWeight(10);
}
void draw() {
if (mousePressed == true){
line(mouseX, mouseY, pmouseX, pmouseY);
}
}
void mouseReleased() {
background(204); //マウスボタンが離されると画面がリセットされる
}
練習:次のような動作をするプログラムを書く
マウスポインタの位置に赤い円が描かれる。マウスボタンを押すと、円の塗り色が変わる。
マウスボタンを押すと、前回マウスボタンを押した位置からの折れ線が描ける。
keyPressed キーが押されている(== true)、押されていない(== false)
キーが押されているとき、円が左から右にすすむ
float x = 0.0;
float speed = 1.0;
void setup() {
size(400, 400);
}
void draw() {
background(204);
if (keyPressed == true) {
x += speed;
//println(key);
}
ellipse(x, height/2, 60, 60);
}
key 押されたキーの文字や記号を納める変数
キーのa(小文字のエー)が押されているとき、円が左から右にすすむ
float x = 0.0;
float speed = 1.0;
void setup() {
size(400, 400);
}
void draw() {
background(204);
if ((keyPressed == true) && (key == 'a')) {
x += speed;
}
ellipse(x, height/2, 60, 60);
}
※大文字小文字を問わないようにするためには、次のように「aまたはAが押されているとき」で条件を設定する
float x = 0.0;
float speed = 1.0;
void setup() {
size(400, 400);
}
void draw() {
background(204);
if ((keyPressed == true) && ((key == 'a') || (key == 'A'))) {
x += speed;
}
ellipse(x, height/2, 60, 60);
}
keyPressed() {...} キーが押されたときに1回だけ {...} の中を実行する
※キーを押しっぱなしにして一定時間経つと、キーの連続入力状態になり、そのスピードに合わせ連続して実行される。
キーが押されると、円が1ピクセルだけ左から右にすすむ
float x = 0.0;
float speed = 1.0;
void setup() {
size(400, 400);
}
void draw() {
}
void keyPressed() {
background(204);
x += speed;
ellipse(x, height/2, 60, 60);
//println(key);
}
keyReleased() {...} キーが離されたときに1回だけ {...} の中を実行する
キーが離されると、円が止まる
float x = 0.0;
float speed = 1.0;
void setup() {
size(400, 400);
}
void draw() {
background(204);
x += speed;
ellipse(x, height/2, 60, 60);
}
void keyReleased() {
speed = 0.0;
}
- Comments (Close): 0
- TrackBack (Close): 0
b-01 動きを制御する - 直線の動き
- 2010年9月27日 14:40
- 2010-b
直線の動き
float x; // 物体の位置
float speed; // 物体のスピード
void setup() {
size(200, 200);
// 位置とスピードの初期化
x = 0;
speed = 1;
}
void draw() {
background(255); // 画面をリセット
x = x + speed; // 位置の計算
// 矩形の描画
rect(x, height/2, 10, 10);
}
練習 - 上記のプログラムを改変してみる
- スピードを速くする
- 右から左に動かす
- 上から下に動かす
- 左から右に動かし、右端まで行ったら、左端から出てくるようにする。(ヒント:if文を使う)
フェード効果を付ける
float x;
float y;
float speed;
void setup() {
size(200, 200);
smooth();
noStroke();
x = 0;
y = 100;
speed = 5;
}
void draw() {
//background(204);
fill(204, 102); //透過色を塗り色に設定
rect(0, 0, width, height); //画面全体を塗る
fill(0);
rect(x, y, 10, 10);
x = x + speed;
//y = y + speed;
if (x > width) x = -10;
}
直線の動き(複雑な形のものを関数を使って)
バスを描く
size(400,400);
rectMode(CENTER);
rect(200,200,120,60); // ボディ
ellipse(165,230,30,30); // 後輪・外側
ellipse(235,230,30,30); // 前輪・外側
ellipse(165,230,20,20); // 後輪・内側
ellipse(235,230,20,20); // 前輪・内側
rectMode(CORNER);
rect(245,180,15,20);// 窓・前
rect(195,180,30,20); // 窓・中
rect(150,180,30,20); // 窓・後
バスを描く(変数を使って)
size(400,400);
int x=200; // ボディの中心のx座標
int y=200; // ボディの中心のy座標
int h=60; // ボディの高さ、幅の基準
int d=30; // 車輪の直径の基準
rectMode(CENTER);
rect(x,y,h*2,h); // ボディ
ellipse(x-35,y+h/2,d,d); // 後輪・外側
ellipse(x+35,y+h/2,d,d); // 前輪・外側
ellipse(x-35,y+h/2,d-10,d-10); // 後輪・内側
ellipse(x+35,y+h/2,d-10,d-10); // 前輪・内側
rectMode(CORNER);
rect(x+45,y-20,h/4,h/3); // 窓・前
rect(x-5,y-20,h/2,h/3); // 窓・中
rect(x-50,y-20,h/2,h/3); // 窓・後
バスを描く(初期化関数とメインループ関数を使って)
int x=200; // ボディの中心のx座標
int y=200; // ボディの中心のy座標
int h=60; // ボディの高さ、幅の基準
int d=30; // 車輪の直径の基準
void setup(){
size(400,400);
noLoop(); // 繰り返さない
}
void draw(){
rectMode(CENTER);
rect(x,y,h*2,h); // ボディ
ellipse(x-35,y+h/2,d,d); // 後輪・外側
ellipse(x+35,y+h/2,d,d); // 前輪・外側
ellipse(x-35,y+h/2,d-10,d-10); // 後輪・内側
ellipse(x+35,y+h/2,d-10,d-10); // 前輪・内側
rectMode(CORNER);
rect(x+45,y-20,h/4,h/3); // 窓・前
rect(x-5,y-20,h/2,h/3); // 窓・中
rect(x-50,y-20,h/2,h/3); // 窓・後
}
グローバル変数
- 関数の外で定義された変数
- どの関数からでもアクセスできる
noLoop
drawの処理を繰り返さない(1回だけdrawの処理を行う)
3台のバスを描く(関数を使わずに1つ1つ描く)
int x=200; // ボディの中心のx座標
int y=200; // ボディの中心のy座標
int h=60; // ボディの高さ、幅の基準
int d=30; // 車輪の直径の基準
void setup(){
size(400,400);
noLoop(); // 繰り返さない
}
void draw(){
// 中央のバス
rectMode(CENTER);
rect(x,y,h*2,h); // ボディ
ellipse(x-35,y+h/2,d,d); // 後輪・外側
ellipse(x+35,y+h/2,d,d); // 前輪・外側
ellipse(x-35,y+h/2,d-10,d-10); // 後輪・内側
ellipse(x+35,y+h/2,d-10,d-10); // 前輪・内側
rectMode(CORNER);
rect(x+45,y-20,h/4,h/3); // 窓・前
rect(x-5,y-20,h/2,h/3); // 窓・中
rect(x-50,y-20,h/2,h/3); // 窓・後
// 左上のバス
rectMode(CENTER);
rect(x-100,y-100,h*2,h); // ボディ
ellipse(x-35-100,y+h/2-100,d,d); // 後輪・外側
ellipse(x+35-100,y+h/2-100,d,d); // 前輪・外側
ellipse(x-35-100,y+h/2-100,d-10,d-10); // 後輪・内側
ellipse(x+35-100,y+h/2-100,d-10,d-10); // 前輪・内側
rectMode(CORNER);
rect(x+45-100,y-20-100,h/4,h/3); // 窓・前
rect(x-5-100,y-20-100,h/2,h/3); // 窓・中
rect(x-50-100,y-20-100,h/2,h/3); // 窓・後
// 右下のバス
rectMode(CENTER);
rect(x+100,y+100,h*2,h); // ボディ
ellipse(x-35+100,y+h/2+100,d,d); // 後輪・外側
ellipse(x+35+100,y+h/2+100,d,d); // 前輪・外側
ellipse(x-35+100,y+h/2+100,d-10,d-10); // 後輪・内側
ellipse(x+35+100,y+h/2+100,d-10,d-10); // 前輪・内側
rectMode(CORNER);
rect(x+45+100,y-20+100,h/4,h/3); // 窓・前
rect(x-5+100,y-20+100,h/2,h/3); // 窓・中
rect(x-50+100,y-20+100,h/2,h/3); // 窓・後
}
※draw関数の中に、同じようなプログラムが繰り返されている。これを効率よく書き換えることで、プログラムの入力を楽にすることができる。
3台のバスを描く(自分で定義した関数を使って)
int h=60; // ボディの高さ、幅の基準
int d=30; // 車輪の直径の基準
void setup() {
size(400, 400);
noLoop(); // 繰り返さない
}
void draw() {
drawBus(200, 200); //中央のバス
drawBus(100, 100); //左上のバス
drawBus(300, 300); //右下のバス
}
void drawBus(int x, int y) {
rectMode(CENTER);
rect(x, y, h*2, h); // ボディ
ellipse(x-35, y+h/2, d, d); // 後輪・外側
ellipse(x+35, y+h/2, d, d); // 前輪・外側
ellipse(x-35, y+h/2, d-10, d-10); // 後輪・内側
ellipse(x+35, y+h/2, d-10, d-10); // 前輪・内側
rectMode(CORNER);
rect(x+45, y-20, h/4, h/3); // 窓・前
rect(x-5, y-20, h/2, h/3); // 窓・中
rect(x-50, y-20, h/2, h/3); // 窓・後
}
- drawBus:バスの描画を定義した関数(わかりやすい任意の名前を付ける)
バスを走らせる
int x; // ボディの中心のx座標
int y; // ボディの中心のy座標
int h = 60; // ボディの高さ、幅の基準
int d = 30; // 車輪の直径の基準
int speed = 1; // 進む速さ
void setup() {
size(400, 400);
x = -h; // ボディの中心のx座標
y = height / 2; // ボディの中心のy座標
//noLoop(); // 繰り返さない
}
void draw() {
background(255); // 画面をリセットする
drawBus(x, y); // バスを描く
x = x + speed; // 進む
if(x > width + h){
x = -h; // バスが右端まで行ったら左端に戻る
}
}
void drawBus(int x, int y) {
rectMode(CENTER);
rect(x, y, h*2, h); // ボディ
ellipse(x-35, y+h/2, d, d); // 後輪・外側
ellipse(x+35, y+h/2, d, d); // 前輪・外側
ellipse(x-35, y+h/2, d-10, d-10); // 後輪・内側
ellipse(x+35, y+h/2, d-10, d-10); // 前輪・内側
rectMode(CORNER);
rect(x+45, y-20, h/4, h/3); // 窓・前
rect(x-5, y-20, h/2, h/3); // 窓・中
rect(x-50, y-20, h/2, h/3); // 窓・後
}
画面のリセット
draw関数の最初で背景を白で塗る(background(255);)ことで、画面をリセットしている
バスを走らせる(キーボードを押したときに)
int x; // ボディの中心のx座標
int y; // ボディの中心のy座標
int h = 60; // ボディの高さ、幅の基準
int d = 30; // 車輪の直径の基準
int speed = 1; // 進む速さ
void setup() {
size(400, 400);
x = -h; // ボディの中心のx座標
y = height / 2; // ボディの中心のy座標
//noLoop(); // 繰り返さない
}
void draw() {
background(255); // 画面をリセットする
drawBus(x, y); // バスを描く
if (keyPressed == true) {
x = x + speed; // 進む
}
if (x > width + h) {
x = -h; // バスが右端まで行ったら左端に戻る
}
}
void drawBus(int x, int y) {
rectMode(CENTER);
rect(x, y, h*2, h); // ボディ
ellipse(x-35, y+h/2, d, d); // 後輪・外側
ellipse(x+35, y+h/2, d, d); // 前輪・外側
ellipse(x-35, y+h/2, d-10, d-10); // 後輪・内側
ellipse(x+35, y+h/2, d-10, d-10); // 前輪・内側
rectMode(CORNER);
rect(x+45, y-20, h/4, h/3); // 窓・前
rect(x-5, y-20, h/2, h/3); // 窓・中
rect(x-50, y-20, h/2, h/3); // 窓・後
}
練習
- line、ellipse、rectなどを使ってものの形を描く(例:乗り物、動物)
- 変数や自分で定義した関数を使って、1と同じ形を3つ描く
- 描いた形を左から右へ動かす
- Comments (Close): 0
- TrackBack (Close): 0
Home> 2010-bアーカイブ
- カテゴリ
-
- 1a
- 1b
- 2010-a (13)
- 2010-b (11)
- 2011-a (10)
- 2011-b (9)
- android (1)
- libraries
- processing.js (1)
- tools (2)
- トピックス (1)
- ノート
- アーカイブ
- 購読
- Recommends
-
- Powerd By















































