シンプルペイント

シンプルなお絵かきアプリを作成してみましょう。

課題

ステップ1

マウスの現在の座標は(mouseX, mouseY)で取得できます。1フレーム前のマウスの座標は(pmouseX, pmouseY)で取得できます。これら2つの点をline関数で結ぶと、マウスの軌跡が描画できます。

line(mouseX, mouseY, pmouseX, pmouseY)

これを使って、単にマウスの軌跡を描画してください。マウスが押されているときだけ線が描画されるものとします。画面のサイズは800 x 700としてください。

ステップ2

画面上部にパレットとなる矩形を描画してください。
SimplePaint1
各マスのサイズは100x100とします。この段階ではまだ配列をつかわずに、単にfillで色を設定し、rectで矩形を描画するという処理を8回繰り返してください。今回は以下のような色を配置しました。

  fill(0, 0, 0);
  fill(255, 0, 0);
  fill(255, 216, 0);
  fill(76, 255, 0);
  fill(0, 255, 33);
  fill(0, 148, 255);
  fill(178, 0, 255);
  fill(255, 255, 255);

上記パレットがクリックされたら、その色の線が描画されるようにしてください。マウスのクリックはmousePressed関数を使って検出してください。線の色はstroke関数で指定します。
SimplePaint2

ステップ3

ステップ2の内容を配列を使って書き換えてください。色の配列は以下のように宣言します。現在選択されている色をcurrentColor変数で保持してください。

color[] palette = {
  color(0, 0, 0),
  color(255, 0, 0),
  color(255, 216, 0),
  color(76, 255, 0),
  color(0, 255, 33),
  color(0, 148, 255),
  color(178, 0, 255),
  color(255, 255, 255)
};
color currentColor = color(0, 0, 0);

i番目の色を取得するには palette[i] とアクセスします。

ステップ4

ENTERキーを押すと画面がクリア、数字の1~9を押すと線の太さをその値に変更されるようにしてください。
キー入力を検出するためにkeyPressed関数を使います。どのキーが押下されたかは変数key、もしくはkeyCodeを参照します。

  • key = どのキーが押されたか、その文字を返します。ただし上下左右キーやShift、Ctrlなどのキーは取得できません
  • keyCode = 各キーに割り当てられたコードをかえします。
    keyやkeyCodeにどのような値が格納されているかは調べることもできますが、println関数を使ってコンソールに出力するのが簡単です。
  • 1 = keyCode:49
  • 2 = keyCode:50
  • ...
  • 9 = keyCode:57
  • ENTER = keyCode:10
    SimplePaint3

解答例

ステップ1

void setup(){
  size(800, 700);
}

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

マウスが押されているか否かは変数mousePressedを参照します。今回のように、描画するときにマウスが押されているか否か調べる場合には、draw関数の中からmousePressed変数を参照しますが、マウスが押下されたときに何等かの処理を行う場合はmousePressed関数を定義します。変数名と関数名が同じなので混乱しがちです。適宜使い分けられるようになってください。

ステップ2

void setup(){
  size(800, 700);
}

void draw(){
  fill(0, 0, 0);
  rect(0, 0, 100, 100);
  fill(255, 0, 0);
  rect(100, 0, 100, 100);
  fill(255, 216, 0);
  rect(200, 0, 100, 100);
  fill(76, 255, 0);
  rect(300, 0, 100, 100);
  fill(0, 255, 33);
  rect(400, 0, 100, 100);
  fill(0, 148, 255);
  rect(500, 0, 100, 100);
  fill(178, 0, 255);
  rect(600, 0, 100, 100);
  fill(255, 255, 255);
  rect(700, 0, 100, 100);
  
  if (mousePressed){
    line(mouseX, mouseY, pmouseX, pmouseY);
  }
}

void mousePressed(){
  if (0 < mouseX && mouseX < 100 && mouseY < 100) {
    stroke(0, 0, 0);
  }
  if (100 < mouseX && mouseX < 200 && mouseY < 100) {
    stroke(255, 0, 0);
  }
  if (200 < mouseX && mouseX < 300 && mouseY < 100) {
    stroke(255, 216, 0);
  }
  if (300 < mouseX && mouseX < 400 && mouseY < 100) {
    stroke(76, 255, 0);
  }
  if (400 < mouseX && mouseX < 500 && mouseY < 100) {
    stroke(0, 255, 33);
  }
  if (500 < mouseX && mouseX < 600 && mouseY < 100) {
    stroke(0, 148, 255);
  }
  if (600 < mouseX && mouseX < 700 && mouseY < 100) {
    stroke(178, 0, 255);
  }
  if (700 < mouseX && mouseX < 100 && mouseY < 100) {
    stroke(255, 255, 255);
  }
}

上部に矩形を描画しています。また、マウスの押下をmousePressed関数で検出し、その座標(mouseX, mouseY)の値に応じて、stroke関数で線の色を設定しています。単純ですが繰り返しが多く冗長な感は否めません。

ステップ3

color[] palette = {
  color(0, 0, 0),
  color(255, 0, 0),
  color(255, 216, 0),
  color(76, 255, 0),
  color(0, 255, 33),
  color(0, 148, 255),
  color(178, 0, 255),
  color(255, 255, 255)
};
color currentColor = color(0, 0, 0);

void setup(){
  size(800, 700);
}

void draw(){  
  if (mousePressed){
    stroke(currentColor);
    line(mouseX, mouseY, pmouseX, pmouseY);
  }
  for(int i = 0 ; i < 8 ; i++) {
    noStroke();
    fill(palette[i]);
    rect(i*100, 0, 100, 100);
  }
}

void mousePressed(){
  int i = (int)(mouseX / 100);
  if (mouseY < 100){
    currentColor = palette[i];
  }
}

for文を使うことでコードがすっきりして変更もしやすくなりました。パレットをrect関数で描画していますが、その周囲の枠線を描画したくなかったのでnoStroke関数を呼び出しています。

ステップ4

color[] palette = {
  color(0, 0, 0),
  color(255, 0, 0),
  color(255, 216, 0),
  color(76, 255, 0),
  color(0, 255, 33),
  color(0, 148, 255),
  color(178, 0, 255),
  color(255, 255, 255)
};
color currentColor = color(0, 0, 0);

void setup(){
  size(800, 700);
}

void draw(){  
  if (mousePressed){
    stroke(currentColor);
    line(mouseX, mouseY, pmouseX, pmouseY);
  }
  for(int i = 0 ; i < 8 ; i++) {
    noStroke();
    fill(palette[i]);
    rect(i*100, 0, 100, 100);
  }
}

void mousePressed(){
  int i = (int)(mouseX / 100);
  if (mouseY < 100){
    currentColor = palette[i];
  }
}

void keyPressed(){
  if (49 <= keyCode && keyCode <= 57) {
    strokeWeight(keyCode - 48);
  }
  if (keyCode == 10) {
    background(200);
  }  
}

数字1~9が押下された場合、そのkeyCodeは49~57の範囲に収まります。その値から48を引いた値を線の太さとして、strokeWeight関数で設定しています。ENTERキーが押下されたとき、すなわちkeyCodeが10だったときはbackground関数を使って画面をクリアしています。