{"id":691,"date":"2011-01-28T10:23:38","date_gmt":"2011-01-28T02:23:38","guid":{"rendered":""},"modified":"2014-03-11T22:36:57","modified_gmt":"2014-03-11T14:36:57","slug":"%e7%b1%bb%e4%bc%bccs%e7%9a%84js%e6%b8%b8%e6%88%8f","status":"publish","type":"post","link":"http:\/\/www.xiaoyebailong.com\/index.php\/2011\/01\/28\/691.htm","title":{"rendered":"\u7c7b\u4f3ccs\u7684js\u6e38\u620f"},"content":{"rendered":"<p>&lt;!DOCTYPE HTML PUBLIC &quot;-\/\/W3C\/\/DTD HTML 4.01\/\/EN&quot; &quot;http:\/\/www.w3.org\/TR\/html4\/strict.dtd&quot;&gt; <br \/>\n&lt;HTML&gt;<br \/>\n&lt;HEAD&gt;<br \/>\n&lt;TITLE&gt;Canvascape &#8211; 3D walker&lt;\/TITLE&gt;<br \/>\n&lt;!&#8211;<br \/>\nThis game is copyright by Benjamin Joffe.<br \/>\nYou may not reproduce or modify this without<br \/>\nwritten permission by the origional author.<br \/>\nEmail him: CanvasGame@gmail.com for suggestions.<br \/>\n&#8211;&gt;<br \/>\n&lt;SCRIPT type=&quot;text\/javascript&quot; &gt;<br \/>\nfunction G_VmlCanvasManager() {<br \/>\nthis.init();<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvasManager.prototype = {<br \/>\ninit: function (opt_doc) {<br \/>\nvar doc = opt_doc || document;<br \/>\nif (\/MSIE\/.test(navigator.userAgent) &amp;&amp; !window.opera) {<br \/>\nvar self = this;<br \/>\ndoc.attachEvent(&quot;onreadystatechange&quot;, function () {<br \/>\nself.init_(doc);<br \/>\n});<br \/>\n}<br \/>\n},<\/p>\n<p>\n&nbsp;<\/p>\n<p>init_: function (doc, e) {<br \/>\nif (doc.readyState == &quot;complete&quot;) {<br \/>\n\/\/ create xmlns<br \/>\nif (!doc.namespaces[&quot;g_vml_&quot;]) {<br \/>\ndoc.namespaces.add(&quot;g_vml_&quot;, &quot;urn:schemas-microsoft-com:vml&quot;);<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ setup default css<br \/>\nvar ss = doc.createStyleSheet();<br \/>\nss.cssText = &quot;canvas{display:inline-block; overflow:hidden; text-align:left;}&quot; +<br \/>\n&quot;canvas *{behavior:url(#default#VML)}&quot;;<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ find all canvas elements<br \/>\nvar els = doc.getElementsByTagName(&quot;canvas&quot;);<br \/>\nfor (var i = 0; i &lt; els.length; i++) {<br \/>\nif (!els[i].getContext) {<br \/>\nthis.initElement(els[i]);<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\n},<\/p>\n<p>\n&nbsp;<\/p>\n<p>fixElement_: function (el) {<br \/>\n\/\/ in IE before version 5.5 we would need to add HTML: to the tag name<br \/>\n\/\/ but we do not care about IE before version 6<br \/>\nvar outerHTML = el.outerHTML;<br \/>\nvar newEl = document.createElement(outerHTML);<br \/>\n\/\/ if the tag is still open IE has created the children as siblings and<br \/>\n\/\/ it has also created a tag with the name &quot;\/FOO&quot;<br \/>\nif (outerHTML.slice(-2) != &quot;\/&gt;&quot;) {<br \/>\nvar tagName = &quot;\/&quot; + el.tagName;<br \/>\nvar ns;<br \/>\n\/\/ remove content<br \/>\nwhile ((ns = el.nextSibling) &amp;&amp; ns.tagName != tagName) {<br \/>\nns.removeNode();<br \/>\n}<br \/>\n\/\/ remove the incorrect closing tag<br \/>\nif (ns) {<br \/>\nns.removeNode();<br \/>\n}<br \/>\n}<br \/>\nel.parentNode.replaceChild(newEl, el);<br \/>\nreturn newEl;<br \/>\n},<\/p>\n<p>\n&nbsp;<\/p>\n<p>initElement: function (el) {<br \/>\nel = this.fixElement_(el);<br \/>\nel.getContext = function () {<br \/>\nif (this._context) {<br \/>\nreturn this._context;<br \/>\n}<br \/>\nreturn this._context = new G_VmlCanvas(this);<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>var self = this; \/\/bind<br \/>\nel.attachEvent(&quot;onpropertychange&quot;, function (e) {<br \/>\n\/\/ we need to watch changes to width and height<br \/>\nswitch (e.propertyName) {<br \/>\ncase &quot;width&quot;:<br \/>\ncase &quot;height&quot;:<br \/>\n\/\/ coord size changed?<br \/>\nbreak;<br \/>\n}<br \/>\n});<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ if style.height is set<\/p>\n<p>\n&nbsp;<\/p>\n<p>var attrs = el.attributes;<br \/>\nif (attrs.width &amp;&amp; attrs.width.specified) {<br \/>\n\/\/ TOD use runtimeStyle and coordsize<br \/>\n\/\/ el.getContext().setWidth_(attrs.width.nodeValue);<br \/>\nel.style.width = attrs.width.nodeValue + &quot;px&quot;;<br \/>\n}<br \/>\nif (attrs.height &amp;&amp; attrs.height.specified) {<br \/>\n\/\/ TOD use runtimeStyle and coordsize<br \/>\n\/\/ el.getContext().setHeight_(attrs.height.nodeValue);<br \/>\nel.style.height = attrs.height.nodeValue + &quot;px&quot;;<br \/>\n}<br \/>\n\/\/el.getContext().setCoordsize_()<br \/>\n}<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>var G_vmlCanvasManager = new G_VmlCanvasManager;<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nfunction G_VmlCanvas(surface) {<br \/>\nthis.m = G_VmlCanvas.MatrixIdentity();<br \/>\nthis.element = surface;<\/p>\n<p>\n&nbsp;<\/p>\n<p>this.mStack = [];<br \/>\nthis.aStack = [];<br \/>\nthis.currentPath = [];<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ Canvas context properties<br \/>\nthis.strokeStyle = &quot;#000&quot;;<br \/>\nthis.fillStyle = &quot;#ccc&quot;;<\/p>\n<p>\n&nbsp;<\/p>\n<p>this.lineWidth = 1;<br \/>\nthis.lineJoin = &#8216;miter&#8217;;<br \/>\nthis.lineCap = &#8216;butt&#8217;;<br \/>\nthis.miterLimit = 10.0;<br \/>\nthis.globalAlpha = 1.0;<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.dec2hex = [];<br \/>\n(function () {<br \/>\nfor (var i = 0; i &lt; 16; i++) {<br \/>\nfor (var j = 0; j &lt; 16; j++) {<br \/>\nG_VmlCanvas.dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);<br \/>\n}<br \/>\n}<br \/>\n})();<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.MatrixIdentity = function() {<br \/>\nreturn [<br \/>\n[1,0,0],<br \/>\n[0,1,0],<br \/>\n[0,0,1]<br \/>\n];<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.MatrixMultiply = function(m1, m2) {<br \/>\nvar result = G_VmlCanvas.MatrixIdentity();<\/p>\n<p>\n&nbsp;<\/p>\n<p>for (var x = 0; x &lt; 3; x++) {<br \/>\nfor (var y = 0; y &lt; 3; y++) {<br \/>\nvar sum = 0;<\/p>\n<p>\n&nbsp;<\/p>\n<p>for (var z = 0; z &lt; 3; z++) {<br \/>\nsum += m1[x][z] * m2[z][y];<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>result[x][y] = sum;<br \/>\n}<br \/>\n}<br \/>\nreturn result;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.CopyState = function(o1, o2) {<br \/>\no2.fillStyle = o1.fillStyle;<br \/>\no2.lineCap = o1.lineCap;<br \/>\no2.lineJoin = o1.lineJoin;<br \/>\no2.lineWidth = o1.lineWidth;<br \/>\no2.miterLimit = o1.miterLimit;<br \/>\no2.shadowBlur = o1.shadowBlur;<br \/>\no2.shadowColor = o1.shadowColor;<br \/>\no2.shadowOffsetX = o1.shadowOffsetX;<br \/>\no2.shadowOffsetY = o1.shadowOffsetY;<br \/>\no2.strokeStyle = o1.strokeStyle;<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.ProcessStyle = function(styleString) {<br \/>\nvar str, alpha = 1.0;<\/p>\n<p>\n&nbsp;<\/p>\n<p>styleString = String(styleString);<br \/>\nif (styleString.substring(0, 3) == &quot;rgb&quot;) {<br \/>\nvar start = styleString.indexOf(&quot;(&quot;, 3);<br \/>\nvar end = styleString.indexOf(&quot;)&quot;, start + 1);<br \/>\nvar guts = styleString.substring(start + 1, end).split(&quot;,&quot;);<\/p>\n<p>\n&nbsp;<\/p>\n<p>str = &quot;#&quot;;<br \/>\nfor (var i = 0; i &lt; 3; i++) {<br \/>\nstr += G_VmlCanvas.dec2hex[parseInt(guts[i])];<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>if ((guts.length == 4) &amp;&amp; (styleString.substr(3, 1) == &quot;a&quot;)) {<br \/>\nalpha = guts[3];<br \/>\n}<br \/>\n} else {<br \/>\nstr = styleString;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>return [str, alpha];<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.ProcessLineCap = function(lineCap) {<br \/>\nswitch (lineCap) {<br \/>\ncase &#8216;butt&#8217;: return &#8216;flat&#8217;;<br \/>\ncase &#8217;round&#8217;: return &#8217;round&#8217;;<br \/>\ncase &#8216;square&#8217;: return &#8216;square&#8217;;<br \/>\n}<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.clearRect = function() {<br \/>\nthis.element.innerHTML = &quot;&quot;;<br \/>\nthis.currentPath = [];<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.beginPath = function() {<br \/>\n\/\/ TODO(glen): Branch current matrix so that save\/restore has no effect<br \/>\n\/\/ as per safari docs.<\/p>\n<p>\n&nbsp;<\/p>\n<p>this.currentPath = [];<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.moveTo = function(aX, aY) {<br \/>\nthis.currentPath.push({type: &#8216;moveTo&#8217;, x: aX, y:aY});<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.lineTo = function(aX, aY) {<br \/>\nthis.currentPath.push({type: &#8216;lineTo&#8217;, x: aX, y:aY});<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.bezierCurveTo = function(aCP1x, aCP1y, aCP2x, aCP2y, aX, aY) {<br \/>\nthis.currentPath.push({type: &#8216;bezierCurveTo&#8217;,<br \/>\ncp1x: aCP1x,<br \/>\ncp1y: aCP1y,<br \/>\ncp2x: aCP2x,<br \/>\ncp2y: aCP2y,<br \/>\nx: aX,<br \/>\ny: aY});<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {<br \/>\n\/\/ VML&#8217;s qb produces different output to Firefox&#8217;s<br \/>\nthis.bezierCurveTo(aCPx, aCPy, aCPx, aCPy, aX, aY);<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.arc = function(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) {<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (!aClockwise) {<br \/>\nvar t = aStartAngle;<br \/>\naStartAngle = aEndAngle;<br \/>\naEndAngle = t;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>var xStart = aX + (Math.cos(aStartAngle) * aRadius);<br \/>\nvar yStart = aY + (Math.sin(aStartAngle) * aRadius);<\/p>\n<p>\n&nbsp;<\/p>\n<p>var xEnd = aX + (Math.cos(aEndAngle) * aRadius);<br \/>\nvar yEnd = aY + (Math.sin(aEndAngle) * aRadius);<\/p>\n<p>\n&nbsp;<\/p>\n<p>this.currentPath.push({type: &#8216;arc&#8217;,<br \/>\nx: aX,<br \/>\ny: aY,<br \/>\nradius: aRadius,<br \/>\nxStart: xStart,<br \/>\nyStart: yStart,<br \/>\nxEnd: xEnd,<br \/>\nyEnd: yEnd});<\/p>\n<p>\n&nbsp;<\/p>\n<p>}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.strokeRect = function(aX, aY, aWidth, aHeight) {<br \/>\n\/\/ Will destroy any existing path (same as FF behaviour)<br \/>\nthis.beginPath();<br \/>\nthis.moveTo(aX, aY);<br \/>\nthis.lineTo(aX + aWidth, aY);<br \/>\nthis.lineTo(aX + aWidth, aY + aHeight);<br \/>\nthis.lineTo(aX, aY + aHeight);<br \/>\nthis.closePath();<br \/>\nthis.stroke();<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.fillRect = function(aX, aY, aWidth, aHeight) {<br \/>\n\/\/ Will destroy any existing path (same as FF behaviour)<br \/>\nthis.beginPath();<br \/>\nthis.moveTo(aX, aY);<br \/>\nthis.lineTo(aX + aWidth, aY);<br \/>\nthis.lineTo(aX + aWidth, aY + aHeight);<br \/>\nthis.lineTo(aX, aY + aHeight);<br \/>\nthis.closePath();<br \/>\nthis.fill();<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ Gradient \/ Pattern Stubs<br \/>\nfunction G_VmlGradient(aType) {<br \/>\nthis.type = aType;<br \/>\nthis.radius1 = 0;<br \/>\nthis.radius2 = 0;<br \/>\nthis.colors = [];<br \/>\nthis.focus = {x: 0, y:0};<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlGradient.prototype.addColorStop = function(aOffset, aColor) {<br \/>\naColor = G_VmlCanvas.ProcessStyle(aColor);<br \/>\nthis.colors.push({offset: 1-aOffset, color: aColor});<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {<br \/>\nvar gradient = new G_VmlGradient(&quot;gradient&quot;);<br \/>\nreturn gradient;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.createRadialGradient = function(aX0, aY0, aR0, aX1, aY1, aR1) {<br \/>\nvar gradient = new G_VmlGradient(&quot;gradientradial&quot;);<br \/>\ngradient.radius1 = aR0;<br \/>\ngradient.radius2 = aR1;<br \/>\ngradient.focus.x = aX0;<br \/>\ngradient.focus.y = aY0;<br \/>\nreturn gradient;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.drawImage = function (image, var_args) {<br \/>\nvar dx, dy, dw, dh, sx, sy, sw, sh;<br \/>\nvar w = image.width;<br \/>\nvar h = image.height;<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (arguments.length == 3) {<br \/>\ndx = arguments[1];<br \/>\ndy = arguments[2];<br \/>\nsx = sy = 0;<br \/>\nsw = dw = w;<br \/>\nsh = dh = h;<br \/>\n} else if (arguments.length == 5) {<br \/>\ndx = arguments[1];<br \/>\ndy = arguments[2];<br \/>\ndw = arguments[3];<br \/>\ndh = arguments[4];<br \/>\nsx = sy = 0;<br \/>\nsw = w;<br \/>\nsh = h;<br \/>\n} else if (arguments.length == 9) {<br \/>\nsx = arguments[1];<br \/>\nsy = arguments[2];<br \/>\nsw = arguments[3];<br \/>\nsh = arguments[4];<br \/>\ndx = arguments[5];<br \/>\ndy = arguments[6];<br \/>\ndw = arguments[7];<br \/>\ndh = arguments[8];<br \/>\n} else {<br \/>\nthrow &quot;Invalid number of arguments&quot;;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>var d = this.Coords(dx, dy);<\/p>\n<p>\n&nbsp;<\/p>\n<p>var w2 = (sw \/ 2);<br \/>\nvar h2 = (sh \/ 2);<\/p>\n<p>\n&nbsp;<\/p>\n<p>var vmlStr = [];<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ For some reason that I&#8217;ve now forgotten, using divs didn&#8217;t work<br \/>\nvmlStr.push(&#8216; &lt;g_vml_:group&#8217;,<br \/>\n&#8216; coordsize=&quot;100,100&quot;&#8217;,<br \/>\n&#8216; coordorigin=&quot;0, 0&quot;&#8217; ,<br \/>\n&#8216; style=&quot;width:100px; height:100px; position:absolute; &#8216;);<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ If filters are necessary (rotation exists), create them<br \/>\n\/\/ filters are bog-slow, so only create them if abbsolutely necessary<br \/>\n\/\/ The following check doesn&#8217;t account for skews (which don&#8217;t exist<br \/>\n\/\/ in the canvas spec (yet) anyway.<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (this.m[0][0] != 1 || this.m[0][1]) {<br \/>\nvar filter = [];<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ Note the 12\/21 reversal<br \/>\nfilter.push(&quot;M11=&#8217;&quot;,this.m[0][0],&quot;&#8217;,&quot;,<br \/>\n&quot;M12=&#8217;&quot;,this.m[1][0],&quot;&#8217;,&quot;,<br \/>\n&quot;M21=&#8217;&quot;,this.m[0][1],&quot;&#8217;,&quot;,<br \/>\n&quot;M22=&#8217;&quot;,this.m[1][1],&quot;&#8217;,&quot;,<br \/>\n&quot;Dx=&#8217;&quot;,d.x,&quot;&#8217;,&quot;,<br \/>\n&quot;Dy=&#8217;&quot;,d.y,&quot;&#8217;&quot;);<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ Bounding box calculation (need to minimize displayed area so that filters<br \/>\n\/\/ don&#8217;t waste time on unused pixels.<br \/>\nvar max = d;<br \/>\nvar c2 = this.Coords(dx+dw, dy);<br \/>\nvar c3 = this.Coords(dx, dy+dh);<br \/>\nvar c4 = this.Coords(dx+dw, dy+dh);<\/p>\n<p>\n&nbsp;<\/p>\n<p>max.x = Math.max(max.x, c2.x, c3.x, c4.x);<br \/>\nmax.y = Math.max(max.y, c2.y, c3.y, c4.y);<\/p>\n<p>\n&nbsp;<\/p>\n<p>vmlStr.push(&#8216; padding:0px &#8216;, Math.floor(max.x), &#8216;px &#8216;, Math.floor(max.y),<br \/>\n&#8216;px 0px;filter:progid:DXImageTransform.Microsoft.Matrix(&#8216;,<br \/>\nfilter.join(&quot;&quot;), &#8216;, sizingmethod=\\&#8217;clip\\&#8217;);&#8217;)<br \/>\n} else {<br \/>\nvmlStr.push(&#8216; top:&#8217;,d.y,&#8217;px; left:&#8217;,d.x,&#8217;px;&#8217;)<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>vmlStr.push(&#8216; &quot;&gt;&#8217; ,<br \/>\n&#8216;&lt;g_vml_:image src=&quot;&#8217;, image.src, &#8216;&quot;&#8217;,<br \/>\n&#8216; style=&quot;width:&#8217;, dw, &#8216;;&#8217;,<br \/>\n&#8216; height:&#8217;, dh, &#8216;;&quot;&#8217;,<br \/>\n&#8216; cropleft=&quot;&#8217;, sx \/ w, &#8216;&quot;&#8217;,<br \/>\n&#8216; croptop=&quot;&#8217;, sy \/ h, &#8216;&quot;&#8217;,<br \/>\n&#8216; cropright=&quot;&#8217;, (w &#8211; sx &#8211; sw) \/ w, &#8216;&quot;&#8217;,<br \/>\n&#8216; cropbottom=&quot;&#8217;, (h &#8211; sy &#8211; sh) \/ h, &#8216;&quot;&#8217;,<br \/>\n&#8216; \/&gt;&#8217;,<br \/>\n&#8216; &lt;\/g_vml_:group&gt;&#8217;);<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/this.element.innerHTML += vmlStr.join(&quot;&quot;);<br \/>\nthis.element.insertAdjacentHTML(&quot;BeforeEnd&quot;,<br \/>\nvmlStr.join(&quot;&quot;));<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.stroke = function(aFill) {<br \/>\nvar strokeColor, fillColor, opacity;<br \/>\nvar lineStr = [];<br \/>\nvar lineOpen = false;<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (aFill) {<br \/>\nvar a = G_VmlCanvas.ProcessStyle(this.fillStyle);<br \/>\nfillColor = a[0];<br \/>\nopacity = a[1] * this.globalAlpha;<br \/>\n} else {<br \/>\nvar a = G_VmlCanvas.ProcessStyle(this.strokeStyle);<br \/>\nstrokeColor = a[0];<br \/>\nopacity = a[1] * this.globalAlpha;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>lineStr.push(&#8216;&lt;g_vml_:shape&#8217;,<br \/>\n&#8216; fillcolor=&quot;&#8217;, fillColor, &#8216;&quot;&#8217;,<br \/>\n&#8216; filled=&quot;&#8217;,(aFill) ? &quot;true&quot; : &quot;false&quot;,&#8217;&quot;&#8217;,<br \/>\n&#8216; style=&quot;position:absolute; width:10; height:10;&quot;&#8217;,<br \/>\n&#8216; coordorigin=&quot;0 0&quot; coordsize=&quot;10 10&quot;&#8217;,<br \/>\n&#8216; stroked=&quot;&#8217;,(aFill) ? &quot;false&quot; : &quot;true&quot;,&#8217;&quot;&#8217;,<br \/>\n&#8216; strokeweight=&quot;&#8217;, this.lineWidth, &#8216;&quot;&#8217;,<br \/>\n&#8216; strokecolor=&quot;&#8217;, strokeColor, &#8216;&quot;&#8217;,<br \/>\n&#8216; path=&quot;&#8217;);<\/p>\n<p>\n&nbsp;<\/p>\n<p>var newSeq = false;<br \/>\nvar min = {x:null, y:null};<br \/>\nvar max = {x:null, y:null};<\/p>\n<p>\n&nbsp;<\/p>\n<p>for (var i = 0; i &lt; this.currentPath.length; i++) {<br \/>\nvar p = this.currentPath[i];<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (p.type == &#8216;moveTo&#8217;) {<br \/>\nlineStr.push(&#8216; m &#8216;);<br \/>\nvar c = this.Coords(p.x, p.y);<br \/>\nlineStr.push(Math.floor(c.x), &#8216;,&#8217;, Math.floor(c.y));<br \/>\n} else if (p.type == &#8216;lineTo&#8217;) {<br \/>\nlineStr.push(&#8216; l &#8216;);<br \/>\nvar c = this.Coords(p.x, p.y);<br \/>\nlineStr.push(Math.floor(c.x), &#8216;,&#8217;, Math.floor(c.y));<br \/>\n} else if (p.type == &#8216;close&#8217;) {<br \/>\nlineStr.push(&#8216; x &#8216;);<br \/>\n} else if (p.type == &#8216;bezierCurveTo&#8217;) {<br \/>\nlineStr.push(&#8216; c &#8216;);<br \/>\nvar c = this.Coords(p.x, p.y);<br \/>\nvar c1 = this.Coords(p.cp1x, p.cp1y);<br \/>\nvar c2 = this.Coords(p.cp2x, p.cp2y);<br \/>\nlineStr.push(Math.floor(c1.x), &#8216;,&#8217;, Math.floor(c1.y), &#8216;,&#8217;,<br \/>\nMath.floor(c2.x), &#8216;,&#8217;, Math.floor(c2.y), &#8216;,&#8217;,<br \/>\nMath.floor(c.x), &#8216;,&#8217;, Math.floor(c.y));<br \/>\n} else if (p.type == &#8216;arc&#8217;) {<br \/>\nlineStr.push(&#8216; ar &#8216;);<br \/>\nvar c = this.Coords(p.x, p.y);<br \/>\nvar cStart = this.Coords(p.xStart, p.yStart);<br \/>\nvar cEnd = this.Coords(p.xEnd, p.yEnd);<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ TODO(glen): FIX (matricies (scale+rotation) now buggered this up)<br \/>\n\/\/ VML arc also doesn&#8217;t seem able to do rotated non-circular<br \/>\n\/\/ arcs without parent grouping.<br \/>\nvar absXScale = this.m[0][0];<br \/>\nvar absYScale = this.m[1][1];<\/p>\n<p>\n&nbsp;<\/p>\n<p>lineStr.push(Math.floor(c.x &#8211; absXScale * p.radius), &#8216;,&#8217;, Math.floor(c.y &#8211; absYScale * p.radius), &#8216; &#8216;,<br \/>\nMath.floor(c.x + absXScale * p.radius), &#8216;,&#8217;, Math.floor(c.y + absYScale * p.radius), &#8216; &#8216;,<br \/>\nMath.floor(cStart.x), &#8216;,&#8217;, Math.floor(cStart.y), &#8216; &#8216;,<br \/>\nMath.floor(cEnd.x), &#8216;,&#8217;, Math.floor(cEnd.y));<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>\n\/\/ TODO(glen): Following is broken for curves due to<br \/>\n\/\/ move to proper paths.<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ Figure out dimensions so we can do gradient fills<br \/>\n\/\/ properly<br \/>\nif (min.x == null || c.x &lt; min.x) {<br \/>\nmin.x = c.x;<br \/>\n}<br \/>\nif (max.x == null || c.x &gt; max.x) {<br \/>\nmax.x = c.x;<br \/>\n}<br \/>\nif (min.y == null || c.y &lt; min.y) {<br \/>\nmin.y = c.y;<br \/>\n}<br \/>\nif (max.y == null || c.y &gt; max.y) {<br \/>\nmax.y = c.y;<br \/>\n}<br \/>\n}<br \/>\nlineStr.push(&#8216; &quot;&gt;&#8217;);<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (typeof this.fillStyle == &#8216;object&#8217;) {<br \/>\nvar focus = {x:&quot;50%&quot;, y:&quot;50%&quot;};<br \/>\nvar width = (max.x &#8211; min.x);<br \/>\nvar height = (max.y &#8211; min.y);<br \/>\nvar dimension = (width &gt; height) ? width : height;<\/p>\n<p>\n&nbsp;<\/p>\n<p>focus.x = Math.floor((this.fillStyle.focus.x \/ width) * 100 + 50) + &#8216;%&#8217;;<br \/>\nfocus.y = Math.floor((this.fillStyle.focus.y \/ height) * 100 + 50) + &#8216;%&#8217;;<\/p>\n<p>\n&nbsp;<\/p>\n<p>var colors = [];<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ inside radius (%)<br \/>\nif (this.fillStyle.type == &#8216;gradientradial&#8217;) {<br \/>\nvar inside = (this.fillStyle.radius1 \/ dimension * 100);<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ percentage that outside radius exceeds inside radius<br \/>\nvar expansion = (this.fillStyle.radius2 \/ dimension * 100) &#8211; inside;<br \/>\n} else {<br \/>\nvar inside = 0;<br \/>\nvar expansion = 100;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>var insidecolor = {offset:null, color:null};<br \/>\nvar outsidecolor = {offset:null, color:null};<\/p>\n<p>\n&nbsp;<\/p>\n<p>\/\/ We need to sort &#8216;colors&#8217; by percentage, from 0 &gt; 100 otherwise ie won&#8217;t<br \/>\n\/\/ interpret it correctly<br \/>\nthis.fillStyle.colors.sort(function (cs1, cs2) {<br \/>\nreturn cs1.offset &#8211; cs2.offset;<br \/>\n});<\/p>\n<p>\n&nbsp;<\/p>\n<p>for (var i = 0; i &lt; this.fillStyle.colors.length; i++) {<br \/>\nvar fs = this.fillStyle.colors[i];<\/p>\n<p>\n&nbsp;<\/p>\n<p>colors.push( (fs.offset * expansion) + inside,&#8217;% &#8216;,fs.color,&quot;,&quot;);<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (fs.offset &gt; insidecolor.offset || insidecolor.offset == null) {<br \/>\ninsidecolor.offset = fs.offset;<br \/>\ninsidecolor.color = fs.color;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (fs.offset &lt; outsidecolor.offset || outsidecolor.offset == null) {<br \/>\noutsidecolor.offset = fs.offset;<br \/>\noutsidecolor.color = fs.color;<br \/>\n}<br \/>\n}<br \/>\ncolors.pop();<\/p>\n<p>\n&nbsp;<\/p>\n<p>lineStr.push(&#8216;&lt;g_vml_:fill&#8217;,<br \/>\n&#8216; color=&quot;&#8217;,outsidecolor.color,&#8217;&quot;&#8217;,<br \/>\n&#8216; color2=&quot;&#8217;,insidecolor.color,&#8217;&quot;&#8217;,<br \/>\n&#8216; type=&quot;&#8217;, this.fillStyle.type, &#8216;&quot;&#8217;,<br \/>\n&#8216; focusposition=&quot;&#8217;, focus.x, &#8216;, &#8216;, focus.y, &#8216;&quot;&#8217;,<br \/>\n&#8216; colors=&quot;&#8217;, colors.join(&#8221;), &#8216;&quot; \/&gt;&#8217;);<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (aFill) {<br \/>\nlineStr.push(&#8216;&lt;g_vml_:fill opacity=&quot;&#8217;, opacity, &#8216;&quot; \/&gt;&#8217;);<br \/>\n} else {<br \/>\nlineStr.push(&#8216;&lt;g_vml_:stroke opacity=&quot;&#8217;, opacity, &#8216;&quot; joinstyle=&quot;&#8217;, this.lineJoin, &#8216;&quot; miterlimit=&quot;&#8217;, this.miterLimit, &#8216;&quot; endcap=&quot;&#8217;, G_VmlCanvas.ProcessLineCap(this.lineCap) ,&#8217;&quot; \/&gt;&#8217;);<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>lineStr.push(&#8216;&lt;\/g_vml_:shape&gt;&#8217;);<\/p>\n<p>\n&nbsp;<\/p>\n<p>this.element.insertAdjacentHTML(&quot;beforeEnd&quot;, lineStr.join(&quot;&quot;));<\/p>\n<p>\n&nbsp;<\/p>\n<p>this.currentPath = [];<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.fill = function() {<br \/>\nthis.stroke(true);<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.closePath = function() {<br \/>\nthis.currentPath.push({type: &#8216;close&#8217;});<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.Coords = function(aX, aY) {<br \/>\nreturn {<br \/>\nx: (aX * this.m[0][0] + aY * this.m[1][0] + this.m[2][0]),<br \/>\ny: (aX * this.m[0][1] + aY * this.m[1][1] + this.m[2][1])<br \/>\n}<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.save = function() {<br \/>\nvar o = {};<br \/>\nG_VmlCanvas.CopyState(this, o);<br \/>\nthis.aStack.push(o);<br \/>\nthis.mStack.push(this.m);<br \/>\nthis.m = G_VmlCanvas.MatrixMultiply(G_VmlCanvas.MatrixIdentity(), this.m);\/\/new G_VmlCanvas.Matrix(this.m.x, this.m.y, this.m.rot, this.m.xScale, this.m.yScale);<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.restore = function() {<br \/>\nG_VmlCanvas.CopyState(this.aStack.pop(), this);<br \/>\nthis.m = this.mStack.pop();<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.translate = function(aX, aY) {<br \/>\nvar m1 = [<br \/>\n[1, 0, 0],<br \/>\n[0, 1, 0],<br \/>\n[aX, aY, 1]<br \/>\n];<\/p>\n<p>\n&nbsp;<\/p>\n<p>this.m = G_VmlCanvas.MatrixMultiply(m1, this.m);<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.rotate = function(aRot) {<br \/>\nvar c = Math.cos(aRot);<br \/>\nvar s = Math.sin(aRot);<\/p>\n<p>\n&nbsp;<\/p>\n<p>var m1 = [<br \/>\n[c, s, 0],<br \/>\n[-s, c, 0],<br \/>\n[0, 0, 1]<br \/>\n];<\/p>\n<p>\n&nbsp;<\/p>\n<p>this.m = G_VmlCanvas.MatrixMultiply(m1, this.m);<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>G_VmlCanvas.prototype.scale = function(aX, aY) {<br \/>\nvar m1 = [<br \/>\n[aX, 0, 0],<br \/>\n[0, aY, 0],<br \/>\n[0, 0, 1]<br \/>\n];<\/p>\n<p>\n&nbsp;<\/p>\n<p>this.m = G_VmlCanvas.MatrixMultiply(m1, this.m);<br \/>\n};<\/p>\n<p>\n&nbsp;<\/p>\n<p>\n\/******** STUBS ********\/<br \/>\nG_VmlCanvas.prototype.clip = function() {;}<br \/>\nG_VmlCanvas.prototype.createPattern = function() {;}<\/p>\n<p>\n&nbsp;<\/p>\n<p>\n&lt;\/SCRIPT&gt;<br \/>\n&lt;STYLE type=&quot;text\/css&quot;&gt;&lt;!&#8211;<\/p>\n<p>\n&nbsp;<\/p>\n<p>H1 {<br \/>\npadding: 5px;<br \/>\nfont-size: 14pt;<br \/>\nfont-style: italic;<br \/>\n}<br \/>\nBODY {<br \/>\nfont-family: arial;<br \/>\nfont-size: 10pt;<br \/>\nbackground-color: #000;<br \/>\ncolor: #CCC;<br \/>\n}<br \/>\n#holder {<br \/>\nposition: relative;<br \/>\nwidth: 400px;<br \/>\nheight:300px;<br \/>\ntop: 10px;<br \/>\nleft: 120px;<br \/>\nborder: 2px solid #333;<br \/>\n}<br \/>\n#sky {<br \/>\nposition: absolute;<br \/>\nleft: 0;<br \/>\ntop: 0;<br \/>\nheight: 150px;<br \/>\nwidth: 400px;<br \/>\nbackground-color: #CCD;<br \/>\nbackground-image: url(sky.jpg);<\/p>\n<p>\n&nbsp;<\/p>\n<p>}<br \/>\n#floor {<br \/>\nposition: absolute;<br \/>\nleft: 0;<br \/>\ntop: 150px;<br \/>\nheight: 150px;<br \/>\nwidth: 400px;<br \/>\nbackground-color: #565;<br \/>\nbackground-image: url(floor.png);<\/p>\n<p>\n&nbsp;<\/p>\n<p>}<br \/>\n#canvas {<br \/>\nposition: absolute;<br \/>\ntop: 0;<br \/>\nleft: 0;<\/p>\n<p>\n&nbsp;<\/p>\n<p>}<br \/>\n#overlay {<br \/>\nposition: absolute;<br \/>\ntop: 0;<br \/>\nleft: 0;<br \/>\nwidth: 400px;<br \/>\nheight: 300px;<br \/>\nbackground-image: url(overlay.gif);<br \/>\n}<br \/>\n#map, #underMap {<br \/>\ntop: 70px;<br \/>\nleft: 20px;<br \/>\nposition: absolute;<br \/>\n}<br \/>\n#copyright {<br \/>\nposition: absolute;<br \/>\ntop: 170px;<br \/>\nleft: 15px;<br \/>\n}<br \/>\nA {<br \/>\ncolor: #66AACC;<br \/>\n}<br \/>\nA:hover {<br \/>\ncolor: lime;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>&#8211;&gt;&lt;\/STYLE&gt;<br \/>\n&lt;\/HEAD&gt;<\/p>\n<p>\n&nbsp;<\/p>\n<p>&lt;BODY&gt;<\/p>\n<p>\n&nbsp;<\/p>\n<p>&lt;H1&gt;Canvascape &#8211; &quot;3D Walker&quot;&lt;\/H1&gt;<\/p>\n<p>\n&nbsp;<\/p>\n<p>&lt;CANVAS id=&quot;underMap&quot; width=&quot;80&quot; height=&quot;80&quot;&gt;&lt;\/CANVAS&gt;<br \/>\n&lt;CANVAS id=&quot;map&quot; width=&quot;80&quot; height=&quot;80&quot;&gt;&lt;\/CANVAS&gt;<\/p>\n<p>\n&nbsp;<\/p>\n<p>&lt;DIV id=&quot;copyright&quot;&gt;<br \/>\n&amp;copy; Benjamin Joffe&lt;BR&gt;<br \/>\n&lt;A href=&quot;mailtCanvasGame@gmail.com&quot; style=&quot;font-size:7pt;&quot;&gt;canvasGame@gmail.com&lt;\/A&gt;<br \/>\n&lt;\/DIV&gt;<\/p>\n<p>\n&nbsp;<\/p>\n<p>&lt;DIV id=&quot;holder&quot; style=&quot;clear:both;&quot;&gt;<br \/>\n&lt;DIV id=&quot;sky&quot;&gt;&lt;\/DIV&gt;<br \/>\n&lt;DIV id=&quot;floor&quot;&gt;&lt;\/DIV&gt;<br \/>\n&lt;CANVAS id=&quot;canvas&quot; width=&quot;400&quot; height=&quot;300&quot;&gt;&lt;\/CANVAS&gt;<br \/>\n&lt;DIV id=&quot;overlay&quot;&gt;&lt;\/DIV&gt;<br \/>\n&lt;\/DIV&gt;<\/p>\n<p>\n&nbsp;<\/p>\n<p>&lt;P&gt;Use the arrow keys to walk around the map. Space bar = jump.&lt;\/P&gt;<br \/>\n&lt;P&gt;What you are seeing is a test using the new Canvas tag to demonstrate its capabilities, Internet Explorer support has recently been added thanks to Google&#8217;s workaround code. See als &lt;A href=&quot;textures.htm&quot;&gt;textured version&lt;\/A&gt;.&lt;\/P&gt;<br \/>\n&lt;P&gt;&lt;A href=&quot;Web&#8217;&gt;http:\/\/www.studiocoast.com.au\/&quot;&gt;Web xiaoyebailong.coming provided by Studio Coast&lt;\/A&gt;&lt;\/P&gt;<\/p>\n<p>\n&nbsp;<\/p>\n<p>&lt;SCRIPT type=&quot;text\/javascript&quot;&gt;&lt;!&#8211;<br \/>\n\/*<br \/>\nThis code is copyright by Benjamin Joffe.<br \/>\nYou may not reproduce or modify this without<br \/>\nwritten permission by the origional author.<br \/>\nEmail him: CanvasGame@gmail.com for suggestions.<br \/>\n*\/<\/p>\n<p>&nbsp;<\/p>\n<p>var map;<br \/>\nvar canvas;<br \/>\nvar overlay;<br \/>\n\/\/variables initiated at the bottom of the code&#8230;<\/p>\n<p>\n&nbsp;<\/p>\n<p>var pi=Math.PI;<\/p>\n<p>\n&nbsp;<\/p>\n<p>var total=0;<\/p>\n<p>\n&nbsp;<\/p>\n<p>Number.prototype.range=function(){<br \/>\nreturn (this+2*pi)%(2*pi);<br \/>\n}<br \/>\nNumber.prototype.roundC=function(){<br \/>\nreturn Math.round(this*100)\/100;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>var total=0;<\/p>\n<p>\n&nbsp;<\/p>\n<p>var samples=200;<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nvar arena=[];<br \/>\narena[0]=[1,1,1,1,1,1,1,1,1,1]<br \/>\narena[1]=[1,0,0,0,0,0,0,0,0,1]<br \/>\narena[2]=[1,0,0,1,0,1,1,1,0,1]<br \/>\narena[3]=[1,0,1,0,0,0,0,1,0,1]<br \/>\narena[4]=[1,0,0,0,0,1,0,1,0,1]<br \/>\narena[5]=[1,0,1,1,0,0,0,0,0,1]<br \/>\narena[6]=[1,0,0,1,0,1,1,1,0,1]<br \/>\narena[7]=[1,1,0,1,0,0,0,1,0,1]<br \/>\narena[8]=[1,0,0,1,0,1,0,0,0,1]<br \/>\narena[9]=[1,1,1,1,1,1,1,1,1,1]<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nvar playerPos=[4,4]; \/\/ x,y (from top left)<br \/>\nvar playerDir=0.4; \/\/ theta, facing right=0=2pi<br \/>\nvar playerPosZ=1;<br \/>\nvar key=[0,0,0,0,0]; \/\/ left, right, up, down<\/p>\n<p>\n&nbsp;<\/p>\n<p>var playerVelY=0;<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nvar face=[];<\/p>\n<p>\n&nbsp;<\/p>\n<p>function wallDistance(theta){<\/p>\n<p>\n&nbsp;<\/p>\n<p>var data=[];<br \/>\nface=[];<\/p>\n<p>\n&nbsp;<\/p>\n<p>var x = playerPos[0], y = playerPos[1];<br \/>\nvar deltaX, deltaY;<br \/>\nvar distX, distY;<br \/>\nvar stepX, stepY;<br \/>\nvar mapX, mapY<\/p>\n<p>var atX=Math.floor(x), atY=Math.floor(y);<\/p>\n<p>\n&nbsp;<\/p>\n<p>var thisRow=-1;<br \/>\nvar thisSide=-1;<\/p>\n<p>\n&nbsp;<\/p>\n<p>var lastHeight=0;<\/p>\n<p>\n&nbsp;<\/p>\n<p>for (var i=0; i&lt;samples; i++) {<br \/>\ntheta+=pi\/(3*samples)+2*pi;<br \/>\ntheta%=2*pi;<\/p>\n<p>\n&nbsp;<\/p>\n<p>mapX = atX, mapY = atY;<\/p>\n<p>\n&nbsp;<\/p>\n<p>deltaX=1\/Math.cos(theta);<br \/>\ndeltaY=1\/Math.sin(theta);<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (deltaX&gt;0) {<br \/>\nstepX = 1;<br \/>\ndistX = (mapX + 1 &#8211; x) * deltaX;<br \/>\n}<br \/>\nelse {<br \/>\nstepX = -1;<br \/>\ndistX = (x &#8211; mapX) * (deltaX*=-1); <br \/>\n}<br \/>\nif (deltaY&gt;0) {<br \/>\nstepY = 1;<br \/>\ndistY = (mapY + 1 &#8211; y) * deltaY;<br \/>\n}<br \/>\nelse {<br \/>\nstepY = -1;<br \/>\ndistY = (y &#8211; mapY) * (deltaY*=-1);<br \/>\n}<br \/>\n&nbsp;<\/p>\n<p>\n&nbsp;<\/p>\n<p>for (var j=0; j&lt;20; j++) {<br \/>\nif (distX &lt; distY) {<br \/>\nmapX += stepX;<br \/>\nif (arena[mapX][mapY]) {<br \/>\nif (thisRow!=mapX || thisSide!=0) {<br \/>\nif (i&gt;0) {<br \/>\ndata.push(i);<br \/>\ndata.push(lastHeight);<br \/>\n}<br \/>\ndata.push(i);<br \/>\ndata.push(distX);<br \/>\nthisSide=0;<br \/>\nthisRow=mapX;<br \/>\nface.push(1+stepX);<br \/>\n}<br \/>\nlastHeight=distX;<br \/>\nbreak;<br \/>\n}<br \/>\ndistX += deltaX;<br \/>\n}<br \/>\nelse {<br \/>\nmapY += stepY;<br \/>\nif (arena[mapX][mapY]) {<br \/>\nif (thisRow!=mapY || thisSide!=1) {<br \/>\nif (i&gt;0) {<br \/>\ndata.push(i);<br \/>\ndata.push(lastHeight);<br \/>\n} <br \/>\ndata.push(i);<br \/>\ndata.push(distY);<br \/>\nthisSide=1;<br \/>\nthisRow=mapY;<br \/>\nface.push(2+stepY)<br \/>\n}<br \/>\nlastHeight=distY;<br \/>\nbreak;<br \/>\n}<br \/>\ndistY += deltaY;<br \/>\n}<br \/>\n}<br \/>\n}<br \/>\ndata.push(i);<br \/>\ndata.push(lastHeight);<\/p>\n<p>return data;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nfunction drawCanvas(){<\/p>\n<p>\n&nbsp;<\/p>\n<p>canvas.clearRect(0,0,400, 300);<\/p>\n<p>\n&nbsp;<\/p>\n<p>var theta = playerDir-pi\/6;<\/p>\n<p>\n&nbsp;<\/p>\n<p>var wall=wallDistance(theta);<\/p>\n<p>\n&nbsp;<\/p>\n<p>map.beginPath();<br \/>\nmap.clearRect(0,0,80,80);<br \/>\nmap.fillStyle=&quot;#3366CC&quot;;<br \/>\nmap.arc(playerPos[0]*8, playerPos[1]*8, 3, 0, 2*pi, true);<br \/>\nmap.fill();<br \/>\nmap.beginPath();<br \/>\nmap.moveTo(8*playerPos[0], 8*playerPos[1]);<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nvar linGrad;<\/p>\n<p>var tl,tr,bl,br;<\/p>\n<p>var theta1,theta2,fix1,fix2;<\/p>\n<p>for (var i=0; i&lt;wall.length; i+=4) {<\/p>\n<p>\n&nbsp;<\/p>\n<p>theta1=playerDir-pi\/6 + pi*wall[i]\/(3*samples);<br \/>\ntheta2=playerDir-pi\/6 + pi*wall[i+2]\/(3*samples);<\/p>\n<p>fix1 = Math.cos(theta1-playerDir);<br \/>\nfix2 = Math.cos(theta2-playerDir);<\/p>\n<p>\n&nbsp;<\/p>\n<p>var h=2-playerPosZ;<\/p>\n<p>\n&nbsp;<\/p>\n<p>var wallH1=100\/(wall[i+1]*fix1);<br \/>\nvar wallH2=100\/(wall[i+3]*fix2);<\/p>\n<p>\n&nbsp;<\/p>\n<p>tl=[wall[i]*2, 150-wallH1*h];<br \/>\ntr=[wall[i+2]*2, 150-wallH2*h]<br \/>\nbr=[wall[i+2]*2, tr[1]+wallH2*2];<br \/>\nbl=[wall[i]*2, tl[1]+wallH1*2]<\/p>\n<p>\n&nbsp;<\/p>\n<p>var shade1=Math.floor(wallH1*2+20); if (shade1&gt;255) shade1=255;<br \/>\nvar shade2=Math.floor(wallH2*2+20); if (shade2&gt;255) shade2=255;<\/p>\n<p>\n&nbsp;<\/p>\n<p>linGrad = canvas.createLinearGradient(tl[0],0,tr[0],0);<br \/>\nlinGrad.addColorStop(0, &#8216;rgba(&#8216;+(face[i\/4]%2==0 ? shade1 : 0)+&#8217;,&#8217;+(face[i\/4]==1 ? shade1 : 0)+&#8217;,&#8217;+(face[i\/4]==2 ? 0 : shade1)+&#8217;,1.0)&#8217;);<br \/>\nlinGrad.addColorStop(1, &#8216;rgba(&#8216;+(face[i\/4]%2==0 ? shade2 : 0)+&#8217;,&#8217;+(face[i\/4]==1 ? shade2 : 0)+&#8217;,&#8217;+(face[i\/4]==2 ? 0 : shade2)+&#8217;,1.0)&#8217;);<\/p>\n<p>\n&nbsp;<\/p>\n<p>canvas.beginPath();<br \/>\ncanvas.moveTo(tl[0], tl[1]);<br \/>\ncanvas.lineTo(tr[0], tr[1]);<br \/>\ncanvas.lineTo(br[0], br[1]);<br \/>\ncanvas.lineTo(bl[0], bl[1]);<br \/>\ncanvas.fillStyle = linGrad;<br \/>\ncanvas.fill();<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nmap.lineTo(playerPos[0]*8+Math.cos(theta1)*(wall[i+1])*8, playerPos[1]*8+Math.sin(theta1)*(wall[i+1])*8);<br \/>\nmap.lineTo(playerPos[0]*8+Math.cos(theta2)*(wall[i+3])*8, playerPos[1]*8+Math.sin(theta2)*(wall[i+3])*8);<\/p>\n<p>\n&nbsp;<\/p>\n<p>\n}<br \/>\nmap.fillStyle=&quot;#FF0000&quot;<br \/>\nmap.fill();<\/p>\n<p>}<\/p>\n<p>\n&nbsp;<\/p>\n<p>function nearWall(x,y){<br \/>\nvar xx,yy;<br \/>\nif (isNaN(x)) x=playerPos[0];<br \/>\nif (isNaN(y)) y=playerPos[1];<br \/>\nfor (var i=-0.1; i&lt;=0.1; i+=0.2) {<br \/>\nxx=Math.floor(x+i)<br \/>\nfor (var j=-0.1; j&lt;=0.1; j+=0.2) {<br \/>\nyy=Math.floor(y+j);<br \/>\nif (arena[xx][yy]) return true;<br \/>\n}<br \/>\n}<br \/>\nreturn false;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>function wobbleGun(){<br \/>\nvar mag=playerVelY;<br \/>\noverlay.style.backgroundPosition=(10+Math.cos(total\/6.23)*mag*90)+&quot;px &quot;+(10+Math.cos(total\/5)*mag*90)+&quot;px&quot;;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nvar jumpCycle=0;<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nfunction update(){<\/p>\n<p>\n&nbsp;<\/p>\n<p>total++;<\/p>\n<p>\n&nbsp;<\/p>\n<p>var change=false;<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (jumpCycle) {<br \/>\njumpCycle&#8211;;<br \/>\nchange=true;<br \/>\nplayerPosZ = 1 + jumpCycle*(20-jumpCycle)\/110;<br \/>\n}<br \/>\nelse if (key[4]) jumpCycle=20;<\/p>\n<p>if (key[0]) {<br \/>\nif (!key[1]) {<br \/>\nplayerDir-=0.07; \/\/left<br \/>\nchange=true;<br \/>\n}<br \/>\n}<br \/>\nelse if (key[1]) {<br \/>\nplayerDir+=0.07; \/\/right<br \/>\nchange=true;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (change) {<br \/>\nplayerDir+=2*pi;<br \/>\nplayerDir%=2*pi;<br \/>\ndocument.getElementById(&quot;sky&quot;).style.backgroundPosition=Math.floor(1-playerDir\/(2*pi)*2400)+&quot;px 0&quot;;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (key[2] &amp;&amp; !key[3]) {<br \/>\nif (playerVelY&lt;0.1) playerVelY += 0.02;<br \/>\n}<br \/>\nelse if (key[3] &amp;&amp; !key[2]) {<br \/>\nif (playerVelY&gt;-0.1) playerVelY -= 0.02;<br \/>\n}<br \/>\nelse {<br \/>\nif (playerVelY&lt;-0.02) playerVelY += 0.015;<br \/>\nelse if (playerVelY&gt;0.02) playerVelY -= 0.015;<br \/>\nelse playerVelY=0;<br \/>\n}<\/p>\n<p>\nif (playerVelY!=0) {<\/p>\n<p>\n&nbsp;<\/p>\n<p>var oldX=playerPos[0];;<br \/>\nvar oldY=playerPos[1]; <br \/>\nvar newX=oldX+Math.cos(playerDir)*playerVelY;<br \/>\nvar newY=oldY+Math.sin(playerDir)*playerVelY;<\/p>\n<p>\n&nbsp;<\/p>\n<p>if (!nearWall(newX, oldY)) {<br \/>\nplayerPos[0]=newX;<br \/>\noldX=newX;<br \/>\nchange=true;<br \/>\n}<br \/>\nif (!nearWall(oldX, newY)) {<br \/>\nplayerPos[1]=newY;<br \/>\nchange=true;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>}<\/p>\n<p>if (playerVelY) wobbleGun();<br \/>\nif (change) drawCanvas();<\/p>\n<p>\n&nbsp;<\/p>\n<p>}<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nfunction changeKey(which, to){<br \/>\nswitch (which){<br \/>\ncase 65:case 37: key[0]=to; break; \/\/ left<br \/>\ncase 87: case 38: key[2]=to; break; \/\/ up<br \/>\ncase 68: case 39: key[1]=to; break; \/\/ right<br \/>\ncase 83: case 40: key[3]=to; break;\/\/ down<br \/>\ncase 32: key[4]=to; break; \/\/ space bar;<br \/>\ncase 17: key[5]=to; break; \/\/ ctrl<br \/>\n}<br \/>\n}<br \/>\ndocument.onkeydown=function(e){changeKey((e||window.event).keyCode, 1);}<br \/>\ndocument.onkeyup=function(e){changeKey((e||window.event).keyCode, 0);}<\/p>\n<p>\n&nbsp;<\/p>\n<p>\nfunction initUnderMap(){<br \/>\nvar underMap=document.getElementById(&quot;underMap&quot;).getContext(&quot;2d&quot;);<br \/>\nunderMap.fillStyle=&quot;#FFF&quot;;<br \/>\nunderMap.fillRect(0,0, 200, 200);<br \/>\nunderMap.fillStyle=&quot;#444&quot;;<br \/>\nfor (var i=0; i&lt;arena.length; i++) {<br \/>\nfor (var j=0; j&lt;arena[i].length; j++) {<br \/>\nif (arena[i][j]) underMap.fillRect(i*8, j*8, 8, 8);<br \/>\n} <br \/>\n}<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>window.onerror=function(){<br \/>\nalert(&#8216;An error has occured, the most likely reason is because you are using an incompatible browser.\\nYou must be using one of the following browsers or a newer version:\\n\\n- Internet Explorer 6\\n- Firefox 1.5\\n- Safari 1.3\\n- Opera 9&#8217;);<br \/>\nwindow.onerror=function(){};<br \/>\nreturn true;<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>window.onload=function(){<br \/>\nmap=document.getElementById(&quot;map&quot;).getContext(&quot;2d&quot;);<br \/>\ncanvas=document.getElementById(&quot;canvas&quot;).getContext(&quot;2d&quot;);<br \/>\noverlay=document.getElementById(&quot;overlay&quot;);<br \/>\ndocument.getElementById(&quot;sky&quot;).style.backgroundPosition=Math.floor(-playerDir\/(2*pi)*2400)+&quot;px 0&quot;;<br \/>\ndrawCanvas();<br \/>\ninitUnderMap();<br \/>\nsetInterval(update, 35);<br \/>\n}<\/p>\n<p>\n&nbsp;<\/p>\n<p>\n\/\/&#8211;&gt;&lt;\/SCRIPT&gt;<\/p>\n<p>&nbsp;<\/p>\n<p>&lt;!&#8211; Start of StatCounter Code &#8211;&gt;<br \/>\n&lt;script type=&quot;text\/javascript&quot; language=&quot;javascript&quot;&gt;<br \/>\nvar sc_project=1082313; <br \/>\nvar sc_invisible=1; <br \/>\nvar sc_partition=9; <br \/>\nvar sc_security=&quot;adb52a92&quot;; <br \/>\n&lt;\/script&gt;<\/p>\n<p>\n&nbsp;<\/p>\n<p>\n&lt;!&#8211; End of StatCounter Code &#8211;&gt;<\/p>\n<p>&nbsp;<\/p>\n<p>&lt;\/BODY&gt;<br \/>\n&lt;\/HTML&gt;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&lt;!DOCTYPE HTML PUBLIC &quot;-\/\/W3C\/\/DTD HTML 4.01\/\/EN&quot; &quot;http:\/\/www.w3.org\/TR\/html4\/strict.dtd&quot;&gt; &#038;lt&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"topic":[],"class_list":["post-691","post","type-post","status-publish","format-standard","hentry","category-technology"],"_links":{"self":[{"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/posts\/691","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/comments?post=691"}],"version-history":[{"count":1,"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/posts\/691\/revisions"}],"predecessor-version":[{"id":66551,"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/posts\/691\/revisions\/66551"}],"wp:attachment":[{"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/media?parent=691"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/categories?post=691"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/tags?post=691"},{"taxonomy":"topic","embeddable":true,"href":"http:\/\/www.xiaoyebailong.com\/index.php\/wp-json\/wp\/v2\/topic?post=691"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}