Showing posts with label CSS. Show all posts
Showing posts with label CSS. Show all posts

Friday, April 4, 2014

Nephew of CSS Shooter (Game Programming)

André Jaenisch (e-acute! and ae not a-umlaut) of https://firefoxosundich.wordpress.com had some comments about my CSS Shooter post at http://firefoxosgaming.blogspot.com/2014/03/css-shooter-game-programming.html that were very useful.

I had used

    document.documentElement.
      style.overflow = 'hidden';


to hide the scrollbars. Because there isn't any "don't show scrollbars" command in Firefox, that seemed like a good idea. Generally people don't use it to hide scrollbars, they use it to clip content outside a particular window.

However, the CSS 2.1 spec, section 11, does define overflow = "hidden" like this:


This value indicates that the content is clipped and that no scrolling user interface should be provided to view the content outside the clipping region.

Because I'm defining the contents of the region, I know there's nothing outside it, so I'm happy to use this when I'm looking at the very edge of the window.

Also, I found an old reference from 2005 to

     overflow: -moz-scrollbars-none 

but it seems to have disappeared and I can't find it on MDN. Anyone know where it went?

André had a different approach, which, rather than use an little-known and possibly not supported in the future API, suggested that I simply reverse the motion slightly before you get to the edge! This works too, with only a little bit of alteration in the code.

Here's his code for the target restart when it hits the left edge:

      // Right edge hit, restart.
      if (tarHor > boardWidth-25) {
        console.log("Target hit right edge!" +
          "Turned around at " + tarHor +
          " + " + boardWidth);
        tarHor = 10;
      }


And here's his code for the bullet:

      // Left edge hit, reverse direction.
      if (ballHor + changeHor < 10) {
        console.log("Ball hit left edge!" +
        "Turned around at " + ballHor +
          " + " + changeHor);
        changeHor = -changeHor;
        ballHor = 10;
        console.log(ballHor + " " + ballVer);
      }
   
      // Right edge hit, reverse direction.
      if (ballHor + changeHor >
        boardWidth - 20) {
          console.log("Ball hit right edge!" +
          "Turned around at " + ballHor +
            " + " + changeHor);
          changeHor = -changeHor;
          // Compensate for unknown width.
          // We want multiples of 10.
          flr = Math.floor(boardWidth / 10);
          ballHor = 10 * flr-30;
        console.log(ballHor + " " + ballVer);
      }


This is perfectly valid and reminds me of the old phrase, "If you can't raise the bridge, lower the river." Games are all about solving problems, and there are usually more than one way to solve a problem.

André suggested that I add this code for the viewport in the head:

      <meta name="viewport"
        content="user-scalable=no,
        initial-scale=1,
        maximum-scale=1,
        width=device-width" />


I'm still not up on viewports but you can read about it here: https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag.


I'm going to be investigating this a lot more as I look more at responsive web design (RWD). Although for games, adaptive web design might be more appropriate. I will be getting a Firefox OS tablet soon and I'll want to write apps that run on it, the two phones I have, and the nearly-forgotten APC Rock I have sitting lonely in a corner. See my post on APC Rock here http://firefoxosgaming.blogspot.com/2014/01/apc-rock-hardware-review.html.

Other Problems

When I was testing André's code, the bullet at the bottom didn't display! At first I thought it was the code and then it was pointed out that maybe the bitmap wasn't there. It wasn't.

In future code, I'll either avoid bitmaps (probably not likely) or write some code that determines whether the bitmap was actually loaded.  There are some ways to do this by loading the bitmap as an Image and then checking to see if it loaded by having an event handler on the image.

André also had an interesting idea of creating a ball by using a CSS rectangle and rounding the corners so it looks like a ball, from Stack Overflow. https://stackoverflow.com/questions/6921792/how-to-draw-circle-in-html-page/6921838#6921838.

Moving Forward

I've been thinking about where to take this blog. My influences are:

  1. Tablet - responsive web design needed!
  2. A return of my love for SVG.
  3. Playing way too much Starbound http://playstarbound.com/
  4. Remembering Sigma Star Saga http://en.wikipedia.org/wiki/Sigma_Star_Saga
So what I'm going to do is create a serious large game in several parts that will consist of the following:

SVG all the way! Why not?
  1. A space shooter that you can fly around in.
  2. Land on other planets in a side-scrolling view.
  3. Enter cities in a top-down view with tiles
  4. Make it an actual RPG with statistics, fighting, upgrades, stores, etc.
Stay tuned, but not iTuned!

Thursday, March 20, 2014

Son of CSS Shell (Game Programming)

As I get further into programming for Firefox OS, I find that I want to go back to basics from time to time. One of my favorite things is to create a shell that can be used to build games on top of. A simple run of code that has all the basics in place. Taking what I've learned, I've created a new shell for you to use for CSS games. When I say CSS games, I am thinking of what some people call CSS sprites. Essentially you move images around on the screen by taking advantage of basic properties of HTML5, CSS, and JavaScript. Not CSS3, mind you, which has become a huge ball of stuff that looks cool but doesn't hang together quite yet.

So here is what I recommend for starting out with CSS sprites. You can read more about those at these earlier posts:

Bouncing a Ball in CSS
http://firefoxosgaming.blogspot.com/2013/10/bouncing-ball-in-css-game-programming.html

Earlier CSS Shell
http://firefoxosgaming.blogspot.com/2013/11/css-shell-game-programming.html

CSS Collision Detection
http://firefoxosgaming.blogspot.com/2013/11/css-detecting-collisions-game.html

The shell has a simple bouncing ball, which is easy to see how it works, but just as easy to remove the bouncing ball part and add your own type of game.

Screen Shots

So, here's what this shell looks like, running on the ZTE Open.


Next, here is the same game running in the App Manager simulator.


And, finally, here's what it looks like in the nightly Firefox desktop browser with the debugger open and resized to a smaller-than-normal size.


The last is pretty useful if you want to instantly simulate different screen sizes and look at the debugging information. The screen is only 343x237, but the ball bounces just fine against the four edges but doesn't enter the debugger space.

The Code

Here is the code:

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="UTF-8">
  <title>
    New CSS Shell
  </title>

  <style>
     
    #ball
    {
      width: 20px;
      height: 20px;
      position: absolute;
      top: 200px;
      left: 100px;
      background-image: url(ball.png);
    }

  </style>

  <div id="ball"></div>   

  <script>

    // Global variables   
    var boardWidth = window.innerWidth;
    var boardHeight = window.innerHeight;   
    var ballHor = boardWidth / 2;
    var ballVer = boardHeight /2;    
    var changeHor = 10;
    var changeVer = 10;
   
    // Log initial board height & width.
    console.log("Board width = "
      + boardWidth);
    console.log("Board height = "
      + boardHeight);
  
    // requestAnimationFrame variations
    var requestAnimationFrame =
    window.requestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.msRequestAnimationFrame;
   
    document.documentElement.
      style.overflow = 'hidden';
  
    // Load event listener
    window.addEventListener("load",
      getLoaded, false);
     
    // Resize event listener
    window.addEventListener("resize",
      resizeMe, false);

    // Get ball information.
    var myBall =
      document.querySelector("#ball");
  
    // Function called on page load.
    function getLoaded() {
   
      // Lock screen orientation to portrait.
      // Uses "moz" prefix.
      window.screen.
        mozLockOrientation("portrait"); 
      console.log("Locked to portrait");
     
      // Background color
      document.body.style.
        backgroundColor = "Peru";
  
      // Start game loop.
      gameLoop();   
      
      // Page loaded message
      console.log("The page is loaded.");
     

      }
  
    // Game loop
    function gameLoop() {
  
      // Repeat game loop infinitely.
      requestAnimationFrame(gameLoop);
  
      // Move the ball once.
      ballMove();      
      }
  

    // Calculate and move the ball. 
    function ballMove() {
  
      // Changes are calculated but do not
      // take effect until next time.     
      myBall.style.left = ballHor + "px";
      myBall.style.top = ballVer + "px";
      
      // Calculate new vertical component.
      ballVer = ballVer + changeVer;

      // Top hit, reverse direction.
      if (ballVer + changeVer < -10)
        changeVer = -changeVer;
    
      // Bottom hit, reverse direction.
      if (ballVer + changeVer >
        boardHeight - 10)
          changeVer = -changeVer;

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

      // Left edge hit, reverse direction.
      if (ballHor + changeHor < -10)
        changeHor = -changeHor;
    
      // Right edge hit, reverse direction.
      if (ballHor + changeHor >
        boardWidth - 10)
          changeHor = -changeHor;
    }

    // Testing in desktop browser only.
    // Changes board size to match new.
    function resizeMe() {
     
      //Change board size.
      boardWidth = window.innerWidth;
      boardHeight = window.innerHeight;  
     
      // Log initial board height & width.
      console.log("Board width = "
        + boardWidth);
      console.log("Board height = "
        + boardHeight);
    }
   
  </script>
</head>

<body>
  <footer>
    <small>
      Copyright &copy; 2014 Bob Thulfram
    </small>
  </footer>
</body>
</html>


What I Have Added

After thinking about it over the past few weeks, here are a few things I've added:
  1. Screen Orientation. The game plays best in portrait mode.
  2. Responsive Design. The game should play on any size phone or tablet.
  3. More Responsive Design. I wanted to test how this looks in browsers on desktops.
  4. I wanted to add a copyright notice in the code.
  5. I felt like a background color helps the screen shot stand out in a blog post. 

Screen Orientation

I've written about Screen Orientation for Firefox OS at http://firefoxosgaming.blogspot.com/2013/11/screen-orientation-and-moz-prefixes.html. And it works! Of course, you need to test this on a real phone. When I tilt the phone with my code, the screen doesn't tilt, it stays oriented in portrait.

However, this doesn't seem to work on the App Manager simulator. There's a little button next to the home button at the bottom that looks like two folders overlapping. Click on that and the screen turns sideways. But it shouldn't! This might be a bug or it might be that this isn't supported yet in the simulator. But it works fine on a phone!

Here's the code:

      window.screen.
        mozLockOrientation("portrait"); 
      console.log("Locked to portrait");


Note that this needs the "moz" prefix for now.

Responsive Design

One thing that I've noticed on a lot of the games I've reviewed is that they don't look the same on different phones. The ZTE Open and the Geeksphone Peak have different sizes! But you want to design your game so it works on any size phone, tablet, or whatever. Maybe not watches, though.

So what I'm doing with this code is to get the actual screen size and make that the size of my game board. I wrote about this in an early topics called How Big A I? at http://firefoxosgaming.blogspot.com/2013/10/how-big-am-i-game-programming.html.

And here is how I implement it. These lines set up the game board to match the actual screen. Instead of a fixed value, I created board size by seeing what the actual screen size is. This is in the global variable section.

    var boardWidth = window.innerWidth;
    var boardHeight = window.innerHeight;   


I also added this to make sure what actually happens:

    console.log("Board width = "
      + boardWidth);
    console.log("Board height = "
      + boardHeight);


It's always a good idea to track what is happening, especially when testing different sized phones.

Really Responsive Design

I often run my code first in the latest Firefox nightly browser. I recommend this, even though you need to be careful because not everything in the desktop browser is in Firefox OS! But it makes the easy development cycle even easier and you can save the phone-specific parts for testing on an actual phone (like Screen Orientation).

I thought it would be fun to resize the browser so I can just drag it to see it small or large. And it is also easy to see the debugged output on a desktop browser.

So I added this code to handle the event of the browser being resized.

    // Resize event listener
    window.addEventListener("resize",
      resizeMe, false);


This will call the function resizeMe every time the browser is resized. I also added this code to prevent the scroll bars from trying to display when the ball bounces into the edge.

    document.documentElement.
      style.overflow = 'hidden';


And here's the function that is called when the window is resized.

    function resizeMe() {
     
      //Change board size.
      boardWidth = window.innerWidth;
      boardHeight = window.innerHeight;  
     
      // Log initial board height & width.
      console.log("Board width = "
        + boardWidth);
      console.log("Board height = "
        + boardHeight);
    }


This is the same code as was used in the global variables, but you need to call it again when the window is resized. And I like outputting the new width and height of the board so I can see what is going on. The third screen shot above shows this working beautifully.

Copyright

Not everyone cares, but I care about copyright. I'm happy to have you use my code in your own games, but I'd like to keep control over how it is published and where it appears. This doesn't have a standard yet, but a growing convention is to use the HTML5 tag small inside a footer tag. So I've added this to the code at the very end, the only thing that is in the actual body of the code.

  <footer>
    <small>
      Copyright &copy; 2014 Bob Thulfram
    </small>
  </footer>


The &copy; will produce a copyright symbol (c).

Background Color

I've used this before here and there, so here it is again.

      document.body.style.
        backgroundColor = "Peru";


I picked the color Peru for no particular reason except that's a nice country! Get your color names at https://developer.mozilla.org/en-US/docs/Web/CSS/color_value. When I did this, I realized that my bouncing ball PNG image had a white background, which didn't look good, so I had to redraw it by filling in all the white bits with Peru color. Which the MDN page will happily tell you is rgb(205, 133,  63). What this means is that the red, green, and blue percents are those three numbers. I plugged those numbers into Paint Shop Pro and the PNG now looks like this, in all its pixel-y greatness.


Wrapping Up

So this is the shell I will be using to create new CSS game bits and I recommend you use the parts you want. I'll do the same for Canvas and CSS but I might do some cool CSS stuff sooner, and there's games to review, and, and, and!



Tuesday, February 11, 2014

Flying Fox Part 1 (Game Programming)

Okay, I'm interested in Flappy Bird, but not because of the success and drama. What interests me is that it is a one-finger game. This works for touch and I think has something to look at. So I'm now going to create a similar game that just uses a finger to move the hero forward.

But I've been intrigued by this ever since I reviewed Captain Rogers. You could say that Captain Rogers is the same as Flappy Bird, in that you are flying through something and avoiding something and that the mechanism is the same. At first I didn't like the game because it was too hard, and I don't like Flappy Bird either. But the mechanic is interesting, so I'm going to create a game that uses touch and moves an object through an always-scrolling maze. But I need something that flies. How about a fox?


This is an image created by Nicu Buculei of Romania, who has been doing cool SVG tutorials for years. This image grew out of a tutorial called Pac-Man baddies with Inkscape and is available on the OpenClipart.org site (where I get all my clip art from). I really love SVG and this game will be done in SVG, using our fox-like friend, who can magically fly.

In earlier SVG game posts, I've just concentrated on shapes like squares and circles, but it's time to take wings and fly. But how to use a beautiful work of art in SVG? You can see the source code for this work of art at http://openclipart.org/detail/19560/game-baddie:-fox-by-nicubunu and I won't paste it in here because it takes up several hundred lines. Now Nicu didn't plot out the art by hand, he used Inkscape, which makes the details of the SVG art hidden, and all you need to do is use the art.

The game will let you keep the fox flying by tapping on the screen. Here's a screen shot of what it looks like on my Geeksphone Peak (now running in FxOS 1.2):



Tap and he flied upward. Don't do anything, and the fox falls! In later posts I'll show how to scroll and how to draw in the obstacles, but being able to import an SVG file is enough for now.
Here is the code for Part 1.

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <title>
    Flying Fox Part 1
  </title>
 
  <style>
        
    #mySVG
    {
      width: 360px;
      height: 620px;
      position: absolute;
      top: 0px;
      left: 0px;
    }
     
  </style>


  <script>

  // --- Global variables ---

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

  // URL for W3C definition of SVG elements
  var svgURL = "http://www.w3.org/2000/svg";
  var svgLink = "http://www.w3.org/1999/xlink";

  // Variables for fox initial position.
  var foxX = boardWidth / 2 - 100;
  var foxY = boardHeight / 2;
  var foxH = 50;
  var foxW = 50;

  // Use requestAnimationFrame.
  var requestAnimationFrame =
  window.requestAnimationFrame ||
  window.mozRequestAnimationFrame ||
  window.webkitRequestAnimationFrame ||
  window.msRequestAnimationFrame;

  // --- Event listeners ---

  // Page load event listener.
  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;
    gameBoard.id = "mySVG";
   
    // You must append the board to the body.
    document.getElementById("pageBody").
      appendChild(gameBoard);

    // Add a background element for color.
    gameBack =
      document.createElementNS(svgURL, "rect");
    gameBack.x.baseVal.valueAsString =
      "0px";
    gameBack.y.baseVal.valueAsString =
      "0px";
    gameBack.width.baseVal.valueAsString =
      boardWidthPixels;
    gameBack.height.baseVal.valueAsString =
      boardHeightPixels;       
    gameBack.style.
          setProperty("fill","Thistle","");
         
    // Attach the background to the game board.
    gameBoard.appendChild(gameBack);

    // Mouse down event listener
    gameBoard.addEventListener(
      "mousedown", foxJump, false);
       
    // Import SVG fox image.
    // Set height, width, x, and y.
    myFox = document.createElementNS(svgURL,"image");
    myFox.setAttribute("height",foxH);
    myFox.setAttribute("width",foxW);
    myFox.setAttribute("x",foxX);
    myFox.setAttribute("y",foxY);
   
    // Use different namespace for xlink.
    myFox.setAttributeNS(svgLink,"href","fox.svg");
   
    // Add the fox to the game board.
    gameBoard.appendChild(myFox);
   
    // Start the game loop.
    gameLoop();
  }

  // Game loop.
  function gameLoop(){

    // Endless loop with requestAnimationFrame.
    requestAnimationFrame(gameLoop);

    // The fox waits to drop.
    // Only you can save him.
    foxWait();
  }

  // Fox is waiting to fall.
  function foxWait() {
 
    // Make the fox fall after one second.
    foxFallTimer = setTimeout(foxFall, 1000);
  }
 
  // Fox is falling.
  function foxFall() {
 
    // Make the fox fall one pixel.
    foxY = foxY + 1;
   
    // Does he hit the floor?
    if (foxY > (boardHeight - 50)){
     
      // Calculate new position.
      foxY = (boardHeight / 2) - 50; 

      // Alert and reset.
      alert("Fox hit the floor!");
      console.log("Fox hit the floor!");
      return;
    }

    // Draw the fox.
    myFox.y.baseVal.valueAsString =
      foxY + "px";
     
    // Report progress.
    console.log("Fox is falling.");
  }
 
  // Fox is jumping.
  function foxJump() {
 
    // Fox jumps up!
    foxY = foxY - 20;
   
    // Does he hit the roof?
    if (foxY < 20) {
     
      // Calculate new position.
      foxY = (boardHeight /2) - 50; 
     
      // Alert and reset.
      alert("Fox hit the roof!");
      console.log("Fox hit the roof!");
      return;
    }
   
    // Otherwise, draw the fox.
    myFox.y.baseVal.valueAsString =
      foxY + "px";
   
    // Report progress.
    console.log("Fox is jumping.");  
  }

  </script>
  
</head>

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

</html>


A lot of this code is similar to other SVG posts I've written, and here's a brief outline.

Shell

Uses the standard HTML5 shell for SVG. For a detailed explanation, see this post: http://firefoxosgaming.blogspot.com/2013/11/bouncing-svg-part-3-game-programming.html.
I have some globals, I set up an event listener, and then start running the game when the page loads.

Game Loop

The game runs in a game loop, using requestAnimationFrame for the basic display timing.

Action

Every time through the game loop, the program goes to a waiting routine that waits one second. After the second has passed, the fox falls a small amount. If the fox hits the ground, the game is reset.

Touch

But to keep the fox from falling, you can tap the screen. I use the mousedown event in much the same way I did in the post Touch and SVG Spirals. Tap on the screen, trap the tap with an event handler, and then move the fox up. But be careful. If the mouse hits the roof, the game is also reset.

SVG

The real meat of this is importing the SVG image. Here's the code that does this:

    // Import SVG fox image.
    // Set height, width, x, and y.
    myFox = document.createElementNS(svgURL,"image");
    myFox.setAttribute("height",foxH);
    myFox.setAttribute("width",foxW);
    myFox.setAttribute("x",foxX);
    myFox.setAttribute("y",foxY);
   
    // Use different namespace for xlink.
    myFox.setAttributeNS(svgLink,"href","fox.svg");
   
    // Add the fox to the game board.
    gameBoard.appendChild(myFox);


This code is in three steps:

1. Create an SVG element called myFox using the SVG image element. Define the height, width, x, and y values to give it a location and size. foxX and foxY will determine where the fox is placed.

2. Then we must import the fox, which is in a separate file called fox.svg. We do this by using a magic technology called XLINK. One of the tricks to working with SVG is to remember that under the hood, SVG is XML, not HTML. Even though HTML5 has graciously allowed SVG to come and live in their house, SVG is still an XML animal. And XLINK is a linking protocol that was designed for XML. To use XLINK, you must introduce a separate namespace. SVG has one and now XLINK does too. Up in the globals, I defined svgLink as the namespace for XLINK, so you must use that when you invoke it, because it isn't part of HTML5 or SVG. But it works just fine. You import it by adding the href attribute to the SVG object myFox and then supply the URL, which in this case is just the filename, fox.svg. Complicated, but you only need to learn it once.

3. Then, once you've created the SVG image and imported the art into the image, you just need to add the image to the main SVG object, gameBoard. The image is now part of the SVG drawing and you can manipulate it all you want through JavaScript.

The fox is now ready to fly. Load this into your phone, watch the fox fall, and then tap to keep him from falling to the floor or hitting the roof.

Background

I had one problem with this that I needed to fix. In my last post when I was raving about how cool App Manager was, I showed a preliminary screen shot of the game I'm writing about now.


You'll notice that the top and left edges show a white margin. That's not what I wanted, and it made me dig out my old code from my post on screen sizes: http://firefoxosgaming.blogspot.com/2013/10/how-big-am-i-game-programming.html. Turns out that I hadn't measured the screen with my code and the new code showed this:


My inner screen size was now 360 x 620 pixels. So I added an SVG rectangle that I could color just to show a completely solid background, helpful to see where the fox is. Here's the code I used:

    // Add a background element for color.
    gameBack =
      document.createElementNS(svgURL, "rect");
    gameBack.x.baseVal.valueAsString =
      "0px";
    gameBack.y.baseVal.valueAsString =
      "0px";
    gameBack.width.baseVal.valueAsString =
      boardWidthPixels;
    gameBack.height.baseVal.valueAsString =
      boardHeightPixels;       
    gameBack.style.
          setProperty("fill","Thistle","");
         
    // Attach the background to the game board.
    gameBoard.appendChild(gameBack);


Standard stuff, just a rectangle. Define it, attach it, color it "Thistle", and you're done.

But when I loaded it into my phone, it still had that damn margin. I check and all browsers give you a margin when you throw an SVG object at them.

But when things don't work, there is the cousin of SVG, known as CSS! By simply giving the SVG board an ID, I could then place it exactly where I want it to go with some simple CSS. I understand browser manufacturers wanting to give a little margin (I don't think this was always true), but I want the game to go right to the edge.

So I added this CSS and everything fit perfectly:

  <style>
        
    #mySVG
    {
      width: 360px;
      height: 620px;
      position: absolute;
      top: 0px;
      left: 0px;
    }
     
  </style>


How cool is that? The mixture of HTML5, CSS, JavaScript, and SVG is really rocking. And thank you to Nicu for sharing with the world how to draw SVG and make it look good.

But it also makes me see that you have to be sure of what your screen is. I'm thinking I might clean up my "How Big?" app and putting it in the Marketplace for other programmers. We will be having more phones, tablets, and devices.

Next up, scrolling the screen.

Wednesday, December 4, 2013

Cage Match! CSS vs Canvas vs SVG (Game Programming)

As promised, here are my opinions on which graphics technologies to use for Firefox OS game programming. Of course, with any technology, you can make anything do almost anything if you work at it long enough. But each of the three are great and have their places. But they might seem to be fighting for your attention and against each other.


On the left is CSS, in the middle is Canvas, and over there on the right is SVG. For this comparison, I'll list specific categories of game programming and how each seems to be pro or con. Your mileage may vary and please let me know if I've missed something.


Performance
All three run pretty fast in today's browsers. If you compare the bouncing ball examples (CSS, Canvas, and SVG), they are all pretty fast. When I first started working on these, I was surprised at how fast they all are, but I shouldn't have been, because all the major browsers (even IE) are now tuning graphics for high performance.

CSS: browsers have been doing CSS forever, so they know how to do it and a lot of CSS is heavily optimized because everybody is using it (though not for animation). There are some new animation techniques that fit under the name of CSS3, but I'm not looking at newer things, only stuff that has been around a long time. If you ask CSS to move something, it does it instantly.

Canvas: slow at first, all browsers now try to add hardware acceleration to Canvas drawing and you'll find that most HTML5 games use Canvas because it works. Redrawing the screen using requestAnimationFrame really speeds up one of the big problems of Canvas, which is moving and erasing where you were (cleaning up after yourself). Still, some operations can be slow if you're doing a lot of pixel manipulation.

SVG: fast if you use the SVG object model directly and bypass the HTML DOM. You're working directly with the SVG engine and all browsers (thanks, IE) are now tuning SVG as it catches on. I think some parts of webkit are still running behind, but I'm sure they are trying. SVG also just seems fast, because you just make a tweak and the objects respond.

Ease of Programming
None of these are easy. Life is short and animation is hard. In terms of ease of programming, I chose the order of these three when I started this blog based on CSS being easy, Canvas taking more skill, and SVG requiring the most skill. In terms of computer languages, I'd rate it this way:

     CSS is similar to BASIC
     Canvas is similar to JavaScript and C#
     SVG is more like C/C++

CSS: the easiest is to use because you just slap bitmaps around. If you're a web monkey, you know what CSS is all about and by using simple JavaScript, you can move things easily enough. You can get something working and know it will work in just about any browser that's still around. Maybe even IE 6. Not particularly well documented as a game programming technique, but it can be used. It would make a nice beginning programming tool for web designers.

Canvas: there are tons of books and articles on HTML5 game programming with Canvas. It works and requires specific techniques. You can't go wrong with this. It reminds me of programming 8-bit computers long ago, where you have to clean up after yourself and be very aware of where every pixel goes. The biggest limitation is that once you spray those pixels on the canvas, you're done. You can't easily move them or keep track of them. Very similar to artistic canvases, in that once you lay down your paint, you can only try to cover it up with more paint and hope for the best.

SVG: This isn't well documented anywhere. Mozilla Developer Network has good documentation on the basic object model but doesn't have many (or any?) examples. There are a few. And it makes it more confusing that there are three different ways to program SVG in a web page now that HTML5 supports the joining of SVG to HTML5 at the hip. But if you learn some simple rules and look up things in the SVG specification, you can figure your way around it. But it has real advantages in terms of keeping track of all your objects, collision detection, etc. You can do more with SVG than the other two, and all of it is fast.

Ease of Art Resources
You have to create the art yourself, one way or the other. Each of the three uses art in different ways.

CSS: uses plain old pixel art. Make a drawing in Photoshop, export it as a PNG, and you're done. There are a zillion different pixel art programs. And there are a zillion artists out there that are really good. Check out deviant art!

Canvas: is an alien/human hybrid. It can use pixel art straight out of Photoshop (or a zillion others) and that's all most people will ever do. However, the alien part is that it can draw shapes on command. Want a box? It can draw it. Want a circle? You can, if you know a circle is just a complete arc. You can design all the twists and turns of the shapes yourself on graph paper, but you can also draw shapes in Adobe Illustrator and with a plug-in, convert it to Canvas commands. Read about it here: http://blog.mikeswanson.com/post/29634279264/ai2canvas.  This gives you the most options for art creation.

SVG: is an alien. It only uses shapes and lines and colors to do its work, so you can't use bitmaps directly. You'll need to create your art by working out the details yourself on graph paper, or use Inkscape or Illustrator to do the heavy lifting for you. I prefer Inkscape because they use SVG all the way down to the core (Illustrator is based on some other technologies and they've added SVG to it along the way). If you want to see a ton of cool SVG art, go to the Open Clipart site. One important fact to point out is that when you create pixel art, you can't do much with it. If you stretch it too much, it looks weird. But SVG is scalable and you can change the size and shape of any SVG art with no loss at all (no loss at all!!!).

Collision
Not all games are about collision, but most action games are, and a phone is a good place for a little quick action! I've written about collision specifically already (CSS, Canvas, SVG) but I'll summarize.

CSS: no collision detection at all. You have to have JavaScript keep track of what is where and when it might collide. That's fine and JavaScript does a great job of keeping track of things. It does have the ability to track a mouse event, so you can tell what object you clicked and process it.

Canvas: has no collision detection either. You need to track where the objects are on your canvas and canvas has no memory of anything except the pixels on it. So JavaScript again saves the day. Unfortunately a canvas has no understanding of where a mouse event lands on the canvas. You can track it by figuring out the coordinates, but the canvas only tells you it was clicked somewhere. It doesn't know. Maybe some day someone will invent something called SmartCanvas. But at least, as I showed in the sample, you can detect what is on the canvas at one spot and make a decision based on that pixel's RBGA color value. Useful if you are tracking a lot of objects with the same color.

SVG: keeps track of everything all the time. It knows every property of every object. You want to know where something is? Ask it. It will tell you its x and y values and its favorite color. In the SVG example of collision, if you look at the code (and you did, right?), you'll see that the mouse click was just a click. It didn't matter where you touched the screen, all that happens is that the red ball jumps. It knows where it is, so it can jump 50 pixels higher. You can do a lot of relative motion, and by using getBBox, you can even track objects as they change size and location. Collision detection is built in.

Special Effects
There's nothing like some special effects to brighten up a game. CSS has the fewest (if you don't count CSS3), Canvas has some very interesting effects if you work at it, but SVG has tons of special effects built in. Tons!

CSS: there are a few CSS effects you can do, but not much that is unusual. You can read about some of them on MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/filter. However, you'll notice quickly that there's a lot of SVG talk on that page, because SVG and CSS are also joined at the hip. A lot of SVG stuff uses CSS! (Everybody knows its a secret.) But I'm not sure how well they work in CSS. (The page on MDN says experimental.)

Canvas: you can do some cool effects with Canvas, but you have to do it pixel by pixel. Tedious and close to assembly language. For some complicated ugly code, check out How to Create Canvas Special Effects.

SVG: it has a lot. If you look at the specification, there are miles of effects just in the Filter Effect section (with lots of cool pictures showing the changes). Plus you can dramatically change size, shape, color, position, etc., with one line of JavaScript for any object. And more. I'm working on some cool glow effects that I'll explain soon (I just love glow effects).

Wrapping Up
There's really no winners and losers. Depending on what you want to do and your skill level and the skill of the artists you work with (or who are you), you can do lots of cool things. Here's my quick summary:

CSS: simple, easy, only uses simple pixel art. And works in every browser. A winner if you are just starting out. But not well known for games (look for CSS sprites if you want to know more). It is the BASIC of the graphics world.

Canvas: very popular. Lots of books. Browsers are really good now about accelerating the canvas so it draws fast and erases fast. Uses pixel art and some shapes. But sometimes seems a little dumb. I'm waiting for Canvas 2.0. Is there even an effort to make it better? Yes, this does resemble C# and JavaScript in that it gets the job done, but has limitations.

SVG: the strange dark animal lurking on the edges. SVG can do all kinds of stuff, but you have to understand what you're doing (or copy code from those who do). But it offers a lot more. SVG is very smart (Smart Vector Graphics) and has a lot of options that are hidden inside every major browser, but which are still partially hidden. Yes, it is like C/C++ in that it provides great performance and endless possibilities, but can be difficult to program. But fun.

So there you have it. As I move forward with more game programming stuff and creating actual games that can go in the Marketplace, I'll be focusing on SVG, but may do some things in Canvas or CSS for fun.

Stay tuned, but not iTuned.

PS: if you feel I've missed anything about any of this, let me know. These are my findings, but you may have found something else.