Pages

Wednesday, March 26, 2014

CSS Shooter (Game Programming)

Recently I created a new CSS shell and wrote about it in Son of CSS Shell at http://firefoxosgaming.blogspot.com/2014/03/son-of-css-shell-game-programming.html. Having done that, I'd like to devote a few posts to working more with just plain old CSS. No Canvas, no SVG, not even CSS3. Some people call this CSS sprites but I'll just call it CSS game programming. And I'll be doing more with actual CSS sprites, which are a collection of images on a single file.

Like this:


But that's later. Right now I'm interested in doing more actual gaming with CSS. Today's game is a simple one, that is a shooter. Inspired by Breakout but with only one brick.


But then I was also inspired by the recent release of Yoshi's Island on the Nintendo 3DS and actually inspired by the earlier version on the Game Boy Advance that used a special moving cursor to aim shots.






Yoshi is in the center and the cursor (on the top right) moves up and down in an arc. At the right moment you press a button and Yoshi's egg flies in that direction! Well, I'm not going to replicate Yoshi's Island but I will say that the best version is on the Game Boy Advance and it looks like that version will be appearing on the Wii U Virtual Console very soon.

So I created a very simple shooter that aims a bullet from the bottom of the screen and shoots it at a target near the top of the screen. And to make it more challenging, the top target moves from left to right across the screen, while the bullet (until fired) moves back and forth. Just click on the screen at the right moment and you can hit the target.

Here's what the game looks like in play.


Tap anywhere to make the fuchsia bullet shoot up.


The bullet is on its way to the top of the screen. In this case, it looks like it is going to hit the green target. And it does! An alert is displayed telling you that you hit the target.


And if you didn't hit the target (easy to do since the cursor moves one way and the target another) you'll be told that you missed, but in either case you can start over again by just tapping on OK.


The Firefox OS App Manager makes it really easy to test and take screen shots. 

This is cool, but I had even more fun creating it by using the desktop of Firefox Nightly. As explained in the Son of CSS Shell post at http://firefoxosgaming.blogspot.com/2014/03/son-of-css-shell-game-programming.html, I created a simple shell that is responsive to whatever size the browser happens to be. So because this game doesn't have anything phone-specific, I ran it in the desktop version and resized it to vaguely phone size. I also hit Control+Shift+K to get the debugger going, and here is what it looks like:


I've just had a hit, but you can see the debugging output that shows me the target and ball matching, and the subsequent collision. You can also see the bullet and target colliding in the upper right-hand corner.

Working this way is very, very fast when you are creating, and if you're not doing something that requires a phone, I recommend it. Of course all  bets are off if you're doing Device Orientation!

Here's a similar screen showing the debugging output of the desktop browser for a miss. You can see that the bullet is on the left, far away from the target in the middle.


Firefox OS makes it so easy to make games that you have no excuse not to!

Code

And here is the code that makes this happen:

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

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

  </style>

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

  <script>

    // Global variables   
    var boardWidth = window.innerWidth;
    var boardHeight = window.innerHeight;   
    var ballHor = boardWidth / 2;
    var ballVer = boardHeight - 50; 
    var tarHor = boardWidth / 2;
    var tarVer = 50;   
    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;
   
    // Stop scroll bars from interfering.
    document.documentElement.
      style.overflow = 'hidden';
  
    // Load event listener
    window.addEventListener("load",
      getLoaded, false);
     
    // Resize event listener
    window.addEventListener("resize",
      resizeMe, false);
     
    // Mouse down event listener
    window.addEventListener(
      "mousedown",
         bulletFly, false);

    // Get target information.
    var myTarget =
      document.querySelector("#target");

    // 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.
      animFrame =
        requestAnimationFrame(gameLoop);
  
      // The ball is now a bullet.
      bulletMove();      
     
      // Move the target.
      targetMove();
      }
  
    // Make the target move.
    function targetMove() {
   
      // Changes are calculated but do not
      // take effect until next time.     
      myTarget.style.left = tarHor + "px";
      myTarget.style.top = tarVer + "px";   

      // Calculate new horizontal component.
      tarHor = tarHor + 10;
    
      // Right edge hit, restart.
      if (tarHor > boardWidth)
          tarHor = 0;
    }
  
    // The bullet flies up.
    function bulletFly() {
   
      // Stop animation loop!
      cancelAnimationFrame(animFrame);    
     
      // Delay for animation motion
      // Outer loop - time set at end     
      loopTimer = setTimeout(function() {
     
        // Animation of the bullet
        // Inner loop - does the drawing
        bulletFrame =
          requestAnimationFrame(bulletFly); 
         
         // Calculate bullet fly up.
        ballVer = ballVer - 50;  
       
        // Changes are calculated but do not
        // take effect until next time.     
        myBall.style.left = ballHor + "px";
        myBall.style.top = ballVer + "px";   

        // Track bullet and target
        console.log("Ball: " + ballVer +
          " ," + ballHor + " Target: " +
          tarHor);
         
        // TEST - REMOVE
        // ballHor = tarHor;
       
        // Test for collision.
        // Horizontal the same
        // Vertical close to top.    
        if  (((ballHor < (tarHor + 20)) &&
              (ballHor > (tarHor - 20))) &&
          (ballVer < 60)) {
             
          // It's a hit!
          console.log("Collision");
          alert("You hit! Start over!");
         
          // Reset everything.
          startOver();
        }
       
        // Test for missing.
        // Vertical less than 50.
        if (ballVer < 60) {
          console.log("Missed!");
          alert("Missed! Start Over!");
         
          // Reset everything.
          startOver();
        }  
      } , 300); // Delay
    }
   
    // Reset everything and start over!
    function startOver(){
   
      // Reset ball and target.
      ballHor = boardWidth / 2;
      ballVer = boardHeight - 50; 
      tarHor = boardWidth / 2;
      tarVer = 50;   
     
      // Stop the drawing.
      cancelAnimationFrame(bulletFrame);
     
      // Stop the loop.
      clearTimeout(loopTimer);
     
      //Go to the game loop and start over.
      gameLoop();
    }
   
    // Calculate and move the ball. 
    function bulletMove() {
  
      // Changes are calculated but do not
      // take effect until next time.     
      myBall.style.left = ballHor + "px";
      myBall.style.top = ballVer + "px";   

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

      // Left edge hit, reverse direction.
      if (ballHor + changeHor < -10) {
        changeHor = -changeHor;
        ballHor = 10;
      }
    
      // Right edge hit, reverse direction.
      if (ballHor + changeHor >
        boardWidth - 10) {
          changeHor = -changeHor;
          // Compensate for unknown width.
          // We want multiples of 10.
          flr = Math.floor(boardWidth / 10);
          ballHor = 10 * flr;        
      }
    }

    // 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>


This uses the Son of CSS shell, so I won't explain any of that here! But here are the new parts that you might like to know about.

Target CSS

I defined the target in CSS like this:

    #target
    {
      width: 20px;
      height: 20px;
      position: absolute;
      top: 200px;
      left: 100px;
      background-color: green;  
    }


Similar to the bullet, but instead of using an imported PNG image, I just used the power of CSS to create a box and give it the background color of green. If you want boxes, CSS can turn them out all day.

I also then gave the target a place in the browser DOM by making a DIV. Remember, there's no code in the body of the page!

  <div id="target"></div>

I also had to select the target to make it known to everybody.

    var myTarget =
      document.querySelector("#target");


This might seem like a strange way to do things, but it works in every browser, and especially in Firefox OS. Just do these things to introduce your CSS objects to the DOM and you can do anything you want with them. Follow these steps:

  1. Define the CSS object using CSS.
  2. Create a DIV with the ID of the CSS object you just defined.
  3. Select the object with querySelector and your CSS object is known to all.

Global

Then I added a few things to the global section that will be useful later:

    var tarHor = boardWidth / 2;
    var tarVer = 50; 


This puts the target near the top. It's horizontal will change when the game starts.  

I also changed a global for the ball:

    var ballVer = boardHeight - 50; 

This makes the vertical position of the ball near the bottom. The horizontal will change when the game starts.

Note: in the code, the bullet is called ball because I kept the old code from the shell. I don't like to change variable names if I don't have to. I hope you don't find it too confusing.

Touch Event

Next I added a touch event, also known as mousedown. The phone will interpret this as a touch event.

    window.addEventListener(
      "mousedown",
         bulletFly, false);


This will create an event listener which will call the bulletFly function when the screen is touched anywhere. And works with mouse clicks in the desktop browser. Two events for the price of one!

Game Loop

Add this function call to the game loop:

  bulletMove();

It was called ballMove() in the shell. It will move the bullet back and forth every time the game loop runs (governed by requestAnimationFrame).

Then add  the function call to move the target with this:

  targetMove();

Moving the Target

This moves the target!

    function targetMove() {
       
      myTarget.style.left = tarHor + "px";
      myTarget.style.top = tarVer + "px";   

      tarHor = tarHor + 10;
    
      if (tarHor > boardWidth)
          tarHor = 0;
    }


This just makes the target move from left to right. The target is drawn but the changes won't take effect until the next time through.

The target horizontal position is incremented by 10 and then a check is made. If the target would go off the right edge, the horizontal position is set to 0.

Moving the Bullet

The bullet moves right to left and then left to right. It makes the game more challenging to have two different motions.

    function bulletMove() {
  
      myBall.style.left = ballHor + "px";
      myBall.style.top = ballVer + "px";   

      ballHor = ballHor + changeHor;

      if (ballHor + changeHor < -10) {
        changeHor = -changeHor;
        ballHor = 10;
      }
    
      if (ballHor + changeHor >
        boardWidth - 10) {
          changeHor = -changeHor;
          flr = Math.floor(boardWidth / 10);
          ballHor = 10 * flr;        
      }
    }


This starts out the same as the ballMove function in the Son of CSS shell. But because it only goes left and right and doesn't hit the top or bottom, it just checks for the left and right edges.

If the left edge is hit, the direction changes and the bullet horizontal is set to 10.

But if the right edge is hit, the direction is changed, but a quick calculation takes place to make sure that the new bullet horizontal position is set to a multiple of 10. Because we can't know the exact screen size, this is one of the fun parts of making a responsive design.

Shooting the Bullet

This is the meat of the program. It does a lot of things!

    function bulletFly() {
   
      cancelAnimationFrame(animFrame);    
     
      loopTimer = setTimeout(function() {
     
        bulletFrame =
          requestAnimationFrame(bulletFly); 
         
        ballVer = ballVer - 50;  
       
        myBall.style.left = ballHor + "px";
        myBall.style.top = ballVer + "px";   

        console.log("Ball: " + ballVer +
          " ," + ballHor + " Target: " +
          tarHor);
         
        // TEST - REMOVE
        // ballHor = tarHor;
       
        if  (((ballHor < (tarHor + 20)) &&
              (ballHor > (tarHor - 20))) &&
          (ballVer < 60)) {
             
          console.log("Collision");
          alert("You hit! Start over!");
         
          startOver();
        }
       
        if (ballVer < 60) {
          console.log("Missed!");
          alert("Missed! Start Over!");
         
          startOver();
        }  
      } , 300); // Delay
    }


First the requestAnimationFrame used in the game loop is canceled. Once the bullet starts on its upward journey, you don't want the game loop to run any longer.

Next, a new loop is created, one that will provide a short delay between each motion of the bullet as it flies up. This loop uses setTimeout with an anonymous function. Inside that function is an inner loop that just runs a different requestAnimationFrame.

This will work in a lot of cases where you want motion. You calculate the motion, have a short delay in an outer loop, and then in an inner loop you use requestAnimationFrame to do the actual drawing. This is very efficient.

Once the loop is running, every time through is will move the bullet up 50 pixels and draw it. I added a console.log here so I could track the bullet.

Then I tested to see if a collision had taken place. This is a bit tricky, and watch those parentheses. I recommend you use an editor that will check parentheses! I use notepad++ and I'm very happy with it.

The calculation sees if the horizontal positions of the bullet and target are within a certain range of each other and then checks the vertical. The && is just a logical AND and says these three conditions have to be true:

  1. The bullet and target are close on one side horizontally.
  2. The bullet and target are close on the other side horizontally.
  3. The bullet is high enough to be close vertically to the target.

If all three are true, you have a collision. A console.log is displayed, an alert is displayed, and the startOver function is called to restart the game. 

If that doesn't happen, then a second check happens to see if the bullet went off the top of the screen. If it did, a similar console.log, alert, and call to startOver takes place.

Note: I added

   ballHor = tarHor;


in my testing to make it easy to see if the bullet was hitting the target but then commented it out. Sometimes this is a useful trick when you are trying to test something in a fast moving game.

Starting Over

I created a separate startOver function because the tasks were shared between colliding and going off the top of the screen.

    function startOver(){
   
      ballHor = boardWidth / 2;
      ballVer = boardHeight - 50; 
      tarHor = boardWidth / 2;
      tarVer = 50;   
     
      cancelAnimationFrame(bulletFrame);
     
      clearTimeout(loopTimer);
     
      gameLoop();
    }


This just sets the initial position of the bullet and target. It then cancels the two loops that were used to move the bullet up, and calls the game loop.

That's it!













Monday, March 24, 2014

Circle Tetris (Game Review)

Here's a game I haven't seen before that takes an old idea and gives it a new twist! Probably everyone knows about Tetris, that Russian game that swept through the world in 1984 by Alexey Pajitnov.

Here is the original, running on an emulation of a Soviet DVK-2 computer.



But there's a new Tetris in the Mozilla Marketplace, called Circle Tetris, created by Guilherme Herzog & Eduardo Costa in Brazil. It looks like this!




That is, if you're not a skilled player. The point of the game is that the blocks drop down from anywhere on the outside and you want them to land in such a way that a complete circle forms. When a circle forms, the pieces disappear and you get an increased score. Or at least I think that is what is happening because there isn't any Help for this game. But maybe that's okay?

Here's how the game starts. One of the cool things is that the circle around Circle Tetris is moving constantly as a nice little decoration.


High scores will show you ... high scores, unless you haven't made a score yet!


And here's the main screen with two pieces.


The red piece has landed and the black piece is falling towards the red piece. You'll need to hit one of the arrow keys to make it fall to either side. 

The button in the middle makes the shape change. It's still the same color but a different arrangement of the four pieces.

There's a helpful gray image that shows where the pieces will land. If you look carefully, you'll see the shadow of the black piece and where it will touch the red piece. One of the things that makes this game really challenging is that the pieces get smaller as they get closer to the center. That makes it very tough to estimate, but you must estimate quickly and move fast.

At the top left you can pause the game and the top right shows your score.

But beware, if your stack of pieces gets too high, the game will be over!


All in all, this is a very cool game. The rules are easy to figure out, but the play is difficult and you will want to go back to see if you can do better. This is a high speed game and requires fast thinking!

Normally I would deduct points for not having any help, but I was reading a cool new book that just came out called  A Game Design Vocabulary: Exploring the Foundational Principles Behind Good Game Design by Anna Anthropy and Naomi Clark and the authors make a case that sometimes it is better to avoid too many rules and make the game clear. They use as an example Super Mario Bros and how the original didn't tell you what to do, but the Wii version has a big arrow telling you to move to the right, even though you can't go to the left. More about that book later, because so far it seems like a breath of fresh air for game design books (and I've read most of them). 

Anyway, you can figure it out pretty fast by experimenting, but getting points is not easy. It doesn't have any music either or sound effects, but that's okay also. 

I'm very forgiving of a game like this when they do one additional thing. You can see the source code for this game! Just go to https://github.com/guiherzog/circle-tetris and it's all there, even the manifest! Sharing is good!

And best of all, it runs very fast on my tiny ZTE Open and the screen shots are courtesy of App Manager. What could be better? I recommend this game as good mental exercise for those with quick minds and fast fingers.

Cost: Free
Genre: Arcade
Score: 5 (out of 5)
Tested on: ZTE Open
Get it at: Firefox Marketplace
https://marketplace.firefox.com/app/circle-tetris

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!



Wednesday, March 19, 2014

Tower Jelly (Game Review)

Well, I've been busy putting together my book, but now I'm back to new stuff and today will be a review of Tower Jelly from TweenSoft.


Actually maybe the title is Tower Jelly Blocks, or at least that's what the About page says:


You be the judge! Anyway, this is a cool, casual game that is perfect for waiting in line. It won't strain your brain, but you'll have to be alert and tap the screen at just the right time to keep playing.

The basic play is pretty simple. And TweenSoft makes it easy to figure out. They have a Help screen that tells you what to do.


Essentially you have a jelly cube swinging from a rope back and forth, and when you tap, it drops. The first cube lands and you must make the next cube land on top of the first. You get extra points if the second cube lands on top of the first. But if you miss the first cube entirely (or enough so you fall off), you lose a life. Three lives lost and the game is over!

And just in case, when you tap Start Game, you'll get some help again!


The only difference from the Help screen that you get to by tapping Help on the Home screen is that you can tap on Next to continue on to the game itself. Here's the start of the game.


The little X in the lower right corner will let you quit any time. If you tap it, you get this:


Which takes you back to the beginning screen or back to the game you are playing. But you don't want to do that, you want to play! As you drop cubes of jelly, they start piling up and the screen view moves up.


Here's a shot of a cube about to land on another cube. The score at the top right is 100, for dropping one cube. On the top right is the number of lives, represented by three linked hearts. At the lower left is a representation of the current stack. There's one on the stack!

After a few more plays:


There are 8 jelly cubes in the tower stack and I've lost two lives. The higher you go, you see stars and also moving clouds. But when you miss a drop for the third time, you see this:


You can see the current high scores (and I'm not one of them).


All in all, a nice little game for taking up a few minutes while you are waiting in line or otherwise bored. Which is a good thing for phone games!

But there are two things that knock off points a little.

Screen Size

The game doesn't fit on the Geeksphone Peak screen. You'll notice a large black area at the bottom.

When I loaded it on to my ZTE Open (both phones running FxOS version 1.2), the screen looks like this:


The screen now fits the phone! And two things that interest me. The bottom of the screen has a little bit of landscape that adds a touch of interest. And I like that little Firefox logo at the bottom that doesn't show up on the Peak. More work needs to be done by TweenSoft to adapt to different size screens. Not easy, and I'll be doing some research and a few posts soon on this subject of screen size.

Audio

There is none. No sound effects, no music. While not required, sound effects add to the fun and a little bit of music is cool. And no one has any excuse to leave out sound effects or music because they can read my post on Adding Music to Your Game at http://firefoxosgaming.blogspot.com/2013/12/adding-music-to-your-game-game.html.

Kudos

When I went to download Tower Jelly onto my ZTE Open, I noticed two apps in the Featured Apps section at the top. The first was RingTone Picker.


I follow @Mte90Net on Twitter and I suggest you do also! It is really cool to be at the top position!

Also I was pleased to see esviji in the #2 spot for all apps! This is a really cool SVG game from Nicolas Hoizey which I reviewed at http://firefoxosgaming.blogspot.com/2014/01/esviji-game-review.html. Way to go!


Score

Cost: Free
Genre: Casual
Score: 4 (out of 5)
Tested on: Geeksphone Peak and ZTE Open
Get it at: Firefox Marketplace https://marketplace.firefox.com/app/tower-jelly

Friday, March 14, 2014

My Book is on Amazon! (Game Programming)

After spending several weeks pulling together relevant blog posts, I decided to take the plunge and publish a book about Firefox OS game programming on Amazon.

You can get the book here: http://www.amazon.com/dp/B00IZUYIGO.

The title is:

Beginning Firefox OS HTML5 Game Programming

This is an Amazon Kindle book, which means it is an eBook you read on your computer, phone, tablet, or whatever. You can read it on a hardware Kindle tablet or with software available for Windows, Mac, Android, iPhone, iPad, and just about anything else (except Firefox OS and Linux).

I debated about what kind of cover to use. I'm not an artist at all (you may have noticed that all my art is clip art or circles or squares) and I wasn't sure what to do, but fortunately Amazon has thought of that and now provides a cover-making app as part of the submission process. You pick an image, color scheme, layout, type, and punch the button. This is what came out:


Well, it doesn't say Look Inside or kindle edition, that's just how they display covers. I'm sure anyone could do better, but it does convey the message of title, author, and that the book is for people who like to type a lot.

One of the things I like about Amazon is that they let you take a peek at the book. So if you click on it, you can see the table of contents and the first few chapters, all the way to part of the first chapter on Canvas!

You can even see the names of the people I thanked for help on this book:

Panagiotis Astithas
Dietrich Ayala
Richard Blechinger
@Boot2Gecko
M. Edward (Ed) Borasky
Monique Brunel
Asa Dotzler
@eliazerk
Robert Helmer
Nicolas Hoizey
Andre Jaenisch
Christer Kaitila
Ben Kelly
Andrzej Mazur
Vivien Nicolas
@nyrrrr
Ivano Palmentieri
Planet Firefox OS
Marek Raida
Eric Shepherd
Joshua Smith
Gabriele Svelto
Gabriele Vidali

One of the wonderful things about the Firefox OS community is how helpful people really are and I definitely appreciate any and all feedback for what I do. Sometimes the help is telling me I made a mistake or need to know that  Local Storage isn't recommended or just for inspiring me in some way. Again, thank you for helping me to produce a book!

When I uploaded the book to Amazon, I was surprised when it said the book was 402 pages (estimated). I knew that the word count was 49,000 words, which would usually be a 400 page book of straight text, but my book has a LOT of pictures and screenshots. So maybe pictures are 1000 words.

What's Next?

In terms of the book, I'm going to fix a few formatting errors (more about that in a minute) and then submit it to the new Amazon CreateSpace service that lets you create print-on-demand paper books that can be sold through Amazon. You can read about it here: https://www.createspace.com/. While I like eBooks for programming (so I can flip back and forth when I'm coding but keep my hands on the keyboard), there is something nice about a paperback. Who knows, maybe a book publisher would like to publish it.

I'm also thinking about putting it on Nook. I like Barnes & Noble and there might be some people there who are interested in Firefox OS.

I investigated some of the other eBook publishing services and here is what I am seeing:

Google Play

I couldn't get a lot of details without signing up, but the word on the street is that they don't have a lot of people looking for books and they might take a bigger cut. I'll pass for now.

Apple iTunes

While it might be amusing to publish on Apple when my motto is "Stay tuned, but not iTuned" I don't like that you must use a Mac to publish with them. I have a Mac Mini but it's packed away. You also have to use their special formatting tool, so more work for me.

Leanpub

A few people suggested them and I investigated and was drawn up short. To publish with them, you must use Markdown. I really don't want to spend weeks reformatting my manuscript for them. They look interesting and they publish a lot of works in progress. This might be a good place to buy. Check them out at https://leanpub.com/

There are other markets, and if you know of something great, let me know. I'm interested in finding people who are interested in Firefox OS. Part of the magic of FxOS (the official acronym) is that it is aimed at people who may not have programmed before and is reaching out to a new world-wide audience.

Speaking of which, my book is available (in English) in these countries through Amazon:

Andorra
Australia
Austria
Belgium
Brazil
Canada
France
Great Britain
Guernsey
Germany
India
Italy
Isle of Man
Japan
Jersey
Lichtenstein
Luxembourg
Monaco
Mexico
New Zealand
San Marino
Switzerland
Spain
United Kingdom
United States
Vatican City

How I Did It

Well, I just wrote a blog and pulled together some of the posts. I never intended to make a book, but as the blog grew and the content was driving to include all the things you need to make a game for Firefox OS, I felt like maybe I could do a book. I wasn't sure it would work and the formatting issues sounded like a big hassle.

Part of the problem is that Amazon Kindle has changed what they require over the years and so there's a lot of misinformation. Also, because this blog is in Google Blogger which has its own formatting issues, I just wasn't sure how to proceed.

Here is what I did and I'm pretty happy with the results. In fact, I feared worse!

Step 1 - LibreOffice

The first step was to read up a lot. Some said to convert your book to HTML others said to use Microsoft Word. Well I obviously know HTML, but I didn't want to spend hours formatting that. Microsoft Word I know how to use but don't like it. Then I decided to give LibreOffice a try and I loved it. LibreOffice (a fork of OpenOffice) is at version 4.2 right now and it is really fast and efficient and is actually a lot easier to use than Word. The problem with Word is that they have a lot of legacy to support so they can't really make sweeping changes. Furthermore, each version of Word is really different but because they want money, I can't afford to upgrade every copy on every machine. On my various machines I have Office 2003, 2010, 2013, and Office365. But I also can put LibreOffice 4.2 on every machine and upgrade them all if there is a major change. LibreOffice will save to a .DOC format that is compatible with several versions of Office. That seemed like a safe bet.

Step 2 - Lay Out the Book

I had an outline based on my blog posts. I then created a title page, copyright page, etc. (known as front matter) and for each of those pages, I ended them with a page break. Next I created page breaks for each chapter and made each chapter title a Heading 1.

Once I did that, LibreOffice has a feature that lets you create a table of contents by using all those Heading 1 chapter titles. I put that between the front matter and the first chapter and it looks good! The table of contents then becomes a set of links for each chapter. To me, a programming book must have a table of contents! You don't need an index because you can search through the eBook.

I just used default formatting for the text and that seemed to work out all right. I used bold and italic when needed, and I had heard that Amazon doesn't like bulleted lists, so every list is a numbered list and not done with automatic numbering, just by hand.

I then copied-and-pasted each blog post to a text file (to remove any hidden Blogger characters) and then copied-and-pasted the pure text into LibreOffice.

And of course, I did some editing, removed parts that were extra, and in general thought about what was there and would it be useful. Writing a blog is one thing, but writing a book is to a wider audience. 

Step 3 - The Code

One of the trickiest parts of a programming book is to format the code. Not only must you make sure that the code is mono-spaced (like a typewriter) but you don't want the code lines to break in unexpected places. One of the things I did (and it was a pain) was to format all my code so it is only 45 characters wide. I did this originally so it would fit nicely in Blogger, but it also fits nicely on Kindle, at least in the Kindle Reader software on my desktop.

LibreOffice can format text as Paragraph and also as Character styles, and I did both for the code. Kindle seemed to pick up on it. I wanted the code to be mono-spaced and bold and 45 characters and it is! This book is all about code!

Step 4 - Pictures

This book had a lot of pictures. Someone else can count them up, but almost every post has screenshots or other helpful material. In my posts I often have clipart that is just a fun decoration, but I didn't bring them over to Kindle. But I did need the screenshots!

Those I formatted as centered and aligned to the bottom, and with no wrap for text. All my pictures were .PNG and Amazon seems to like those (I think it converts them to .JPG).

Step 5 - Upload

I already had an Amazon account. I went to https://kdp.amazon.com/ and got started. They wanted information and none of it was hard to figure out what they wanted. There were choices about pricing and royalties, name, tax stuff, etc. I then made a cover and uploaded my manuscript.

A few minutes later, the book was published and I'm there.

Promote Firefox OS

One of the main reasons to do this book is to help promote Firefox OS and show people how easy it is to program. Especially games, which are a big driver of adoption for an OS. If you want to tweet or blog about my book, that would be great. I don't know how to do reviewer copies, but maybe you do. Anything that we can do to tell the world that programming games on Firefox OS is fun and easy will help. I know nothing about promoting a book or anything, I'm just a retired engineer who likes to code. And really likes Firefox OS!

Wednesday, March 5, 2014

HTML5 Game Frameworks (Game Programming)

HTML5 game frameworks is an interesting subject. There are dozens of them around, all promising to make game programming easy. Personally I'm interested in using just HTML5, CSS, JavaScript, and CSS. But there are two frameworks I thought I should mention that work in Firefox OS.

Construct 2

Construct 2, by Scirra, has been around a lot and is perfect for people who want to make HTML5 games but don't want to do all the coding. You can learn all about Construct 2 at https://www.scirra.com/.

Basically you drag and drop bits, choose behaviors from menus, and build your game. I've tried almost all applications like this and Construct 2 is the best. Why? Because they seem to have the best community and they are very transparent about what they do and why. Run by two brothers in London, Ashley and Thomas Gullen, you feel like they are responsive to problems and their forum is legendary for people (not just Ashley and Thomas) helping you out if you get stuck. They have a ton of tutorials and their engine is updated frequently.

The cost is reasonable. You can buy if for 79 pounds if you are not a professional, and 259 pounds if you are, the difference being how much money you make from their product. I can't say enough of how helpful they are, and how advanced as well. They're really on top of things like WebGL and they export the games you make to the following targets:

Web (HTML5), Wii U, iOS, Android, Win 8, Win 8 Phone, Windows desktop, Mac, Linux, Blackberry 10, Firefox Marketplace, Tizen, Facebook, Chrome Web Store, Amazon Appstore!
Just for fun (and as part of some long-forgotten contest), I put an app in the Chrome Web Store and it was very easy to create, even though it has an odd format. You can check out its fabulous features here: https://chrome.google.com/webstore/detail/tilt-a-twirl/klabggekijaanbjbakdimcdikdhihhdn?hl=en-US.

If writing code freaks you out, you probably aren't reading this, but if you have a friend who doesn't code but who wants to make games, go for it! Construct 2 is also used a lot in the industry for prototyping bigger games. And the best part is that you can put your games in the Firefox OS Marketplace!

Phaser

I haven't had a chance to try out Phaser, but it is getting a lot of notice. I'd place it somewhere between hand-coding and Construct 2. You still code, but you use Phaser to do the heavy lifting, and it adds things that would be very hard to do in raw code, like Physics.

Check out Phaser here: http://www.photonstorm.com/phaser. The main honcho is Richard Davey and he seems very helpful. Again, like Construct 2, there are lots of tutorials and the community is very active and the updates are frequent. I'm hoping to try out Phaser pretty soon and see how well it likes Firefox OS, but Mr. Davey says it will work in Firefox OS and if anyone has done this, let me know.

A Game A Week

I'm a proud member of the One Game A Month jam at http://www.onegameamonth.com/ but I recently ran across a site where someone is doing one game a week! I was doubtful at first. After all, many can do a game jam in a weekend, but they often are wasted afterward and the pace isn't easy to keep up!

But this weekly site, called http://www.lessmilk.com/. The author, one Thomas Palef, has been doing a game a week for a few months and the games are cool. As I dug a little deeper, I found that he's coding in Phaser. This is a very, very good argument for using Phaser if you want to code fast.

He also walks you through a two-part tutorial on making an Angry Birds clone. I fear that this will be the new standard for simple gaming, but who am I to complain? He also had a nice short article on pixel art at http://blog.lessmilk.com/pixel-art-how-i-made-the-princess-in-game-6/. This is a person to watch.

I was amused that he said
Since I started this project I've received a lot of supportive emails, which is awesome. But there's more: I've also had emails that have opened up new opportunities for me:
  • I got a job offer from a big company
  • A publisher contacted me to buy some of my games
  • A small company wants me to build them exclusive games
  • A couple of indie teams want me to help them as a game designer on some interesting projects
  • I even got contacted by a PhD student who wants me to help him with his thesis
So if you want a job in the game industry, just do something cool and people will come to you!

Right now I'm happy doing this blog and preparing my book, but I expect Mr. Palef to be a rising star!

My Book

I've revised about two thirds of the posts I want to use for my book and things are going along smoothly. I'm finding that there is a lot of details to follow to format it so Amazon will like it, and with any luck I'll finish in about two weeks.

I'm hoping that my book will help get the word out that Firefox OS is easy to program and fun! I appreciate all the offers I've had to help publicize the book and I'll be looking to see if I can also put it on Nook, Google Books, and Leanpub. Maybe I should put it in the Apple store for amusement. After all, when the iPhone came out, Steve Jobs wanted everyone to write apps in HTML5!

I'll keep you posted!

Twitter

I've been having a lot of fun discovering Twitter. I never used it before starting this blog, and my thought was that it might be a good way to let people know that there was a blog on Firefox OS game programming and game playing. But I've since found out that it is a fun way to find out what's going on in the worlds I care about: Firefox OS and game programming.

Yesterday Twitter told me I couldn't follow any more people! It turns out they don't want you to follow more than 2000 people, so I've been unfollowing a few people who had followed me but who weren't tweeting things I was interested in. And if I want to follow people who I discover, I'll have to unfollow someone else.

So right now, if I follow you because of Firefox OS, I won't ever unfollow you. Same goes with any HTML5 game programmers. And also any game programmers that do pixel art or otherwise something that catches my attention (like ASCII Art). And an occasional odd person that has something interesting. And definitely not anyone who can sell me how get more followers or how to maximize my web site profits!

Right now I have 798 followers, but I'm not seeking followers unless you like Firefox OS game programming and game playing or Firefox in general or Pixel Art games or ASCII Art games or goofy game developers like the people who hang out at @OneGameAMonth or, well, you get the idea.

2000 tweets, 2000 follows, 798 followers.

Oh, and this blog has had a total of 23,000 views. The most popular page was on Device Orientation, which is definitely a cool subject. Second-most was my comparison of CSS, Canvas, and SVG, and third was IndexedDB.

Not surprising, most of my readers are in the USA:

United States
11512
France
1003
Germany
995
United Kingdom
536
Brazil
511
Spain
459
Canada
351
Ukraine
344
Italy
329
Serbia
148

Browsers weren't a surprise:

Firefox
12171 (52%)
Chrome
4884 (21%)
Safari
2710 (11%)
Internet Explorer
2134 (9%)

And Operating Systems wasn't too surprising:

Windows
10148 (44%)
Macintosh
6857 (29%)
Linux
2705 (11%)
Android
1246 (5%)

I appreciate every single one of you that takes the time to read what I write and I intend to keep going. As I said last time, I'm torn between these next paths:

1. Advanced topics like WebGL, WebAudio, WebSockets, WebWorkers, etc.

2. Going back and fleshing out more about how to use CSS for gaming.

3. Writing a series that leads to a full RPG!

4. Doing lots more with SVG, the undiscovered country.

5. More about creating music and art.

6. Making games in Construct 2 and/or Phaser.

7. There is no 7!

8. Working with servers. Node and MMORPG.
If anyone has any requests, let me know!

Well, I guess I'd better flip some coins and get back to work on reformatting and rewriting my book.