07-03 お絵かきデータの保存と読み込み

練習問題7-3-1

次の配列を、S キー を押したときに message.txt として保存するプログラムを作りましょう。

  • keyPressed の ??? を埋めて完成させなさい。
  • ファイルをダウンロードしてメモ帳などで開いてみなさい。
  • 何か気づいたことがあれば、先生に報告してください。
let messages = ["船の操縦は","海図を読み","帆の高みに","風向を見て","遠望しつつ","波を駆けて","疾走したい"];

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

function keyPressed() {
  if(key === "s"){
    saveStrings(messages, "message.txt")
  }
}

開きました。

気づいたことと言っていいのかわかりませんが、キー押したか判断させるにはキャンバスを押さなければいけないということを今知りました。前まではなんとなくそうなると思ってはいましたが、AIに動かない原因を聞いたところ、そのように言われたのでわかりました。

練習問題7-3-2

次のプログラムをそのまま入力して実行しなさい。

  1. ファイル選択ボックスから、練習問題7-3-1 で保存した message.txt を選ぶ
  2. もう一度ファイルを選び、今度は 画像ファイル.png や .jpg など)を選ぶ
  3. 1 と 2 で結果が違う理由は、ソースコードのどこで判別されているか見つけ、先生に報告しなさい

先ほどダウンロードしたtextだと表示されましたが、画像などだと表示されませんでした。
そしてifを使ってtextだけを読み込んでいるということに気づきました。なので、ifをコメントアウトして、画像などをやってみると、ファイルの名前が表示されました。
ソースコードというのは多分ファイル名だということで話を進めます。
私の見解では、textという形のファイルだけを今認識できる状況に設定されているのだと思いました。

練習問題7-3-3

練習問題6-5-6 のプログラムに、S キー で座標を drawing.txt として保存する機能を追加しなさい。

06-05 では、クリックした座標を pointX と pointY 配列に入れていました。saveStrings で扱えるように、この配列を 1行1点 のテキストファイルにして保存するようにしなさい。
keyPressed に S キーの処理を追加し、saveDrawing 関数を追加して完成させなさい。

let canvas;
let pointX = [];
let pointY = [];
let isDrawing = false;
let isShaking = false;
let pointXY=[];

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

function draw() {
  background(255);
  drawGrid();
  drawPaths();
  drawPreview();
}

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 drawPaths() {
  stroke(0);
  strokeWeight(3);
  for (let i = 0; i < pointX.length - 1; i++) {
    if (pointX[i+1]!==-1&&pointX[i]!==-1) {
        shakeLine(pointX[i], pointY[i], pointX[i + 1], pointY[i + 1]);
    }
  }
}

function drawPreview() {
  if(isDrawing){
    if(pointX.length>=1){
      line(pointX[pointX.length-1], pointY[pointY.length-1], mouseX,mouseY)
    }
  }
}

function mousePressed() {
  if (mouseButton === LEFT) {
    pointX.push(mouseX);
    pointY.push(mouseY);
    isDrawing = true
  } else if (mouseButton === RIGHT) {
    pointX.push(-1)
    pointY.push(-1)
    isDrawing = false;
  }
}

function keyPressed(){
  
  if (key === "c" || key === "C") {
  pointX = []
  pointY = []
  isDrawing = false
  }
  if(key === " "&&!isShaking){
    isShaking = true
  }else if(key===" "){
    isShaking = false
  }
  if (key === "s" || key === "S") {
    for(let i=0; i<pointX.length; i++){
      pointXY.push(pointX[i]+","+pointY[i])
    }
    saveDrawing()
  }
}

function saveDrawing() {
  saveStrings(pointXY, "drawing.txt")
}

function shakeLine(x1, y1, x2, y2) {
  let r = random(-5, 5)
  if(isShaking){
    line(x1+r, y1+r, x2+r, y2+r)
  }else{
    line(x1, y1, x2, y2)
  }
}
最初はsaveStringsの中でXとYを足して並べられないかと考えていたのですが、そうするとなぜか一文字ずつ縦に並んでしまって、断念しました。
なので問題には書かれていなかった変数を作ってしまいましたが、
まあ、動くし、大丈夫ですよね!

練習問題7-3-4

練習問題7-3-3 のプログラムに、練習問題7-3-2 と同様の ファイル読み込み 機能を追加しなさい。

  • setup() で createFileInput を表示する
  • ファイル選択ボックスの位置は、練習問題7-3-2 と同じく input.position(10, 10) で キャンバス左上 に置く
  • テキストファイルが選ばれたら、split で行に分解して配列に入れ、さらに各行を split で , を境に分けて pointX と pointY に戻す

完成したら、次の2つの確認を行いなさい。

  1. 絵を描いて保存し、消したあと読み込んで復元できるか確認する
  2. 保存した drawing.txt の座標を書き換えて読み込み直し、絵に反映されるか確認する
let canvas;
let pointX = [];
let pointY = [];
let isDrawing = false;
let isShaking = false;
let pointXY=[];
let textData=[];

function setup() {
  canvas = createCanvas(400, 400);
  canvas.elt.addEventListener("contextmenu", function (e) {e.preventDefault();});
  let input = createFileInput(fileSelected);
  input.position(10, 10);
}

function draw() {
  background(255);
  drawGrid();
  drawPaths();
  drawPreview();
}

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 drawPaths() {
  stroke(0);
  strokeWeight(3);
  for (let i = 0; i < pointX.length - 1; i++) {
    if (pointX[i+1]!==-1&&pointX[i]!==-1) {
        shakeLine(pointX[i], pointY[i], pointX[i + 1], pointY[i + 1]);
    }
  }
}

function drawPreview() {
  if(isDrawing){
    if(pointX.length>=1){
      line(pointX[pointX.length-1], pointY[pointY.length-1], mouseX,mouseY)
    }
  }
}

function mousePressed() {
  if (mouseButton === LEFT) {
    pointX.push(mouseX);
    pointY.push(mouseY);
    isDrawing = true
  } else if (mouseButton === RIGHT) {
    pointX.push(-1)
    pointY.push(-1)
    isDrawing = false;
  }
}

function keyPressed(){
  
  if (key === "c" || key === "C") {
  pointX = []
  pointY = []
  isDrawing = false
  }
  if(key === " "&&!isShaking){
    isShaking = true
  }else if(key===" "){
    isShaking = false
  }
  if (key === "s" || key === "S") {
    for(let i=0; i<pointX.length; i++){
      pointXY.push(pointX[i]+","+pointY[i])
    }
    saveDrawing()
  }
}

function saveDrawing() {
  saveStrings(pointXY, "drawing.txt")
}

function shakeLine(x1, y1, x2, y2) {
  let r = random(-5, 5)
  if(isShaking){
    line(x1+r, y1+r, x2+r, y2+r)
  }else{
    line(x1, y1, x2, y2)
  }
}

function fileSelected(file) {
  pointX=[]
  pointY=[]
  pointXY=[]
  if (file.type === "text") {
    textData = file.data.split("\n");
    for(let i=0; i<textData.length; i++){
      pointXY = textData[i].split(",")
      pointX.push(float(pointXY[0]))
      pointY.push(float(pointXY[1]))
    }
  }
}

ファイルを選択を押してしまうと、そこから線が伸びてしまうので、一回pointXとpointYを空にしてから読み込んでいます。

  1. Q 絵を描いて保存し、消したあと読み込んで復元できるか確認する
    A どうやって証明したらいいのかわかりませんが、できました。
  2. Q 保存した drawing.txt の座標を書き換えて読み込み直し、絵に反映されるか確認する
    A こちらも同証明すればいいかわかりませんがうまくいきました。

コメントする