8bitrocket.com
9May/133

Coding By Google – AS3 to PHP with Simple MYSQL DB Query and Data Return Tutorial (Free Code)

By Jeff Fulton (@8bitrocket on twitter)

Coding By Google - AS3 to PHP with Simple MYSQL DB Query and Data Return Tutorial (Free Code)

Here at Producto Studios, I use Google to look up code all day long.  Yes, I have written books on Javascript, Flash, Actionscript, and HTML5, but I still find myself looking stuff up all the time. There just is too much to know when trying to fulfill the requirements of a project.

So, a few days ago a needed to Call a PHP script from AS3, hit MySql,  and return back some data.  Nothing fancy, but not something I have not done in a while (since my Zynga days). I used a couple different resources to cobble together the code, but not any one that had everything I needed.  so I thought in the sense a fairness in sharing,  I would present this basic version (that could probably be much more secure, etc) in case anyone needed a starter in how to accomplish this task.

The PHP

I am by no means a PHP superstar.  I grew up on Perl, moved to vbscript, then to .net, then hid from server side coding until I had to learn a little PHP a couple years back. I think it is an excellent language though and use it as often as I can.

Our example is going to accept in an email address, check to make sure it is a valid email (hopefully this will solve most SQL injection problems, but if there is a better way, please let me know).  It will then look up a user in the MySQL Database with the email address. If the user exists, it will pass back the first and last name of the user.  Since this is pure PHP, any script, even JQUERY could call it and use it.  For this example though, Flash AS3 is going to be the m method used.

The Server Side PHP Script

You will have to provide your own database IP address or DNS name, along with the user, pass and db name.

  1. <?php
  2. $email = $_REQUEST['email'];
  3. $returnString="retval=";
  4. if (filter_var($email, FILTER_VALIDATE_EMAIL)) {
  5.    $mysqli= new mysqli("xxx.xxx.xxx.xxx", "user", "pass", "db");
  6.    $sql="SELECT *FROM `user` WHERE email = '".$email."'";
  7.    $res=mysqli_query($mysqli, $sql);
  8.    if ($res) {
  9.       while ($newArray=mysqli_fetch_array($res, MYSQLI_ASSOC)) {
  10.       $first = $newArray['first'];
  11.       $last = $newArray['last'];
  12.       $returnString=$returnString."&first=".$first."&last=".$last;
  13.    }
  14.    echo $returnString;
  15. }
  16.    mysqli_free_result($res);
  17.    mysqli_close($mysqli);
  18. }else{
  19.    echo $returnString;
  20. }
  21. ?>

The Client Side Actionscript

This is the AS3 version of the script used to call the PHP.

 

  1. package {
  2.   import flash.events.*;
  3.   import flash.net.URLLoader;
  4.   import flash.net.URLRequest;
  5.   import flash.net.URLVariables;
  6.   import flash.net.URLLoaderDataFormat;
  7.   import flash.net.URLRequestMethod;
  8.   import flash.display.MovieClip;
  9.   public class Main extends MovieClip{
  10.     private var EMAIL_REGEX: RegExp = /^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$/i;
  11.     private var formattedEmailAddress:String;
  12.     public function Main() {
  13.       trace("test as3 to php to mysql and back");
  14.       var email="Teff@Test.com";
  15.       formattedEmailAddress=email.toLowerCase();
  16.       if (formattedEmailAddress.match(EMAIL_REGEX)) {
  17.         trace("good email address format");
  18.         trace("checking database for email address...");
  19.         checkDbForEmail();
  20.       }else{
  21.         trace("bad email address format");
  22.       }
  23.     }
  24.     private function checkDbForEmail():void {
  25.       var url="http://addresstoyourserver/doesemailexist_tutorial.php";
  26.       var loader : URLLoader = new URLLoader;
  27.       var urlreq:URLRequest = new URLRequest(url);
  28.       var urlvars: URLVariables = new URLVariables;
  29.       loader.dataFormat = URLLoaderDataFormat.VARIABLES;
  30.       urlreq.method = URLRequestMethod.POST;
  31.       urlvars.email = formattedEmailAddress;
  32.       urlreq.data = urlvars;
  33.        loader.addEventListener(Event.COMPLETE, completed);
  34.       trace("calling loader");
  35.       loader.load(urlreq);
  36.     }
  37.     private function completed(event:Event): void{
  38.       trace("php event") ;
  39.       var loader2: URLLoader = URLLoader(event.target);
  40.       trace("first=", loader2.data.first);
  41.       var firstname:String=loader2.data.first;
  42.       var lastname:String=loader2.data.last;
  43.       if (firstname == null || firstname =="") {
  44.         trace("Sorry, that email does not exist in our database");
  45.       }else{
  46.        trace("user exists");
  47.       }
  48.     }
  49.   }
  50. }

That's all there is to it. I'm not christening this as the only or the best way to accoimplish this task, just one way that works and is moderately secure.  If you have a better way, please sent it over and I'll credit you and post your additions and comments.

Jeff Fulton is the Chief Technology Officer at Producto Studios, and co-author of The Essential Guide To Flash Games,as well as The HTML5 Canvas 1st and 2nd editions.
He can be reached at info[at]8bitrocket.com and at the @8bitrocket twitter address.

2Jul/120

HTML5 Canvas : Animating Gradients To Create A Retro Atari Style Color Cycle

We just finished our semi-final run into the Atari Pong Developer Contest last week, but I'm still feeling a little "retro".   This weekend I decided to see if I could replicate an old-style Atari color-cycle in HTML5 using the Canvas API alone: no bitmaps or anything other helpers.

The results are below.

(note, if you can't see this try it in Google Chrome)

At first I did not know how I was going to achive this, but the answer came fairly quickly.    I decided to use the Canvas API  createLinearGradient() function.   createLinerGradient() works like this.  You set-up a gradient "line" the represents the direction of the color gradient.  Then you create "color stops" that represent the colors to the gradient.    I'll show this in the code  code later.

To get started, I first, I set-up an animation loop:

function drawScreen() {
}
function gameLoop() {
   window.setTimeout(gameLoop, 20);
   drawScreen() 
}

Next, I created a simple array of objects that represented the colors of the gradient and the color stops.  Colors stops are percentage of the gradient. I started with red, then added yellow, blue, green, purple, and red again.  I had to add red twice so that the color flowed back the beginning.  Notice that the percentages for both reds are only 1/2 of the others (.125 as instead of  .25)

var colorStops = new Array(
 {color:"#FF0000", stopPercent:0},
 {color:"#FFFF00", stopPercent:.125},
 {color:"#00FF00", stopPercent:.375},
 {color:"#0000FF", stopPercent:.625},
 {color:"#FF00FF", stopPercent:.875},
 {color:"#FF0000", stopPercent:1});

Next, inside the drawScreen()  function I created the gradient.

First, I set-up up a gradient on the current path.  The  arguments to the function represent the "line" that the gradient will follow.  Since I wanted the gradient to be in a straight vertical line, I centered it in the middle of the canvas, and drew it directly down to the bottom.

var gradient = context.createLinearGradient( 
               theCanvas.width/2,
               0,
               theCanvas.width/2, 
               theCanvas.height);

Next, I loop through the colorStops array calling gradient.addColorStop() for each color in the array.    A "gradient color stop"() has two arguments: the color and the percentage.  I already set these up in the array, so now they are just applied in a loop.
After each gradient color stop() is added, I increment the percentage of each color by .015.  This effectively moves the color "up" .  If the gradient color stop percentage value goes above 1, I set it back to 0, which moves it back to the bottom of the gradient.

for (var i=0; i < colorStops.length; i++) {     
   var tempColorStop = colorStops[i];     
   var tempColor = tempColorStop.color;     
   var tempStopPercent = tempColorStop.stopPercent;     
   gradient.addColorStop(tempStopPercent,tempColor);    
   tempStopPercent += .015;     
   if (tempStopPercent > 1) {
       tempStopPercent = 0;
   }
   tempColorStop.stopPercent = tempStopPercent;;
   colorStops[i] = tempColorStop;
 }

In reality, the gradient is not being "animated", I'm just changing the location of each color by changing the gradient color Stop percentage.  However, the effect is the same.  It looks like the colors are cycling.

Finally, I display the text using the gradient as the color for fillStyle.

  context.fillStyle = gradient;
  context.fillText ( message, xPosition ,yPosition);

That's it.  I'm sure all kinds of other, way more awesome, effects can be created with animated gradients, but this is just a start.

You can get the code here.

-8bitsteve

4Feb/120

Interesting notes on External Interface JavaScript Call-Backs To Flash

This week we had a big project due for a new Movie that is coming out in a few weeks time.         The majority of the site was built-in Flash but I needed to use an External Interface call to JavaScript in order to display dynamic content in an iFrame div pop-up. The first call from Flash to JavaScript to open the window and display the dynamic link worked fine on every browser  I tested.   When the call is made, I turn on translucent white cover layer in Flash so the site appears behind it and the game pop-up appears on top, in HTML. So far, so good.

The problems started to crop up when I added functionality to the game pop-up window to close the the pop-up box and then tell Flash to remove the white translucent layer. It just would not work on every browser.   For reference, here is a brief set of code that Flash AS3 uses to tell JavaScript that is has a call-back function when making the initial ExternalInterface call:

ExternalInterface.addCallback("gameClose", gameClose);

So, basically this tells JavaScript that when the ExternalInterface call is made, the "gameClose" function should be added by the DOM to the Flash Movie Object and the gameClose (second paramter) is the name of the call-back function in AS3 that will be called.

The AS3 gameClose() function simply turns off the translucent white cover layer.

In Javascript, when the close button on the div that holds the game iframe is clicked, this code is fire off:

var callResult=thisMovie("flashObject").gameClose();

"flashObject" is both the name="" and id="" attribute that I put into my Object and Embed Tags. At first I was using the SwfObject to do this, but some of the browsers were coming back with dom errors saying that gameClose() was not a function. I then tried to use the straight Object tags that are exported from Flash on publish. Still, I had inconsistent ability to fire off the gameClose() call back function.  It was getting weird.

I then switched up to the old-style Object tag with an embed tag inside like this:

&lt;object id="flashObject" name="flashObject"
classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
width="800" height="600" align="middle"&gt;
 &lt;param name="movie" value="site.swf" /&gt;
 &lt;param name="wmode" value="transparent" /&gt;
 &lt;param name="allowscriptsccess" value="always" /&gt;
 &lt;param name="allowsetworking" value="true" /&gt;
 &lt;param name="menu" value="false"/&gt;
&lt;embed src="site.swf" width="800" height="600"
id="flashObject" name="flashObject"
type="application/x-shockwave-flash"
allowscriptsccess="always" allowsetworking="true"
wmode="transparent" menu="false"&gt;&lt;/embed&gt;&lt;/object&gt;

This got the call-back to work in both Firefox and Chrome (previously it was only working in Chrome).  The problem was that IE 9 simply would tell me that gameClose() was not part of the DOM. It actually could not even recognize that "flashObject" was an object on the page.

Frustrated, I put in code to try to echo back what "flashObject" actually was:

if (document["flashObject"] == null) {
       swf= window["flashObject"];
 }else{
      swf= document["flashObject"];
 }

 console.log("swf=" + swf):

On the browsers where the close button worked fine, "swf" was logged as an HTMLEmbedObject. On the browsers where it did not work, it came back as a
NodeList.

So, of course gameClose() did not exist on the NodeList because is was a actually a collection of nodes with the name "flashObject". There were two of those, one in the Object tag and one in the embed tag.

The answer was to loop through the node list and find the node that was actually the HTMLEmbedObject type (or just simply use the second node in the flashObject collection for iE). The second node was the embed tag that IE was looking for while the object tag would throw an error.

It worked and I was on my way to finishing the project in the "nick" of time.

14Dec/110

HTML5 Canvas Christmas Tree Drag And Drop Demo And Tutorial

Here is another demo from DevCon5.  Yesterday we showed you an action game, now we will show you something completely different.  A Drag And Drop style decoration application of the type we produced by the dozens ta Mattel throughout the first 10 years of this century.  We present to you: Christmas Tree Decorator.  Music by Mike Peters/The Children Of The Revolution.   This was developed for Google chrome and has not been optimized for other browsers yet.

One of the most interesting thing about this demo (to us) is that we display the mouse button pointer when rolling over things that can be clicked and dragged.  This might not sound like much, but since the HTML5 Canvas does not contain any DOM objects, we had to achieve the effect with our own custom code.  Here is how we did it:

 

  • First, in JavaScript we listen for Canvas “mousemove” event:

[cc lang="javascript"]
theCanvas.addEventListener("mousemove",onMouseMove, false)
[/cc]

 

  • Next we test to see if the mouse if over any of the bulbs.  We keep all bulbs in single array named clickBlocks to make this easy.
[cc lang="javascript"']
function onMouseMove(event) {
		var mouseX;
		var mouseY;

		if ( event.layerX ||  event.layerX == 0) { // Firefox
			mouseX = event.layerX ;
			mouseY = event.layerY;
		} else if (event.offsetX || event.offsetX == 0) { // Opera
			mouseX = event.offsetX;
			mouseY = event.offsetY;
		}
		for (var i =0; i &lt; blocks.length; i++) {

			if (blocks[i].dragging) {
				blocks[i].x = mouseX - BLOCK_WIDTH/2;
				blocks[i].y = mouseY - BLOCK_HEIGHT/2;

			}
		}

		var cursor ="default";
		for (i=0; i< blocks.length; i++) {
			var tp = blocks[i];
			if ( (mouseY >= tp.y) && (mouseY <= tp.y+tp.height) && (mouseX >= tp.x) && (mouseX <= tp.x+tp.width) ) {
				cursor = "pointer";
			}
		}
		theCanvas.setAttribute("style", "cursor:" + cursor);

		for (i=0; i< clickBlocks.length; i++) {
			var tp = clickBlocks[i];
			if ( (mouseY >= tp.y) && (mouseY <= tp.y+tp.height) && (mouseX >= tp.x) && (mouseX <= tp.x+tp.width) ) {
				cursor = "pointer";
			}
		}
		theCanvas.setAttribute("style", "cursor:" + cursor);
	}
[/cc]
  • The key lines in that code, change the cursor depending on what the  mouse is over using CSS

[cc lang="javascript"]

theCanvas.setAttribute("style", "cursor: pointer”);

[/cc]

or

[cc lang="javascript"]

theCanvas.setAttribute("style", "cursor:default" );

[/cc]

Don't forget, you can join our new HTML5 Game Development forums and talk about this kind of stuff all day long!

9Mar/110

Road Test: Adobe "Wallaby" Flash->HTML5 Converter Preview Version

A couple days ago, Adobe released a preview version of  "Wallaby", their Flash->HTML5 converter.  It's been a badly kept secret for the past few months that Adobe was working on something like this, but with the release they have finally come clean on their efforts.

Here is what they says about it:

"Wallaby" is the codename for an experimental technology that converts the artwork and animation contained in Adobe® Flash® Professional (FLA) files into HTML. This allows you to reuse and extend the reach of your content to devices that do not support the Flash runtimes. Once these files are converted to HTML, you can edit them with an HTML editing tool, such asAdobe Dreamweaver®, or by hand if desired. You can view the output in one of the supported browsers or on an iOS device.

You can get the Wallby preview version here: http://labs.adobe.com/downloads/wallaby.html

Both Mac And PC versions are available.

There is a long list of things that are not supported right now.  you can find that list here:

http://labs.adobe.com/wiki/index.php/Wallaby#Release_Notes

We tested the application, and it appears to work as advertised.   Using the application is very simple.   All you do is locate a .fla to convert to HTML, and select a location to place the converted files.

When Wallby has completed the conversion, you should have a .html file to load and test. We noticed that these work best in Safari and Chrome.  They did not work in Opera or Firefox. This makes sense, as it was designed to work with WebKit.

Here are a couple examples we made very quickly.  The first one simply moves a logo a cross the screen using a classic tween.

Rocket Test Move HTML5

Rocket Test Move SWF

The second one moves the same logo, while it spins, fades and changes size:

Rocket Test Move. Spin, Fade

Rocket Test Move, Spin, Fade  SWF

A couple things we noticed:

1. So far, ActionScript is not supported at all.

2. The output is CSS, JavaScript and SVG.  It does not look like the HTM5 Canvas is leveraged for anything at all (yet).

We look forward to testing newer versions when they are released.  We'll keep you posted.

11Feb/110

Quick Guide To wmode And Flash Embedding

When embedding Flash .SWFs in HTML, there are several choices you can make for the wmode parameter.  I've always been a bit confused about which was which, so I set out to today to pull together as much information as possible on the subject.  Here is a quick run down of the choices, and what they mean for your Flash .swf.

wmode=window : Usually the default option.  This puts the Flash movie on top of all other content on the HTML page. This means Flash won't play well with other HTML elements, and it won't adhere to z-index ordering.  In some cases, this mode will net you the best performance for your Flash game or application. This appears to be the safest option for getting your Flash to work properly in the majority of web browsers.

wmode=opaque : This mode is supposed to let Flash play well within an HTML page and adhere to z-index  ordering.   This option will disable hardware GPU rendering and default to software rendering. This mode is not recommended for use with mobile platforms displaying video. This mode also sometimes interferes with capturing keyboard events in Flash.   At the same time, some game developers have found that opaque nets them smoother frame rates.

wmode=transparent : If the background of your Flash movie is transparent, the HTML page will show through. Just like opaque, this option is supposed to play well with other HTML elements and has it's uses in the arena.  However, this option takes a significant amount of processing power to render the transparency.   Like opaque, this option will automatically disable hardware GPU rendering and default to software rendering, is not  is not recommended for use with mobile platforms displaying video and sometimes interferes with capturing keyboard events in Flash.

wmode=gpu : Uses the GPU for hardware accelerated rendering.  This may sound like a good idea, but that is not always the case.  Although running on the GPU can be very fast, in some cases loading and reloading graphics data to the GPU can be costly and time consuming.  You need to test this with your apps and the target devices to make sure it is beneficial to performance.

wmode=direct : This mode bypasses  the browser when rednering. This mode is required for Flash "StageVideo" to work in Flash player 10.2.  This mode appears to not play well with some HTML elements (similar to wmode=window).

This is what I could find today. If you have any additions, subtractions, or updates to this, please tell use in the comments below.

7Feb/110

Game Programming Tool Kit: A Binary Search in AS3

Every game programmer needs a basic set of tools to use in building his/her games. In this series we will cover everything from basic computer science algorithms and simple design patterns to more complex artificial intelligence implementations. If it can be used some how, some way in game development, then it is ripe for discussion and implementation in this series.

A Binary Search In AS3

With a binary search we can find an element in a sorted array faster (conceivably) than looping through the array  comparing the value we are looking for with the value of each element in the array.  I say conceivably because there are certain circumstances where the loop can be faster. Those cases would be when the value you are search for happens to be near the beginning of your search.

The version we are going to look at is a classic "needle in the haystack" style problem.  We are going to create and array called the "hayStack". It will contain a sorted list of numbers from the smallest to the largest. We will create a second integer variable called the "needle". The needle will be a value that exists in the array. We will use a classic example of recursion to search the "hayStack" for the needle value.

The recursive function, called "arraySearch()" will accept in four parameters:

1. The needle value

2. The hayStack array

3. The first element to use in the search. In our example we will search the entire array, so this value is 0, but it can be any value as long as it is not greater than the last parameter in the search.

4. The last element to use in the search. In our example this will be the hayStack.length-1, but it can be any value as long as it is greater than the first parameter.

The arraySearch() function will first find the middle of the array and then check to make sure that the last value is greater than the first value passed in.

If the value in the hayStack at the middle index is greater than the needle value then the arraySearch() function will recursively call itself but pass in middle-1 as the new last value.

If the value in the hayStack at the middle index is less than the needle value then the arraySearch() function will recursively call itself, but pass the middle+1 as the new first value.

Finally the middle value will be passed back as the correct index of the needle value.

[cc lang="javascript" width="550"]

package
{
import flash.display.Sprite;
/**
* ...
* @author Jeff Fulton
*/
public class BinarySearch extends Sprite
{

public function BinarySearch()
{
var needle:int = 55;
var hayStack:Array = [1, 2, 3, 4, 5, 6, 10, 21, 32, 33, 34, 41, 47, 51, 52, 53, 54, 55, 66, 69, 71, 73, 76, 90];
var location:int = arraySearch(needle, hayStack, 0, hayStack.length - 1);

trace(location);
}

private function arraySearch(needle:int, hayStack:Array, first:int, last:int):int {

var middle:int = Math.floor((last + first)/2);
if (first > last) {
trace("first > last");
// check for error in data passed in
return -1;
} else if (hayStack[middle] > needle) {
return arraySearch(needle, hayStack, first, middle-1);
} else if (hayStack[middle] < needle) {
return arraySearch(needle, hayStack, middle+1, last);
} else {
return middle;
}

}

}
}

[/cc]

Executing this code will result in the value "17" being traced out as 55 is the 17th (0-relative) element in the hayStack array.

Now, try to set the first value to 10 and the last value to 9.
[cc lang="javascript" width="550"]
var location:int = arraySearch(needle, hayStack, 10, 9);
[/cc]

The result will be a "-1" returned because the first value is greater than the last value.

Next, change the needle to the value "0" (or any other value that is not in the hayStack() array. Change the arraySearch() call back to it original format:
[cc lang="javascript" width="550"]
var needle:int = 0;
var hayStack:Array = [1, 2, 3, 4, 5, 6, 10, 21, 32, 33, 34, 41, 47,51, 52, 53, 54, 55, 66, 69, 71, 73, 76, 90];
var location:int = arraySearch(needle, hayStack, 0, hayStack.length - 1);
[/cc]

If the value is not found, eventually the recursion will result in first > last and a -1 will result.

The recursive function can be replaced with an iterative version:

[cc lang="javascript" width="550"]

private function arraySearchIteration(needle:int, hayStack:Array, first:int, last:int):int {
var middleFound:Boolean = false;
var middle:int;
while (!middleFound) {
middle = Math.floor((last + first) / 2);

if (needle == hayStack[middle] || first > last) {
middleFound = true;
}else if (needle > hayStack[middle]) {
first++;
}else {
last = middle-1;
}

}

return(middle);

}
[/cc]

That's it for a simple binary search. This is relatively simple, yet powerful technique that can be applied to solve any number of game related problems from looking for the correct MovieClip to remove from the game screen to looking up words in a  word list. One problem with this technique though is that it requires a sorted list. In the future we will examine using a hash table to solve this problem.  While using a hash table is a much faster (in some cases) than a binary search, it is much more complex than the simple recursion/iteration that we have constructed here.

5Feb/110

Shorter, More Game Focused Tutorials Targeting More Technologies Are Coming

OK, now that our HTML5 Canvas book is in production, we are planning a return to game tutorials that have been so popular here.  However, in 2011, people want more than just AS3 tutorials.  Keeping look back at this space for shorter, more precise code snippets and tutorials on game algorithms and solutions to common problems.   We will present them in AS3, JavaScript/Canvas and/or Corona Lau for mobile.

19Aug/100

Tutorial: Turn Your Flash Game Into A Google Chrome Web App (beta)

While the Google Chrome App Store will not be available until October 2010, you can still package-up your apps and test them as Chrome Web Apps.   Google has some extensive documentation on the subject, but we are going to slice it down and show you the easiest path to success.

Step 1: Get The Right Browser...Windows Only!

Yep, the only Chrome build that supports the installation of Chrome Web Apps, right now, is Chrome for Windows.  You will have to subscribe to the Chrome "Dev Channel" and then download the browser.  This is really simple.  I didn't really "subscribe" at all, I just downloaded the dev channel version of Chrome to my Windows machine.

Step 2: Set-up The Browser To Load Apps

After you have downloaded Chrome, you need to create a short-cut in Windows so you can change the path to the Chrome.exe executable.  You need to do this so you can add the "--enable-apps" option to the execution path.  This option allows you to test the "loading extensions" functionality which is the basis of the Chrome Web App technology.

Here is an example of the link to put in the Target box of a short-cut in Windows XP:

[cc lang="javascript" width="550"]

"C:\Documents and Settings\username\Local Settings\Application Data\Google\Chrome\Application\chrome.exe" -enable-apps

[/cc]

Step 3: Prepare Your Flash Game

Now you need to get all the assets together in a folder/directory that you will provide as part of the Chrome App installable package.  This includes:

  1. .swf file
  2. An HTML file that holds your .swf
  3. a 24x24 px .png icon
  4. a 124x124.png icon
  5. Any other assets the .swf needs to load externally

For this example, I decided to use our game "Palindromes Plus". First I found the Mochi version of palindromesplus.swf and the converted the cartridge icon image we use into  24x24 and 124x124 icons.

I then created a palindromesplus.html page.  To make it simple, I made the background of the HTML page black, and centered the game on the screen.

Step 4: Create Your Manifest.json File

The manifest.json file is required for every Chrome Web App.  It describes  meta-data about the game you are creating, and where to find some essential assets.  Most of this file is  (like name, description, version) self-explanatory.   However, a couple items could use a little sunlight to make them clear:

  • "app:launch" section:  The "app:launch" section contained describes how this app will execute:
  • web_url: This is the complete URL to an app that exists on the web.  You can deploy an app a s a Chrome web app without embedding the code in your directory/.crx file (more on that later)
  • local_path : a relative path to the html file that will launch your app.  This is required for a "server-less" app that can run offline.  This is the style we are creating for our Flash game.
  • "permissions" section:  This section defines some security constraints around your app for specific Chrome APIs and storage.   This is where you would place urls that your app might call for web services and xml rpc requests. We don't really use this, so we left the default from the Google example ( here)
    • notifications : Allows the app to use the proposed HTML5 notifications
    • unlimited_storage : Allows for unlimited HTML5 Server-side storage.

There are other options you can read about all the manifest.json file options here: http://code.google.com/chrome/extensions/manifest.html

[cc lang="javascript" width="550"]
{
"name": "Palindromes Plus",
"description": "Unscramble The Palindromes",
"version": "1",
"app": {
"launch": {
"local_path": "palindromesplus.html"
}
},
"icons": {
"24": "24.png",
"128": "128.png"
},
"permissions": [
"unlimited_storage",
"notifications"
]
}

[/cc]

Step 5: Create Your Application Folder

After you have your manifest.json, .html file, .swf, and and .png file files,  you need to create a folder file to hold them all.  Create a folder and place all of the files inside of it.

Step 6: Launch The Chrome Developer Version

Find the shortcut you created to the Chrome Browser  with the "-enable-apps" command line option and launch it.

Step 7: Install The Extension (Chrome Web App)

  1. Find the Wrench icon in the upper right hand corner of Chrome and click it.
  2. Choose The Tools Menu
  3. Choose The Extension menu
  4. Click the (+) next to Developer to open Developer mode

You should see the following screen:

To load your extension, click the [load packed extension] button and find the folder you put the files into.  Once you find it and click [OK], the extension will load.

Now, to try the Chrome Web App, simply click on a New Tab, and you should see the icon you created:

Click the icon to play the game.

Step 8: Create a .crx File

A .CRX file will be needed to distribute your app in the Chrome App Store.  This is very easy to create.  Follow the directions to get back to the developer mode.   Then click the [pack extension] button.

This will bring-up the following screen:

For the "extension root directory", find the folder you created with the manifest.json, etc.

Click [OK]

A .crx and .pem license file will be created for your app.  Hold on to these for when the Google App Store is ready to accept new applications, or for when Google Chrome can load packed extensions (not available yet).

A .crx is simple a .zip file with the extension changed.  You should be able make these without using Chrome very easily.

That's It...But It's Still Beta

Google says all of this could change wholly or partly by the time the Google App Store launches, but we thought it would be cool to give some idea of what the process and work flow will look like once the Chrome Web App Store is ready for action.

Here is a zipped directory for the Palindromes Plus extension: palindromes.zip that you use to try this on your own.  It includes the .swf, a sample manifest.json file, and icons.

Here is the .crx  abd pem files we created for Palindromes Plus:  palindromes.crx and palindroms.pem (.zip)


9Aug/100

HTML5 Canvas Resize On The Fly, In An HTML Page

I've been playing around a lot with the HTML5 Canvas lately, and I discovered some very interesting things that about the size of Canvas as displayed on an HTML page.

The best way to show these is to show a demo of what I'm talking about first.  Here is a link to the demo:
http://www.8bitrocket.com/wp-content/uploads/2010/08/CanvasResizeBlog.html

Note: This demo works best in Google ChromeThe Range controls listed below will not appear in Firefox...yet.

What you will notice on the demo page is a 500x300 Canvas with the text "Text Wrangler" applied to to it.  Below the Canavs are 4 HTML form controls:

  1. A Text box to change the text
  2. An HTML5 Range Control to change the size of the text
  3. An HTML5 Range Control to change the width of the Canvas
  4. An HTML5 Range Control to change the height of the Canvas

Changing the size of the text is a no-brainer.  I added that to show that the Canvas itself could be manipulated with a form control on an HTML page.   However, the range controls for the width and the height of the Canvas are what I'm concentrating on here.  If you play with them you will notice that the width and size of the Canvas can be changed on a page dynamically.  I coded the text to stay in the middle of the Canvas, no matter what the size, with this code:

[cc lang="javascript" width="550"]
var metrics = context.measureText(message)
var textWidth = metrics.width;
var xPosition = (theCanvas.width/2 - textWidth/2);
var yPosition = (theCanvas.height/2);

[/cc]

The measureText() method is native to the Canvas context object.  It only has one property, width.    Since text has a default baseline of "middle", you can center text vertically by placing it at the middle pixel on the screen.  However, text default to a horizontal alignment of "start", which means you need to either set it to "center" or subtract 1/2 the width of the text to get a proper horizontal center at the midpoint of the Canvas.

Now, if you play with the range controls to chnage the width and the height of the Canvas, notice how it interplays with rest of the page.   The form elements move up and down the page as the the height is changed.   The text on the Canvas stays the same scale and centered, no matter how big or small the Canvas might be.   This appears to be the opposite of what is specified in the Canvas API:

The intrinsic dimensions of the canvas interface element equal the size of the coordinate space, with the numbers interpreted in CSS pixels. During rendering, the image must be scaled to fit this layout size.

The image does not appear to scale when the Canvas is resized.  In fact, it simply allows for more of the Canvas to be viewed.  I saw the same effect in Safari.  It is possible that I'm reading the API spec wrong too.  No matter, the cool part is that the Canvas can completely redisplay itself, on the fly, with updated width and height without reloading the page.

It appears to me that the HTML5 Canvas is built to allow for the same types of free-flowing liquid user interfaces that can be created in Flash using "noscale" and JavaScript, but with the added feature of being able to resize the entire Canvas on the fly in real-time.  I've NEVER seen that done with Flash.  I'm not saying you can't do it, I've just never seen it done before.

Here are some code highlights:

The HTML5 form controls below the Canvas interact with the Canvas by listening for events only.  When any control is changed, event handlers are used to capture that change and then render it on the Canvas.

[cc lang="javascript" width="550"]
var context = theCanvas.getContext('2d');
var formElement = document.getElementById("textBox");
formElement.addEventListener('change', textBoxChanged, false);

formElement = document.getElementById("textSize");
formElement.addEventListener('change', textSizeChanged, false);

formElement = document.getElementById("canvasWidth")
formElement.addEventListener('change', canvasWidthChanged, false);

formElement = document.getElementById("canvasHeight")
formElement.addEventListener('change', canvasHeightChanged, false);

[/cc]

Here are the Event Handlers functions.  Notice that to change the width and height of the Canvas, we simply update the the width and height attributes of the Canvas object. (Note: theCanvas is the id of the the Canvas object in the HTML page)

[cc lang="javascript" width="550"]
function textBoxChanged(e) {
var target = e.target;
message = target.value;
drawScreen();
}

function textSizeChanged(e) {
var target = e.target;
fontSize = target.value;
drawScreen();
}

function canvasWidthChanged(e) {
var target = e.target;
theCanvas.width = target.value;
drawScreen();
}

function canvasHeightChanged(e) {
var target = e.target;
theCanvas.height = target.value;
drawScreen();
}

[/cc]

Here is the code in the drawScreen() function that renders the text based on the current width and height of the Canvas.

[cc lang="javascript" width="550"]
var metrics = context.measureText(message)
var textWidth = metrics.width;
var xPosition = (theCanvas.width/2 - textWidth/2);
var yPosition = (theCanvas.height/2);
var tempColor = "#000000";
context.fillStyle = tempColor;
context.fillText ( message, xPosition ,yPosition);
context.strokeStyle = "#FF0000";
context.strokeText ( message, xPosition,yPosition);
[/cc]

Check out the demo again:

http://www.8bitrocket.com/wp-content/uploads/2010/08/CanvasResizeBlog.html

This site is protected by Comment SPAM Wiper.