blocklyでobjectを動かす。 その6

#概要

blocklyでobjectを動かして見る。
自動運転シミュレーションしてみた。

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d05c8878-1371-d139-f555-d9a3a63769ca.png)


#ステージを作る

```
<canvas id="canvas" width="240" height="128"></canvas>
```

#ブロックを書く。

```

Blockly.Blocks.run = {
	init: function() {
		this.jsonInit({
        message0: "run",
	      output: "Boolean",
	      style: "math_blocks",
	      tooltip: "%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",
	      helpUrl: "%{BKY_MATH_RANDOM_FLOAT_HELPURL}"
	  })
  }
};

Blockly.Blocks.r = {
	init: function() {
		this.jsonInit({
			message0: "r %1",
			args0: [{
				type: "input_value",
				name: "TEXT"
			}],
			previousStatement: null,
			nextStatement: null,
			style: "text_blocks",
			tooltip: Blockly.Msg.TEXT_PRINT_TOOLTIP,
			helpUrl: Blockly.Msg.TEXT_PRINT_HELPURL
		})
	}
};

Blockly.Blocks.s0 = {
	init: function() {
		this.jsonInit({
        message0: "s0",
	      output: "Number",
	      style: "math_blocks",
	      tooltip: "%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",
	      helpUrl: "%{BKY_MATH_RANDOM_FLOAT_HELPURL}"
	  })
  }
};

Blockly.Blocks.s1 = {
	init: function() {
		this.jsonInit({
        message0: "s1",
	      output: "Number",
	      style: "math_blocks",
	      tooltip: "%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",
	      helpUrl: "%{BKY_MATH_RANDOM_FLOAT_HELPURL}"
	  })
  }
};

Blockly.Blocks.s2 = {
	init: function() {
		this.jsonInit({
        message0: "s2",
	      output: "Number",
	      style: "math_blocks",
	      tooltip: "%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",
	      helpUrl: "%{BKY_MATH_RANDOM_FLOAT_HELPURL}"
	  })
  }
};

Blockly.Blocks.s3 = {
	init: function() {
		this.jsonInit({
        message0: "s3",
	      output: "Number",
	      style: "math_blocks",
	      tooltip: "%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",
	      helpUrl: "%{BKY_MATH_RANDOM_FLOAT_HELPURL}"
	  })
  }
};

Blockly.Blocks.s4 = {
	init: function() {
		this.jsonInit({
        message0: "s4",
	      output: "Number",
	      style: "math_blocks",
	      tooltip: "%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",
	      helpUrl: "%{BKY_MATH_RANDOM_FLOAT_HELPURL}"
	  })
  }
};

```

#フローを書く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e642ea40-37ad-ed33-6bff-1bd73aa0013a.png)

#objectを書く。


```

Blockly.JavaScript.run = function(a) {
    return ["run()", Blockly.JavaScript.ORDER_ATOMIC]
};

Blockly.JavaScript.r = function(a) {
    return "r = " + (Blockly.JavaScript.valueToCode(a, "TEXT", Blockly.JavaScript.ORDER_NONE) || "0") + ";\n"
};


Blockly.JavaScript.s0 = function(a) {
    return ["s0", Blockly.JavaScript.ORDER_FUNCTION_CALL]
};
Blockly.JavaScript.s1 = function(a) {
    return ["s1", Blockly.JavaScript.ORDER_FUNCTION_CALL]
};
Blockly.JavaScript.s2 = function(a) {
    return ["s2", Blockly.JavaScript.ORDER_FUNCTION_CALL]
};
Blockly.JavaScript.s3 = function(a) {
    return ["s3", Blockly.JavaScript.ORDER_FUNCTION_CALL]
};
Blockly.JavaScript.s4 = function(a) {
    return ["s4", Blockly.JavaScript.ORDER_FUNCTION_CALL]
};

var canvas2 = document.createElement("canvas");
var ctx2 = canvas2.getContext("2d");
function c2() {
  var rectWidth = 200;
  var rectHeight = 110;
  var rectx2 = 50;
  var rectY = 130
  var cornerRadius = 50;
	canvas2.width = 500
	canvas2.height = 500
	ctx2.fillStyle = "#0a0"
	ctx2.strokeStyle = "#888"
	ctx2.fillRect(0, 0, canvas2.width, canvas2.height)
	ctx2.save()
	ctx2.beginPath();
	ctx2.moveTo(rectx2 - cornerRadius * .15, rectY);
	ctx2.lineTo(rectx2 + rectWidth - cornerRadius, rectY);
	ctx2.arcTo(rectx2 + rectWidth, rectY, rectx2 + rectWidth, rectY + cornerRadius, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth, rectY + rectHeight);
	ctx2.arcTo(rectx2 + rectWidth, rectY + cornerRadius + rectHeight, rectx2, rectY + rectHeight + cornerRadius, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius, rectx2, rectY + cornerRadius + rectHeight, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius * 2 + rectHeight * 2, rectx2 + rectWidth * 2, rectY + cornerRadius + rectHeight * 2, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth + cornerRadius, rectY + cornerRadius * 1.85 + rectHeight * 2);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + cornerRadius * 1.85 + rectHeight * 2, rectx2 + rectWidth * 2, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + rectHeight, rectx2-rectWidth, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 1.5, rectY + rectHeight, rectx2+ rectWidth, rectY - rectHeight, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth, rectY - rectHeight, rectx2, rectY, cornerRadius);
	ctx2.lineTo(rectx2 + cornerRadius * .25, rectY - cornerRadius * .85);
	ctx2.arcTo(rectx2 - cornerRadius * .25, rectY - cornerRadius * .25, rectx2, rectY, cornerRadius / 2);
	ctx2.strokeStyle = "#f00"
	ctx2.lineWidth = 40;
	ctx2.stroke();	
	ctx2.restore()
	ctx2.save()
	ctx2.beginPath();
	ctx2.moveTo(rectx2 - cornerRadius * .15, rectY);
	ctx2.lineTo(rectx2 + rectWidth - cornerRadius, rectY);
	ctx2.arcTo(rectx2 + rectWidth, rectY, rectx2 + rectWidth, rectY + cornerRadius, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth, rectY + rectHeight);
	ctx2.arcTo(rectx2 + rectWidth, rectY + cornerRadius + rectHeight, rectx2, rectY + rectHeight + cornerRadius, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius, rectx2, rectY + cornerRadius + rectHeight, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius * 2 + rectHeight * 2, rectx2 + rectWidth * 2, rectY + cornerRadius + rectHeight * 2, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth + cornerRadius, rectY + cornerRadius * 1.85 + rectHeight * 2);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + cornerRadius * 1.85 + rectHeight * 2, rectx2 + rectWidth * 2, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + rectHeight, rectx2 - rectWidth,rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 1.5, rectY + rectHeight, rectx2 + rectWidth, rectY - rectHeight, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth, rectY - rectHeight, rectx2, rectY, cornerRadius);
	ctx2.lineTo(rectx2 + cornerRadius * .25, rectY - cornerRadius * .85);
	ctx2.arcTo(rectx2 - cornerRadius * .25, rectY - cornerRadius * .25, rectx2, rectY, cornerRadius / 2);
	ctx2.lineWidth = 39;
	ctx2.stroke();
	ctx2.restore()
	ctx2.save()
	ctx2.beginPath();
	ctx2.moveTo(rectx2 - cornerRadius * .15, rectY);
	ctx2.lineTo(rectx2 + rectWidth - cornerRadius, rectY);
	ctx2.arcTo(rectx2 + rectWidth, rectY,rectx2 + rectWidth, rectY + cornerRadius, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth, rectY + rectHeight);
	ctx2.arcTo(rectx2 + rectWidth, rectY + cornerRadius + rectHeight, rectx2, rectY + rectHeight + cornerRadius, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius, rectx2 ,rectY + cornerRadius + rectHeight, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius * 2 + rectHeight * 2,rectx2 + rectWidth * 2, rectY + cornerRadius + rectHeight * 2, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth + cornerRadius, rectY + cornerRadius * 1.85 + rectHeight * 2);
	ctx2.arcTo(rectx2 + rectWidth * 2,rectY + cornerRadius * 1.85 + rectHeight * 2, rectx2 + rectWidth * 2, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY +rectHeight, rectx2 - rectWidth, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 1.5, rectY+rectHeight, rectx2 + rectWidth, rectY - rectHeight, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth,rectY - rectHeight, rectx2, rectY, cornerRadius);
	ctx2.lineTo(rectx2 + cornerRadius * .25, rectY - cornerRadius * .85);
	ctx2.arcTo(rectx2 - cornerRadius * .25, rectY - cornerRadius * .25, rectx2, rectY, cornerRadius / 2);
	ctx2.strokeStyle = "yellow"
	ctx2.lineWidth = 3;
	ctx2.stroke();
	ctx2.restore()
	ctx2.save()
	ctx2.beginPath();
	ctx2.moveTo(rectx2 - cornerRadius * .15, rectY);
	ctx2.lineTo(rectx2 + rectWidth - cornerRadius, rectY);
	ctx2.arcTo(rectx2 + rectWidth, rectY, rectx2 + rectWidth, rectY + cornerRadius, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth, rectY + rectHeight);
	ctx2.arcTo(rectx2 + rectWidth, rectY + cornerRadius + rectHeight, rectx2 , rectY + rectHeight + cornerRadius, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius, rectx2 ,rectY + cornerRadius + rectHeight, cornerRadius);
	ctx2.arcTo(rectx2, rectY + cornerRadius * 2 + rectHeight * 2, rectx2 + rectWidth * 2, rectY + cornerRadius + rectHeight * 2, cornerRadius);
	ctx2.lineTo(rectx2 + rectWidth + cornerRadius, rectY+cornerRadius * 1.85 + rectHeight * 2);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY+cornerRadius * 1.85 + rectHeight * 2, rectx2 + rectWidth * 2, rectY ,cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 2, rectY + rectHeight, rectx2 - rectWidth, rectY, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth * 1.5, rectY + rectHeight, rectx2 + rectWidth, rectY - rectHeight, cornerRadius);
	ctx2.arcTo(rectx2 + rectWidth, rectY - rectHeight, rectx2, rectY, cornerRadius);
	ctx2.lineTo(rectx2 + cornerRadius * .25, rectY - cornerRadius * .85);
	ctx2.arcTo(rectx2 - cornerRadius * .25, rectY - cornerRadius * .25, rectx2, rectY, cornerRadius / 2);
	ctx2.strokeStyle = "#888"
	ctx2.lineWidth = 2;
	ctx2.stroke();
  var sx = 150;
  var sy = 20;
	ctx2.save()
	ctx2.beginPath();
	ctx2.moveTo(rectx2 + sx, 314 + rectY - sy);
	ctx2.lineTo(rectx2 + sx, 314 + rectY + sy);
	ctx2.strokeStyle = "#f00"
	ctx2.lineWidth = 2;
	ctx2.stroke();
	ctx2.restore()
	ctx2.save()
	ctx2.beginPath();
	ctx2.fillStyle = "#fff"
	ctx2.fillRect(rectx2 + sx - 1, 314 + rectY - sy, 1, 5)
	ctx2.fillRect(rectx2 + sx,     314 + rectY - sy + 5, 1, 5)
	ctx2.fillRect(rectx2 + sx - 1, 314 + rectY - sy + 10, 1, 5)
	ctx2.fillRect(rectx2 + sx,     314 + rectY - sy + 15, 1, 5) 
	ctx2.fillRect(rectx2 + sx - 1, 314 + rectY, 1, 5)
	ctx2.fillRect(rectx2 + sx,     314 + rectY + sy - 15 , 1, 5)
	ctx2.fillRect(rectx2 + sx - 1, 314 + rectY + sy - 10, 1, 5)
	ctx2.fillRect(rectx2 + sx,     314 + rectY + sy - 5, 1, 5)
	ctx2.stroke();
	ctx2.restore()
}
c2();
function sense(src, s0, s1) {
  var p = 0;
  for (var y = s1; y < s1 + 20; y++) 
  {
    for (var x = s0; x < s0 + 20; x++) 
    {
      var r = src.data[(y * 240 + x) * 4];
      var g = src.data[(y * 240 + x) * 4 + 1];
      var b = src.data[(y * 240 + x) * 4 + 2];
      p += r + g + b;
    }
  }
  return p / 20 / 20 / 3 / 256;
}

var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var OFF = document.createElement("canvas");
var OFF_CTX = OFF.getContext("2d");
var FOV = Math.PI / 3;
var DEPTH = 2 * Math.tan(FOV * 0.5);
var EYE = canvas.width / DEPTH;
OFF.height = canvas.height;
OFF.width = Math.ceil(canvas.height * DEPTH);
var car = {
    x: 50,
    y: 70,
    z: 18,
    a: Math.PI * 2,
    vx: 0,
    vy: 0,
    vz: 0,
    va: 0,
    px: 0,
    py: 0
};
var state = 0;
var r = 0;
var s0, 
	s1,
	s2,
	s3,
	s4;
function run() {
    car.vx = Math.cos(car.a) / 1;
    car.vy = Math.sin(car.a) / 1;
    car.va = 0;
    if (r == 0)
    {
        car.va = -Math.PI / 30;
    }
    if (r == 1)
    {
        car.va = Math.PI / 30;
    }
    car.x += car.vx;
    car.y += car.vy;
    car.a += car.va;
    var horizon = Math.floor(canvas.height * 0.01);
    var scale = EYE * car.z;
    var yMin = Math.ceil(scale / OFF.height);
    var yMax = canvas.height - horizon;
    var near = scale / yMax - 1;
    OFF_CTX.clearRect(0, 0, OFF.width, OFF.height);
    OFF_CTX.save();
    OFF_CTX.translate(OFF.width * 0.5, OFF.height + near)
    OFF_CTX.rotate(Math.PI * 1.5 - car.a);
    OFF_CTX.drawImage(canvas2, -car.x, -car.y);
    OFF_CTX.restore();
    ctx.fillRect(0, horizon, canvas.width, yMax);
    for (var y = yMin; y < yMax; y += height)
    {
        var top = scale / y;
        var width = top * DEPTH;
        var height = Math.ceil(scale / Math.floor(top) - y);
        var bottom = scale / (y + height);
        ctx.drawImage(OFF, (OFF.width - width) * 0.5, OFF.height + near - top, width, top - bottom, 0, horizon + y, canvas.width, height);
    }
    var src = ctx.getImageData(0, 0, canvas.width, canvas.height);
    s0 = sense(src, 30, 107);
    s1 = sense(src, 70, 107);
    s2 = sense(src, 110, 107);
    s3 = sense(src, 150, 107);
    s4 = sense(src, 190, 107);    
    ctx.fillStyle = "gray";
    ctx.fillRect(30, 107, 20, 20);
    ctx.fillRect(70, 107, 20, 20);
    ctx.fillRect(110, 107, 20, 20);
    ctx.fillRect(150, 107, 20, 20);
    ctx.fillRect(190, 107, 20, 20);
    ctx.font = "14px arial black";
    var text = "a: " + Math.floor(car.a * 10);
    ctx.fillText(text, 10, 12);
    text = "xyz: " + Math.floor(car.x) + "  " + Math.floor(car.y) + "  " + Math.floor(car.z);
    ctx.fillText(text, 10, 24);
    ctx.fillStyle  = "white"; 
		return "ture";
}
```

#成果物

https://embed.plnkr.co/plunk/LUF7WmE1l8fU0q7f


以上。