[html5] r7884 - [e] (0) New canvas example. Fixing https://www.w3.org/Bugs/Public/show_bug.cgi?i [...]

whatwg at whatwg.org whatwg at whatwg.org
Fri May 31 17:14:50 PDT 2013


Author: ianh
Date: 2013-05-31 17:14:46 -0700 (Fri, 31 May 2013)
New Revision: 7884

Modified:
   complete.html
   index
   source
Log:
[e] (0) New canvas example.
Fixing https://www.w3.org/Bugs/Public/show_bug.cgi?id=21183
Affected topics: Canvas, HTML

Modified: complete.html
===================================================================
--- complete.html	2013-05-31 20:35:03 UTC (rev 7883)
+++ complete.html	2013-06-01 00:14:46 UTC (rev 7884)
@@ -256,7 +256,7 @@
 
   <header class=head id=head><p><a class=logo href=http://www.whatwg.org/><img alt=WHATWG height=101 src=/images/logo width=101></a></p>
    <hgroup><h1 class=allcaps>HTML</h1>
-    <h2 class="no-num no-toc">Living Standard — Last Updated 31 May 2013</h2>
+    <h2 class="no-num no-toc">Living Standard — Last Updated 1 June 2013</h2>
    </hgroup><dl><dt><strong>Web developer edition:</strong></dt>
     <dd><strong><a href=http://developers.whatwg.org/>http://developers.whatwg.org/</a></strong></dd>
     <dt>Multiple-page version:</dt>
@@ -38596,6 +38596,181 @@
 
   </div>
 
+  <div class=example>
+
+   <p>The 2D rendering context for <code><a href=#the-canvas-element>canvas</a></code> is often used for sprite-based games. The
+   following example demonstrates this:</p>
+
+   <iframe height=216 src=/demos/canvas/blue-robot/index.html width=396></iframe>
+
+   <p>Here is the source for this example:</p>
+
+   <pre><!DOCTYPE HTML>
+<title>Blue Robot Demo</title>
+<base href="http://www.whatwg.org/demos/canvas/blue-robot/">
+<style>
+  html { overflow: hidden; min-height: 200px; min-width: 380px; }
+  body { height: 200px; position: relative; margin: 8px; }
+  .buttons { position: absolute; bottom: 0px; left: 0px; margin: 4px; }
+</style>
+<canvas width="380" height="200"></canvas>
+<script>
+ var Landscape = function (context, width, height) {
+   this.offset = 0;
+   this.width = width;
+   this.advance = function (dx) {
+     this.offset += dx;
+   };
+   this.horizon = height * 0.7;
+   // This creates the sky gradient (from a darker blue to white at the bottom)
+   this.sky = context.createLinearGradient(0, 0, 0, this.horizon);
+   this.sky.addColorStop(0.0, 'rgb(55,121,179)');
+   this.sky.addColorStop(0.7, 'rgb(121,194,245)');
+   this.sky.addColorStop(1.0, 'rgb(164,200,214)');
+   // this creates the grass gradient (from a darker green to a lighter green)
+   this.earth = context.createLinearGradient(0, this.horizon, 0, height);
+   this.earth.addColorStop(0.0, 'rgb(81,140,20)');
+   this.earth.addColorStop(1.0, 'rgb(123,177,57)');
+   this.paintBackground = function (context, width, height) {
+     // first, paint the sky and grass rectangles
+     context.fillStyle = this.sky;
+     context.fillRect(0, 0, width, this.horizon);
+     context.fillStyle = this.earth;
+     context.fillRect(0, this.horizon, width, height-this.horizon);
+     // then, draw the cloudy banner
+     // we make it cloudy by having the draw text off the top of the
+     // canvas, and just having the blurred shadow shown on the canvas
+     context.save();
+     context.translate(width-((this.offset+(this.width*3.2)) % (this.width*4.0))+0, 0);
+     context.shadowColor = 'white';
+     context.shadowOffsetY = 30+this.horizon/3; // offset down on canvas
+     context.shadowBlur = '5';
+     context.fillStyle = 'white';
+     context.textAlign = 'left';
+     context.textBaseline = 'top';
+     context.font = '20px sans-serif';
+     context.fillText('WHATWG ROCKS', 10, -30); // text up above canvas
+     context.restore();     
+     // then, draw the background tree
+     context.save();
+     context.translate(width-((this.offset+(this.width*0.2)) % (this.width*1.5))+30, 0);
+     context.beginPath();
+     context.fillStyle = 'rgb(143,89,2)';
+     context.lineStyle = 'rgb(10,10,10)';
+     context.lineWidth = 2;
+     context.rect(0, this.horizon+5, 10, -50); // trunk
+     context.fill();
+     context.stroke();
+     context.beginPath();
+     context.fillStyle = 'rgb(78,154,6)';
+     context.arc(5, this.horizon-60, 30, 0, Math.PI*2); // leaves
+     context.fill();
+     context.stroke();
+     context.restore();
+   };
+   this.paintForeground = function (context, width, height) {
+     // draw the box that goes in front
+     context.save();
+     context.translate(width-((this.offset+(this.width*0.7)) % (this.width*1.1))+0, 0);
+     context.beginPath();
+     context.rect(0, this.horizon - 5, 25, 25);
+     context.fillStyle = 'rgb(220,154,94)';
+     context.lineStyle = 'rgb(10,10,10)';
+     context.lineWidth = 2;
+     context.fill();
+     context.stroke();
+     context.restore();
+   };
+ };
+</script>
+<script>
+ var BlueRobot = function () {
+   this.sprites = new Image();
+   this.sprites.src = 'blue-robot.png'; // this sprite sheet has 8 cells
+   this.targetMode = 'idle';
+   this.walk = function () {
+     this.targetMode = 'walk';
+   };
+   this.stop = function () {
+     this.targetMode = 'idle';
+   };
+   this.frameIndex = {
+     'idle': [0], // first cell is the idle frame
+     'walk': [1,2,3,4,5,6], // the walking animation is cells 1-6
+     'stop': [7], // last cell is the stopping animation
+   };
+   this.mode = 'idle';
+   this.frame = 0; // index into frameIndex
+   this.tick = function () {
+     // this advances the frame and the robot
+     // the return value is how many pixels the robot has moved
+     this.frame += 1;
+     if (this.frame >= this.frameIndex[this.mode].length) {
+       // we've reached the end of this animation cycle
+       this.frame = 0;
+       if (this.mode != this.targetMode) {
+         // switch to next cycle
+         if (this.mode == 'walk') {
+           // we need to stop walking before we decide what to do next
+           this.mode = 'stop';
+         } else if (this.mode == 'stop') {
+           if (this.targetMode == 'walk')
+             this.mode = 'walk';
+           else
+             this.mode = 'idle';
+         } else if (this.mode == 'idle') {
+           if (this.targetMode == 'walk')
+             this.mode = 'walk';
+         }
+       }
+     }
+     if (this.mode == 'walk')
+       return 8;
+     return 0;
+   },
+   this.paint = function (context, x, y) {
+     if (!this.sprites.complete) return;
+     // draw the right frame out of the sprite sheet onto the canvas
+     // we assume each frame is as high as the sprite sheet
+     // the x,y coordinates give the position of the bottom center of the sprite
+     context.drawImage(this.sprites,
+                       this.frameIndex[this.mode][this.frame] * this.sprites.height, 0, this.sprites.height, this.sprites.height,
+                       x-this.sprites.height/2, y-this.sprites.height, this.sprites.height, this.sprites.height);
+   };
+ };
+</script>
+<script>
+ var canvas = document.getElementsByTagName('canvas')[0];
+ var context = canvas.getContext('2d');
+ var landscape = new Landscape(context, canvas.width, canvas.height);
+ var blueRobot = new BlueRobot();
+ // paint when the browser wants us to, using requestAnimationFrame()
+ function paint() {
+   context.clearRect(0, 0, canvas.width, canvas.height);
+   landscape.paintBackground(context, canvas.width, canvas.height);
+   blueRobot.paint(context, canvas.width/2, landscape.horizon*1.1);
+   landscape.paintForeground(context, canvas.width, canvas.height);
+   requestAnimationFrame(paint);
+ }
+ paint();
+ // but tick every 150ms, so that we don't slow down when we don't paint
+ setInterval(function () {
+   var dx = blueRobot.tick();
+   landscape.advance(dx);
+ }, 100);
+</script>
+<p class="buttons">
+ <input type=button value="Walk" onclick="blueRobot.walk()">
+ <input type=button value="Stop" onclick="blueRobot.stop()">
+<p>
+ <small> Blue Robot Player Sprite by <a href="http://johncolburn.deviantart.com/">JohnColburn</a>.
+ Licensed under the terms of the Creative Commons Attribution Share-Alike 3.0 Unported license.</small>
+</p></pre>
+
+  </div>
+
+
+
   
 
 
@@ -101872,6 +102047,13 @@
 
   
 
+  <div itemscope="" itemtype=http://n.whatwg.org/work>
+   <p>The Blue Robot Player sprite used in the canvas demo is based on
+   <a href=http://johncolburn.deviantart.com/art/Blue-Robot-Player-Sprite-323813997 itemprop=work>a work</a> by
+   <a href=http://johncolburn.deviantart.com/ itemprop=http://creativecommons.org/ns#attributionURL>JohnColburn</a>.
+   (<a href=http://creativecommons.org/licenses/by-sa/3.0/ itemprop=license>CC BY-SA 3.0</a>)</p>
+  </div>
+
   <p>Thanks also to the Microsoft blogging community for some ideas,
   to the attendees of the W3C Workshop on Web Applications and
   Compound Documents for inspiration, to the #mrt crew, the #mrt.no

Modified: index
===================================================================
--- index	2013-05-31 20:35:03 UTC (rev 7883)
+++ index	2013-06-01 00:14:46 UTC (rev 7884)
@@ -256,7 +256,7 @@
 
   <header class=head id=head><p><a class=logo href=http://www.whatwg.org/><img alt=WHATWG height=101 src=/images/logo width=101></a></p>
    <hgroup><h1 class=allcaps>HTML</h1>
-    <h2 class="no-num no-toc">Living Standard — Last Updated 31 May 2013</h2>
+    <h2 class="no-num no-toc">Living Standard — Last Updated 1 June 2013</h2>
    </hgroup><dl><dt><strong>Web developer edition:</strong></dt>
     <dd><strong><a href=http://developers.whatwg.org/>http://developers.whatwg.org/</a></strong></dd>
     <dt>Multiple-page version:</dt>
@@ -38596,6 +38596,181 @@
 
   </div>
 
+  <div class=example>
+
+   <p>The 2D rendering context for <code><a href=#the-canvas-element>canvas</a></code> is often used for sprite-based games. The
+   following example demonstrates this:</p>
+
+   <iframe height=216 src=/demos/canvas/blue-robot/index.html width=396></iframe>
+
+   <p>Here is the source for this example:</p>
+
+   <pre><!DOCTYPE HTML>
+<title>Blue Robot Demo</title>
+<base href="http://www.whatwg.org/demos/canvas/blue-robot/">
+<style>
+  html { overflow: hidden; min-height: 200px; min-width: 380px; }
+  body { height: 200px; position: relative; margin: 8px; }
+  .buttons { position: absolute; bottom: 0px; left: 0px; margin: 4px; }
+</style>
+<canvas width="380" height="200"></canvas>
+<script>
+ var Landscape = function (context, width, height) {
+   this.offset = 0;
+   this.width = width;
+   this.advance = function (dx) {
+     this.offset += dx;
+   };
+   this.horizon = height * 0.7;
+   // This creates the sky gradient (from a darker blue to white at the bottom)
+   this.sky = context.createLinearGradient(0, 0, 0, this.horizon);
+   this.sky.addColorStop(0.0, 'rgb(55,121,179)');
+   this.sky.addColorStop(0.7, 'rgb(121,194,245)');
+   this.sky.addColorStop(1.0, 'rgb(164,200,214)');
+   // this creates the grass gradient (from a darker green to a lighter green)
+   this.earth = context.createLinearGradient(0, this.horizon, 0, height);
+   this.earth.addColorStop(0.0, 'rgb(81,140,20)');
+   this.earth.addColorStop(1.0, 'rgb(123,177,57)');
+   this.paintBackground = function (context, width, height) {
+     // first, paint the sky and grass rectangles
+     context.fillStyle = this.sky;
+     context.fillRect(0, 0, width, this.horizon);
+     context.fillStyle = this.earth;
+     context.fillRect(0, this.horizon, width, height-this.horizon);
+     // then, draw the cloudy banner
+     // we make it cloudy by having the draw text off the top of the
+     // canvas, and just having the blurred shadow shown on the canvas
+     context.save();
+     context.translate(width-((this.offset+(this.width*3.2)) % (this.width*4.0))+0, 0);
+     context.shadowColor = 'white';
+     context.shadowOffsetY = 30+this.horizon/3; // offset down on canvas
+     context.shadowBlur = '5';
+     context.fillStyle = 'white';
+     context.textAlign = 'left';
+     context.textBaseline = 'top';
+     context.font = '20px sans-serif';
+     context.fillText('WHATWG ROCKS', 10, -30); // text up above canvas
+     context.restore();     
+     // then, draw the background tree
+     context.save();
+     context.translate(width-((this.offset+(this.width*0.2)) % (this.width*1.5))+30, 0);
+     context.beginPath();
+     context.fillStyle = 'rgb(143,89,2)';
+     context.lineStyle = 'rgb(10,10,10)';
+     context.lineWidth = 2;
+     context.rect(0, this.horizon+5, 10, -50); // trunk
+     context.fill();
+     context.stroke();
+     context.beginPath();
+     context.fillStyle = 'rgb(78,154,6)';
+     context.arc(5, this.horizon-60, 30, 0, Math.PI*2); // leaves
+     context.fill();
+     context.stroke();
+     context.restore();
+   };
+   this.paintForeground = function (context, width, height) {
+     // draw the box that goes in front
+     context.save();
+     context.translate(width-((this.offset+(this.width*0.7)) % (this.width*1.1))+0, 0);
+     context.beginPath();
+     context.rect(0, this.horizon - 5, 25, 25);
+     context.fillStyle = 'rgb(220,154,94)';
+     context.lineStyle = 'rgb(10,10,10)';
+     context.lineWidth = 2;
+     context.fill();
+     context.stroke();
+     context.restore();
+   };
+ };
+</script>
+<script>
+ var BlueRobot = function () {
+   this.sprites = new Image();
+   this.sprites.src = 'blue-robot.png'; // this sprite sheet has 8 cells
+   this.targetMode = 'idle';
+   this.walk = function () {
+     this.targetMode = 'walk';
+   };
+   this.stop = function () {
+     this.targetMode = 'idle';
+   };
+   this.frameIndex = {
+     'idle': [0], // first cell is the idle frame
+     'walk': [1,2,3,4,5,6], // the walking animation is cells 1-6
+     'stop': [7], // last cell is the stopping animation
+   };
+   this.mode = 'idle';
+   this.frame = 0; // index into frameIndex
+   this.tick = function () {
+     // this advances the frame and the robot
+     // the return value is how many pixels the robot has moved
+     this.frame += 1;
+     if (this.frame >= this.frameIndex[this.mode].length) {
+       // we've reached the end of this animation cycle
+       this.frame = 0;
+       if (this.mode != this.targetMode) {
+         // switch to next cycle
+         if (this.mode == 'walk') {
+           // we need to stop walking before we decide what to do next
+           this.mode = 'stop';
+         } else if (this.mode == 'stop') {
+           if (this.targetMode == 'walk')
+             this.mode = 'walk';
+           else
+             this.mode = 'idle';
+         } else if (this.mode == 'idle') {
+           if (this.targetMode == 'walk')
+             this.mode = 'walk';
+         }
+       }
+     }
+     if (this.mode == 'walk')
+       return 8;
+     return 0;
+   },
+   this.paint = function (context, x, y) {
+     if (!this.sprites.complete) return;
+     // draw the right frame out of the sprite sheet onto the canvas
+     // we assume each frame is as high as the sprite sheet
+     // the x,y coordinates give the position of the bottom center of the sprite
+     context.drawImage(this.sprites,
+                       this.frameIndex[this.mode][this.frame] * this.sprites.height, 0, this.sprites.height, this.sprites.height,
+                       x-this.sprites.height/2, y-this.sprites.height, this.sprites.height, this.sprites.height);
+   };
+ };
+</script>
+<script>
+ var canvas = document.getElementsByTagName('canvas')[0];
+ var context = canvas.getContext('2d');
+ var landscape = new Landscape(context, canvas.width, canvas.height);
+ var blueRobot = new BlueRobot();
+ // paint when the browser wants us to, using requestAnimationFrame()
+ function paint() {
+   context.clearRect(0, 0, canvas.width, canvas.height);
+   landscape.paintBackground(context, canvas.width, canvas.height);
+   blueRobot.paint(context, canvas.width/2, landscape.horizon*1.1);
+   landscape.paintForeground(context, canvas.width, canvas.height);
+   requestAnimationFrame(paint);
+ }
+ paint();
+ // but tick every 150ms, so that we don't slow down when we don't paint
+ setInterval(function () {
+   var dx = blueRobot.tick();
+   landscape.advance(dx);
+ }, 100);
+</script>
+<p class="buttons">
+ <input type=button value="Walk" onclick="blueRobot.walk()">
+ <input type=button value="Stop" onclick="blueRobot.stop()">
+<p>
+ <small> Blue Robot Player Sprite by <a href="http://johncolburn.deviantart.com/">JohnColburn</a>.
+ Licensed under the terms of the Creative Commons Attribution Share-Alike 3.0 Unported license.</small>
+</p></pre>
+
+  </div>
+
+
+
   
 
 
@@ -101872,6 +102047,13 @@
 
   
 
+  <div itemscope="" itemtype=http://n.whatwg.org/work>
+   <p>The Blue Robot Player sprite used in the canvas demo is based on
+   <a href=http://johncolburn.deviantart.com/art/Blue-Robot-Player-Sprite-323813997 itemprop=work>a work</a> by
+   <a href=http://johncolburn.deviantart.com/ itemprop=http://creativecommons.org/ns#attributionURL>JohnColburn</a>.
+   (<a href=http://creativecommons.org/licenses/by-sa/3.0/ itemprop=license>CC BY-SA 3.0</a>)</p>
+  </div>
+
   <p>Thanks also to the Microsoft blogging community for some ideas,
   to the attendees of the W3C Workshop on Web Applications and
   Compound Documents for inspiration, to the #mrt crew, the #mrt.no

Modified: source
===================================================================
--- source	2013-05-31 20:35:03 UTC (rev 7883)
+++ source	2013-06-01 00:14:46 UTC (rev 7884)
@@ -42243,6 +42243,21 @@
 
   </div>
 
+  <div class="example">
+
+   <p>The 2D rendering context for <code>canvas</code> is often used for sprite-based games. The
+   following example demonstrates this:</p>
+
+   <iframe src="/demos/canvas/blue-robot/index.html" width="396" height="216"></iframe>
+
+   <p>Here is the source for this example:</p>
+
+   <pre>EXAMPLE canvas/blue-robot/index.html</pre>
+
+  </div>
+
+
+
   <!--END 2dcontext-->
 
 
@@ -114353,6 +114368,13 @@
 
   <!--START dev-html-->
 
+  <div itemscope itemtype="http://n.whatwg.org/work">
+   <p>The Blue Robot Player sprite used in the canvas demo is based on
+   <a itemprop="work" href="http://johncolburn.deviantart.com/art/Blue-Robot-Player-Sprite-323813997">a work</a> by
+   <a itemprop="http://creativecommons.org/ns#attributionURL" href="http://johncolburn.deviantart.com/">JohnColburn</a>.
+   (<a itemprop="license" href="http://creativecommons.org/licenses/by-sa/3.0/">CC BY-SA 3.0</a>)</p>
+  </div>
+
   <p>Thanks also to the Microsoft blogging community for some ideas,
   to the attendees of the W3C Workshop on Web Applications and
   Compound Documents for inspiration, to the #mrt crew, the #mrt.no




More information about the Commit-Watchers mailing list