Showing posts with label everywhere a DOM DOM. Show all posts
Showing posts with label everywhere a DOM DOM. Show all posts

Thursday, November 7, 2013

Bouncing SVG - Part 3 (Game Programming)

In the first two parts of this series I wrote about how to use SVG to animate a bouncing ball. The first one was about putting the SVG in the body with tags and the second was about creating the SVG from scratch with JavaScript. In this, the third part, I want to write about a third way of doing SVG. This new way is not hardly documented anywhere and will take some work, but the payoff might be worth it, especially if performance is important to your game.



I've already talked about the DOM (Document Object Model) and you probably have heard about it. The DOM is actually the API of web browsers and you can use JavaScript to make the DOM do cool tricks. For example, if you have a sequence of paragraphs, you can change their order by manipulating the DOM. Every bit of a web page is part of the DOM. You can "walk" the DOM to see how your web page is constructed and in general mess around a lot.

But because SVG is independent and XML based, when you add it to the HTML DOM, something magical happens. The regular HTML DOM can get at the SVG and that was how the manipulation of SVG was done in Part 2 of this series:
  1. The SVG was added to the page with createElementNS.
  2. JavaScript was able to manipulate it through the HTML DOM with setAttribute.
But there was something hidden going on. There was ... another DOM!

This DOM is called the SVG DOM.

NOTE: actually, the DOM in the first two examples isn't really the HTML DOM, it is the XML DOM which is a sibling to the HTML DOM. It's easier to call it the HTML DOM. Everything about DOM is shadowy and hidden in Mirkwood somewhere. But right now let's just talk about the SVG DOM.

When you add SVG to your HTML5 web page, there are two ways to get at the SVG DOM. One way (in Parts 1 and 2) is going through the HTML DOM. The HTML DOM does some of the work for you, especially in converting some of the messy parts of the original SVG spec. But you pay a price for this conversion. When your calls go to and from the SVG DOM by way of the HTML DOM, things can slow down. For bouncing a ball, you won't notice any difference. But if you are doing something complicated, the difference can make ... a difference.

But you can sneak around the HTML DOM and call the SVG DOM. The way of doing it is different, but the way you do it is more like programming and less like markup. So here's today's program, similar in many ways to earlier ball bouncing, but using JavaScript in a way that is unique to SVG.

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      SVG in the SVG DOM
    </title>
    
    <script>

      // --- Global variables ---

      // Width and height of board in pixels
      var boardWidth = 320;
      var boardHeight = 460;
      var boardWidthPixels = boardWidth + "px";
      var boardHeightPixels = boardHeight + "px";

      // URL for W3C definition of SVG elements
      var svgURL = "http://www.w3.org/2000/svg";
          
      // Variables for ball initial position.
      var ballHor = boardWidth / 2;
      var ballVer = boardHeight /2;
      var ballHorPixels = ballHor + "px";
      var ballVerPixels = ballVer + "px";
      var changeHor = 10;
      var changeVer = 10;
     
      // Covers all bases for requestAnimationFrame.
      var requestAnimationFrame =
      window.requestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.msRequestAnimationFrame; 
     
      // --- Event listeners ---
     
      // Page load event listener (hear it loading?).
      window.addEventListener("load",
        runFirst, false);
               
      // Runs when page loads.    
      function runFirst() { 

        // Define the game board as an SVG element.
        gameBoard =
          document.createElementNS(svgURL, "svg");
         
        // Width and height of the SVG board element.
        gameBoard.width.baseVal.valueAsString =
          boardWidthPixels;
        gameBoard.height.baseVal.valueAsString =
          boardHeightPixels;
         
        // You must append the board to the body.
        document.getElementById("pageBody").
          appendChild(gameBoard);
       
        // Define the ball as an SVG element.
        paddleBall =
          document.createElementNS(svgURL, "circle");
         
        // Width,  height, radius, and color of ball.
        paddleBall.cx.baseVal.valueAsString =
          ballHorPixels;
        paddleBall.cy.baseVal.valueAsString =
          ballVerPixels;
        paddleBall.r.baseVal.valueAsString =
          "10px";
        paddleBall.style.
          setProperty("fill","fuchsia","");
         
        // Attach the ball to the game board.
        gameBoard.appendChild(paddleBall);
        
        // Start the game loop.
        gameLoop();
        }
       
      // Game loop.
      function gameLoop(){
     
          // Endless loop with requestAnimationFrame.
        requestAnimationFrame(gameLoop);
      
        // Move the ball.
        ballMove();        
        }
     
      // --- Move the ball. ---    
      function ballMove() {
     
        // Changes are calculated but do not
        // take effect until next time through loop.
         
        // Calculate new vertical component.
         ballVer = ballVer + changeVer;

        // If top is hit, change direction.
        if (ballVer + changeVer < 0)
          changeVer = -changeVer;
       
        // If bottom is hit, reverse direction.
        if (ballVer + changeVer > boardHeight)
          changeVer = -changeVer;

         // Calculate new horizontal component.
        ballHor = ballHor + changeHor;

        // If left edge hit, reverse direction.
        if (ballHor + changeHor < 0)
          changeHor = -changeHor;
       
        // If right edge is hit, do something.
        if (ballHor + changeHor > boardWidth)
          changeHor = -changeHor;
       
        // Draw the ball with new coordinates.
        paddleBall.cx.baseVal.valueAsString =
          ballHor + "px";
        paddleBall.cy.baseVal.valueAsString =
          ballVer + "px";   
        }    

        </script>
    </head>
   
    <body id="pageBody">
    </body>

</html>


This code starts out very much like Part 2. We're creating SVG objects in the browser with nothing in the body. But after createElementNS, the code looks weird. Here's how the SVG board size is set:

        gameBoard.width.baseVal.valueAsString =
          boardWidthPixels;
        gameBoard.height.baseVal.valueAsString =
          boardHeightPixels;


Actually, there were some new global variables. They were additions to the earlier ones, but instead of numbers, the height and width have to be set in pixels, not just a number. Behind the scenes, SVG uses a quirky numbering system which I'll get in to in another post later.

Anyway, you might think you could type:

                  gameBoard.width = 320;

But you can't. You have to add a few quirky things, but once you know those quirks, it's not that hard. Here's how to understand this code:

       gameBoard.width.baseVal.valueAsString =
          boardWidthPixels;


The first quirky part is that you have to throw in a new keyword, baseVal. This tells JavaScript to tell SVG that you want to use a normal SVG value for a length (length here means a measure of distance, and applied to height or width) the alternative is animVal, for animation, which you don't want. Why, you ask? Well, if you look up the SVG DOM page for rect (which is what we are defining) and can figure out that in normal SVG, you call it rect, but in SVG DOM, you call it SVGRectElement, you'll find it here: https://developer.mozilla.org/en-US/docs/Web/API/SVGRectElement.

Go look at that page. Mozilla has done a good job of putting the pieces there in the right order. But what you need to see at that page is that width and height are defined as a SVGAnimatedLength type. SVG animation was a cool idea back in the year 2000 (Conan O'Brien reference), but it never quite got itself together. You can animate SVG with JavaScript (don't ask about SMIL). Because of this, you have to make a slight twist and define the width and height with normal units, and use baseVal. And when you do that, you further need to feed the width and height values as strings, not as numbers. So we need to set our height and width as pixels.  You can get some clues here in the SVGLength topic on MDN https://developer.mozilla.org/en-US/docs/Web/API/SVGLength.

If you use this technique, you can do all kinds of programming tricks with SVG and you can bypass the DOM. Mozilla has a great page that lists all the various DOM categories and even what's in and what's out. It includes the three big DOM sets (DOM, HTML DOM, and SVG DOM). In the beginning was the DOM and then HTML DOM came forth and said let's make it easier, and finally SVG DOM came in and said let's party! https://developer.mozilla.org/en-US/docs/DOM/DOM_Reference. Talking about these is a pain, however, and I wish they'd give them easier names, like DOM Red, DOM Blue, DOM Green or something. Well, I guess they think they made it easy. The stock DOM is just DOM and it calls an element ... Element. The HTML DOM calls the same element HTMLElement (so you know it's the same if you whack off the HTML part), and the equivalent for SVG is called ... wait for it ... SVGElement. These prefixes actually have a reason, which is that they are used to keep the things with the same name apart. These prefixes are so you know what namespace you are in at any moment (if you're that poor overworked guy, the browser developer).

So all this info is in the Mozilla Developer Network, but you have to pick it apart. The SVG spec also has the same information, and the reason it is hard to follow is that specs are written for browser developers, not game programmers like you and me. But the really cool part is that all of these whacky things in the SVG DOM namespace are implemented in every browser that supports SVG. Mind you, not every blinking object and property actually are implemented because about 15% of SVG is just too obscure or not needed. Things involving Fonts, Text, and Animation are funky and/or just don't work and aren't a high priority for the browser developers.

But all these techniques work on every modern browser. Firefox! Chrome! Even IE! And even their friends on mobile devices and their cousins SeaMonkey! and Opera! And even that weird uncle in the background who made a pile of money in some way people don't want to talk about, Safari!

SVG is everywhere.

Oops, forgot one more cool quirk that SVG allows you to use in the SVG DOM. SVG and CSS are BFF! A lot of the values are right in line with CSS. So after you create the ball using this new SVG DOM technique, you can define the color by a CSS style, like this:

        paddleBall.style.setProperty("fill","fuchsia","");

Because this 3rd way of messing with SVG is working with the SVG DOM, everything is an object and objects have properties. Repeat this until it makes sense:

           HTML DOM = elements and attributes
           SVG DOM =  objects and properties

They are really the same concept, but the first is a markup thing and the second is a programming thing.

So anything that can have a property set can be set using "style". And one of the fun things about SVG is that it has a lot of style.

I'll be writing about this 3rd type of programming for SVG more in this blog but I want to get back to writing about game programming. I've written about three different game technologies you can use for drawing: CSS, Canvas, and SVG, and I'm hoping that you'll now be able to think about which way you want to go with programming. Here's my take on the three:

CSS - cool for a lot of games but needs more investigation on my part.
Canvas - almost everyone is using this now. It's good, but may not be the best in tight spaces.
SVG - lots of interesting possiblities, especially for tight spaces.

I'd like to do more with SVG for sure, but also see how CSS can fit in somewhere. So stay tunes. Next programming post, I want to get started on the next phase of game programming, which is touch! And a little bit more SVG for added flavor.

And, you don't need to pick just one. You can use any or all of these three technologies in the browser simultaneously. One of the best examples of this was a called Glow and showed who was downloading Firefox at any moment.


It showed a map of the world, drawn in SVG, and little points of light every place that someone was downloading Firefox, and the points of light were little dots created with Canvas. It was cool to watch and see how at night in the Americas, the downloads were in Europe, and the opposite was true for daytime in the Americas. Gone now, but you can read about it here.

Wednesday, November 6, 2013

Bouncing SVG - Part 2 (Game Programming)

In my first post on SVG (http://firefoxosgaming.blogspot.com/2013/11/bouncing-svg-part-1-game-programming.html), I covered the simplest way to use SVG in a game. Create your images using SVG tags in the body of your HTML5 document and then manipulate them using setAttribute to make things move.

That's not a bad way to work, but I have found that creating objects through JavaScript seems to make for faster action on the page. But there's a logical reason. The SVG tags have to be parsed and then translated into the DOM. For something simple like bouncing a ball, you won't see any difference. In fact, for the different ways I've written about for bouncing a single ball, you aren't likely to notice any difference because the work done by the browser is easy. In fact, for a lot of action games, you'll have to slow down the programming to be fair to the user. Ball bouncing needs to be fast, but not too fast. Although when I watch Olympic ping pong, it seems too fast to me.



So if you create your own SVG objects on the fly in JavaScript, the creation is faster and it is just cooler. I personally find it exciting to think that I'm starting with a blank web page and I'm adding thing to it in JavaScript. Maybe its a matter of taste. But it's nice to have options.

So, here's option 2 for SVG. Make it all in JavaScript and the DOM. Actually, in option 1, you were using the DOM to get at the attributes of the ball you created with tags. The main reason I started with tags is that there are tons of books, websites, and blogs explaining how to create SVG images using tags. For example, want to make an ellipse? Check out Mozilla's docs on the SVG ellipse.

But there aren't very many docs or examples on how to do scripting with SVG, because most people began by thinking that SVG is a way to represent static vector images and stopped there. Well, don't stop, keep going!

Here is the code for a bouncing ball using the second technique of SVG, creating art on the fly and using the DOM to get at it.

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      SVG in the XML DOM
    </title>
   
    <script>
   
      // --- Global variables ---

      var boardWidth = 320;
      var boardHeight = 460;
      var ballHor = boardWidth / 2;
      var ballVer = boardHeight /2;
      var changeHor = 10;
      var changeVer = 10;
     
      // Covers all bases for requestAnimationFrame.
      var requestAnimationFrame =
      window.requestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.msRequestAnimationFrame; 

     
      // URL for W3C definition of SVG elements
      var svgURL = "http://www.w3.org/2000/svg";
        
      // Page load event listener (hear it loading?)
      window.addEventListener("load",
        runFirst, false);
               
      // Run this first.
      function runFirst() { 
     
        // Define the game board as an SVG element.
        gameBoard =
          document.createElementNS(svgURL, "svg");
         
        // Width and height of the SVG board element
        gameBoard.setAttribute("width", boardWidth);
        gameBoard.setAttribute("height", boardHeight);        

        // You must append the board to the body.
        document.getElementById("pageBody").
          appendChild(gameBoard);
         
        // Define the ball as an SVG element.
        paddleBall =
          document.createElementNS(svgURL, "circle");
         
        // Width,  height, and radius of the ball
        paddleBall.setAttribute("cx", ballHor);
        paddleBall.setAttribute("cy", ballVer);
        paddleBall.setAttribute("r", 10);
        // Fuchsia = #FF00FF
        paddleBall.setAttribute( "fill", "#FF00FF");
         
        // Attach the ball to the game board.
        gameBoard.appendChild(paddleBall);
       
        // Start the game loop.
        gameLoop();
        }
       
      // Game loop - governed by requestAnimationFrame.
      function gameLoop(){
     
        // Restart the loop with requestAnimationFrame.
        requestAnimationFrame(gameLoop);
     
        // Move the ball.
        ballMove();        
        }
     
      // Move the ball.    
      function ballMove() {
     
        // Changes are calculated but do not
        // take effect until next time through loop.
         
        // Calculate new vertical component.
         ballVer = ballVer + changeVer;

        // If top is hit, change direction.
        if (ballVer + changeVer < -10)
          changeVer = -changeVer;
       
        // If bottom is hit, reverse direction.
        if (ballVer + changeVer > boardHeight - 10)
          changeVer = -changeVer;

         // Calculate new horizontal component.
        ballHor = ballHor + changeHor;

        // If left edge hit, reverse direction.
        if (ballHor + changeHor < -10)
          changeHor = -changeHor;
       
        // If right edge is hit, do something.
        if (ballHor + changeHor > boardWidth - 10)
          changeHor = -changeHor;
       
        // Draw the ball with new coordinates.
        paddleBall.setAttribute("cx", ballHor);
        paddleBall.setAttribute("cy", ballVer);
        }
       
      </script>
    </head>
   
    <body id="pageBody">
    </body>

</html>


Most of this is the same as earlier ball bouncing examples. HTML5, load the code, start the loop, check for changes, repeat! But if you read this from top to bottom, you'll notice that the body of the page is now empty. There's nothing there! Well, almost nothing. The body now has an id of "pageBody" and you'll need this to anchor your SVG objects to.

Here's the basic process for using SVG in a web page using JavaScript:
  • Create the object using createElementNS.
  • Modify it by setting the attributes.
  • Add the object to the page or another object.
createElementNS

This is similar to createElement but it creates an element in a specified namespace. This is needed so you don't get your SVG objects mixed up with your other objects. SVG is definitely its own animal, but it plays well with others if you feed it properly.

createElementNS starts out by creating the SVG pane. I call it a pane because I don't want to call it a canvas, but the idea is similar to the canvas in Canvas. The SVG pane is where you place all your SVG objects. All the objects have to fit inside the boundaries of the object or they won't display (you might want to do this to have objects hide off-screen until they are ready for their big scene).

The first use of createElementNS is this:

   gameBoard = document.createElementNS(svgURL, "svg");

I had previously defined an URL (path to a web site) for svgURL.

   var svgURL = "http://www.w3.org/2000/svg";

SVG uses this URL to clue the browser in that we are talking about SVG as defined in the year 2000. Maybe someday they will change this, but right now this works for everyone for SVG. It says "I'm SVG and I'm special."

The second parameter of createElementNS is "svg". You can call it anything you want, but it is the name of the newly created element. However, you want to assign the value of createElementNS to a variable. I picked gameBoard and that's what you use to grab on to the SVG pane.

setAttribute

Once you've created your SVG object, it's just floating in space somewhere but it has no color, size, or odor. That's no fun. You need to assign it values. For the SVG pane, you want to give it a size and nothing else because for this example, the SVG pane is just a container that the ball will bounce around in. So this code will define the size:

        gameBoard.setAttribute("width", boardWidth);
        gameBoard.setAttribute("height", boardHeight);


 The board width and height were previously defined as 320x460, the size of my lovely little ZTE Open phone.

appendChild

The third step is to attach your SVG object to the web page (or another SVG object). You do this by using appendChild. Here's the code to attach the object:

        document.getElementById("pageBody").appendChild(gameBoard);

This can be tricky to read as it has three parts:
  1. The word "document" which is the page document.
  2. getElementbyID("pageBody") which is the way that you grab the page body.
  3. appendChild(gameBoard) which adds the SVG pane to the body.
The three pieces are joined by dots. Essentially you're adding a new element to the existing page element which in turn is part of the whole document.

At this moment, when you  add the SVG pane as a child of the page, the SVG pane is now part of the page. Because we didn't give it any color, it doesn't look different. But its there and it says, "I am SVG and I am 320x460 wide and high. Hear me roar!"

Not much fun, yet. Now to create the familiar Fuchsia ball, you just repeat the three step process above.
  1. Create the ball.
  2. Give it attributes.
  3. Attach it to the SVG container.
Here's the code that does this:

        // Define the ball as an SVG element.
        paddleBall =
          document.createElementNS(svgURL, "circle");
         
        // Width,  height, and radius of the ball
        paddleBall.setAttribute("cx", ballHor);
        paddleBall.setAttribute("cy", ballVer);
        paddleBall.setAttribute("r", 10);
        // Fuchsia = #FF00FF
        paddleBall.setAttribute( "fill", "#FF00FF");
         
        // Attach the ball to the game board.
        gameBoard.appendChild(paddleBall);


At the moment this code runs, the ball will appear on the screen. The rest of the code is similar to the other examples. And in the ballMove section, you move the ball with this code:

        paddleBall.setAttribute("cx", ballHor);
        paddleBall.setAttribute("cy", ballVer);


which was used in the first SVG example.

There you have it. Create your objects, give 'em attributes, attach them to something, and bang 'em around! What could be easier? This technique isn't well documented, but it works and you can get the attribute names and values from the Mozilla docs at https://developer.mozilla.org/en-US/docs/Web/SVG/Element. There are lots of elements, but luckily Moz has sorted them into 13 categories further down the page. Working with paths can be tricky, but you can draw a path with Inkscape, save it as SVG, and see what the path actually is in numbers and letters.

But there's one more way to do SVG that is even cooler. In a complicated game, this third way will make everything fly. Stay tuned!

Bouncing SVG - Part 1 (Game Programming)

Earlier in this blog I wrote about bouncing a ball in CSS and several posts about bouncing a ball with Canvas. But there's a third web technology that might be perfect for some types of games, and its name is SVG. You may have heard about it, you may know that SVG stands for Structured Vector Graphics, but you probably don't know more than that, because the story of SVG is one of starts and stops, success and failure, and yes, slowly but surely, SVG keeps marching on. I won't bore you with the whole story, because this set of three posts is all about the three ways to use SVG to bounce balls so you can make choices about the graphic technology you want to use to make games for Firefox OS phones.

In the late 90's, the world was discovering the web. But the web was slow, especially when it came to graphics and pictures. Why not use vector graphics and describe them mathematically? Just a few lines and you have a fast-loading picture. Microsoft came up with one system (VML) and Adobe came up with another (PGML). Some others became interested and a new standard was invented that took parts of both and combined them to make SVG. It was a cool dream, but it didn't quite come together.

Microsoft didn't want to support SVG and they stuck with VML but didn't really promote it as a graphics language. The main use for VML was to represent Office Art for Office 2000, but not much else. Adobe promoted SVG but it was a constant uphill battle because without Microsoft support, nothing much was going to happen. VML was forgotten, and even though there were a dozen books about SVG, nothing much happened. 

One of the main reasons for the sidelining of SVG was that the Internet was speeding up fast and graphics now loaded just fine, thank you. It was a bitmap world!

Until Tim Bernars-Lee wrote a prominent article that called attention to the fact that Microsoft wasn't supporting important standards like SVG. Anyone else might have been ignored, but Tim was the founder of the Internet, so Microsoft decided to hire some new folks and make Internet Explorer support web standards (they'd shut down the team and sent them over to DirectX, allowing Firefox and Chrome to take up the slack).

So SVG was now implemented in most browsers, but the story doesn't end there, at least for game programming. Most everyone who knew about SVG looked at it as a lightweight way to have vector drawings. Professional illustrators had been doing this for years (with ... Illustrator). But as a static art format, SVG wasn't all that interesting.

The final thing that made SVG really useful was that when HTML5 was being created, some bright person decided it might be cool to have SVG be supported as if it were HTML. This was really cool because before that, SVG was seen only as an XML format. Nice, but a pain to work with. 

But by being able to treat SVG as a HTML, you could code that would put SVG shapes, lines, and paths in your web page. For example, the code below will create a red circle in a web page using HTML5.

<!DOCTYPE html>
<head>
</head>
<body>
<h3>This is SVG</h3>
<svg width="120" height="120" >
<circle cx="60" cy="60" r="50" fill="red" />
</svg>
</body>
</html>
And here is what it looks like:

All that I did was to add the SVG element, define its width and height, and then inside the element, I defined a red circle with a center of 60,60 and a radius of 50 pixels. SVG is still XML underneath, but you can treat it as any other element, and SVG has a lot of things it can do: shapes, paths, shading, text. Everything is defined by a markup language, and now it fits right in with HTML like they were siblings (they both have the parent of XML).

And you might ask yourself, how well is SVG supported, now that Internet Explorer supports it (and who cares about them anyway)? Chrome 4 and Firefox 2 were the first supporters, but right now, according to that wonderful site, Can I Use?, all the major browsers support SVG.(Opera Mini was the last holdout). And of course, Firefox, Firefox OS, and Firefox for Android support it too. 

But, if you look closely at the Can I Use? statistics, it says 84% support. The reason for this is that the SVG specification http://www.w3.org/TR/SVG/ is an extremely complicated document and has a lot nooks and crannies that aren't supported by anyone and may never be. The spec is still at version 1.1 (Second Edition) and change is slow. Parts that are not likely to be complete include typography and animation. But 84% of a huge spec is just fine (and the other 16% you don't care about unless you are a mad typographer.

The point here is that SVG is now in every browser, it does graphics with vectors, and its now much easier to use because you can treat it like any other HTML elements. It's right there for the taking! But because of the checkered history, people got excited about SVG (a dozen books!), but then lost interest when Microsoft wouldn't play along. And the Internet got fast, so no one cared anyway.

So why bother? SVG isn't just a pretty face. It has hidden depths, very deep depths. Here's the secret:

SVG CAN MOVE!

SVG can be moved, shaken, stirred, and in general, messed about with. Every element and attribute can be manipulated with JavaScript. So make your game bits and move them around. Because there are no bitmaps, you can have very lightweight graphics, and lightweight is cool on a Firefox OS phone. And Firefox has a pretty extensive set of reference pages on SVG at https://developer.mozilla.org/en-US/docs/Web/SVG. Of course!

Let's move something. How about a bouncing ball? 

But before I start throwing code (and fuchsia balls) at you (and after all that boring Internet history), I need to explain why there are three basic ways to use SVG in HTML5.
  1. The easiest way is to build your SVG art in the body of the browser. I did this just a few paragraphs ago by making a red circle. But the red circle can be manipulated by JavaScript. You can change the size, color, and position very easily. You can stretch it, mangle it, whatever you want. But unlike Canvas, SVG doesn't leave anything behind when it changes. The new size, color, position are preserved in the web page memory. None of this annoying draw, move, erase old, repeat. Just draw and move!
     
  2. The next way is to create all your SVG element and attributes on the fly with JavaScript. Want a circle? Make it in JavaScript. This all of a sudden becomes programming instead of markup language. You create elements, you modify them, and you do it all in JavaScript. You do this by using the HTML DOM (Document Object Model). You create SVG objects, define their attributes, and it is magic! More about this with the next programming post.
     
  3. But there's more. SVG has its own DOM. When you programmed SVG with method #2 (and actually #1 for the JavaScript part), you were talking to the SVG DOM through the HTML DOM.It turns out there is a way to go directly to the SVG DOM, and bypass the HTML DOM. This is faster and you can do even more manipulation. It's definitely tricky,but gives you greater persormance and control. And if you know how to read the SVG specification, all the answers are there. More about all this DOM stuff in the second programming post after this (sandwiched in with game reviews). 
Today's post will cover the first technique. Create an SVG object in the body with SVG tags, and then manipulate it with JavaScript. I'll use a lot of the same structure I used for CSS and Canvas, and the look and feel of the output will be the same, and, like all the other code I've put in this blog, it has been tested on Firefox OS on the ZTE Open phone.

Here's the code:

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      SVG in the body
    </title>
   
    <script>
   
      // Global variables
     
      var boardWidth = 320;
      var boardHeight = 460;     
      var ballHor = boardWidth / 2;
      var ballVer = boardHeight /2;
      var changeHor = 10;
      var changeVer = 10;
     
      // Covers all bases for various browser support.
      var requestAnimationFrame =
      window.requestAnimationFrame ||
      window.mozRequestAnimationFrame ||
      window.webkitRequestAnimationFrame ||
      window.msRequestAnimationFrame; 


      // This function is called on page load.
      function drawGameSVG() {
       
        // The page is loaded.
        console.log("The page is loaded.");   

        // Start the game loop.
        gameLoop();
      }
     
      // Game loop.
      function gameLoop() {
     
        // Move the ball once each loop.
        ballMove();
     
        // Restart the loop with requestAnimationFrame.
        requestAnimationFrame(gameLoop);   
      }

       // Move the ball.   
      function ballMove() {
     
        // Changes are calculated but do not
        // take effect until next time through loop.
       
        // Set the SVG attributes of the ball.
        ball.setAttribute("cx", ballHor);
        ball.setAttribute("cy", ballVer);
         
        // Calculate new vertical component.
         ballVer = ballVer + changeVer;

        // If top is hit, change direction.
        if (ballVer + changeVer < -10)
          changeVer = -changeVer;
       
        // If bottom is hit, reverse direction.
        if (ballVer + changeVer > boardHeight - 10)
          changeVer = -changeVer;

         // Calculate new horizontal component.
        ballHor = ballHor + changeHor;

        // If left edge hit, reverse direction.
        if (ballHor + changeHor < -10)
          changeHor = -changeHor;
       
        // If right edge is hit, do something.
        if (ballHor + changeHor > boardWidth - 10)
          changeHor = -changeHor;   
      }

     </script>
  </head>
 
  <body onload="drawGameSVG()">

    <!-- Create the SVG board. -->
    <svg width="320" height="460" id="board" >
      <!-- Create the ball. -->
      <circle cx="150" cy="150" r="10" fill="Fuchsia" id="ball" />
     
    </svg>
  </body>

</html>


The body of the page does two things:
  1. Call the drawGameSVG function when the page loads.
  2. Creates an SVG container with the id of "board" and a ball with the idea of "ball". You need to define these with an id so JavaScript can grab them later. SVG always needs a container to start with. The ball is the only visible aspect and the properties of position (cx,cy), radius (r), fill (fuchsia), and id (ball) are needed to have a complete ball.
The JavaScript is nearly the same as the Canvas code. It starts the game loop, uses requestAnimationFrame to keep the loop going, but uses some new commands to actually move the ball once the new position has been calculated:

        // Set the SVG attributes of the ball.
        ball.setAttribute("cx", ballHor);
        ball.setAttribute("cy", ballVer);


When the ball was defined in the body with SVG tags, it had the id of "ball". That id is used here, and the attributes of the ball are modified in the function called ballMove. The method setAttribute is used to change the definition of the "cx" and "cy" positions to match whatever the new ball position is (as defined by ballHor and ballVer). ball is an object, and because HTML5 treats SVG elements as HTML elements, you can change any attribute by using setAttribute.

So, that's it. Not so hard, really. You can check out the MDN SVG pages, and especially look at the tons of samples they have at https://developer.mozilla.org/en-US/docs/Web/SVG/Element. SVG is huge, but I'll try to cover it as I go along, because there's a lot there that can be of value to game developers using HTML5.

Also it might be good to say that if you're not patient enough to do elaborate drawings in SVG by hand coding every twist and turn, you don't have to. There are two very excellent drawing programs that support SVG extremely well. The first is Inkscape, which is a free open source program that is just astounding. I'll talk more about Inkscape later, but it is worth checking out, and is 100% based on SVG. The other SVG art program is Adobe Illustrator, which is not free, but is also now supporting SVG pretty well. But my heart is with the wonderful folks at http://inkscape.org/ I love their motto: "Draw freely."

As with this post, and any others, if I didn't express something well or you have questions, make a comment and I'll try to answer it. This game programming stuff is complicated, especially with all the tons of technologies available free in Firefox OS!