<html>
<head>
<title>Turtle Monad</title>
<script src="TurtleMonad.js" ></script>
<script>
var _canvas = null;
var _ctx = null;
function initCanvas() {
_canvas = document.getElementById("canvas");
_ctx = _canvas.getContext('2d');
}
</script>
<style>
#canvas {border: 1px solid blue;
</style>
</head>
<body onload="initCanvas()">
<h1>Turtle Monad</h1>
<canvas id="canvas" width="300" height="300" >
<h1>キャンバスがサポートされていません。</h2>
</canvas>
</body>
</html>
var TurtleOp = {
GO : 1,
ROTATE : 2,
unit : function() {
return [];
},
mult : function(a, b) {
return Array.concat(a, b);
}
};
var Turtle = {
QUEUE_MODE : 1,
DIRECT_MODE : 0,
_mode : undefined,
_canvas : undefined,
_width : undefined,
_height : undefined,
_ctx : undefined,
_x : undefined,
_y : undefined,
_dir : undefined,
_operations : undefined
};
Turtle.init = function() {
Turtle._mode = Turtle.QUEUE_MODE;
Turtle._canvas = _canvas;
Turtle._ctx = _ctx;
Turtle._width = Turtle._canvas.width;
Turtle._height = Turtle._canvas.height;
Turtle._x = 0;
Turtle._y = 0;
Turtle._dir = (1/2)*Math.PI;
Turtle._operations = TurtleOp.unit();
Turtle._ctx.setTransform(1, 0, 0, -1,
Math.round(Turtle._width/2),
Math.round(Turtle._height/2)
);
Turtle.draw();
};
Turtle.setMode = function(mode) {
Turtle._mode = mode;
};
Turtle.operate = function (op) {
var old = Turtle._operations;
Turtle._operations = TurtleOp.mult(old, op);
if (Turtle._mode == Turtle.DIRECT_MODE) {
Turtle.execOperations();
}
};
Turtle.draw = function() {
var dirHead = Turtle._dir;
var dirRight = Turtle._dir + (Math.PI* (3/4));
var dirLeft = Turtle._dir - (Math.PI* (3/4));
var x = Turtle._x;
var y = Turtle._y;
var r = 10;
var ctx = Turtle._ctx;
ctx.clearRect(-Turtle._width/2, -Turtle._height/2,
Turtle._width, Turtle._height);
ctx.beginPath();
ctx.moveTo(x + r*Math.cos(dirHead), y + r*Math.sin(dirHead));
ctx.lineTo(x + r*Math.cos(dirRight), y + r*Math.sin(dirRight));
ctx.lineTo(x + r*Math.cos(dirLeft), y + r*Math.sin(dirLeft));
ctx.lineTo(x + r*Math.cos(dirHead), y + r*Math.sin(dirHead));
ctx.fill();
};
Turtle._action_go = function (r) {
var x = Turtle._x;
var y = Turtle._y;
var dir = Turtle._dir;
Turtle._x = x + r*Math.cos(dir);
Turtle._y = y + r*Math.sin(dir);
};
Turtle._action_rotate = function (arc) {
var dir = Turtle._dir;
Turtle._dir = dir + arc;
};
Turtle.execOperations = function() {
var ops = Turtle._operations;
for (var i = 0; i < ops.length; i++) {
var op = ops[i];
var action = op[0];
var param = op[1];
switch (action) {
case TurtleOp.GO:
Turtle._action_go(param); break;
case TurtleOp.ROTATE:
Turtle._action_rotate(param); break;
default: throw "Unbelievable!";
}
}
Turtle._operations = TurtleOp.unit();
Turtle.draw();
};
function start() {
Turtle.init();
}
function fd(r) {
Turtle.operate([[TurtleOp.GO, r]]);
}
function bk(r) {
Turtle.operate([[TurtleOp.GO, -r]]);
}
function rt(a) {
Turtle.operate([[TurtleOp.ROTATE, -(a/360)*(2*Math.PI)]]);
}
function lt(a) {
Turtle.operate([[TurtleOp.ROTATE, (a/360)*(2*Math.PI)]]);
}
function x() {
Turtle.execOperations();
}
function q() {
return Turtle._operations;
}
function qmode(f) {
if (f) {
Turtle.setMode(Turtle.QUEUE_MODE);
} else {
x();
Turtle.setMode(Turtle.DIRECT_MODE);
}
};