blocklyでobjectを動かす。 その6


概要

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

写真

ステージを作る

<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}"
      })
  }
};

フローを書く。

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";
}

成果物

以上。