Showing posts with label HTML DOM. Show all posts
Showing posts with label HTML DOM. Show all posts

Monday, October 28, 2013

Bouncing a Ball in CSS (Game Programming)

I'm going to start a series looking at the 6 ways you can use simple graphics for games in Firefox OS.

What's that you say? Isn't Canvas the way to do graphics for games? Six ways? Simple?

Well, maybe not always simple, but here are the ways I'm going to demonstrate, in between reviewing other people's games:
  1. CSS sprites - easy for some games, works in every browser except maybe some really old ones.
  2. Canvas using bitmaps - this is the most popular. Blast a bitmap, you're done, almost.
  3. Canvas using lines and shapes - advanced, but might be cool with some kinds of games.
  4. SVG body - create SVG shapes in the body and move them around.
  5. SVG in the HTML DOM - create SVG shapes in the HTML5 DOM and manipulate them.
  6. SVG in the SVG DOM - SVG has its own DOM - "It's a secret to everybody" (Zelda)
But for today, you can use CSS (Cascading Style Sheets) to move bitmaps around on the screen. CSS has been around a long time, but most people think of it as a way to define the typefaces, layout, and colors of a web page. But you can use CSS to define graphics that you can move around. I won't use it in this post, but the coolest part of CSS is something called CSS Sprites, which lets you do simple animation.

So I've written a really simple program that just lets a ball bounce around your Firefox OS screen. You can't do anything but watch. It's just a demonstration of one way to do graphics. I'll use the same model for the other 5 ways to do graphics (and I'm not counting WebGL which is a cool 3D technology and I'm not using any JavaScript libraries either. (I tend to avoid JavaScript libraries because I like to know every detail of what is going on.)

Here is the code I've written. Copy it, slap it into a text file, use the same manifest as before, even the same icon. You can of course change the icon and you should change the personal details in the manifest as well.

But before you see the code, a bit about the Firefox OS development cycle. When you start up the Firefox OS Simulator, you pick a folder that has the manifest in it. If you want to make a change to your code, you need to:
  1. Stop the simulator (click "Running" and it will say "Stopped").
  2. Click on the x at the very far right to remove the app from the simulator.
  3. Reload the simulator (F5 is your friend).
In addition, if you have pushed your app to the phone, you will want to delete that app before you try to push a new version again. Do that by long-pressing on the app, touch the little x, allow your app to be killed, and then press the Home button to make the other apps stop wiggling (in fear that they will be killed next).

Now you are ready to put in this code (in a file named index.html):

<!DOCTYPE HTML>
<html>
 
  <head>
    <meta charset="UTF-8">
    <title>
      CSS Bounce 320x460
    </title>
 
    <style>
        
      #ball
      {
        width: 20px;
        height: 20px;
        position: absolute;
        top: 200px;
        left: 100px;
        background-image: url(ball.png);
       }

    </style>
   
    <div id="ball" />   
   
    <script type="text/javascript">

    // Global variables
     
      var boardWidth = window.innerWidth;
      var boardHeight = window.innerHeight;
     
      var ballHor = boardWidth / 2;
      var ballVer = boardHeight /2;
     
      var changeHor = 10;
      var changeVer = 10;

      // Get ball information.
      var myBall = document.querySelector("#ball");
     
      // Function called on page load.
      function playBall() { 

        // Play the game until the ball stops.
        gameLoop = setInterval(ballMove, 16);
       
        // Output to debugger.
        console.log("The page is loaded.");

      }

      // Move the ball.
    
      function ballMove() {
     
        // Changes are calculated but do not
        // take effect until next time through loop.
       
        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;
      
        }

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

</html>


The code (unlike Gaul) is divided into 5 parts:
  1. The HTML5 shell, which just sets up the document for Firefox OS.
  2. The CSS definition, which defines the ball.
  3. A div element, which gives the ball a place to live.
  4. A script, which will set things up, create a game loop, and move the ball.
  5. The body, which loads the script named playBall.
Here's what the ball looks like on my ZTE Open:


It is purple and bounces. The ball is a 20x20 bitmap with transparent edges. It's really a square but is pretending to be a circle.

An interesting thing about the bitmap is that it is in the same folder as your manifest and index.html files. You don't need to tell the manifest to bring it along, it magically grabs the file referred to in the CSS url section and knows where it is. Firefox OS makes it so easy.

Here's a brief description of the parts of the app:
  1. All Firefox OS apps must have an HTML5 code structure. In this case, I've made sure I have a head and a body, and I've set the charset to UTF-8. Titles are good too.
  2.  Next I set up the CSS definitiion of the ball. CSS is a markup language that is pretty easy to learn. In this case I've just created something called "ball" that has width, height, position type, top, left, and background image defined. The background image is defined by a bitmap called "ball.png."
  3. Next I created a simple div element. Interestingly enough, I put it in the head, because its location is defined by the CSS style (width = 200px, height = 100px). The div has an id and the CSS defines what the element with that id is.
  4. Next is the script part, which is called from the body when the page loads. The script just defines some global variables and then used querySelector to grab the ball as an object defined by CSS. The ball is ready to be bounced around. Note that "#ball" refers to the div with the id of "ball" that is defined CSS. But the ball is now accessed through "myBall" to give it full JavaScript access. This is that perfect marriage between HTML (the div), CSS style, and JavaScript that means you don't need anything else like Canvas or SVG.

    After the globals and the querySelector, the script contains two functions: playBall and ballMove. The playBall function sets up a game loop that will repeat every 16 milliseconds, which is a magic number that seems to work with most browsers. The loop repeats and each time through, it calls ballMove, which ... moves the ball.

    Actually, the position of the ball is calculated the first time ballMove is called and then the next time it moves the ball. This is weird but seems to work well. The calculation just adds a fixed amount (10 pixels) and then sees if the ball can go there. The ball has a direction it is already going (ballHor and ballVer). The important part is that checks are made to see if the ball will go out of bounds. If it does, the direction will change and the next time through the ball will be moved to a new position. This may seem a bit goofy, but it works. Note that I subtract 10 pixels to account for the amount the ball moves each time it moves.
  5. Finally, the body just simply calls the playBall function when it is loaded.
All this is in less than 100 lines, but you now have something that actually does animation. Note that if you test this in any browser, it will bounce to the edges no matter how big or small, and that this works just fine in Firefox, Chrome, and Internet Explorer. I gave up trying to test Safari, but this should work there. But between you and me, we only care about Firefox!

Let me know if I've not explained things. I'm assuming you know intermediate HTML5, CSS, and JavaScript, but I may have skated past some thing too quickly. Working with CSS is quirky sometimes because you have to reference objects very specifically and you have to keep each one of the three marriage partners (HTML, CSS, and JavaScript) happy. 

Thursday, October 24, 2013

How Big Am I? (Game Programming)

My review of Candy Crush made me think that one of the first things I want to do is see how much room I have in my new house (the ZTE Open Firefox OS phone). Often games need fixed sizes, and it is a good idea to know how big your screen really is. The Candy Crush guy had a great game, but it was a little too big for the phone.

If your app is mainly text based, you can just let the type flow wherever it wants. But games almost always need specific items in specific places. So it is important to know exactly what size your game board is!

I wondered about this, and so I wrote a small app and found some answers.

I used the innerWidth, outerWidth, innerHeight, and outerHeight properties of the HTML DOM window object. This is supported in Mozilla, so we know we are good to go: https://developer.mozilla.org/en-US/docs/Web/API/window.innerWidth.

Here's what these properties do:

innerWidth = width of the viewport (not including scrollbars and chrome)
outerWidth = width of the whole window (includes scrollbars and chrome)
innerHeight = height of the viewport (not including scrollbars and chrome)
outerHeight = height of the whole window (includes scrollbars and chrome)

Chrome is not a browser name; here it means the stuff that surrounds the actual content of your page. Usually there is more chrome at the top and bottom (menus, notifications, etc.). You care about the inner parts because that's where your game takes place.

So I wrote a web page that looks around from the inside and tells us what it sees.

<!DOCTYPE = html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,
  height=device-height, user-scalable=false;">
<title>Hello Firefox</title>
<script>
w = window.outerWidth;
w2 = window.innerWidth;
w3 = w + " " + w2;
h = window.outerHeight;
h2 = window.innerHeight;
h3 = h + " " + h2;
howBig = w3 + " " + h3;
alert(howBig);
</script>
</head>
<body>
<h1>Hello</h1>
<p>This is a hello page.</p>
</body>
</html>


 Most of this is straight HTML5 stuff. Firefox OS likes UTF-8 so I put it in.

Next I added the viewport information. That just tells the page to make the page the same size as the device width and height, and won't let the user modify the page size. We want our window to fit snugly into the screen of the ZTE Open.

Next, I wrote some simple code that gets the inner and outer widths and heights so I could see what happens.

So then here comes the cool part. I ran this code in the Firefox OS Simulator and here's what I got:

What this tells me is that the inner width and height in the simulator is 320x460. There's chrome at the top and bottom, but not that much.

Next I pushed it to the ZTE Open and took a screen shot:






As you will notice, the inner height and width on the ZTE Open is the same as the simulator: 320x460. However, the chrome is a bit more. The width is an additional 26 pixels but the height is a less because there isn't the Firefox browser chrome that the simulator uses (that's the part that says "Firefox OS Simulator" in the first screenshot and has the three buttons at the top right).

The point of all this is that the simulator still tells you the inner dimensions of the screen on the phone (320x460) which is what the specs say. But this is the inner screen dimensions and corresponds to the viewport size. So when designing your app for Firefox OS, make sure you check what screen real estate you have. Especially as new phones and tablets come out, find out what room you actually have.

Why? Well, if you know how big something is, you can juggle things around to make them fit. When Android and iPhone came out, their screen sizes were "standard" but they quickly changed as various new phones came out with different sizes. Checking this out will make your life easier!

My two favorite sayings for programming are:

Trust No One

and 

The Truth is Out There

Both from the X-Files, but they apply to programming. You must test everything yourself and never assume that something written is true. But, on the other hand, if you search long enough, you'll get the right answer.

Maybe one of the best reasons to play around with this is that you can write the same app for the Firefox OS phone and have your app run in a Firefox browser. And maybe if we're very good little children, we'll get to play with a Firefox OS tablet.