Pages

Thursday, January 30, 2014

Sanctuary RPG (Game Review)

The purpose of this blog is to talk about Firefox OS games and game programming. However, every once in a while a game tickles my fancy just the right way and so I'm going to review a game that is only on Windows!

What is so special about Sanctuary RPG? Well, for one thing, the graphics are all in ASCII (or is it ANSI)? Making 3D games seem to me a lot easier, but there's something really cool about people like Black Shell Games. Crazy is also another word, but I prefer awesome when talking about ASCII graphics. And mix that with RPG and you get some fun stuff.

You can get this game, which is in Beta but is almost finished (version 0.92), from http://www.sanctuaryrpg.com. It hasn't actually been released, but they are looking for an official release around March 30. The cost is 100% free and donations are optional. (Simply click on "No Thanks" in the download prompt.) The minimum donation was $1 but I was happy give more. If you give enough, they'll make you a producer (which will impress your friends and you can put it in your resume or CV)!

Boot it up and here's what you see.


Press that Any key on your keyboard and you get this:


The ASCII art here really looks smooth and descriptive. Continue on to:






Please forgive the formatting. I had to make these screens big enough to read, so they stick out on the right side of the blog and cover up some of the outside text. But I like this enough to make it so you can read the text and admire the ASCII art.

Why do I like this so much? Well, it reminds me of a series of games for the Apple II called EAMON. In 1980, a madman named Donald Brown created a game called EAMON, but he made it into an engine and invited other people to create games with it. One of the cool features was that you could build up your character and play other games using equipment from earlier EAMON games you played. Sometimes that might mean you had a ray gun that you could use to mow down barbarians with, but it was relatively balance. There were about 200 EAMON adventures, but I had at least 50. That was back in the day when you didn't download things but sent away for floppies filled with games from a catalog. Sanctuary RPG isn't a game engine (yet) but it has the spirit of those early days and uses some nice ASCII art to wrap it in.

All this has made me think that it might be fun to create an RPG like Sanctuary and put it in the Firefox OS Marketplace. Maybe even make an engine! So I'll think about this, and if anyone knows of any text adventure games in the Marketplace, I'll review them for sure.

But on to this really well-done RPG that should be in the Marketplace. I wonder what it was written in. The original EAMON was written in Apple BASIC. But JavaScript is the new BASIC, but 1000 times better.

Back to Sanctuary RPG (or sRPG as they call it). Pick a Campaign by clicking on 1 and pressing Enter.


You choose the type of person you want to be. I always pick Barbarian for any new game and often call him Jughead. In this screen I had already picked Jughead, and am going to pick a new class. There are 6 choices. How about Paladin?


Ah, yes, Paladins are always angsty! No one understands them! But they have perks!


And


There's more than a bit of complication here, but remember, if you don't like your character, you can always roll another. Anyway, you then choose a gender and a name, and then how difficult do you want this to be.


So you can recover from death, but you get 10% less loot. Interesting choice! You then choose a category for your race


And then a race to go with it.




I picked Paladin and now I must pick a race. Not just D&D! So I picked a Silian. I like the subtle humor here. "Machine, robot, and biological; one of these they are not." How cool is that. My guess is that the Silians are robot machines!

Then you can get a nice introduction to the story. It has to do with a magic sword:


And someone named Cynthia who wanted it ... badly!


She gets the sword and becomes a monster. So a guy named Cyrus the Magnificent (really!) tries to stop her.


 Oops, it didn't work!



Cyrus is dead (or is he?)  So you must stop her. But you have some help from a mysterious stranger.


She gives you a key, gold, and a weapon.

And now the game begins. Here's a typical screen.


You'll travel, battle, find loot, and save the world from Cynthia (now known as the Matron). I really like this game and find it strangely inspiring. Text-based adventures could have a place on the phone, though the beautiful ASCII art is beyond me (though I seem to remember some programs that will convert a photo to ASCII art, so maybe ....

Cost: free (donations accepted). This game is still in Beta!
Genre: ASCII RPG
Score: 5 (out of 5)
Tested on: PC
Get it at: http://www.sanctuaryrpg.com

PS: you can also get the soundtrack for this game (a very cool one) by Rafael Smith at http://rafaelsmith.bandcamp.com/album/srpg-the-original-soundtrack for $3 or more.  43 songs!!!

Monday, January 27, 2014

Color Balls (Game Review)

Color Balls is an easy-to-learn, difficult-to-master game that is peaceful and soothing. All you do is move colored balls around on the screen. The goal is to get five balls of the same color in a row. But that's not always easy, which makes this a good puzzle game.


Tap Play and you'll get a different opening screen every time. Here is one:


You'll notice that this game is made by Zielok.com. They make Android and HTML5 games and they are cool enough to share their source code at http://www.zielok.com/source/colorballs5source.zip. Also, not shown in the screen shot, is a little notice at the bottom of the screen that says "Made with Tulaloo Game Maker." I've never heard of them, but Tulaloo looks like an interesting HTML5 game engine and it works in Windows, Mac, and (yay!) Linux. Check them out at http://www.tululoo.com/. I'm getting interested in some of the more popular HTML5 game making applications, and hope to do some blog posts on Scirra Construct 2, Phaser, and Tululoo! I still like HTML5, JavaScript, CSS, and SVG as my weapons of choice, but I hearing good things about some of these engines.

So how does this game play? In the screen above, you have some random balls. You move by tapping on an existing ball and then tap where you want it to go. Here my second move:


Two dark blue balls now next to each other. I'm going to attempt to build down. But ...

The game moves. And I'm blocked by a light green ball.


Well, maybe I can take advantage of that! I now will try to make a light green row horizontally.



And the computer makes a move. But I keep going!


One more ball. The computer can't stop me. I place 5 in a row and they vanish and my score is now 31. And so it goes.


When you can't play any more, tap the "End Game" button at the top right and see your final score. Simple but cool.

I like simple puzzle games like this and I like even more when someone shares the source code and yet even more when they use a game engine and tell us about it! So this game gets the R5!

Cost: Free
Genre: Puzzle
Score: 5 (out of 5)
Tested on: Geeksphone Peak (Firefox OS)
Get it at: Firefox Marketplace

Tuesday, January 21, 2014

Craigen (Game Review)

Feels like forever since I reviewed a game, but really it was only three big posts in a row that weren't games (Paddlefox, APC Rock, Submitting to the Marketplace) but before that I would do a game review between every programming/hardware post. Well, now the games are piling up in Thulfram Towers and yet there are hot things going on with the Rock and I'm almost ready to update my ZTE Open! But that's not what today is about. Today is the telling of the great tale of brave Craigen, noble warrior of Poland and Enclave Games!


Craigen is a barbarian hero who must cross the Dragon Pass and defeat orcs. Why? Well, here's the story of Craigen, starting at a local inn (in medieval Poland?)


You don't want to skip past his tale. And his need for ale.


Barbarians need their ale, that's for sure!


Those pesky orcs have done it again! Something must be done. And Craigen is the one to do it.


And so begins the game. I love it when someone makes a story for a game, even as simple as this one is. And the art is really fun. The artists at Enclave have a really good sense of the absurd. In case you don't remember, Enclave are the people who brought you Captain Rogers.


From the far future to the distant past, Enclave has it covered. Where will their next game take place?

One of the things that I really like about Enclave is that they are really thinking about what works on a phone. What is touch? What happens when there is no keyboard or mouse?  In Captain Rogers, you did everything with one finger (more than one gets awkward on a phone).

Here are the Captain Rogers instructions:


One finger. Tap to go up, release to go down. I had trouble adapting to this, but at the same time, I admire the innovation and think there's something great in the making with phone games and Enclave is leading the charge.

With our barbarian hero Craigen, the instructions are a little different, but again, very innovative.


Tap on the left to jump and tap on the right to slash with your sword. Simple, clean, and fast. Of course, you have to get used to this, but that's the point of innovation. This is a "runner" type game. You run from the left to the right and you must keep going. But watch out for ditches!

Here's Craigen, about ready to jump over a ditch.


If he misses and falls in the ditch, it's Game Over.


But it's not just jumping, you can (and must kill). You'll run into all kinds of monsters, like this guy. Slash before he gets you. Hurry!


This game is tough! In the shot above, Craigen has to jump up and then slash the skeleton fast!

One nice thing about this game is that there is a button on the right to turn off the cool music, and a button on the left to Pause.


You'll want to pause to take a breath and plan your next action, because there are a lot of ditches and monsters.

I've been playing a lot of early and middle Mario games and this game reminds me of them in a good way. You have to plan your next moves and react fast. There's lots of challenge and this is something you can play again and again, trying to get to the ale. I haven't made it there yet, but I'll keep trying.

This is just a perfectly fun game and I want to see more from Enclave.

Cost: Free
Genre: Runner
Score: 5 (out of 5)
Tested on: Geeksphone Peak (Firefox OS)
Get it at: Firefox Marketplace

Monday, January 20, 2014

Submitting an App (Game Programming)

I just submitted an app to the Firefox OS Marketplace and so can you! The app hasn't been accepted yet, and when I submitted it, my response was that I am 88 in a queue of 88 and that the estimated working time is 3 working days. How exciting!

I decided to submit my PaddleFox game that I wrote about at http://firefoxosgaming.blogspot.com/2014/01/paddlefox-game-programming.html.  The app is a very simple game that lets you hit a ball with a paddle. This game was a culmination of several posts and (very soon) I will have a page that lists the various technologies I write about. Essentially it uses SVG to create and move a ball and paddle, and uses the SVG getBBox method to detect collisions.

Here is what PaddleFox looks like:



Just so you know, I put this in the Marketplace as a free game. I intend to improve it in various ways as time goes on, and as soon as I figure out a way to get a web site and put it there, I'll also enter it in the One Game A Month site because the #1GAM people are really fun. I'm sure I'm the worst, but I'm shooting for doing all or part of one game a month for this blog, so why not?

Firefox OS Marketplace

Really, putting your game in the Firefox OS Marketplace is pretty easy. Prepare your app, make some icons, make a manifest, and submit it. If something goes wrong in the process, you can do it until it works.

The Application

My application was a simple 1-page HTML5 file and you can see the code and my explanation here: http://firefoxosgaming.blogspot.com/2014/01/paddlefox-game-programming.html. 268 lines of code with no bitmaps. I didn't do any music or sound effects because I wanted to keep it simple.

The Manifest

The manifest is a text file called manifest.webapp. This is a structured JSON file that specifies what the app does. I didn't have any special code that needed permissions. You just specify the name of the app and a short description, the launch path, who you are, and the language you support.

Here's mine:

{
  "name": "Paddlefox",
  "description": "Hit the ball with the paddle",
  "launch_path": "/index.html",
  "icons": {
    "60": "/icons/FB-60.png",
    "90": "/icons/FB-90.png",  
    "120": "/icons/FB-120.png",
    "128": "/icons/FB-128.png"   
  },
  "developer": {
    "name": "Bob Thulfram",
    "url": "http://firefoxosgaming.blogspot.com"
  },
  "default_locale": "en"
}


Here's the info from Mozilla Developer Network on manifests: https://developer.mozilla.org/en-US/Apps/Developing/Manifest. This text file uses a JSON format for the data. Here is the JSON specification http://json.org/ and in case you wanted to know, JSON stands for JavaScript Object Notation.

You don't really need to be an expert at JSON, but follow the examples and be sure you put the commas and brackets in the right place. And make sure that your paths and names are correct, especially for the icons!

Icons

You'll notice in the manifest above there are 4 icons. I got a warning saying I should have added 2 more sizes, but I got errors until I added the four I did. Originally there were only two icons you had to have, but now you must do the four sizes above (60, 90, 120, and 128). The optional ones are 32x32 and 256x256!

Here's my 128x128 pixel icon:


How did I make it? Well, no artists were involved, that's for sure. The most important part of my icon adventure was going here: http://www.mozilla.org/en-US/styleguide/products/firefox-os/icons/. That is part of the Mozilla style guide that shows you some of the issues with icons. The important part was the download at the bottom. All I did was to download the templates, load them into a pixel art editor, and make some changes. I used Paint Shop Pro but you can use Photoshop or anything else. I used Paint Shop Pro because I wanted to do some layers. I took the template, spilled some pixels of a different color on it, smeared things around, and slapped some type on top. I'm sure a monkey could do better. I did one icon at 128x128 and then resized the other three, making a total of 4 icons in all.

Once I had the HTML5 page (index.html) in the root of a folder and the manifest at the same level, and the icons in a folder below that, the next step was to zip them up. I used 7Zip but there are plenty of other zip file makers.

So, armed with a zip file containing my web page, manifest,and 4 icons, I then went to the Marketplace. But before I went, I read this great article on MDN: https://developer.mozilla.org/en-US/Marketplace/Submission/Submitting_an_app on submitting an app.

Submission

You submit your apps starting here: https://marketplace.firefox.com/developers/submit/. Actually, the first thing you should do is to get a Mozilla Persona account. Read about that here and get one https://login.persona.org/. You'll need it anyway if you want to buy an app later. Make one, buy one! You can read about how I signed up for Persona at http://firefoxosgaming.blogspot.com/2014/01/heroine-dusk-game-review.html.

Now that you have a Persona, sign in and accept the terms of working with the Marketplace. Then you go to a page that lets you choose what kind of app you want to submit. The first choice is free or paid/in-app-purchases.

Then you pick the hardware you want your app to run on.
  • Phone
  • Firefox Desktop
  • Firefox on Android
  • Tablet
I noticed that they didn't list the VIA APC yet!

Then the choice is packaged app or hosted. Packaged apps are zipped up and submitted to the Marketplace. Hosted apps are hosted on a web site you own. Some of these choices are made for you, depending on what you pick.

If you want paid/in-app-purchases, you must (at this time) only supply apps for the phone.You can choose to be packaged or hosted. If you want your app to be free, and you choose phone, you can be hosted or packaged. But if you want to do apps for the desktop, android,and tablet, not just phone, you can only be hosted and you must be free! Sound complicated, but when you get there, the buttons will only let you choose certain options, so know what you want before you go.

I chose phone, packaged, and free, because that's the easiest. That's what I wanted anyway.

Once you've made your choices, there's a button to click that lets you select the file you want to submit. One file, it must be zip, it must have a manifest, icons, and ... your app!

Then, if you did everything right, your file will pass the tests. I had some problems with the icons (not enough) and the JSON notation (commas) but each time I failed, I could go back, fix whatever was wrong, and then resubmit right there.

I did get a warning that they wanted those two other icons, but they weren't required. I also got a warning that my submission failed the CSP (Content Security Policy). The rules for CSP are here: https://developer.mozilla.org/en-US/Apps/CSP.

It gave me line number in my index.html, 28, and the contents of that line:

  <script>

I think this is telling me that I should put my JavaScript stuff in a separate file instead of between two script tags in the head. But it was only a warning so I'll research more and fix it when I submit improvements (unless it fails in the final submission process). They're very careful about not allowing JavaScript to be a vector for evil things.

Once I only had warnings, I went on. A few more questions. They wanted my privacy statement (I said I'm not gathering data or using it - but they have a nice template if you do something more complicated). They also wanted a description of the app, a web site, and an email for support. I did all of that, and then one last (easy) step.

They had a few questions to determine the age rating. My app had nothing that would offend anyone, so I just said no to all the questions and now have a certificate that was automatically placed in my submission saying that my game is safe for all ages.

Then I pushed the final button and got the notice that I'll be in the store when I go through that 88 person queue. I'll be curious how long it really takes. Let me know if you see my app in the store and I'll put a comment here and tweet about it.

By the way, now it says 88 out of 100 which means I didn't move forward in the line, but more people are piling up behind me!

Friday, January 17, 2014

APC Rock (Hardware Review)

I'll add more bits about this as I discover more, but the Fox has landed!


I had a little trouble yesterday because all I had was a VGA cable, but today I managed to find a HDMI to DVI and when I turned it on, the above screen appeared. It's the Firefox OS lock screen for PC. (Don't know if that's the official name.)

Swipe with your mouse to get this:


And again for the next screen.

How cool is that? The picture is a little fuzzy because I took it with my Geeksphone Peak.

I don't know how to take screen shots or even load an app on to this and I don't have WiFi hooked up, but the Fox has defnitely landed!

And a bargain at $59 US. Their site says $79 but that's a mistake. They answer email! And the shipping was fast (and I think maybe another $25 from Taiwan to the Seattle). Who are they? Why, this wonderful device is called the ASR Rock and it is made by the folks at VIA. I've known about VIA for several years and have a few computers made by them. Their specialty (among others) is making x86 Intel-compatible chips. The computers I had were about the size of a hardcover book and they sell this board for $99 with a book-like enclosure.

If you want to know more, check out http://apc.io/products/rock/. Essentially this is a single-board computer that is about the size of a phone. It comes with a power supply and not much else. But it does come with Firefox OS and a metal shield to fit inside a computer case. The board is compatible with the Neo-ITX form factor, which  is compatible with Mini-ITX and MicroATX. (That's geek for small form factor cases.) The board is bigger than a Raspberry Pi but very similar in concept except it boots Firefox OS! All I did was plug in the power, plug in the HDMI, plug in a USB keyboard and mouse, and I now have a Firefox OS PC and two Firefox OS Phones (ZTE Open and Geeksphone Peak).

This Changes Everything

A few days ago, Andre Jaenisch wanted to know why I was using absolute positioning when this isn't considered (by many) to be a best practice. I'm so used to doing this that I needed to think more about this.

Absolute positioning was needed the way I was using text elements mixed with SVG. One of the fundamental issues of writing games in a browser is that you have to be very aware of the display flow of the elements in a browser. Usually what you type is what you get, but once you start calculating and mixing different kinds of elements, you have to be careful. In that example, I had put the text in the body and then the SVG in the JavaScript code. It looked great in the desktop browser, but on the phone the bottom half of the SVG pane was cut off. The Head and Paragraph elements had pushed it down!

The answer was to take the text elements out of the browser flow and slap them down on top of the SVG pane, which was meant to take up the whole phone screen. So that's why I did it there, but now my head is spinning, realizing that the game is changing.

When I started a few months ago, it looked like the phone would be the main outlet for Firefox OS, and the screen size was the same for the first few phones. So I targeted that, never dreaming that those speedy Firefox boys and girls were working day and night behind the scenes to bring more goodies.

So now the Firefox OS PC (is it a PC? The chip is VIA ARM (no Intel here) but it can fit in a PC box and use PC peripherals. How soon will I be writing my blog on that?

And just last week the Firefox OS tablet was announced and the first tablets are now being tossed around at Firefox towers in the UK, courtesy of Foxconn (is this the beginning of the Fox conspiracy?)

What next? Laptops? FoxBooks? FoxWatches? Where's my Fox Toothbrush?

Anyway, Andre, I'll now think about making responsive games. Right now I'm concerned with making very simple games that show basic principles, so I don't want to add any extra of anything. I'm not teaching computer science, I'm showing how to make some games for Firefox OS. Same reason I use globals -- they make the code more efficient for small games. But in a big game with many screens, globals might not be a good idea, and name spaces are very important (SVG uses namespaces).

But now I am thinking about it. A game like PaddleFox would be easy to adapt, but an RPG might be more difficult. Responsive design is growing very fast and SVG can be part of it. But there's an even newer slant called adaptive design that is somewhat similar but instead of just changing the width and height, it displays different information depending on the device. So your watch gets one set of data and your Firefox OS PC gets another. Something to think about.

Now to get back to getting the wireless running on my APC Rock!

Wednesday, January 15, 2014

PaddleFox (Game Programming)

One of the simplest games to create is a variation of Pong that is based on the real-life sport of Racquetball. You can play by yourself and don't need a partner. Just slam the ball against a court made of three walls and bat it back and forth. I wanted to be more unique to choose a name for this game, so after some thought and research, I picked PaddleFox.

Why pick a name? Part of this series of posts is to create real games, and right now seems like a good time to pull together a lot of the technologies I've been exploring to make a "real" game and see how to put it in the store. This isn't going to be the greatest game in the marketplace and I certainly wouldn't charge money for it. I might expand on it later. There's an absolutely fabulous game I do love that is on the Android called Juggle by those wizards of Dundee, Scotland, known as Denki. I recommend it and I'd like to try something like it as I build up more skill. (Essentially it is similar to the game I'm building today, but introduces more balls and different sized ones.)

I'll see about submitting this game to the Firefox OS Marketplace and keep you posted. As I improve it over time, I'll let you know about that too. But I also have lots more game techniques I want to explore that aren't about bouncing balls, and can't wait to get going on a space shooter, a platform game, and a lite RPG.

But on to today's game. There's a ball, there's a paddle, and that's it. Hit the ball and it bounces off. Miss the ball and the game is over (but you don't need a quarter to play over again). This game uses SVG, but you can do the same game by using the corresponding bouncing ball and collision techniques I wrote about for CSS and Canvas.

Here is ... PaddleFox!


Tested and run on a Geeksphone Peak, my new pride and joy. I feel guilty not playing with my ZTE Open. I know it is sitting in the corner missing me, but I'm hoping to get back to it when I can safely upgrade to Firefox OS 1.3 so I can start using the App Manager.

Basically this game combines the bouncing ball technology of creating SVG with JavaScript and the SVG DOM with the Collision Detection built into SVG with getBBox with a touch of Touch! SVG is still a largely undiscovered country for game programming (but see a good one in esviji).

So, here's the code:

<!DOCTYPE HTML>
<html>
  <head>
    <meta charset="utf-8">
    <title>
      PaddleFox
    </title>
   
    <style>
   
    #myHead
    {
      position:absolute;
      top: 10px;
      left: 10px;
    }
   
    #myPara
   
    {
      position:absolute;
      top: 60px;
      left: 10px;
    }
   
    </style>
    
    <script>

      // --- Global variables ---

      // Width and height of board in pixels
      var boardWidth = 320;
      var boardHeight = 460;
      var boardWidthPixels = boardWidth + "px";
      var boardHeightPixels = boardHeight + "px";
     
      var padMove = 20;  // Amount the paddle moves.
      var score = 0;     // Initial score.

      // URL for W3C definition of SVG elements
      var svgURL = "http://www.w3.org/2000/svg";
          
      // Variables for ball initial position.
      var ballHor = boardWidth / 2 - 20;
      var ballVer = 50;
      var ballHorPixels = ballHor + "px";
      var ballVerPixels = ballVer + "px";
     
      // Amount of vertical and horizontal change.
      // Think of this is a vector. Speed + direction.
      var changeHor = 5;
      var changeVer = 5;
     
        // Covers all versions of requestAnimationFrame.
        window.requestAnimationFrame =
        window.requestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.msRequestAnimationFrame; 
     
      // Page load event listener.
      window.addEventListener("load",
        runFirst, false);
       
      // Mousedown event listener.
      window.addEventListener(
        "mousedown", whereMouse, false);
                       
      // Runs when page loads.    
      function runFirst() { 

        // Define the game board as an SVG element.
        gameBoard =
          document.createElementNS(svgURL, "svg");
         
        // Width and height of the SVG board element.
        gameBoard.width.baseVal.valueAsString =
          boardWidthPixels;
        gameBoard.height.baseVal.valueAsString =
          boardHeightPixels;
         
        // You must append the board to the body.
        document.getElementById("pageBody").
          appendChild(gameBoard);
       
        // Define the ball as an SVG element.
        paddleBall =
          document.createElementNS(svgURL, "circle");
         
        // Width,  height, radius, and color of ball.
        paddleBall.cx.baseVal.valueAsString =
          ballHorPixels;
        paddleBall.cy.baseVal.valueAsString =
          ballVerPixels;
        paddleBall.r.baseVal.valueAsString =
          "10px";
        paddleBall.style.
          setProperty("fill","fuchsia","");
         
        // Attach the ball to the game board.
        gameBoard.appendChild(paddleBall);
       
        // Define the paddle.
        myPaddle =
          document.createElementNS(svgURL, "rect");
         
        // X, Y, width, height, and color of paddle.
        myPaddle.x.baseVal.valueAsString = "90px";
        myPaddle.y.baseVal.valueAsString = "400px";
        myPaddle.width.baseVal.valueAsString = "130px";
        myPaddle.height.baseVal.valueAsString = "20px";
        myPaddle.style.setProperty("fill", "darkcyan","");
       
        // Attach the paddle to the board.
        gameBoard.appendChild(myPaddle);
       
        // Color the page elements.
        pageBody.style.backgroundColor = "black";
        myHead.style.color = "red";
        myPara.style.color = "white";      
        
            // Start the game loop.
            gameLoop();
      }
       
      // Game loop. Runs as fast as it can.
    function gameLoop(){
     
            // Endless loop with requestAnimationFrame.
            requestAnimationFrame(gameLoop);
      
        // Move the ball.
        ballMove();        
    }
     
    // Move the ball.
    function ballMove() {
     
      // Changes are calculated but do not
      // take effect until next time through loop.
         
      // Calculate new vertical component.
      ballVer = ballVer + changeVer;

      // If top is hit, bounce off.
      if (ballVer + changeVer < 10)
        changeVer = -changeVer;
       
      // If bottom is hit, the game is over.
      if (ballVer + changeVer + 10 > boardHeight) {
        changeVer = -changeVer;
        // You missed!
        console.log("Hit bottom");
       
        // Game over - actions
        // Set the score to zero.
        score = 0;
        myPara.textContent = "Score = " + score;
       
        // Alert the player.
        alert("You missed the ball!  Start again");
       
        // Start over again.
        // Set ball position.
        ballHor = boardWidth / 2 - 20;
        ballVer = 50;
       
        // Set ball vector.
        changeHor = 5;
        changeVer = 5;
       
        // Set paddle position.
        myPaddle.setAttribute("x", "90px");
       
        // Exit here and don't do any more now.
        return;
      }

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

      // If left edge hit, bounce off.
      if (ballHor + changeHor < 10)
        changeHor = -changeHor;
       
      // If right edge is hit, bounce off.
      if (ballHor + changeHor + 10 > boardWidth)
        changeHor = -changeHor;
       
      // Does a collision take place with paddle?    
      // Get bounding box of ball.
      bbBall = paddleBall.getBBox();      
      // Get bounding box of paddle.
      bbPaddle = myPaddle.getBBox();        
     
      // Compare bounding boxes.   
      // Is the ball intersecting the paddle?
      // Four conditions must be met.
      if  ((bbBall.x > bbPaddle.x) &&
        (bbBall.x < (bbPaddle.x + 140)) &&
        (bbBall.y > bbPaddle.y) &&
        (bbBall.y < bbPaddle.y + 10)){
          console.log("HIT"); 
         
          // If hitting the paddle, reverse vertical.
          changeVer = -changeVer;
         
          // Make a small spin to create variation.
          spin = Math.floor((Math.random()*5)) - 2;
          // Add spin to horizontal vector.
          changeHor = changeHor + spin; 
         
          // Bounce ball up to untangle from paddle.
          ballVer = ballVer - 20;
         
          // Increase score.
          score = score + 1;
          myPara.textContent = "Score = " + score;
      }         

      // Draw the ball with new coordinates.
      paddleBall.cx.baseVal.valueAsString =
        ballHor + "px";
      paddleBall.cy.baseVal.valueAsString =
        ballVer + "px"; 
    }

    // Handle mousedown event.
    // Tap once each time to move paddle.
    function whereMouse(evt) {
   
      // Get mouse coordinates.
      mouseX = evt.clientX;
      mouseY = evt.clientY;
     
      // Current paddle position.
      oldX = myPaddle.x.baseVal.value;   
     
      // Calculate which side click is on.
      // If tap is on right of center.
      if (mouseX > 160) {
        newX = oldX + padMove;
        // If new x would go off screen.
        if (newX > 210)
          newX = oldX;
      }
      // If tap is on left side of center.
      else {
        newX = oldX - padMove;
        // If new x would go off screen.
        if (newX < 10)
          newX = oldX;
      }
     
      // Move paddle.
      myPaddle.setAttribute("x", newX);     
    }   

  </script>
</head>
   
<body id="pageBody">
<h1 id="myHead">PaddleFox</h1>
  <p id="myPara">Score = 0</p>
</body>

</html>


268 lines of code. That's not too many! Here's how it works.

Shell

I use a standard HTML5 shell. The minimum you need to tell the browser that you're talkin' HTML5 and UTF-8. Here's the layout I use, but all this is up to you. The HTML5 part is not. Even though it is not directly about SVG, my post on CSS Shell is a good starter.

In general, here's how my shell is laid out. You can also call this a template, but I like shells, and Susie sells them down by the seashore!
  1. HTML5 minimum code
  2. CSS
  3. Globals
  4. Event listeners
  5. Page Load event handler
  6. Game Loop
  7. Function blocks
  8. Other event handlers
  9. HTML UI code (if any)
The HTML5 and Globals should be easy enough to figure out. I use globals when I want something to be accessible in any event handler.

CSS

Sometime I use CSS and sometimes I don't. When you are using SVG (which has cousins in CSS on its mother's side), you can avoid CSS, but it's always there in the background, cooking up delicious meals. Here's today's CSS:

    <style>
   
    #myHead
    {
      position:absolute;
      top: 10px;
      left: 10px;
    }
   
    #myPara
   
    {
      position:absolute;
      top: 60px;
      left: 10px;
    }
   
    </style>


I use the CSS here to position the heading and paragraph. If you don't absolutely position these text elements, the SVG pane will be drawn after these, but this will make it go off the bottom of the screen! When doing games, you need to make sure that everything is absolutely positioned.  Just to be different, I colored these text elements in code a little later:

        pageBody.style.backgroundColor = "black";
        myHead.style.color = "red";
        myPara.style.color = "white";      


I did this in the page load. I'm actually more comforable with JavaScript than CSS, but I'm learning CSS fast.

Event Listeners

Games are usually all about events, and you need to listen for them. Here are the listeners:

       window.addEventListener("load",
        runFirst, false);
      
      // Mousedown event listener.
      window.addEventListener(
        "mousedown", whereMouse, false);

The first is listening for the page load event and the second is looking for a mouse down event. On Firefox OS, the mouse down event is what I use for simple touch. Your finger is a mouse! You want just the mouse down, not the click (which is mouse down plus mouse up). Fast and Firefoxy!

Page Load Event Handler

I throw in everything here that should happen before you start running the game. This includes:
  1. SVG definitions for the SVG pane, the ball (a circle), and the paddle (a rect). This is explained in the SVG post about SVG with JavaScript and the SVG DOM with the Collision Detection built into SVG with getBBox
     
  2. Whatever else I want to set up (coloring the text, in this case).
     
  3. A simple call to the game loop. Game loops govern the action cycle in an arcade game and they've been around forever. 
Game Loop

This is a simple game loop. It just loops around and around, governed by requestAnimationFrame. All it does is draw the ball (ballMove).

Function Block

The only function I have is (that isn't an event handler or the game loop) is the one that moves the ball. This function, ballMove, does most of the heavy lifting. It does the following things:
  1. Calculate the new ball position based on the changes you made the last time through the loop. This is a little goofy, but works. The loop is always processing what happened last time through. For example, if you hit a ball, you bounce, but the actual bounce doesn't happen until you come back again. Fortunately the game loop is bringing you back several times a second, depending on the negotiation between requestAnimationFrame and your browser. First the vertical component of your ball's vector (direction of travel and speed) is calculated, later the horizontal component follows.

    ballVer = ballVer + changeVer;
  2. A check is made to see if you hit the top of the screen. If you did, you bounce!

          if (ballVer + changeVer < 10)
            changeVer = -changeVer;

     
  3. Next a similar check is made to see if you hit the bottom of the screen. Oh, oh! You don't want to do that. If you did, the following actions take place: your score is reset to zero, the player is alerted, the ball is reset to its original position, so is the paddle, and then you return to the game loop without drawing the ball in this function block.

          if (ballVer + changeVer + 10 > boardHeight) {
            changeVer = -changeVer;

            console.log("Hit bottom");
           
            score = 0;
            myPara.textContent = "Score = " + score;
           
            alert("You missed the ball!  Start again");
           
            ballHor = boardWidth / 2 - 20;
            ballVer = 50;
           
            changeHor = 5;
            changeVer = 5;
           
            myPaddle.setAttribute("x", "90px");
           
            return;
  4. Next you do the same for horizontal positions. Bounce off the left and right walls.

          ballHor = ballHor + changeHor;

          if (ballHor + changeHor < 10)
            changeHor = -changeHor;
           
          if (ballHor + changeHor + 10 > boardWidth)
            changeHor = -changeHor;
  5. Now its time to see if the ball hits the paddle or not. This is a smart ball and does all the thinking. The paddle just moves (but elsewhere). This is a simple process. Get the bounding boxes of the ball and paddle. Even though the ball is round, a box can be used to determine collisions. Then once you get the bounding boxes, use their data to check a rectangle that sits on top of the box. If the ball enters that rectangle, a collision takes place. That collision will then make the ball reverse its vertical vector component, add a small random change to the horizontal vector component (called spin), pop the ball up a bit so it doesn't stay tangled in the paddle, and adds +1 to your score.

          bbBall = paddleBall.getBBox();      
          // Get bounding box of paddle.
          bbPaddle = myPaddle.getBBox();        
         
          // Compare bounding boxes.   
          // Is the ball intersecting the paddle?
          // Four conditions must be met.
          if  ((bbBall.x > bbPaddle.x) &&
            (bbBall.x < (bbPaddle.x + 140)) &&
            (bbBall.y > bbPaddle.y) &&
            (bbBall.y < bbPaddle.y + 10)){
              console.log("HIT"); 
             
              // If hitting the paddle, reverse vertical.
              changeVer = -changeVer;
             
              // Make a small spin to create variation.
              spin = Math.floor((Math.random()*5)) - 2;
              // Add spin to horizontal vector.
              changeHor = changeHor + spin; 
             
              // Bounce ball up to untangle from paddle.
              ballVer = ballVer - 20;
             
              // Increase score.
              score = score + 1;
              myPara.textContent = "Score = " + score;


    The only tricky part is the actual collision detection.

                if ((bbBall.x > bbPaddle.x) &&
            (bbBall.x < (bbPaddle.x + 140)) &&
            (bbBall.y > bbPaddle.y) &&
            (bbBall.y < bbPaddle.y + 10)){


    This checks four conditions to make sure that the ball's bounding box is inside the paddle's bounding box and uses the && to say that all four must happen to trigger the collision.
  6. Finally if you didn't hit the bottom of the screen, the ball is drawn.

          paddleBall.cx.baseVal.valueAsString =
            ballHor + "px";
          paddleBall.cy.baseVal.valueAsString =
            ballVer + "px"; 
This is the only trick part, but it seems to work well. And unlike Canvas, you don't have to erase anything, you just move stuff. Well, CSS game programming can just throw stuff around, but only SVG can do really cool shape modification and filters (more about that later, lots more).

Mousedown Event Handler

 This is triggered any time you touch the screen. In order to make this a game, you have to do something. My thought is to make it simple, so you touch on the left half of the screen to move the paddle left, and touch on the right half to make it go right. Each time you tap the screen, the paddle will jump a specific number of pixels and you'll have to tap it again to move it again. This provides a small amount of challenge.

Interestingly enough, when testing this on desktop Firefox, the clicking to move is clumsy and slow. But on a phone, it's fast and very intuitive. No keyboard, no mouse, just your finger. Tap anywhere on the left to move left, etc.

The mousedown handler does the following:
  1. Get the coordinates of where the tap took place.
  2. Get the current paddle X position (we're only moving left and right).
  3. Calculate where the click took place. Center is at 160 pixels right of the left edge. If the tap is on the right, add padMove to the paddle X value. But check to make sure the paddle doesn't move off the right edge.
  4. Do the same for the left of center tap. Again, make sure you don't move the paddle off the left edge.
  5. Move the paddle!
Here's the code for the mousedown handler:

      mouseX = evt.clientX;
      mouseY = evt.clientY;
     
      oldX = myPaddle.x.baseVal.value;   

      if (mouseX > 160) {
        newX = oldX + padMove;

        if (newX > 210)
          newX = oldX;
      }

      else {
        newX = oldX - padMove;

        if (newX < 10)
          newX = oldX;
      }
     
      myPaddle.setAttribute("x", newX);     


Wrapping It Up

You just start the game and move the paddle, stopping the ball from its mad passion to slam into the bottom of the screen. Rack up your score and keep playing. Maybe even have fun. But the real point is to see how to pull together the elements of creation, motion, and collision to make a simple arcade game.

Next I'm going to try to put this in the Marketplace and relate my adventures. After that, more game programming, more game reviews, and so on until I run out of ideas (not soon). Any ideas you have or any simple game types you'd like me to create would be appreciated. Well, maybe not Call of Duty.

Written while listening to the soothing strains of the Panzer Dragoon Saga Memorial Edition soundtrack. One of my all-time favorite games, totally only on the Sega Saturn. I don't have it any longer but I still remember finishing it and really liking the world it took place in, one of archaeology and dragons.

Monday, January 13, 2014

esviji (Game Review)

It's probably not a secret to anyone that I love SVG (Scalable Vector Graphics), but I'm continually surprised more people aren't making games in SVG. One of the biggest advantages of SVG is that you can make something fit anywhere, because it is ... scalable!


And now, out of the blue, comes a game from Nicolas Hoizey that not only uses SVG, but, if you say the name out loud, is SVG!


Nicolas claims this game is based on Puzzle Bobble (also known as Bust-A-Move) from Taito, and while there are certain similarities (I find both soothing and fun), I think esviji is definitely in a class by itself, and somewhat more challenging.

In case you weren't around for Puzzle Bobble, here's what Puzzle Bobble's screen looks like:


The two little dinosaurs at the bottom pull a gun turret back and forth, shooting a colored ball at a pile of colored balls. If you hit one of the same color, all of those balls explode. The two dinosaurs are Bub and Bob and that game is a spinoff of Bubble Bobble, which is a platformer! But esviji isn't really the same at all, and in fact, more challenging.

Here's the actual playing screen of esviji.


Very simple, very elegant. Low-key, understated, just what you might expect from France. But very different from Puzzle Bobble!!!

You have the game name, the score, level, and lives. You have a pause button at the upper right. And you have some nice colored balls at the lower left corner, and a ball on the upper right. Your mission is to guide the ball by sliding it up and down and letting go at the right moment. You want to smash into a green ball with a 2 on it. Get all the balls off the screen and you go on to the next level.

But there's more. You'll notice stair steps on the upper left. If you let go the ball so it goes across and hits one, the ball will bounce off the step and down to hit the ball you want to hit. If you hit one ball, it explodes. But your ball keeps going and will explode another if it is the same color, and so on. Then if it comes to a ball of a different color, it changes into that ball.

Lots of strategy, but you can take your time and think about what you want to do. Simple but deep. And this game has all the components of a complete game. There are sound effects you can turn on and off, high score saving, and a very good tutorial. Here's how you navigate to get the information.

From the start screen:


If you touch the gears on the right, you go here:


Turning the sound on and off is good, but even better is the Tutorial. It's a simple set of cut scenes showing you how to play!


And


And so on. Really well done tutorial and leaves no questions about how to play! None!

Going back to the Start screen, if you choose the middle button (the blue ribbon award image), you go here:


You'll notice that the scores are ranked by difficulty, and I obviously chose beginner. When you start the actual game, you'll get these choices:


I'll have to work up to ... Crazy! But I like that there's room to grow.

When you play the game, you can hit the Pause button (which looks like this: | | ). The Pause screen looks like this:


All in all, very elegant. You can start slow and keep going for a long time. The only thing that I would add is some kind of background music, but because Firefox OS can play music and sound on separate channels, you can play your own music in the Firefox OS Music player and still hear the sound effects of your game.

But there's more!  Nicolas Hoizey has chosen to share his source code at https://github.com/nhoizey/esviji. I haven't had the time to dig in to it, but it looks like he's creating the SVG shapes in the body of the document and then moving them. He uses the SVG Animate tag but also uses JavaScript, so I'll be curious if he wants to share his basic architecture of the game at some point. I didn't know SVG/Animate was supported, and, uh, it looks like it still isn't in Internet Explorer 11. But it works fine in Firefox and Chrome. And super-fine in Firefox OS, Firefox on Android, or the "home screen of any IOS 6+ device".

Because Animate wasn't supported by IE 9 or 10 or 11, I've not looked at it much and my main interest is using JavaScript for object creation and animation anyway. So this is an interesting development in the SVG game world, a very small corner that I would like to see grow.

I'm in love with this game and will keep it on my phones forever! Thank you, Nicolas Hoizey! And please do more. Let's not wait another 20 years.

Cost: Free
Genre: Arcade
Score: 7 (out of 5)
Tested on: Geeksphone Peak (Firefox OS)
Get it at: Firefox Marketplace https://marketplace.firefox.com/app/esviji