07-04 画像ファイルの読み込み

練習問題7-4-2

例題7-4-1 では、画像を 元の大きさのまま 左上に置きました。
image() に幅と高さを指定すると、表示サイズを変えられます。

次のように表示しなさい。

  • 画像の左上が キャンバスの中央
  • 幅 100、高さ 100
let stamp;

function preload() {
  stamp = loadImage("stamp.png");
}

function setup() {
  createCanvas(300, 300);
  background(249, 244, 229);

  // image(画像, x, y) … 左上が (x, y) になる位置に描く
  image(stamp, width/2, height/2, 100, 100);
}
textを読み込むときも最初は簡単だったので、もうだまされません
どうせまためちゃくちゃ難しくなるに違いありません

練習問題7-4-3

練習問題7-4-2 では、松ぼっくりが 歪み、しかも 中心からずれて 表示されました。
読み込んだ画像の もともとの幅と高さ は、stamp.width と stamp.height で調べられます。

次のプログラムを完成させなさい。

  • 幅を 100 に固定し、高さは比率が崩れないように計算する
  • 画像の 中心 が、キャンバスの 中心 に来るように表示する
let stamp;

function preload() {
  stamp = loadImage("stamp.png");
}

function setup() {
  createCanvas(300, 300);
  background(249, 244, 229);
  let w = 100
  let h = stamp.height/stamp.width
  print(w)
  print(h)
  // image(画像, x, y) … 左上が (x, y) になる位置に描く
  image(stamp, width/2-w/2, height/2-h*w/2, w, w*h);
}
数学は苦手ではありませんが得意でもない私にとっては結構難しかったです。ヒントを見ないとできませんでした。

練習問題7-4-4

クリックした位置に松ぼっくりのスタンプを置くプログラムを作りましょう。
06-04 や 06-05 と同じく、座標は配列に保存し、draw のたびに描き直します。

  • 左クリック … クリック座標を stampX / stampY に push
  • draw … 方眼を描いたあと、保存した座標すべてにスタンプを描く
  • スタンプの 幅は 40。高さは練習問題7-4-3 と同じく、比率が崩れないように計算する
  • スタンプの 中心 がクリック位置になるようにしなさい(左上ではなく中心)
let stamp;
let stampX = [];
let stampY = [];

function preload() {
  stamp = loadImage("stamp.png");
}

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(249, 244, 229);
  drawGrid();
  drawStamps();
}

function drawGrid() {
  stroke(220);
  strokeWeight(1);
  for (let x = 0; x <= width; x += 20) {
    line(x, 0, x, height);
  }
  for (let y = 0; y <= height; y += 20) {
    line(0, y, width, y);
  }
}

function drawStamps() {
  let w = 40
  let h = stamp.height/stamp.width
  for(let i=0; i < stampX.length; i++){
    image(stamp, stampX[i]-w/2, stampY[i]-w*h/2, w, w*h)
  }
}

function mousePressed() {
  if(mouseButton === LEFT){
    stampX.push(mouseX)
    stampY.push(mouseY)
  }
}
やっぱり行が増えると、管理が難しくなってきますね、
それに加えて、スペルミスも治りません。

例題7-4-5

ここまで、スタンプはいつも同じ向きでした。向きを変えて描くには、いったん描画空間を移動・回転させてから image() を呼びます。その操作に translate と rotate を使います。

まず 1枚だけ をキャンバス中央で 斜めに 描いてみましょう。
次のプログラムを入力して実行し、新しく出てきた命令について自分でまとめなさい。

予想なのであっているかはわかりませんが、translateは関与できる図形や画像のxとyを先に入れておいて、次のxやyを設定するときからも関与できるけれど見えなくして、見やすくするためにあると思いました。
rotateは図形や画像の回転軸をずらせると思いました。
答えを聞いてからのまとめ
translateはpushからpopまでの間、原点を移動させる
rotateは原点を中心に世界を回すイメージ

練習問題7-4-6

練習問題7-4-4 を改造し、スタンプが ランダムな角度 で置かれるようにしなさい。

  • 例題7-4-5 と同じく、push → translate → rotate → image → pop の順で描く
  • 角度は stampAngle 配列に保存し、クリック時に random(360) で決める
let stamp;
let stampX = [];
let stampY = [];
let stampAngle = [];

function preload() {
  stamp = loadImage("stamp.png");
}

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(249, 244, 229);
  drawGrid();
  drawStamps();
}

function drawGrid() {
  stroke(220);
  strokeWeight(1);
  for (let x = 0; x <= width; x += 20) {
    line(x, 0, x, height);
  }
  for (let y = 0; y <= height; y += 20) {
    line(0, y, width, y);
  }
}

function drawStamps() {
  let w = 40
  let h = stamp.height/stamp.width
  for(let i=0; i < stampX.length; i++){
    push()
    translate(stampX[i], stampY[i])
    rotate(stampAngle[i])
    image(stamp,-w/2, -w*h/2, w, w*h)
    pop()
  }
}

function mousePressed() {
  if(mouseButton === LEFT){
    stampX.push(mouseX)
    stampY.push(mouseY)
    stampAngle.push(Math.ceil(random(359)))
  }
}
仕組みは理解していたので簡単にできる想定でしたが、結構やることが多くて、その過程で大量のミスを量産しましたが、今回は様々なエラーをAIに頼らずに解決することができました。

練習問題7-4-7

アニメ「ゆるキャン△」でおなじみの 「\コンニチワ/」 を、各松ぼっくりの  に表示しなさい。

  • 文字の位置X:画像の左右中央
  • 文字の位置Y:画像より 10px 上
  • 文字サイズ:9pt
let stamp;
let stampX = [];
let stampY = [];
let stampAngle = [];

function preload() {
  stamp = loadImage("stamp.png");
}

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background(249, 244, 229);
  drawGrid();
  drawStamps();
}

function drawGrid() {
  stroke(220);
  strokeWeight(1);
  for (let x = 0; x <= width; x += 20) {
    line(x, 0, x, height);
  }
  for (let y = 0; y <= height; y += 20) {
    line(0, y, width, y);
  }
}

function drawStamps() {
  let w = 40
  let h = stamp.height/stamp.width
  textAlign(CENTER, BOTTOM)
  textSize(9)
  for(let i=0; i < stampX.length; i++){
    push()
    translate(stampX[i], stampY[i])
    rotate(stampAngle[i])
    image(stamp,-w/2, -w*h/2, w, w*h)
    text("\コンニチワ/", 0, -w*h/2-10)
    pop()
  }
}

function mousePressed() {
  if(mouseButton === LEFT){
    stampX.push(mouseX)
    stampY.push(mouseY)
    stampAngle.push(Math.ceil(random(359)))
  }
}
左右中央っていうのがよくわからなかったですが、多分これであっていると思います。

コメントする