// Turtle graphics in Google Gadget // // tested with IE6 & Firefox2 & Safari // IE = !!(window.attachEvent && !window.opera); if (IE) { document.namespaces.add("v", "urn:schemas-microsoft-com:vml"); document.styleSheets[0].addRule("v\\:*", "behavior: url(#default#VML)"); } // ---------- Canvas Object for IE var VMLCanvas = new Object(); VMLCanvas.newImageShape = function(obj) { var shape = document.createElement("v:image"); return shape; } VMLCanvas.newWorldShape = function(obj) { var group = document.createElement("v:group"); group.coordsize = obj.width + "," + obj.height; group.style.width = obj.width; group.style.height = obj.height; var rect = document.createElement("v:rect"); rect.style.width = "100%"; rect.style.height = "100%"; rect.fillcolor = obj.fill; group.appendChild(rect); return group; } VMLCanvas.newPolylineShape = function(obj) { var shape = document.createElement("v:polyline"); shape.setAttribute("strokecolor", obj.stroke); shape.setAttribute("strokeweight", obj.strokeWidth); shape.setAttribute("filled", "false"); return shape; } VMLCanvas.add = function(parent, child) { parent._shape.appendChild(child._shape); } VMLCanvas.updateRect = function(obj) { obj._shape.src = obj.src; obj._shape.style.width = obj.width; obj._shape.style.height = obj.height; obj._shape.style.left = obj._x - obj.width / 2; obj._shape.style.top = obj._y - obj.height / 2; obj._shape.style.rotation = obj._angle; } VMLCanvas.updatePolyline = function(obj) { var points = ""; if (obj._vertices.length < 2) return; for (var i = 0; i < obj._vertices.length; i++) { points += Math.floor(obj._vertices[i][0]) + "," + Math.floor(obj._vertices[i][1]) + " "; } obj._shape.points.Value = points; } VMLCanvas.showAsWorld = function(obj) { document.getElementById("world").appendChild(obj._shape); } // ---------- Canvas Object for SVG (Firefox and Safari) var SVGNS = "http://www.w3.org/2000/svg"; var SVGCanvas = new Object(); SVGCanvas.newImageShape = function(obj) { var shape = document.createElementNS(SVGNS, "image"); return shape; } SVGCanvas.newWorldShape = function(obj) { var svg = document.createElementNS(SVGNS, "svg"); svg.setAttribute("width", obj.width); svg.setAttribute("height", obj.height); var rect = document.createElementNS(SVGNS, "rect"); rect.setAttribute("fill", obj.fill); rect.setAttribute("width", obj.width); rect.setAttribute("height", obj.height); svg.appendChild(rect); return svg; } SVGCanvas.newPolylineShape = function(obj) { var shape = document.createElementNS(SVGNS, "polyline"); shape.setAttribute("stroke", obj.stroke); shape.setAttribute("stroke-width", obj.strokeWidth); shape.setAttribute("fill", "none"); return shape; } SVGCanvas.showAsWorld = function(obj) { document.getElementById("world").appendChild(obj._shape); } SVGCanvas.add = function(parent, child) { parent._shape.appendChild(child._shape); } SVGCanvas.updateRect = function(obj) { obj._shape.setAttributeNS("http://www.w3.org/1999/xlink", "href", obj.src); obj._shape.setAttribute("width", obj.width); obj._shape.setAttribute("height", obj.height); var left = obj._x - obj.width / 2; var top = obj._y - obj.height / 2; obj._shape.setAttribute("transform", "translate(" + left + ", " + top + ") " + "rotate(" + obj._angle + ", " + obj.width / 2 + ", " + obj.height / 2 + ")"); } SVGCanvas.updatePolyline = function(obj) { var points = ""; if (obj._vertices.length < 2) return; for (var i = 0; i < obj._vertices.length; i++) { points += Math.floor(obj._vertices[i][0]) + "," + Math.floor(obj._vertices[i][1]) + " "; } obj._shape.setAttribute("points", points); } Canvas = IE ? VMLCanvas : SVGCanvas; // ---------- Scheduler var scheduler = { tasks: [], add: function(func) { this.tasks.push(func); }, tick: function() { if (this.tasks.length > 0) { (this.tasks.shift())(); } }, timer: undefined, initialize: function() { this.tasks = []; if (this.timer) clearInterval(this.timer); this.timer = setInterval(function () { scheduler.tick() }, 50); } } scheduler.initialize(); // ---------- World var world = { width: 200, height: 200, fill: "#CF8E6B", add: function (obj) { Canvas.add(this, obj) } } world._shape = Canvas.newWorldShape(world); // ---------- Trail var trail = { stroke: "#632D01", strokeWidth: 2, _vertices: [], initialize: function () { this._vertices = [] }, addVertex: function (p) { this._vertices.push(p); Canvas.updatePolyline(this); } } trail._shape = Canvas.newPolylineShape(trail); // ---------- Turtle var turtle = new Image(); turtle.exportNames = ["src", "_angle", "_x", "_y"]; turtle.src = "http://yamamiya.takashi.googlepages.com/worm_s.png"; turtle._angle = 0; turtle._x = world.width / 2; turtle._y = world.height / 2; turtle._shape = Canvas.newImageShape(turtle); turtle.setAngle = function(degree) { this._angle = degree; Canvas.updateRect(turtle); }; turtle.getAngle = function() { return this._angle } turtle.forwardBy = function(distance) { var t = this; scheduler.add(function() { var radian = t._angle * Math.PI / 180; t._x = t._x + (distance * (Math.sin(radian))); t._y = t._y - (distance * (Math.cos(radian))); Canvas.updateRect(turtle); trail.addVertex([t._x, t._y]); }); } turtle.forwardBy(0); turtle.turnBy = function(degree) { var t = this; scheduler.add(function() { t._angle = (t._angle + degree) % 360; Canvas.updateRect(turtle); }); } // ---------- Initialization world.add(trail); Canvas.updatePolyline(trail); world.add(turtle); Canvas.updateRect(turtle); window.onload = function () { Canvas.showAsWorld(world); } function doIt() { scheduler.initialize(); eval(document.getElementById("workspace").value); } function reset() { scheduler.initialize(); trail.initialize(); turtle._x = world.width / 2; turtle._y = world.height / 2; turtle._angle = 0; turtle.forwardBy(0); Canvas.updatePolyline(trail); Canvas.updateRect(turtle); }
]]>