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ファイルのメタ情報を表示する

Minim AudioMetaData

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 を利用したテルミンのような楽器をつくる。

IMG_1594

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

オブジェクト指向プログラミングでプログラムを書く

円を描くプログラムを、オブジェクト指向プログラミングで書いてみる。

oop1

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);
  }
}

クラス定義を別ファイルで管理する

manage-class1-1

manage-class2-1

manage-class3-1

manage-class4-1

※以降、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 ライブラリを利用する。

ライブカメラの映像を表示する

そのまま表示する

sketch_1b_10_1

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分割で表示する

sketch_1b_10_2

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

色情報を取得して再描画する

sketch_1b_10_3

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室では、インストールの権限制限があり、みなさん自身ではインストールができません。利用したい場合は事前に相談ください。

そのまま表示する

sketch_1b_10_5

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ライブラリを使用するときよりも、コードがシンプルになる

加工して表示する

sketch_1b_10_6

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の更新

20101106-161835

  • 幅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 カラーピッカー(画面の色を調べる)

pixels0

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 画像の色を調べて、その一部を画面に表示する

pixels1

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などで再描画する)

pixels2

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() アルファ値

pixels3

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 時、分、秒

コンソールに日時を表示する

1b-06 時間

void setup() {
  frameRate(1); //フレームレートを1に設定(毎秒1回draw関数を実行)
}

void draw() {
  int s = second(); //秒
  int m = minute(); //分
  int h = hour(); //時
  println(h + ":" + m + ":" + s); //コンソールに日時を表示
}

コンソールに日時を表示する(分と秒は2ケタで表示)

1b-06 時間

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);
}

時間を視覚化する

長方形の長さで、時計を表現する

1b-06-3

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

画像シーケンスでアニメーションをつくる

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); //画像を表示
}

練習:動きを加える

  1. 表示の際、画像をほんの少しランダムに配置する
  2. 表示の際、画像を1pxずつ下げて表示する
  3. 表示の際、不透明度を設定し、残像のように見せる

マウスの動きで、アニメーションをコントロールする

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を順に直線で結ぶ

1b-07-1

配列を使わないプログラム(変数を使わない)

// 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 「過去のデータを記憶する」

1b-06-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 「複数の動きを処理する」

1b-07-1-[I@8ab08f 1b-07-1-[I@4fe91e

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 「用意したデータを選ぶ」

1b-07-3-1 1b-07-3-2 1b-07-3-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() 文字を描く関数

text1

text("あいうえお愛", 10, 35); // 表示するテキスト, x座標, y座標

text2

text("あいうえお愛", 10, 35, 40, 40); // 表示するテキスト, x座標, y座標, 表示領域の幅, 表示領域の高さ

text3

fill(0); //塗色を設定する
text("あいうえお愛", 10, 35, 40, 40);

textSize() 文字サイズを指定する

textSize

fill(0);
textSize(16);
text("あいうえお愛", 10, 35);

textAlign() 文字揃えを指定する

textAlign

fill(0);
textAlign(CENTER);
text("あいうえお愛", 50, 35);

String 文字列のデータ型

text1

String s = "あいうえお愛";
text(s, 10, 35);

指定したフォントで文字を描く

準備

以下のようにフォントデータを生成しておく

08-12 08-13

PFont 変数でフォントデータを扱う場合のデータ型 , textFont 使用するフォントを指定

08-14

size(500, 200);

PFont myFont = loadFont("HelveticaNeue-Bold-24.vlw");
textFont(myFont);

text("I Love Processing!", 0, 100);

キーボードからの入力に反応する「押されたキーの文字を表示する」

1b_05_2

※事前に「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;
  }
}

練習

  1. 文字の出現位置をランダムにしてみる
  2. 文字の色をランダムにしてみる
  3. スペースキーを押すと、画面がリセットされる
  • Comments (Close): 0
  • TrackBack (Close): 0

b-02 反応させる(マウス、キーボードからの入力に)

  • 2010年10月 4日 14:40
  • 2010-b

mouseX, mouseY マウスポインタの位置(座標)

現在のマウスポインタの位置に円が描かれる。

ib_4_0

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

void draw() {
  ellipse(mouseX, mouseY, 60, 60);
}

練習

  • マウスポインタの位置に円がくっついて動く
  • マウスポインタの位置に「10pxの黒い円」を描く
  • マウスのy座標に合わせて円の大きさを変える
  • マウスのx座標に合わせて円の塗り色を変える

pmouseX, pmouseY 前フレームのマウスポインタの位置(座標)

前フレームのマウスポインタの位置から現フレームのマウスポインタの位置に線が描かれる。(マウスを動かすと、線が描かれるように見える)

1b_4_1

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

void draw() {
  line(mouseX, mouseY, pmouseX, pmouseY);
}

練習

  • マウスポインタの位置が、画面の左側のときは線の太さを5, 画面の右側のときは線の太さを10にする

mousePressed マウスボタンが押されている(== true)、押されていない(== false)

マウスボタンを押している間、線が描かれる。

1b_4_2

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

void draw() {
  if (mousePressed == true){
    line(mouseX, mouseY, pmouseX, pmouseY);
  }
}

mousePressed() {...} マウスボタンが押されたときに1回だけ {...} の中を実行する

マウスボタンを押すと、円が描かれる。

1b_4_3

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); //マウスボタンが離されると画面がリセットされる
}

練習:次のような動作をするプログラムを書く

マウスポインタの位置に赤い円が描かれる。マウスボタンを押すと、円の塗り色が変わる。

ib_4_5

マウスボタンを押すと、前回マウスボタンを押した位置からの折れ線が描ける。

ib_4_4

keyPressed キーが押されている(== true)、押されていない(== false)

キーが押されているとき、円が左から右にすすむ

1b_05_1

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

直線の動き

1b-02-1-26 1b-02-1-52 1b-02-1-79

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);
}

練習 - 上記のプログラムを改変してみる

  1. スピードを速くする
  2. 右から左に動かす
  3. 上から下に動かす
  4. 左から右に動かし、右端まで行ったら、左端から出てくるようにする。(ヒント: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;
}

直線の動き(複雑な形のものを関数を使って)

バスを描く

processing 1b-1

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); // 窓・後

バスを描く(変数を使って)

processing 1b-1

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); // 窓・後

バスを描く(初期化関数とメインループ関数を使って)

processing 1b-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); // 窓・後
}

グローバル変数

  • 関数の外で定義された変数
  • どの関数からでもアクセスできる

noLoop

drawの処理を繰り返さない(1回だけdrawの処理を行う)

3台のバスを描く(関数を使わずに1つ1つ描く)

processing 1b-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台のバスを描く(自分で定義した関数を使って)

processing 1b-1

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); // 窓・後
}

練習

  1. line、ellipse、rectなどを使ってものの形を描く(例:乗り物、動物)
  2. 変数や自分で定義した関数を使って、1と同じ形を3つ描く
  3. 描いた形を左から右へ動かす
  • Comments (Close): 0
  • TrackBack (Close): 0

Index of all entries

Home> 2010-bアーカイブ

カテゴリ
アーカイブ
購読
Recommends
Processing: A Programming Handbook for Visual Designers and Artists Learning Processing: A Beginner's Guide to Programming Images, Animation, and Interaction (Morgan Kaufmann Series in Computer Graphics and Geometric Modeling) FORM+CODE -デザイン/アート/建築における、かたちとコード Form+Code in Design, Art, and Architecture (Design Briefs) Generative Gestaltung Generative Art Built with Processing[Ver. 1.x対応版] -デザイン/アートのためのプログラミング入門 Getting Started With Processing Arduinoをはじめよう ビジュアライジング・データ ―Processingによる情報視覚化手法 +GAINER―PHYSICAL COMPUTING WITH GAINER
Powerd By

Return to page top