06-04 クリック位置を配列に保存

練習問題6-4-1

第4章の 配列 を思い出しながら、クリックした座標を記録するところから始めましょう。
次の雛形の ??? を埋めて完成させなさい。

let starX = [];
let starY = [];

function setup() {
  createCanvas(400, 400);
  background(18, 24, 60);
}

function draw() {
}

function mousePressed() {
  // ここに配列の記録処理を書く
  starX.push(mouseX)
  starY.push(mouseY)

  // デバッグ用
  print("starX = " + starX);
  print("starY = " + starY);

  // 星の描画
  drawStar(mouseX, mouseY, 36, 10);
}

function drawStar(x, y, w, h) {
  noStroke();
  fill(255, 230, 160);
  ellipse(x, y, w, h);
  ellipse(x, y, h, w);
}
復習という感じでしたのであまり感想はないです。

練習問題6-4-2

練習問題6-4-1 では、mousePressed の中で星を描いていました。
配列に保存した座標を使い、draw の中で すべての星を描き直す プログラムに改造しなさい。

let starX = [];
let starY = [];

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

function draw() {
  background(18, 24, 60);
  noStroke();
  for(let i=0; i<starX.length; i++){
    drawStar(starX[i], starY[i], 36,10)
  }
}

function mousePressed() {
  starX.push(mouseX);
  starY.push(mouseY);
}

function drawStar(x, y, w, h) {
  fill(255, 230, 160);
  ellipse(x, y, w, h);
  ellipse(x, y, h, w);
}

条件がi<starX.lengthだと、starXしか参照しないので、starYの数が違う場合は変になってしまいますが、このプログラムだとそれはないので、Xだけにしました。

練習問題6-4-3

練習問題6-4-2 では、星は 静止 していました。
06-01 で学んだ frameCount を使い、星を キラキラ光らせ なさい。

キラキラさせるには、星の大きさを draw が呼ばれる たびに切り替える 必要があります。
frameCount が 30フレーム(カウント)ごと に、星の大きさを 36 と 44 で切り替えてください。

let starX = [];
let starY = [];

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

function draw() {
  background(18, 24, 60);

  noStroke();
  for (let i = 0; i < starX.length; i++) {
    let w=36
    if(frameCount%60<30){
      w=44
    }
    drawStar(starX[i], starY[i], w, w * 0.28);
  }
}

function mousePressed() {
  starX.push(mouseX);
  starY.push(mouseY);
}

function drawStar(x, y, w, h) {
  fill(255, 230, 160);
  ellipse(x, y, w, h);
  ellipse(x, y, h, w);
}

大きさを変えるタイミングや大きさを一定時間保持するところで、結構時間がかかりました。

練習問題6-4-4

練習問題6-4-3 で星がキラキラ光るようになりました。
クリックした 順番どおり に、隣り合う星同士を line で結び、星座 にしてみましょう。

線は星より 先に 描いてください。右クリックの操作は、まだ入れなくてかまいません。
次の雛形の ??? を埋めて完成させなさい。

let starX = [];
let starY = [];

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

function draw() {
  background(18, 24, 60);
  stroke(80, 50, 120)
  strokeWeight(5)
  // 星と星を線で結ぶ
  for(let i=0; i<starX.length; i++){
    line(starX[i], starY[i], starX[i+1], starY[i+1])
  }
  // 星を描く
  noStroke();
  for (let i = 0; i < starX.length; i++) {
    let w;

    if (frameCount % 60 < 30) {
      w = 36;
    } else {
      w = 44;
    }
    drawStar(starX[i], starY[i], w, w * 0.28);
  }
}

function mousePressed() {
  starX.push(mouseX);
  starY.push(mouseY);
}

function drawStar(x, y, w, h) {
  fill(255, 230, 160);
  ellipse(x, y, w, h);
  ellipse(x, y, h, w);
}
この課題ではすぐにline(starX[i], starY[i], starX[i+1], starY[i+1])という書き方を思いつきましたが、いざ書いてみると、線が表示されず、考えてもわからなかったのでAIに聞きました。ところがAIが言ってきたのはor (let i = 0; i < starX.length; i++)ここはor (let i = 0; i < starX.length-1; i++)のほうが正しいということでした。そしてそれを踏まえてもう一度考えてみると、どうやら線がnoStrokeの影響で描かれていなかったことに気づき、修正しました。

練習問題6-4-5

練習問題6-4-4 では、線は 常に 表示されていました。
今度は、線を 描いたり、消したり できるようにします。

let canvas;
let starX = [];
let starY = [];
let showLines = false;

function setup() {
  canvas = createCanvas(400, 400);
  canvas.elt.addEventListener("contextmenu", function (e) {e.preventDefault();});
}

function draw() {
  background(18, 24, 60);

  // 星と星を線で結ぶ
  stroke(200, 200, 255, 120);
  strokeWeight(5);
  if(showLines){
    for (let i = 0; i < starX.length - 1; i++) {
      line(starX[i], starY[i], starX[i + 1], starY[i + 1]);
    }
  }

  // 星を描く
  noStroke();
  for (let i = 0; i < starX.length; i++) {
    let w;

    if (frameCount % 60 < 30) {
      w = 36;
    } else {
      w = 44;
    }
    drawStar(starX[i], starY[i], w, w * 0.28);
  }
}

function mousePressed() {
  if(mouseButton===LEFT){
    starX.push(mouseX);
    starY.push(mouseY);
  }
  if(mouseButton===RIGHT){
    if(showLines){
      showLines=false
    }else{
      showLines=true
    }
  }
}

function drawStar(x, y, w, h) {
  fill(255, 230, 160);
  ellipse(x, y, w, h);
  ellipse(x, y, h, w);
}

これはものすごく難しかったです。覚えていることを使うのはある程度できるのですが、知らないことを手探りでやるのはものすごく大変でした。なので途中からAIに相談しながら作りました。最初に手間取ったのはtrueとfalseの使い方が全く分かりませんでした。イメージとしては裏で使われているものだと思っていたので、使い方に気づくまで結構時間がかかりました。
次に出てきた問題は右クリックと左クリックの判定方法がわからないという物です。ここで行き詰まり、AIに相談しました。最初はプログラムだけをそのまま張り付けてしまい、いろいろな訂正を受けました。ifのtrueとfalseの判断は変数だけでできるということと、誤字やmousePressedを二つ書くと後ろのプログラムしか動作しないなどを教わりました。その後mouseButtonを使うといいといわれました。そこからはたくさんの凡ミスをしながらもAIに教えてもらい何とか完成させました。

練習問題6-4-6

練習問題6-4-5 を改造し、C キー を押したら星を すべて消す プログラムを作りなさい。

let canvas;
let starX = [];
let starY = [];
let showLines = false;

function setup() {
  canvas = createCanvas(400, 400);
  canvas.elt.addEventListener("contextmenu", function (e) {e.preventDefault();});
}

function draw() {
  background(18, 24, 60);

  // 星と星を線で結ぶ
  stroke(200, 200, 255, 120);
  strokeWeight(5);
  if(showLines){
    for (let i = 0; i < starX.length - 1; i++) {
      line(starX[i], starY[i], starX[i + 1], starY[i + 1]);
    }
  }

  // 星を描く
  noStroke();
  for (let i = 0; i < starX.length; i++) {
    let w;

    if (frameCount % 60 < 30) {
      w = 36;
    } else {
      w = 44;
    }
    drawStar(starX[i], starY[i], w, w * 0.28);
  }
}
function keyPressed(){
  if(key === "c"){
    starX=[]
    starY=[]
  }
}

function mousePressed() {
  if(mouseButton===LEFT){
    starX.push(mouseX);
    starY.push(mouseY);
  }
  if(mouseButton===RIGHT){
    if(showLines){
      showLines=false
    }else{
      showLines=true
    }
  }
}

function drawStar(x, y, w, h) {
  fill(255, 230, 160);
  ellipse(x, y, w, h);
  ellipse(x, y, h, w);
}
少しわからないところがあったのでAIに聞きました。聞いたのは配列の中身を空っぽにする方法です。

練習問題6-4-7

現在、すべての星が 同じタイミング で明滅しています。
より夜空らしく見えるように、練習問題6-4-6 のプログラムを改造し、星ごとに明滅のタイミングがずれるようにしなさい。

let canvas;
let starX = [];
let starY = [];
let showLines = false;

function setup() {
  canvas = createCanvas(400, 400);
  canvas.elt.addEventListener("contextmenu", function (e) {e.preventDefault();});
}

function draw() {
  background(18, 24, 60);

  // 星と星を線で結ぶ
  stroke(200, 200, 255, 120);
  strokeWeight(5);
  if(showLines){
    for (let i = 0; i < starX.length - 1; i++) {
      line(starX[i], starY[i], starX[i + 1], starY[i + 1]);
    }
  }

  // 星を描く
  noStroke();
  for (let i = 0; i < starX.length; i++) {
    let w;

    if ((frameCount+starX[i]+starY[i])% 60 < 30) {
      w = 36;
    } else {
      w = 44;
    }
    drawStar(starX[i], starY[i], w, w * 0.28);
  }
}
function keyPressed(){
  if(key === "c"){
    starX=[]
    starY=[]
  }
}

function mousePressed() {
  if(mouseButton===LEFT){
    starX.push(mouseX);
    starY.push(mouseY);
  }
  if(mouseButton===RIGHT){
    if(showLines){
      showLines=false
    }else{
      showLines=true
    }
  }
}

function drawStar(x, y, w, h) {
  fill(255, 230, 160);
  ellipse(x, y, w, h);
  ellipse(x, y, h, w);
}
私はこの方法しか思いつきませんでした。これでも動きはするので、個人的にはいいと思っています。模範解答は違うのでしょうか?

コメントする