カテゴリー
Processing

Processing(おまけ)

制作保管庫

マトリックス風テクスチャ

映画マトリックスの世界観を表したデジタルっぽいテクスチャを作ってみた。

int[][] num = new int[9][35]; //数字を格納
int[] pos = new int[35]; //文字のポジションを格納
int[] r = new int[35]; //カラーのR値
int[] b = new int[35]; //カラーのB値
String[][] moji = new String[19][35]; //文字を格納
String[] input = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O",
                  "P","Q","R","S","T","U","V","W","X","Y","Z","",""};
        
int flag = 0; //フラグ

void setup(){
  size(700,700);
  background(0);
  
}

void draw(){
  
  background(0);
  textSize(30);
  
  if(flag == 0){
    for(int j = 0; j <35; j++){ //ランダムな値を各配列に格納
      pos[j] = int(random(5,500));
      r[j] = int(random(0,210));
      b[j] = int(random(0,170));
      
      for(int i = 0; i <19; i++){
        moji[i][j] = input[int(random(0,28))];
      }
      
      for(int i = 0; i <9; i++){
        num[i][j] = int(random(0,10));
      }
    }
    flag = 1;
  }
  
  
    for(int j = 0; j <35; j++){ //テキストの表示
       
        for(int i = 0; i <19; i++){
        
          if(i%2 != 0){
            fill(r[j],255,b[j],90);
            text(moji[i][j],j*30,pos[j]+i*30);
            
          }
          
        }
        
        for(int i = 0; i <9; i++){  
          fill(r[j],255,b[j],90);
          text(num[i][j],j*30,pos[j]+i*60);
        }
    } 
}  
   

ビットマップ画像生成

ビットマップフォントのデザインをしたくてつくってみた。

int size = 7; //縦横のサイズを宣言
int pos_X[]; //マス目のx座標
int pos_Y[]; //マス目のy座標
int flag =0; //ファイル保存時のフラグ

int dot_X = 0; //色を塗る場所の座標
int dot_Y = 0;

void setup(){
  size(490,490);
  background(255);
  pos_X = new int[size+1];
  pos_Y = new int[size+1];
}



void grid(){ //グリッド線の表示
  
  for(int i = 0; i <= size; i++){
    for(int j = 0; j <= size; j++){
      pos_X[j] = j*size*10;
      pos_Y[i] = i*size*10;
      
      if(key == '1'){
        noFill();
        stroke(0);
        rect(pos_X[j],pos_Y[i],size*10,size*10);
      }
      if(key == '2'){
        noFill();
        stroke(255);
        rect(pos_X[j],pos_Y[i],size*10,size*10);
      }
      
    }
  }
}

void drawDot(int x, int y){ //マスを塗る場所を定める
  
    for(int i = 0; i < size; i++){
        for(int j = 0; j < size; j++){
          if((pos_X[j] <= x && x <= pos_X[j+1]) && (pos_Y[i] <= y && y <= pos_Y[i+1])){
      
           dot_X = pos_X[j];
           dot_Y = pos_Y[i];
           
          }
        }
    }
}

void mouseClicked(){
  
  if(key == 'b'){
    stroke(0);
    fill(0);
  }
  if(key == 'w'){
    stroke(0);
    fill(255);
  }
  
  rect(dot_X,dot_Y,size*10,size*10); 
}

void draw(){
 
  grid();
  drawDot(mouseX,mouseY);
  
  if (key == 's') {
 
    if(flag == 0){
    //画像を作成
    PImage img = createImage(width, height, RGB);
     
    //画面を画像にコピー
    loadPixels();
    img.pixels = pixels;
    img.updatePixels();
     
    //画像のピクセル情報を切り出して保存
    img = img.get(0, 0, width, height);
    
    img.save("data/picture.png");
      flag = 1;
    }
    
    if(key == '3'){
      flag = 0; 
    }
      
  }
}

カテゴリー
Processing

Processing(Step5)

複雑な図形を描く

普段使っているrect()や、ellipse()で四角形や円は描画できます。しかし、星型や多角形などの図形を描画するにはどうしたらいいしょう。

そこで、使えるのが、vertexです。合わせて、beginShape()endShape()を使い、図形を描くことができます。使い方はこうです。

  1. beginShape()と書き、図形を定義していきます。
  2. vertex(x座標,y座標,z座標)を指定し、図形の頂点を指定する。
  3. endShape()と書き、図形を完成させましょう。

正六角形

以下のコードを見てみましょう。vertexを使う前にこの2つを覚えておきましょう。

pushMatrix() → 現在の座標を保存する。
popMatrix() → 保存した座標を再展開する。

上記の2つをbeginShape()とendShape()で描画した図形を挟むように記述することで、座標を維持したまま描くことが出来ます。また、三角関数もプロセシングでは、扱うことが出来ます。

三角関数

  • sin(a)…サイン(正弦)を求める
  • cos(a)…コサイン(余弦)を求める
  • tan(a)…タンジェント(正接)を求める
  • degrees(a)…角度の単位をラジアンから「度」へ変換する
  • radians(a)…角度の単位を「度」からラジアンへ変換する

この場合は、vertexで頂点の位置を指定する時に使用しています。図形を使う時には良く使うので、覚えておきましょう。

int r = 150;

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

void draw() {
  background(255);
  
  pushMatrix(); // 正六角形を描画
  translate(width/2,height/2);
  fill(255,0,0);
  strokeWeight(2);
  stroke(255, 0, 0);
  beginShape();
  for (int i = 0; i < 6; i++) {
    vertex(r*cos(radians(360*i/6)), r*sin(radians(360*i/6)));
  }
  endShape(CLOSE);
  popMatrix();
}

実行すると、以下のようになります。

星型

次は、星型を描いてみましょう。

int r = 150;
int R = 0;
int inR = 0; //中心点から谷までの距離
int outR = 0; //中心点から先端までの距離

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

void draw() {
  background(255);
  
  pushMatrix(); //星を描画
  translate(width/2,height/2);
  rotate(radians(-90));
  fill(255,0,0);
  strokeWeight(2);
  stroke(255, 0, 0);
  
  outR = r;
  inR = outR/2;
  
  beginShape();
  for (int i = 0; i < 10; i++) {
   if (i%2 == 0) {
      R = outR;
    } else {
      R = inR;
    } 
    
    vertex(R*cos(radians(360*i/10)), R*sin(radians(360*i/10)));
  }
  endShape(CLOSE);
  popMatrix();
}

星形の難しいところは、尖っている所、へこんでいる所が存在することです。そのため、頂点の位置の角度に気をつけなければなりません。尖ってる→へこみ→尖ってる…と連続した規則性を持っているので、それをコードとして表現できれば、簡単です。

肝となるのが、以下のコードです。偶数、奇数で角度をずらす処理をしています。これをすることで、星の規則性を再現できます。

beginShape();
  for (int i = 0; i < 10; i++) {
   if (i%2 == 0) {
      R = outR;
    } else {
      R = inR;
    } 

関数を作る

上で、複雑な図形を描きましたが、これをいくつか描画したいとなったら、面倒くさいですよね。そこで、自分で星を描画する関数を作れば、いつでも簡単に描画できます。以下のコードを見てみましょう。

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

void star(int x, int y, int r, int num){ //星を描画する関数
  int p = num*2;
  int R;
  
  int outR = r; //中心点から先端までの距離
  int inR = r/2; //中心点から谷までの距離
  
  pushMatrix(); 
  scale(0.5); //星のサイズを変更
  translate(x,y);
  rotate(radians(-90));
  
  beginShape();
  for (int i = 0; i < p; i++) {
   if (i%2 == 0) {
      R = outR;
    } else {
      R = inR;
    } 
    
    vertex(R*cos(radians(360*i/p)), R*sin(radians(360*i/p)));
  }
  endShape(CLOSE);
  popMatrix();
}

void draw() {
  background(255);
  fill(255,0,0);
  strokeWeight(2);
  stroke(255, 0, 0);
  
  for(int i = 0; i < 5; i++){
   
    star(width/3+i*300,3*height/4,150, 5);
  }
}

void star()を新たに作っています。()内には引数として取得したい値を設定しています。

void star(int x, int y, int r, int num){ //星を描画する関数
}

その後、draw関数内で呼び出す際に、値を入れてあげると、star関数に値が引き渡されるようになっています。

star(width/3+i*300,3*height/4,150, 5);

繰り返し処理で、関数を呼び出してあげることで、何度も描画できるようになり、簡略化できます。

ゲームを作ってみよう

今まで習ったことを生かして、 シューティングゲームを作ってみましょう。

自機を作成

自機は、マウスを追従するようにしたいので、マウスの座標を引数に取る関数を作成します。

また、画面外から出ないように条件を付けています。

void machine(int x, int y){ //自機を描画する関数
  rectMode(CENTER);
  noStroke();
  fill(0,0,255);
  
  if( 50 > x ){   //画面内から出ないように描画
    x = 50;  
  }
  if( width - 50 < x ){
    x = width - 50;  
  }
  if( height/2 + 50 > y ){
    y = height/2+50;  
  }
  if( height - 50 < y ){
    y = height - 50;  
  }
  
  rect(x,y,100,100);
  
}

ビームを作成

シューティングといえば、ビームが発射されますよね。上から下に移動していくビームを作成しましょう。

ビームの座標、スピードを保持する変数、さらに、状態を遷移するようにフラグを立てておきましょう。

//ビーム関数用の変数
int beam_sp = 0;
int flag = 2;
int beam_posX = 0;
int beam_posY = 0;

ビームを発射するときには、マウスを押したときの処理とフラグで管理しています。マウスを押したとき、ビームの初期位置をマウスの位置に変更し、1度、スピードも0となります。その後、上に向かって移動していきます。画面外に到達したときは、フラグを2にして発射されていない最初の状態と同じになります。

void beam(int x,int y){ //ビーム描画用の関数

  if(mousePressed){ //マウスを押したときの処理
    flag = 0;
    beam_posX = x;//ビームの位置座標をマウスの位置にする
    beam_posY = y;
  }
  if(flag == 0){ //マウスを押したときにビームを初期位置に変更
    beam_sp = 0;
    flag = 1;
  }
  if(flag ==1){ //ビームの移動処理
    fill(0,255,150);
    rect(beam_posX,beam_posY-10-beam_sp,10,50);
    beam_sp += 20;
  }
  if(y-10-beam_sp <= 0){ //画面外にビームが出たときの処理
    beam_sp = 0;
    flag = 2;
  }
  
}

敵の作成

敵は複数ほしいので、自機とは違い、配列で変数を組み、個々の座標、スピードを管理します。

//敵の関数用の変数
int enemy_x[]=new int[10];
int enemy_y[]=new int[10];
int enemy_sp[]=new int[10]; 

敵の動きはx軸と水平に動き、画面端で折り返すように設定しています。また、ビームが衝突したときは、敵が消えるという動きを画面外に座標を変えることで実装しています。

void enemy(int x, int y, int sp){ //敵の描画
  rectMode(CENTER);
  fill(255,0,0);
  noStroke();
  for(int i=0;i<10;i++){
    
    rect(enemy_x[i],enemy_y[i],50,50);
    
    enemy_x[i] += enemy_sp[i]; //敵にスピードを付加
  
      if(enemy_x[i] >= width - 50){ //画面端に行ったら敵が折り返す
        enemy_sp[i]--;  
      }
      if(enemy_x[i] <= 50){
        enemy_sp[i]++;
      }
      //ビームが衝突した時の処理
      if((x < enemy_x[i]+25 && x > enemy_x[i]-25 && y-25-sp <= enemy_y[i]+25)
      || (x < enemy_x[i]+25 && x > enemy_x[i]-25 && y-25-sp <= enemy_y[i]+25)){
        enemy_sp[i] = 0;
        enemy_x[i] = -500;
        enemy_y[i] = -500;
        beam_sp = 0;
        flag = 2;
      }
  }
}

最終的なコードと実行結果が以下のようになります。

//ビーム関数用の変数
int beam_sp = 0;
int flag = 2;
int beam_posX = 0;
int beam_posY = 0;

//敵の関数用の変数
int enemy_x[]=new int[10];
int enemy_y[]=new int[10];
int enemy_sp[]=new int[10]; 

void setup(){
  size(1000,1000);
  background(255);
  
  for(int i = 0;i < 10;i++){
  enemy_x[i]=int(random(width));
  enemy_y[i]=int(random(50,400));
  enemy_sp[i]=int(random(3,5));
  }
}

void machine(int x, int y){ //自機を描画する関数
  rectMode(CENTER);
  noStroke();
  fill(0,0,255);
  
  if( 50 > x ){   //画面内から出ないように描画
    x = 50;  
  }
  if( width - 50 < x ){
    x = width - 50;  
  }
  if( height/2 + 50 > y ){
    y = height/2+50;  
  }
  if( height - 50 < y ){
    y = height - 50;  
  }
  
  rect(x,y,100,100);
  
}

void beam(int x,int y){ //ビーム描画用の関数

  if(mousePressed){ //マウスを押したときの処理
    flag = 0;
    beam_posX = x;//ビームの位置座標をマウスの位置にする
    beam_posY = y;
  }
  if(flag == 0){ //マウスを押したときにビームを初期位置に変更
    beam_sp = 0;
    flag = 1;
  }
  if(flag ==1){ //ビームの移動処理
    fill(0,255,150);
    rect(beam_posX,beam_posY-10-beam_sp,10,50);
    beam_sp += 20;
  }
  if(y-10-beam_sp <= 0){ //画面外にビームが出たときの処理
    beam_sp = 0;
    flag = 2;
  }
  
}

void enemy(int x, int y, int sp){ //敵の描画
  rectMode(CENTER);
  fill(255,0,0);
  noStroke();
  for(int i=0;i<10;i++){
    
    rect(enemy_x[i],enemy_y[i],50,50);
    
    enemy_x[i] += enemy_sp[i]; //敵にスピードを付加
  
      if(enemy_x[i] >= width - 50){ //画面端に行ったら敵が折り返す
        enemy_sp[i]--;  
      }
      if(enemy_x[i] <= 50){
        enemy_sp[i]++;
      }
      //ビームが衝突した時の処理
      if((x < enemy_x[i]+25 && x > enemy_x[i]-25 && y-25-sp <= enemy_y[i]+25)
      || (x < enemy_x[i]+25 && x > enemy_x[i]-25 && y-25-sp <= enemy_y[i]+25)){
        enemy_sp[i] = 0;
        enemy_x[i] = -500;
        enemy_y[i] = -500;
        beam_sp = 0;
        flag = 2;
      }
  }
}

void draw(){
  background(255);
  stroke(40);
  
  beam(mouseX,mouseY);//ビームを描画する関数呼び出し
  enemy(beam_posX,beam_posY,beam_sp);//敵を描画する関数呼び出し
  machine(mouseX,mouseY);//自機を描画する関数呼び出し
  
}

この段階では、点数や時間を実装していません。ゲームでは、そういった要素もありますので、改良してみてください。

カテゴリー
Processing

Processing(Step4)

文字を扱う

文字に関する関数には以下のようなものがあります。

  • text(表示するテキスト, x座標, y座標, 表示領域の幅, 表示領域の高さ)…文字を描画する
  • textSize(数字)…文字サイズを変更する
  • textAlign(位置)…文字揃えを指定する

この関数を使用し、コードを書いてみましょう。

void setup() {
  size(1000, 1000);
  background(255);
  PFont myFont = loadFont("Meiryo-48.vlw");//フォントの読み込み
  textFont(myFont);
}

void draw() {
  fill(0);
  textSize(100);
  textAlign(CENTER);
  text("あいうえお",width/2,height/2);
}

実行画面では、あいうえおが表示されるはずです。

この画像には alt 属性が指定されておらず、ファイル名は image-16-961x1024.png です

ただ、英語と違って問題があります。日本語のフォントが対応していないフォントがあります。そのため、日本語を利用する場合は特に注意が必要です。

ツール→フォント作成より日本語が扱えるフォントを作成しておかなければなりません。サイズ、スムーズ、文字(日本語)を指定してからOKを押すと、フォントのファイルがこのスケッチの保存先と同じ場所に保存されます。

その後、以下のコードを書いておくことでファイルの読み込みを行います。

PFont myFont = loadFont("Meiryo-48.vlw");//フォントの読み込み
textFont(myFont);

myFontという変数に保存しており、textFontの引数として指定することで変更しています。ちなみに変数の名前は自由に決められます。

配列

複数の変数を制御していときに用いるのが、配列である。例えば、以下のようにコードを書いてみるとする。

String char1 = "Hello";
String char2 = "Thank you";
String char3 = "Good";
String char4 = "Bye";
String char5 = "How are you?";

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

void draw() {
  fill(0);
  textSize(100);
  textAlign(CENTER);
  text(char1,width/2,height/3);
  text(char2,width/2,height/3+100);
  text(char3,width/2,height/3+200);
  text(char4,width/2,height/3+300);
  text(char5,width/2,height/3+400);
}

実行すると以下のように各文字が表示されると思います。

しかし、1つ1つ変数を宣言して記述するのは、大変ですよね。そこで、一括管理できる配列の出番です。

String char1 = "Hello";
String char2 = "Thank you";
String char3 = "Good";
String char4 = "Bye";
String char5 = "How are you?";

これを簡潔に書くとこのようになります。

String[] chat ={"Hello","Thank you","Good","Bye","How are you?"};

下の図のようにボックスで考えるとわかりやすいです。chatというなたくさんの空きボックスを作り、その1つずつに各文字を格納していくイメージです。 そのため、引き出す時は使いたいボックスの数字を指定して取り出してあげればいいのです。

引き出す時は、このように記述します。

text(chat[0],width/2,height/3);

0番目に入っているものを引き出すという意味になります。つまり、この場合はHelloが出力されます。

これを踏まえた上で、先ほどのコードをよりスマートに書くと以下のようになります。繰り返し処理と配列を使うことでスッキリとした見た目になると思います。このようにプログラムを書く上で、より簡潔に分かりやすくことが求められます。

String[] chat ={"Hello","Thank you","Good","Bye","How are you?"};

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

void draw() {
  fill(0);
  textSize(100);
  textAlign(CENTER);
  for(int i = 0; i <= 4; i++){
    text(chat[i],width/2,height/3 + i * 100);
  }
}

多次元配列

上で説明した配列よりもさらに拡張したのが多次元になります。2次元、3次元と配列を作っていくことができます。ここでは、2次元を解説します。2次元でも格納していくイメージですが、下の図のように考えるとわかりやすいでしょう。

横一列だったボックスが縦にも拡がっているでしょう。縦×横で2次元配列は成り立っています。続いて、コードと実行結果を見てみましょう。

int[][] num = {{0, 1, 2, 3, 4},
            {5, 6, 7, 8, 9},
            {10, 11, 12, 13, 14}};

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

void draw() {
  fill(0);
  textSize(100);
  textAlign(CENTER);
  for(int i = 0; i <=2; i++){
    for(int j = 0; j <=4; j++){
      text(num[i][j],width/5+j*150,height/3+i*150);
    }
  }
}

先ほどの図と比べてみてください。各数字が配列に格納されているのがわかりますよね。

int[][] num = {{0, 1, 2, 3, 4},
            {5, 6, 7, 8, 9},
            {10, 11, 12, 13, 14}};

このように記述することで、num[][]の中に、順番に数を格納しています。また、配列の中身を始めに指定せずに計算した値を格納することもできます。それが、次のコードです。

int[][] num = new int[3][5];

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

void draw() {
  fill(0);
  textSize(100);
  textAlign(CENTER);
  for(int i = 0; i <=2; i++){
    for(int j = 0; j <=4; j++){
      num[i][j] = int(random(0,14)); //ランダムな値を2次元配列に格納
      noLoop(); //ランダム関数の処理を終了
      text(num[i][j],width/5+j*150,height/3+i*150); //ランダムに配列に入った数字を出力
    }
  }
}

最初に以下のように入れ物である配列の行、列がいくつあるのか宣言しておくことで、入れ物の容量が決まります。

int[][] num = new int[3][5];

その後、ランダム関数で値を格納していきます。その際には繰り返し処理のfor文で、配列の行、列をずらしながら、格納しています。

num[i][j] = int(random(0,14)); //ランダムな値を2次元配列に格納

最終的な実行結果は、こんな感じになります。

時間を使う

プロセシング内では、時間を取り扱う関数も存在します。時間を使って行う処理や、単純に現在時刻を表示するなど用途は様々です。

  • hour()…時数を扱う
  • minute()…分数を扱う
  • second()…秒数を扱う

まずは、これを使って時間を表示してみましょう。以下がコードになります。

void setup() {
  size(1000,1000);
  frameRate(1); //フレームレートを1に設定(毎秒1回draw関数を実行)
  textSize(100);
  textAlign(CENTER);
  fill(0);
}

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

ここで大事なのがフレームレートの設定です。draw関数の実行される間隔が決まります。もし、1秒以外で設定すると秒数のカウントがずれるので、気をつけてください。

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

実行すると以下のようになります。

時間を視覚的に表現することも可能です。時間の値を図形の引数に使うことで、時間に合わせて動く四角形が作れます。

void setup() {
  size(1000,1000);
  frameRate(1); //フレームレートを1に設定(毎秒1回draw関数を実行)
  textSize(100);
  textAlign(CENTER);
  
}

void draw() {
  int h = hour(); //時
  int m = minute(); //分
  int s = second(); //秒
  
  background(255);
  
  noFill();
  strokeWeight(5);
  rect(0, 0, h*20, height/4); 
  rect(0, height/3, m*8, height/4);
  rect(0, height*2/3, s*8, height/4);
  
  fill(0);
  text(h + ":" + m + ":" + s,width/2,height); //コンソールに日時を表示
}
カテゴリー
Processing

Processing(Step3)

図形を並べる

for文の活用

Step2で図形を描画しましたが、例えば、100個の円を描画したいとなった時に1つずつ作っていたら、面倒くさいですよね。そのためには、Step1で学んだ繰り返し処理を用います。まずは、次のコードを実行してみましょう。

int n = 7; //並べる円の数

void setup()
{
    size(1000, 1000); 
    background(255); //背景色を白にする
    noStroke(); //図形の枠線を描かない
    fill(255,0,0); //図形の塗りつぶしを赤色にする
}

void draw()
{
  for(int i = 1; i <= n; i = i+1){//円の数が7になるまで繰り返し処理をする
  ellipse(100+i*100,height/2,100,100);//x軸を100ずつ増加させながら描画する
  }
}

実行すると、以下のような画面になると思います。

重要な処理はここのコードになります。

 for(int i = 1; i <= n; i = i+1){//円の数が7になるまで繰り返し処理をする
  ellipse(100+i*100,height/2,100,100);//x軸を100ずつ増加させながら描画する

for文を用いることで、連続して同じ円を表示しています。nの値をいじることで、円の数を好きに増やすことができるので、複数の図形など描きたいときに非常に楽になります。また、円の引数に繰り返し処理で使っているiを使うことで描画位置をずらしたり、大きさを変えていけるので値を色々といじってみると面白いです。

while文の活用

上記のプログラムはwhile文を用いても、同じように表示させることができます。書き換えた場合のコードは以下になります。

int i = 1; //繰り返し処理の基準値
int n = 7; //並べる円の数

void setup()
{
    size(1000, 1000); 
    background(255); //背景色を白にする
    noStroke(); //図形の枠線を描かない
    fill(255,0,0); //図形の塗りつぶしを赤色にする
}

void draw()
{
  while(i <= 7){//円の数が7になるまで繰り返し処理をする
  ellipse(100+i*100,height/2,100,100);//x軸を100ずつ増加させながら描画する
  i += 1;
  }
}

図形を動かす

まずは、以下のコードを実行してみましょう。

int x = 0; //円のx座標を保存する変数

void setup()
{
    size(1000,1000); //画面サイズを1000x1000にする
    background(255); //背景色を白色にする
    rectMode(CENTER); //四角形の描画モードを変更
}

void draw()
{
    noStroke(); //枠線なし
    fill(255,0,0); //塗りつぶし色を赤に設定
    rect(x, height/2, 200, 200);
    x = x + 1; //x座標を1増やす
}

これを実行すると、このような画面になると思います。

四角形が右にずっと描画されてしまうと思います。さらに、四角形の軌跡が残ってしまいます。なぜかというと、draw関数に書かれた処理は毎フレーム(一定の秒数毎)実行されてしまうので、上書きされてしまうのです。なので、描画するごとに背景を再度描画すれば、軌跡が残りません。以下のコードをdraw関数内に加えてみましょう。

background(255); //背景色を白色にする

そうすると、このようになります。

しかし、プログラムは実行し続けているので、四角形は永遠に右に描画し続けてしまいます。そこで、条件処理を付け加えることで、より四角形の動きをコントロールしましょう。

if文の活用

先ほどのコードに付け加え、以下のようにしてみましょう。

int x = 0; //円のx座標を保存する変数

void setup()
{
    size(1000,1000); //画面サイズを1000x1000にする
    background(255); //背景色を白色にする
    rectMode(CENTER); //四角形の描画モードを変更
}

void draw()
{
    background(255); //背景色を白色にする
    noStroke(); //枠線なし
    fill(255,0,0); //塗りつぶし色を赤に設定
    rect(x, height/2, 200, 200);
    x = x + 1; //x座標を1増やす
    if(x-100 > width)//四角形のx座標が画面サイズより大きくなったら
    { 
        x = 0; //x座標を0にする(四角形は左端に戻る)
    }
}

このif文が重要になります。

  if(x-100 > width)//四角形のx座標が画面サイズより大きくなったら
    { 
        x = 0; //x座標を0にする(四角形は左端に戻る)
    }

四角形左辺のx座標を画面のサイズと比較して、その値を超えたら、四角形のx座標を0に戻すことで、画面左端に再度描画されるということになります。

マウスに追従する

今までは、キャンバス上に描くだけでしたが、マウスの動きに合わせて動く円を作成したいと思います。プロセシングでは、マウスのクリックや位置を検出してくれる機能があるので、それを使います。まずはコードをコピーしてみましょう。

void setup() {
  size(1000, 1000);
  background(255); //背景色を白色にする
}

void draw() {
  background(255); //背景色を白色にする
  noStroke(); //枠線なし
  fill(255,0,0); //塗りつぶし色を赤に設定
  ellipse(mouseX, mouseY, 200, 200);
}

円の引数にmouseX、mouseYを設定することで描画される位置が、マウスに追従するようになります。

また、マウスが押されているときのみ表示するなら、こう書き換えます。

if (mousePressed == true){
  ellipse(mouseX, mouseY, 200, 200);
  }

if文を使い、条件を変え描画しています。mousePressedというマウスボタンを押しているときは検出します。それ以外にも使える関数があるので、以下にまとめて記載しておきます。

  • mousePressed…マウスボタンが押されたとき
  • mouseReleased…マウスボタンを離したとき
  • keyPressed…キーを押したとき(キーを指定することができる)

キーの処理をするときは以下のようにコードを書きます。

if ((keyPressed == true) && (key == 'a')){
}

ランダムを利用する

プロセシングでは、random関数を利用することで無作為に図形を描いたり、サイコロのように数字を出したりすることができます。以下のように記述するだけで利用できます。

random(最小値、最大値)

この引数のなかに例えば、最小値に0、最大値に100と入れれば、0~100未満の中から数字が無作為に選ばれます。(最大値のみの記述でもOK)これを利用するとこのようにコードが書けます。

int n = 7; //並べる円の数

void setup()
{
    size(1000, 1000); 
    background(255); //背景色を白にする
    noStroke(); //図形の枠線を描かない
}

void draw()
{
  for(int i = 1; i <= n; i = i+1){//円の数が7になるまで繰り返し処理をする
    fill(random(255),random(255),random(255)); //図形の塗りつぶしをランダムにする
    ellipse(100+i*100,height/2,100,100);//x軸を100ずつ増加させながら描画する
    
    if(i==7){
    noLoop(); //円を7つ書き終えたときにdraw()の繰り返し処理を止める
    }
  }
}

図形の塗りつぶしをランダム関数にすることで、描画する図形の色を変えています。

引数として値が取得できるものには、何でも使用できるので、図形の大きさ、位置、色等、様々なことに応用できます。自分で変数を設定し、ランダムな値を代入するには、以下のようにfloat型で指定する必要があります。

float color = random(100); 

実践的な条件分岐

図形を動かす時にも使ったようにif文を使えば、random関数で得た値でも、より細かく処理できるようになります。例えば以下のコードです。

int n = 7; //並べる図形の数
int m = 0; //図形を決める番号

void setup()
{
    size(1000, 1000); 
    background(255); //背景色を白にする
    noStroke(); //図形の枠線を描かない
    rectMode(CENTER);//四角形の描画モード変更
}

void drawTriangle(int x, int y, int r) {  //三角形を作る関数
  pushMatrix();
  translate(x, y);  // 中心となる座標
  rotate(radians(-90));

  // 円を均等に3分割する点を結び、三角形をつくる
  beginShape();
  for (int i = 0; i < 3; i++) {
    vertex(r*cos(radians(360*i/3)), r*sin(radians(360*i/3)));
  }
  endShape(CLOSE);

  popMatrix();
}

void draw()
{
  for(int i = 1; i <= n; i = i+1){//図形の数が7になるまで繰り返し処理をする
    fill(random(255),random(255),random(255)); //図形の塗りつぶしをランダムにする
    
    m = int(random(1,4));
    if(m == 1){
    ellipse(100+i*100,height/2,100,100);//x軸を100ずつ増加させながら描画する
    }
    if(m == 2){
    rect(100+i*100,height/2,100,100);//x軸を100ずつ増加させながら描画する
    }
    if(m == 3){
    drawTriangle(100+i*100,height/2,50);//x軸を100ずつ増加させながら描画する
    }
    
    if(i==7){
    noLoop(); //図形を7つ書き終えたときにdraw()の繰り返し処理を止める
    }
  }
}

プログラム内では、ランダムに選ばれた数によって描画する図形を分けています。1が出たら円、2が出たら四角、3が出たら、三角と定めています。実行すると、以下のようになります。

case文の活用

上のコードはcase文を用いても記述することができます。今回は3種類を場合分けしていますが、沢山条件を分けたいときには、こちらの方が使いやすい時もあります。以下がそのコードです。

int n = 7; //並べる図形の数
int m = 0; //図形を決める番号

void setup()
{
    size(1000, 1000); 
    background(255); //背景色を白にする
    noStroke(); //図形の枠線を描かない
    rectMode(CENTER);//四角形の描画モード変更
}

void drawTriangle(int x, int y, int r) {
  pushMatrix();
  translate(x, y);  // 中心となる座標
  rotate(radians(-90));

  // 円を均等に3分割する点を結び、三角形をつくる
  beginShape();
  for (int i = 0; i < 3; i++) {
    vertex(r*cos(radians(360*i/3)), r*sin(radians(360*i/3)));
  }
  endShape(CLOSE);

  popMatrix();
}

void draw()
{
  for(int i = 1; i <= n; i = i+1){//図形の数が7になるまで繰り返し処理をする
    fill(random(255),random(255),random(255)); //図形の塗りつぶしをランダムにする
    
    m = int(random(1,4));
    switch(m){
      case 1:
        ellipse(100+i*100,height/2,100,100);//x軸を100ずつ増加させながら描画する
        break;
      case 2:
        rect(100+i*100,height/2,100,100);//x軸を100ずつ増加させながら描画する
        break;
      case 3:
        drawTriangle(100+i*100,height/2,50);//x軸を100ずつ増加させながら描画する
        break;
      default:
      break;
    }
    if(i==7){
    noLoop(); //図形を7つ書き終えたときにdraw()の繰り返し処理を止める
    }
  }
}
カテゴリー
Processing

Processing(Step2)

Processingの基礎

テンプレート

プロセッシングでプログラムを行う上で必要となる2つのブロックがあります。それが、以下の2つです。

void setup()
{
//一度だけ実行される
}

void draw()
{
//繰り返し実行される
}

setup(){}内で書かれたコードは1度のみ、draw(){}では、何度も実行されます。まずは、setup(){}から使って見ましょう。次のコードをコピーして実行してみてください。

void setup()
{
    size(1000,1000); //画面サイズを1000x1000にする
    background(255,255,255); //背景色を白色にする
}

実行すると以下の白い画面が出力されると思います。

size(x,y)で、キャンバスを作成します。(x,y)は座標を引数として受け取ります。下の画像のようにxの値、yの値が決まります。プロセッシング内で図形などの配置をするものは同じように座標が決まるので、覚えておきましょう。

そして、background(R,G,B)によってキャンバスの色が変わります。()内は、色を決定するRGBの値は引数としています。

RGBカラーとは

光の三原色「R(赤)・G(緑)・B(青)」のことを表しています。値は1~255までで、(0,0,0)で黒色、(255,255,255)で白色になります。自分がどの色を使いたいか知りたいのでしたら、メニューバーのツール→色選択で各色のRGB値を確認できます。

図形を描画してみよう!

以下のコードを記述して、キャンバスに円を描いてみましょう。

void setup()
{
    size(1000,1000); //画面サイズを1000x1000にする
    background(255,255,255); //背景色を白色にする
    fill(0,0,255); //図形の塗りつぶし色を青にする
    stroke(0,255,0); //線の色を緑にする
    strokeWeight(10); //線の太さを10にする
}

void draw()
{
    ellipse(500, 500, 500, 500); //(500, 500)の位置に直径500の円を描く
}

円が描画できたと思います。新たにfill()とstroke()が出てきますが、どちらもRGB値を引数として図形の色を変更しています。また、strokeWeight()の引数に数字を入力することで、線の太さが変わります。円を描画するellipseでは、引数で(x座標, y座標, x軸の直径, y軸の直径)を取得しています。中の値を色々といじって確認してみましょう。座標には、現在のキャンバスのサイズを引数として取得でき、次のように書くと画面サイズが変わっても、中央に円を表示できます。

ellipse(width/2, height/2, 500, 500); //(横の長さの半分, 縦の長さの半分)の座標を軸に直径500の円を描く

続いて、同じプログラムのellipse()関数の下に以下のコードを書いてみましょう。

rect(500,500, 300, 300); //(500, 500)の位置に四角形を描く

実行すると以下のようになるはずです。円の上に四角形が描画されました。rext関数は、ellipse関数と同じように引数を取得しますが、図形の中心の座標ではなく、左上の頂点の座標になっているので、注意が必要です( rectMode(CENTER) を関数前に記述すれば、円と同じように引数を取れる)。また、基本ルールとして上から順にプログラムが実行されるとStep1で説明しましたが、図形は後から描画したものが、上書きされて表示されます。

2つの図形の色を変えたい場合は、どうしたらいいでしょうか?以下のコードを記述し、先ほどのコードと比較してみましょう。

void setup()
{
    size(1000,1000); //画面サイズを1000x1000にする
    background(255,255,255); //背景色を白色にする
}

void draw()
{
    fill(0,0,255); //図形の塗りつぶし色を青にする
    stroke(0,255,0); //線の色を緑にする
    strokeWeight(10); //線の太さを10にする
    ellipse(500, 500, 500, 500); //(500, 500)の位置に直径500の円を描く
    
    fill(255,0,0); //図形の塗りつぶし色を赤にする
    stroke(0,0,255); //線の色を青にする
    strokeWeight(5); //線の太さを5にする
    rect(500,500, 300, 300); //(500, 500)の位置に四角形を描く
}

変更した点は各図形を描画する前に色の変更をする関数を記述したことです。こう記述することにより、次の図形の色等を任意に変え、複数の図形を描画するコードにも対応できるようになりました。

もし、下の図形も見えるようにしたい場合、透過できることも覚えておいた方が良いでしょう。四角形の色を指定する際に以下のように4つ目の引数を与えてみましょう。

fill(255,0,0,200); //図形の塗りつぶし色を赤にする
    stroke(0,0,255,200); //線の色を青にする
    strokeWeight(5); //線の太さを10にする
    rect(500,500, 300, 300); //(500, 500)の位置に直径300の円を描く

そうすると、円が見えるようになるはずです。透明度は、カラーの指定後、0~255の値で設定できます。値が大きくなるほど、透過していきます。

画像を取り込んで見よう!

最初に以下のコードをコピーして実行してみてください。

PImage img;

void setup()
{
    size(1000, 1000);
    img = loadImage("logo.png");//画像の読み込み
}

void draw()
{
    background(255);//背景を白にする
    imageMode(CENTER); //画像の中心の座標指定を設定する
    image(img, width/2,height/2, 150, 150);//画像の位置、大きさを設定
}

エラーが出るはずです。それは、画像を読み込みたい場所から取得できないからです。そのため、まずは何か適当な画像を見つけて、このスケッチを保存した同じフォルダ内に保存してください。

コードの始めにPImageライブラリの定義を忘れないようにしましょう。

PImage img;

画像が違う名前であれば、プログラム内のこの部分を変更しましょう。””の中を保存した画像と同じ名称、そしてpngやjpgなどの形式を書き、変更してください。

実行すると、以下のように画像を表示することが出来ます。

音声を取り込もう!

画像と同じようにまずは、音声ファイルをダウンロードしておきましょう。保存場所も同じように使うスケッチと同じ場所に置いておきます。音を扱うためには、プロセッシングのライブラリからMinimというライブラリを使います。メニュー→スケッチ→ライブラリインポート追加から以下の画面に映ります。そして、Minimライブラリをインストールします。

その後、インポートから選択します。

スケッチに以下のコードが挿入されていれば、音を扱えるようになります。

import ddf.minim.*;

確認出来たら、以下のコード全てを記述しましょう。

import ddf.minim.*;
import ddf.minim.analysis.*;
import ddf.minim.effects.*;
import ddf.minim.signals.*;
import ddf.minim.spi.*;
import ddf.minim.ugens.*;

Minim minim;
AudioPlayer song;
 
void setup()
{
  minim = new Minim(this);
  song = minim.loadFile("ファイル名");//音楽ファイル読み込み
}

void draw()
{
}

void keyPressed()
{
  if ( key == 'K' )//Kキーを押したときに
  {
    song.play();//音楽をプレイする
  }
}
 
void stop()
{
  song.close();//音楽を止める処理
  minim.stop();
  super.stop();
}

これを実行すれば、Kキーを押したときに音楽が再生されます。

手順としては、Minimオブジェクトを作成し、定義します。

Minim minim;

void setup()
{
  minim = new Minim( this );
}

続いて、音源ファイルを読み込みます。準備段階の処理なので、setupメソッドで書いておくと良いです。

AudioPlayer song;
    :
void setup()
{
    :
song = minim.loadFile( "ファイル名" );

そして、上で生成したsongというAudioPlayerをplayで呼び出します。

song.play();

終わる時の処理も忘れてはならないです。スケッチが終了される時に呼び出されるメソッド、stopの中に記述することで処理が完了します。

void stop()
{
  song.close();
  minim.stop();
  super.stop();
}

カテゴリー
Processing

Processing(Step1)

開発環境のセットアップ

Processingの導入

下記サイトよりダウンロードして使うことができます。https://processing.org/download/

下の画像にある赤丸に囲まれた部分から自分のパソコンにあったソフトウェアを選択してくだい。ダウンロードが終了したら、デスクトップにショートカットを作って置くと次から使いやすいです。

ソフトの起動

まずは、起動してみましょう。すると、次の画面になるので、矢印のファイル(File)から日本語設定をしましょう。最初から設定されている場合は次へ進みましょう。

以下の3点に気をつけて設定してください。

  • 言語が日本語かどうか
  • フォントをMacなら”Osaka”、Windowsなら”Ms Gothic”に変更する。(コード内のコメントが日本語にならない場合)
  • テキストの複雑な入力を有効にするにチェックを入れる

画面の見方

下の画像の通り、エディタ部分にコードを記述し、実行。コンソールに出力されるようになっています。1つ1つのファイルはスケッチと呼ばれます。

はじめに、以下のコードをエディタにコピー&ペーストして実行を押し、結果を確認してみましょう。

println("Hello World!");

成功すると、以下の画像のようにコンソールに”Hello World!”が表示されます。これが、プログラミングの第一歩となります。

スケッチの保存

左上のファイルから保存をすることができます。保存先はわかりやすい場所に設定しておくと良いです。また、”開く”から自分の保存したスケッチを読み込むことができます。

プログラミングの基本

プログラムは上から

行単位でコードを記述していきますが、基本的には上から順に実行されていきます。そのため、記述する順番には気をつけなければいけません。

コメントを書く

以下のコードのように、プログラムを記述した後に「//」または「/*~*/」を用い入力されたものはコメントと呼ばれます。これは、ソースコードの一部として認識されないので、どんな処理を行うプログラムなのか残しておくものです。他の人が見ても分かりやすいように常に書いておくことを意識しましょう。また、コードを書く時にはセミコロン(;)を忘れないようにしましょう。

println("Hello World!");//Hello Worldの文字列を出力
println("Hello World!");/*Hello Worldの文字列を出力*/

変数と型

リテラル

リテラルとは、プログラミング用語を1つで、値を表しています。あなたが普段使う数字や文字などは、ソースコードを記述する際には、違う扱い方をしなければなりません。例えば、このように記述されます。

2020 //整数リテラル
2020.0 //浮動小数点リテラル
"2020" //文字列リテラル

*同じ数字でも文字として記述する場合は、””(ダブルクォーテーション)で囲まなければいけません。平仮名、カタカナ、漢字でも同じです。

変数と型

まずはじめに変数とは、値を格納しておく入れ物のようなものと考えておくといいでしょう。

int a = 5; //int型の変数aを宣言して5を代入する
float b = 3.14 //float型の変数bを宣言して3.14を代入する
String str = "Hello World!" //String型の変数strを用意して文字列Hello World!を代入

上のように記述すると、a, b, strにはそれぞれ5, 3.14, HelloWorld!と値が代入されます。

上のコードにあるintfloatStringといったものは型と呼ばれます。変数は入れ物といいましたが、どんな入れ物を入れるか決めるのが、型になります。例えば、intを記述すれば、その入れ物には整数しか入れられません。小数点や、文字を保持することができないのです。型には以下のような種類があります。この項目では、よく使う型を挙げています。

Primitive(プリミティブ)型 …基本的な整数、浮動小数点といったものを扱う型

  • int: 整数を扱う型。-2147483648から+2147483647までの32bitの値を扱えます。
  • long:intと同じで整数を扱えますが、64bitの値を扱えます。-9223372036854775808から+9223372036854775807までの値が使えます。
  • float:浮動小数点を扱う型です。簡単に言えば、円周率などの3.14など小数点を持つ型で32bitまで、扱えます。
  • double:floatと同じ、浮動小数点を扱う型ですが、64bitまで扱え、小数第6以上等の高い精度が必要なものに使います。
  • char:16bitの整数を扱う型ですが、プロセッシングでは、文字1文字を使うときに多用されます。例えば、”あ”を保持したいときなど。
  • boolean:true(真) or false(偽)のどちらか1つを扱います。YesかNoのように2種類の状態を何かを処理したいときに使います。

Composite(コンポジット)型…沢山のデータを扱うときに使う型。種類は色々ありますが、まずはString型を覚えておくと良いでしょう。

  • String:文字列を扱う型で、char型では1文字ですが、これは複数の文字を扱う時に使用します。

変数の宣言

型を利用して、変数を宣言しましょう。プログラムで使うためには、使いますよと始めに書いておかなければなりません。以下のように初めに、宣言をして後に数字を代入しても良いし、宣言時に値を決めておくこともできます。注意として、”=”は普通なら同じと意味ですが、プログラミングでは代入という意味もあることを頭に入れておいて下さい。

int a; //int型の変数aを宣言
a = 5; //変数aに5を代入
float f = 5.5; //float型の変数fを宣言し、5.5を代入

演算子

四則演算

基本的なルールは数学で習った計算のルールに沿って、計算を行います。以下はコードでの表記の仕方です。

1 + 1 //足し算(プラス)
2 - 3 //引き算(マイナス)
4 * 5 //掛け算(アスタリスク)
6 / 3 //割り算(スラッシュ)
7 % 3 //余剰演算子(パーセンテージ)答えは7/3の余りの1

()を使えば、普段の計算通り、先に計算する方を指定することもできます。

(1 + 1) * 4 //答え8

また、変数の宣言時にも計算結果を代入することができます。

int a = 3;
int b = 2 * 3; //b = 6
int c = a * 4; //c = 12

文字列

以下のコードのように文字列でも足し算を行うことができます。ただし、引き算はできないので、注意が必要です。

String a = "Hello";
String b = "World";
String c = a + c ; //Hello World

条件式

コードを書いていくと条件によって、異なる処理をしたい場合がでてくると思います。そんな時に条件式が必須になってきます。以下がその書き方です。主に大なり、小なり、イコールといった数学のルールに沿った書き方をします。

a >= 5 //aは5以上である
a > 5 //aは5より大きい(5は含まない)
b <= c //bはc以下である
b < c //bはcより小さい(cは含まない)
x == 10 //xは10と等しい

また、複数の条件を使うこともできます。「&&」でandの意味、「||」でorの意味になります。これを使うことで複雑な処理ができるようになるので、覚えておきましょう。

x > 1 && x < 10 //xは1より大きいかつ10より小さい
x <= y || 5 > z //xはy以下またはzが5より小さい
x == 1 && y == 5 && z == 7 //xは1かつyは5かつzは7

関数

関数はメソッドとも呼ばれ、ある機能を持った命令のことです。これを知っておくことで色々なコードを記述することができますので、是非覚えておきましょう。例えばこちらです。println()は文字列を表示する関数です。()の中身は引数と呼ばれ、この中に入力するものによって出力されるものが変わります。

println("Hello World!");

*関数によっては戻り値と呼ばれる値を返すものもあり、その戻り値によって他の処理をする場合もあります。

関数一覧はこちらから

条件分岐、繰り返し構文

ある条件の時に実行したい処理がある場合には、以下の3つの文を利用してプログラムを組みます。

繰り返し構文、条件分岐

同じ処理を何度もしたいけど、沢山書くのは大変、そんな時に使うのが繰り返し構文になります。

for文

for()の中に書かれた条件だけ、{}内の処理が繰り返されます。

for (初期化式; 条件式; 再初期化式) 
{
    //繰り返し実行される
}

例えば、以下のように書いた場合、iの値が5になるまでprintlnをi回繰り返すということになります。

for(int i = 1; i <= 5; i = i + 1)
{
    println(i);
}

while文

for文と同じように繰り返し実行するもので、この2つを上手く使い分けてコードを書いていきましょう。

while(条件式)
{
    //条件式を満たしている間だけ繰り返し実行する
}

先ほどのfor文をwhile文で直したものが以下のようになります。

int i = 1; //int型の変数iを用意して1を代入
while(i <= 5) //iが5以下の間
{ 
    println(i);
    i = i + 1; //iの数を1増やす
}

if~else文

この文は、ある特定の条件で実行する内容を変えたいときに使います。

if(条件式)
{
    //条件式が真であるときのみこのブロック内のコードが実行させる
} 
else 
{
    //どの条件式も満たさないとき
}

例えば、入力された値が5より大きいならYes、そうでないならNoという処理をしたいなら以下のように書きます。

int a = 5;
if(a > 5)
{
    println("Yes");
} 
else 
{
    println("No");
}

switch文

3つより沢山の選択肢から何かを選ぶときには使いやすい文です。上のif文を使っても記述できますが、こちらの方が分かりやすいかもしれません。

switch(条件式) {
	case :
	case :
	case :
	case :
	default:break;
}

例えば、数字1,2,3の中から2が出たときに正解とするなら、以下のようになります。注意として条件式には整数に変換できる型のみが使用できます(byte、char、intなど)。また、case毎にbreakがない場合以下が勝手に実行されるので、気をつけましょう。

int a = 2;
switch(a) {
	case 1:
               println("不正解");
        break; 
	case 2:
               println("正解");
               break;
	case 3:
               println("不正解");
              break;
	default:
                println("該当しません");
                break;
}