8bitrocket.com
20May/100

Google Chrome Web Store: Finally, A REAL Place To Sell Flash Games To Consumers?

Maybe I'm the last to find out about these things, but The Google Chrome Web Store looks like the first really promising way to monetize web apps written in Flash, HTML 5, Silverlight, etc.  It appears to work on the sample principle as the iPhone store, but make apps available to any browser that is HTML 5 compliant.

Creating apps appears to be very simple.  Here is what Google says in their docs:

"You can easily make any existing web app installable.
There's no need to rewrite it or change technologies. Alternatively, you can also create fully offline, or "serverless" apps.
"

ANY app?  Wow.  They continue with this information about the store itself:

"The Chrome Web Store is an open marketplace for web apps
that will enable you to reach millions of users with your apps.
The store will be integrated with Google Chrome,
making it easy for Google Chrome users
to discover apps and install them directly from the store.
You'll also be able to sell your apps using an integrated payment system.
"

If this holds true, you can create a Flash, Silverlight  or HTML 5 Canvas game or app, host it in a web page, and sell it in the store.    You can create the app as stand-alone, and save data to a Flash Shared object, or to the HTML 5 browser storage.  Alternatively, you can make the app server-side compatible, multi-player, etc. (apparently). 

To me, this appears to be the most promising technique yet to monetize games and apps on the web.  I like that Google has taken (what appears to be) to opposite tactic from Apple.  They will allow ANY app into their store, as long as it runs in web browser.  That appeals to me very much.

To get involved developing for the store, it looks like you should start here: http://groups.google.com/a/chromium.org/group/chromium-apps/topics

19May/100

Essential Guide To Flash Games Chapter 13 Part 1. Modified BasicScreen and new ImageButton class

Essential Guide To Flash Games Chapter 13 Part 1.  Modified BasicScreen and new ImageButton class

The Essential Guide To Flash Games only contains 12 chapters, so what is chapter 13? Chapter 13 and beyond will be additions to the book and efg framework that build on what has been created so far. When adding or changing classes in the original efg framework we need to be extra careful that all existing games will still compile. For this reason we will not make wholesale changes to existing classes, but we will add functionality where we can. In some cases we can add this functionality to existing classes through new methods by adding new constructor parameters with default values. In other cases we need to build new classes or extend existing ones.

If you have taken a look at the book and have visited this site for any length of time you will notice that some of the book chapters were greatly expanded versions of tutorials that we had presented as blog entries. Everything was re-written to work with the efg framework and re-coded to fit within some basic common coding standards. We have decided that we will continue to support the book in a similar manner. With chapter 13 and beyond you will be getting a preview of what could possibly be included in the second edition of the book (also in an expanded form). By utilizing the framework and expanding on the existing code-base we are also demonstrating how creating a re-usable, expandable framework can aid the developer in simplifying future development efforts through shared code libraries, re-use and iteration. Plus it's fun and I get to channel all of my tutorials and dev into an area that will be useful now and in the future.

You will benefit most from this information if you have some familiarity with the book or the efg framework. The entire framework and set of game examples is a free download on the book site. It will make much more sense if you have the book in some form as a reference though.

Chapter 13: Part 1
Modified BasicScreen and the new ImageButton Classes

The plan all along has been for us to keep updating the Essential Guide To Flash Games book with more game and more chapters. Now that the book has been out for a couple months we are going to begin that process by updating the efg framework a bit. The BasicScreen class as presented in the book is a little limited in functionality (on purpose). The point was to build a foundation that readers could add to and extend as needed. It turns out that Steve and I needed to do just that when we sent a couple of the book games (Blaster Mines and Tunnel Panic) virally to promote the book release. We found that we needed to add two basic functions to the class to make it more useful:

1. The ability to add an image to a screen
2. The ability to use images in place of the the text in the SimpleBlitButton class.

The new ImageButton class

We will begin by taking a look a the first new class, ImageButton. Rather than extend the SimpleBlitButton class we found it much more straight-forward to create a similar class with slightly different functionality. This class i adds the ability for the an image to be used for the "off" and "over" states of the button.. In fact, this class is designed to also be expanded with other button states of needed.

Here is the full text of this class. It should be saved in the com/efg/framework package with the name ImageButton.as.

This class only contains the physical look of the button states and provides a mechanism function for changing the state based on a constant. It does not actually contain the listening functions to respond to events. The container class (BasicScreen) will be used for this as it is with the SimpleBlitButton class.

This class extends the Sprite class and contains a single Bitmap object (buttonBitmap). The bitmapData attribute of buttonBitmap will be swapped based on the state of the button. This class was designed to function very similar to the BasicBlitButton class in the original framework.

Note: the "_" character in the code is used to designate line continuation. If you are going to cut and paste the code, search for these lines and re-attach them in you IDE. They are necessary to ensure that the page layout of the site is not affected by the length of the code lines.

<font color="blue" size="3"><br /><br />package com.efg.framework {<br />   import flash.display.Bitmap;<br />   import flash.display.BitmapData;<br />   import flash.display.Sprite;<br />   import flash.geom.Point;<br />   /**<br />   * ...<br />   * @author Jeff Fulton<br />   */<br />   public class ImageButton extends Sprite{<br />      public static const OFF:int = 1;<br />      public static const OVER:int = 2;<br />		<br />      public var buttonBitmap:Bitmap;<br />      public var offBitmapData:BitmapData;<br />      public var overBitmapData:BitmapData;<br />		<br />      public function ImageButton(off:BitmapData, over:BitmapData, location:Point) {<br />         offBitmapData = off;<br />         overBitmapData = over;<br />         buttonBitmap = new Bitmap(offBitmapData);<br />         addChild(buttonBitmap);<br />         x = location.x;<br />         y = location.y;<br />         this.buttonMode = true;<br />         this.useHandCursor = true;<br />      }<br />		<br />      public function changeButton(typeval:int):void {<br />         if (typeval == OFF) {<br />            buttonBitmap.bitmapData = offBitmapData;<br />         }else {<br />            buttonBitmap.bitmapData = overBitmapData;<br />         }<br />      }<br />   }<br /><br />}<br /><br /></font><br />

ImageButton Constants

The constants designate the two simple states of the button: OFF or OVER. These will be controlled by the container class (BasicScreen) and passed into the changeButton() function as needed.

The constructor

The constructor accepts in the two BitmapData objects representing the look for the OFF and OVER states for the button. It also accepts in a Point class instance used to position the button inside it's container object (the BasicScreen class in this example).

The changeButton() function

This function is the public interface used to change the button state. It is a simple if/else statement now, but can be expanded to add further states if needed. It accepts an integer typeval. This integer must be one of the defined state constants. The bitmapData attribute of the buttonBitmap will be swapped based on the typeval passed in.

 

The modified BasicScreen class

The original BasicScreen class in the efg framework remains essentially intact, but we are going to add in functionality to add a background image and use an instance of the ImageButton class in place of the SimpleBlitButton if desired.

We we be adding a new function called addImage() that will allow the developer to add a single image to the BasicScreen instance. We thought about allowing the developer to add "N" number of images, but this would necessitate creating our own interface for managing the layering (or display list) inside the BasicScreen. We might add that functionality in the future, but for now a single image can be added to a BasicScreen instance. We will also create a new function called createImageButton() that will allow the current single button on the BasicScreen to be an ImageButton instance instead of the BasicBlitButton. There is a lot more we can do with this class such as allow the creation of multiple buttons, adding swfs as well as multiple images, etc. For now we will be adding this simple functionality and tackle the more advanced additions in a later addition to the framework.

<font color="blue" size="3"><br />package  com.efg.framework<br />{<br />   // Import necessary classes from the flash library<br />	import flash.display.Bitmap;<br />	import flash.display.BitmapData;<br />	import flash.display.Sprite;<br />	import flash.events.Event;<br />	import flash.geom.Point;<br />	import flash.text.TextField;<br />	import flash.text.TextFormat;<br />	import flash.events.Event;<br />	import flash.events.MouseEvent;<br />	import flash.text.TextFormatAlign;<br />	<br />	<br />	/**<br />	 * ...<br />	 * @author Jeff Fulton<br />	 */<br />	public class BasicScreen extends Sprite {<br />		<br />		<br />      public var displayText:TextField = new TextField();<br />      public var backgroundBitmapData:BitmapData;<br />      public var backgroundBitmap:Bitmap;<br />      public var okButton:SimpleBlitButton;<br />      public var imageButton:ImageButton;<br />	<br />		<br />      public var imageBitmapData:BitmapData;<br />      public var imageBitmap:Bitmap;<br />		<br />      public var useImageButton:Boolean = false;<br />		<br />		<br />      //ID is passed into the constructor. When the OK button is clicked, <br />      //a custom event sends this id back to Main<br />		<br />      private var id:int;<br />		<br />      //Constructor accepts our two passed in vars and then calls init<br />		<br />      public function BasicScreen(id:int,width:Number, height:Number, _<br />       isTransparent:Boolean, color:uint) {<br />			<br />         this.id = id;<br />         backgroundBitmapData = new BitmapData(width, height, isTransparent, color);<br />         backgroundBitmap = new Bitmap(backgroundBitmapData);<br />         addChild(backgroundBitmap);<br />      }<br />		<br />      public function addImage(bitmapData:BitmapData):void {<br />         imageBitmapData = bitmapData;<br />         imageBitmap = new Bitmap(imageBitmapData);<br />         addChild(imageBitmap);<br />      }<br />		<br />      public function createDisplayText(text:String, width:Number, _<br />       location:Point, textFormat:TextFormat):void {<br /> <br />         displayText.antiAliasType = flash.text.AntiAliasType.ADVANCED;<br />         displayText.y = location.y;<br />         displayText.x = location.x;<br />         displayText.width = width;<br />         displayText.defaultTextFormat=textFormat;<br />         displayText.text = text;<br />         addChild(displayText);<br />      }<br />		<br />      public function createOkButton(text:String,location:Point, width:Number, _<br />       height:Number, textFormat:TextFormat, offColor:uint=0x000000, _<br />       overColor:uint=0xff0000, positionOffset:Number=0):void {<br />			<br />         useImageButton = false;<br />         okButton = new SimpleBlitButton(location.x, location.y, width, height, _<br />          text, 0xffffff, 0xff0000, textFormat, positionOffset);<br /><br />         addChild(okButton);<br />         okButton.addEventListener(MouseEvent.MOUSE_OVER, okButtonOverListener, false, 0, true);<br />         okButton.addEventListener(MouseEvent.MOUSE_OUT, okButtonOffListener, false, 0, true);<br />         okButton.addEventListener(MouseEvent.CLICK, okButtonClickListener, false, 0, true);<br />      }<br />	<br />      public function createImageButton(imageOff:BitmapData,  imageOver:BitmapData, _<br />       location:Point):void {<br />         <br />         useImageButton = true;<br />         imageButton = new ImageButton(imageOff, imageOver, location);<br />         imageButton.addEventListener(MouseEvent.MOUSE_OVER, okButtonOverListener, false, 0, true);<br />         imageButton.addEventListener(MouseEvent.MOUSE_OUT, okButtonOffListener, false, 0, true);<br />         imageButton.addEventListener(MouseEvent.CLICK, okButtonClickListener, false, 0, true);<br />         addChild(imageButton);<br />      }<br />		<br />		<br />		<br />      public function setDisplayText(text:String):void {<br />         displayText.text = text;<br />      }<br />		<br />      //Listener functions <br />      //okButtonClicked fires off a custom event and sends the "id" to the listener.<br />      private function okButtonClickListener(e:MouseEvent):void {<br />         dispatchEvent(new CustomEventButtonId(CustomEventButtonId.BUTTON_ID,id));<br />      }<br />		<br />      private function okButtonOverListener(e:MouseEvent):void {<br />         if (useImageButton) {<br />            imageButton.changeButton(ImageButton.OVER);<br />         }else{<br />            okButton.changeBackGroundColor(SimpleBlitButton.OVER);<br />         }<br />      }<br />		<br />      private function okButtonOffListener(e:MouseEvent):void {<br />         if (useImageButton) {<br />            imageButton.changeButton(ImageButton.OFF);<br />         }else{<br />            okButton.changeBackGroundColor(SimpleBlitButton.OFF);<br />         }<br />      }<br />		<br />	}<br />	<br />}<br /></font><br />

The addImage() function

The addImage() function takes a BitmapData instance as it only parameter and sets the public imageBitmap variable's bitmapData attribute to reference it. We made this a public attribute so we would not need to code an interface for all of the transformations such as scale, alpha, etc that the developer might want to apply to the image. The external calling class can control this imageBitmap directly. This also applies to positioning the image. We will see an example shortly on how to do this.

The createImageButton() function

This function takes in the same parameters as the ImageButton class: A BitmapData instance for the "OFF" state, a BitmapData instance for the "OVER" state, and a point instance for the location of the button. In turn, this function creates an instance of ImageButton called imageButton and also sets the internal class variable useImageButton to true. This allows the code to switch between using the SimpleBlitButton and the ImageButton as the click through "ok" button. If we were adding this to the framework's Main.as class we would use that button click to move to the next state in the game loop state machine. For part 1 we simply demonstrate how to use these two classes together without utilizing the entire framework. In part two we will start to utilize the GameFrameWork.as base class and integrate in these new classes.

Creating the BasicScreenDemo.as

Using the the new ImageButton and expanded BasicScreen class we are going to create a simple example called BasicScreenDemo.as. I have done my demo in FlashDevelop and will embed the images needed at compile time. If you are using the Flash IDE you should import the images into the library using the same class names that I use in my embed. I have provided code that will allow you to use images from the library. You will need to comment out the embed statements and the change the variable instantiation for the BitmapData instances to the "//Flash IDE " lines. If you are using Flash CS4 or CS5 you can embed your assets as long as you set the location of the FlexSDK. In CS5 you will automatically be prompted to do this when you try to compile the first time.

Note: The zip file download contains code, project files, assets, and the .fla file (in CS4 format) to support both versions

Creating the project

1. Inside the /source/projects folder you will want to create a new folder called "ch13_classupdates".

2. Inside this folder you will want to create a folder called "flashIDE" or "flexSDK" depending on the development environment of your choice.

3. If you are using Flash Develop, Create a Flash Develop project (AS3 Project) inside the flexSDK folder with a class path of com.efg.demos.classupdates. This will create a src/com/efg/demos/classupdates folder. You will also want to create a folder called "assets" in this folder: src/com/efg/demos/classupdates/assets.

4. If you are using the FlashIDE you will want to create the com/efg/demos/classupdates folder inside the source/projects/ch13_classupdates/flashIDE folder. You will also want to Create the BasicScreenDemo.fla in this folder: source/projects/ch13_classupdates/flashIDE/BasicScreenDemo.as

5. Set the dimensions to 400x400 with a frame rate of 30.

6. Add the classes folder that contains the com/efg/framework package to your class path.

Creating the BasicScreenDemo.as class

The BasicScreenDemo.as file will be the "always compile" or "document class" (depending on your IDE of choice).

<font color="blue" size="3"><br />package com.efg.demos.classupdates<br />{<br />	import flash.display.Bitmap;<br />	import flash.display.BitmapData;<br />	import flash.display.Sprite;<br />	import flash.events.Event;<br />	import com.efg.framework.BasicScreen;<br />	import flash.geom.Point;<br />	/**<br />	 * ...<br />	 * @author Jeff Fulton<br />	 */<br />	public class BasicScreenDemo extends Sprite {<br />		<br />      [Embed(source = 'assets/asciirooidstitle.jpg')]<br />      public static const TitleJpg:Class;<br />		<br />      [Embed(source = 'assets/playbutton_off.jpg')]<br />      public static const PlayButtonOffJpg:Class;<br />		<br />      [Embed(source = 'assets/playbutton_on.jpg')]<br />      public static const PlayButtonOnJpg:Class;<br />		<br />      private var titleScreen:BasicScreen;<br />		<br />      //FlexSDK <br />      private var titleBitmap:Bitmap = new TitleJpg();<br />      // end Flex SDK<br />		<br />      //Flash IDE<br />      //private var titleBitmapData:BitmapData = new TitleJpg(0,0);<br />      //end flash IDE<br />		<br />      public function BasicScreenDemo():void {<br />         if (stage) init();<br />         else addEventListener(Event.ADDED_TO_STAGE, init);<br />      }<br />		<br />      private function init(e:Event = null):void {<br />         removeEventListener(Event.ADDED_TO_STAGE, init);<br />         // entry point<br />			<br />         titleScreen = new BasicScreen(1, 400, 400, false, 0x000000);<br />			<br />         //Flex SDK<br />         titleScreen.addImage(titleBitmap.bitmapData);<br />         //end Flex SDK<br />			<br />         //Flash IDE<br />         //titleScreen.addImage(titleBitmapData);<br />         //end Flash IDE<br />			<br />         titleScreen.imageBitmap.x = 50;<br />			<br />         titleScreen.useImageButton = true;<br />			<br />         //Flex SDK<br />         titleScreen.createImageButton(new PlayButtonOffJpg().bitmapData, new PlayButtonOnJpg().bitmapData, _<br />          new Point(150, 300));<br />         //end Flex SDK<br />			<br />         //Flash IDE<br />         //titleScreen.createImageButton(new PlayButtonOffJpg(0,0), new PlayButtonOnJpg(0,0), _<br />           new Point(150, 300));<br />         //end Flash IDE<br />         addChild(titleScreen);<br />		}<br />		<br />	}<br />	<br />}<br /></font><br />

This demonstration class simply creates an instance of the BasicScreen class (titleScreen) and then adds an instance of the TitleJpg embedded/imported class to the BasicScreen with the addImage() function call. To add the ImageButton we call the createImageButton() function passing in the PlayButtonOffJpg class, the PlayButtonOnJpg, and a Point instance to place the ImageButton on the TitleScreen.

Here are the assets that we use in this demo:

title
asciirooidstitle.jpg

on
playbutton_on.jpg

off
playbutton_off.jpg

Below is the working swf example:

By moving the mouse pointer over and off the "Play" Button the state will change.


Download the .zip file with all code, assets, and project files.

18May/100

HTML 5 Canvas: Using Processing.js To Develop Canvas Apps

This weekend, a friend of mine named Mike Foti noticed my pained expressions when I was talking about the HTML 5 Canvas, and he decided to help salve some of my injuries from my first few tests by pointing me towards a project named processing,js. processing.js is an MIT Media Labs project that began as a way to make the creation of Java Applets easier. It has been ported to work with the HTML 5 Canvas, and so far it looks promising.

The idea behind processing.js is to create a "programming language" that is used to create HTML 5 Canvas apps. If you think of the Canvas as a low-level display API, then processing.js is sort of like what ActionScript is to the SWF specification: it's an easier to use abstraction layer that assists in making applications.

If you look at the processing.js reference, you will see a lot of very useful looking functions that look like they will help take some of the pain put of creating Canvas applications. These include a lot of functions for mouse and keyboard support drawing graphics, etc., but also for application flow likeĀ  app loops and frame rates. However, one glaring omission is sound support. My friend had told me that he had seen a lot of Canvas apps that used processing.js on the web, and that makes a lot of sense to me. Since processing.js (or simply, Processing) has been around for a some time for Java, my inkling is that many Java developers have simply ported their Java Processing apps to the Canvas using processing.js. They make for stunning demos, but if they don't explore the Canvas at the API level are they missing something? The lack of sound in many of those demo apps may stem from the lack of support in processing.js, and not the lack of support in the Canvas (although support *is* lacking in the Canavs API). This is just a theory mind-you, but it seems like a fairly obvious situation to me.

Still curious, I sat down today and decided to port my "Gaudy Text Animation" HTML 5 demo from a couple days ago into processing.js. The results were mixed. While processing.js does appear to make some things simpler, it did not solve all my problems.

Here is a run-down of the conversion:

Support Processing.js In An HTML Page

The first thing you need to do when creating an app with processing.js is to include the library in the HTML page. After you have downloaded the current version, and place it somewhere that the HTML code can find. I simply put it in the same directory as my demo file. The following two pieces of code should be put in the section of your page.

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

[/cc] Next, you need to add support in JavaScript to get the processing interpreter running. This acts much like the Window load event we create with the native canvas API. [cc lang="javascript" width="550"]
[/cc]

(note: the above code was borrowed and modified from here: http://lethain.com/entry/2008/may/10/getting-started-with-processing-js/ )

In my previous HTML 5 Canvas examples I put all my code in the of the page. However, proper way to create an app with processing.js is to put the majority of the code in the . You do this by creating a
[cc lang="javascript" width="550"]


[/cc]

Application Loop

Now it is time to look at some code that is specific to processing.js. There are two main functions that you need to create for processing.js, both are called automatically.

  • setup(): is used to create the initial application settings
  • draw(): is used to redraw the screen on every frame

In setUp() you set -up things like the dimensions of Canvas, default colors, and the frame rate

[cc lang="javascript" width="550"]
void setup()
{
size(600, 150);
stroke(255);
frameRate(30);
}
[/cc];

In draw() you start making things happen. The most basic this you do, is set the background color (0=black). Also note that variables are declared Java-style, and can be declared outside of the functions. We will be using all of these variables to make the text appear. Notice that many of Phenobarbitals are the same as the ones we used in the "Gaudy Text Animation" HTML 5 demo.


[cc lang="javascript" width="550"]
String text1SizeDir = "up";
String text1Dir = "right";
int text1FontSize = 20;
int text1Xpos = 5;
String text1AlphaDir = "down";
float text1Alpha = 255;
void draw()
{
background(0);
}
[/cc]

Drawing Text Changes

While the setup and execution of a processing.js app differs from a standard Canvas app, the actual code to create the moving text is only slightly modified. This is because processing.js remains and "immediate mode" environment, and thus requires the entire screen to be repainted on every frame. However, in some ways it does feel like it is slightly easier to work with processing.js than the straight Canvas API. This text example might not be a good example of where one might be better than the other.

Drawing the text with processing.js looks like this:

[cc lang="javascript" width="550"]
font = loadFont("_sans");
textFont(font,text1FontSize);
fill(256, 0, 0) ;
text("Hello Canvas",text1Xpos,80);
[/cc]

Drawing the text with the Canvas API looked like this:

[cc lang="javascript" width="550"]
context.font = text1FontSize + 'px _sans';
context.fillStyle = '#FF0000';
context.textBaseline = 'top';
context.fillText ( text1 , text1Xpos, 80);
[/cc]

Note, the fill() function in processing .js is used to change the color of the text and apply an alpha transparency which we will do below.

Moving Text Changes

Moving the text across the screen is very similar in both the Canvas API and processing.js. The major difference comes when you apply the text to the screen (the last line of each example)

Moving the text with processing.js

[cc lang="javascript" width="550"]if (text1Dir == "right") {
text1Xpos += 10;

if (text1Xpos > 460) {
text1Dir = "left";
}
} else {
text1Xpos -= 10;

if (text1Xpos < 10) {
text1Dir = "right";
}

}
text("Hello Canvas",text1Xpos,80);
[/cc]

Moving the text with the Cavas API

[cc lang="javascript" width="550"]metrics = context.measureText(text1)
text1Width = metrics.width;
if (text1Dir == "right") {
text1Xpos += 10;

if (text1Xpos > 600-text1Width) {
text1Dir = "left";
}
} else {
text1Xpos -= 10;

if (text1Xpos < 10) {
text1Dir = "right";
}

}

context.fillText ( text1 , text1Xpos, 180);
[/cc]

Sizing Text Changes

Resizing the text to make it grow and shrink is also very similar in both processing.js and the Canvas API. The major difference is that you set the font and text size with two different calls with processing.js, while you do it with one function call with the Canvas API.

Sizing the text with processing.js

[cc lang="javascript" width="550"]if (text1SizeDir == "up") {
text1FontSize += 1;
if (text1FontSize > 40) {
text1SizeDir = "down"
}

} else {
text1FontSize -= 1;
if (text1FontSize < 20) {
text1SizeDir = "up"
}

}
font = loadFont("_sans");
textFont(font,text1FontSize);
[/cc]

Sizing the text with the Canvas API

[cc lang="javascript" width="550"]if (text1SizeDir == "up") {

text1FontSize += 2;

if (text1FontSize > 40) {
text1SizeDir = "down";
}
} else {

text1FontSize -= 2;

if (text1FontSize < 20) {
text1SizeDir = "up";
}

}
context.font = text1FontSize + 'px _sans';
[/cc]

Text Alpha Changes

Apply the alpha transparency to text is a bit easier with processing.js. Instead of setting a global context as you would with the Canvas API, you can apply the alpha transparency when you set the color of the text for drawing.

Text alpha fade with processing.js

[cc lang="javascript" width="550"]if (text1AlphaDir == 'up') {
text1Alpha +=16;
if (text1Alpha > 255) {
text1Alpha = 255;
text1AlphaDir = "down";
}
} else {
text1Alpha -=16;
if (text1Alpha < 0) {
text1Alpha = 0;
text1AlphaDir = "up";
}

}
fill(256, 0, 0,text1Alpha) ;
[/cc]

Text alpha fade with the Canvas API

[cc lang="javascript" width="550"]if (text1AlphaDir == 'up') {
text1Alpha +=.1;
if (text1Alpha > .9) {
text1AlphaDir = "down";
}
} else {
text1Alpha -=.1;
if (text1Alpha < .1) {
text1AlphaDir = "up";
}

}
context.globalAlpha = text1Alpha;
[/cc]

Text Shadow Changes

I could not find any built-in transformation for making a "shadow" in processing.js (I'm not saying it is not there, I just did not find it...yet), so I simply made two version of the text, one off center by 2 pixels for both x and y, and colored it a lighter color. We simply update both of these every frame instead of setting the global context for shadow as we do with the Canvas API.

Text Shadow with processing.js

[cc lang="javascript" width="550"]fill(200, 200, 200,text1Alpha);
text("Hello Canvas",text1Xpos+2, 82);
[/cc]

Text Shadow with the Canvas API

[cc lang="javascript" width="550"]context.shadowColor = '#DDDDDD';
context.shadowOffsetX = '2';
context.shadowOffsetY = '2';
context.shadowBlur = '2';
[/cc]

Full Code And Examples

See The Example of Gaudy Processing.js Text Demo

See the earlier Example of Gaudy Text Animation" HTML 5 demo using the Canvas API

Full code listing for processing.js Gaudy Text Demo:

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



[/cc]

16May/100

GameDev.net Gives The Essential Guide To Flash Games 4 Gs!

GameDev.net has reviewed The Essential Guide To Flash games, and has given it 4 Gs! 

Here is a good quote:

"The level of the book starts off quite simply. While it might help to
know a bit of computer programming, knowledge of ActionScript or the
"Flash way of doing things" isn't important. If you have a little bit of
programming, the book will move at a reasonable pace to teach you the
rest."

While the review has a few inaccuracies (there are 10 games, not 6, and while we don't create and graphics for title screens we certainly create them in our framework and we also show you how to create a high score table with Mochi services), it's still nice to see a review in the wild.

You can read the review here:
http://www.gamedev.net/columns/books/bookdetails.asp?productid=778

16May/100

EGM Magazine Spring 2010 Review: EGM Returns In Stunning Fashion

I was never a huge fan of EGM magazine.  Its' name was too close to Electronic Games, and it always appeared to be written for a generation of gamers just beyond my grasp.  However, with few options, I subscribed in 2008, only to have the magazine go out of business a couple issues later.

Last year, the original publisher, Steve Harris, bought the rights to the magazine and has spent the better part of a year revising it for relaunch.  If the first issue is any indication, he may have produced the best game related magazine in almost 15 years. Now I wonder what I missed for so long.

Steve Harris has a long history with video games and video game magazines.  He hold several world record high scores for arcade game (including Swimmer, one of my all-time favorites). He founded EGM back in 1989, and was the publisher of the reborn Electronic Games magazine of the 90's.  If anyone could create a modern video game magazine worth reading, it is Steve Harris.

Harris has created two new magazine actually, an online-only publication named EGMi, and the new printed version of EGM.  The Spring 2010 issue was just released, and I picked-it-up at the local Barnes And Noble (while trying to spot my own book in the computer section...it was there!).

I was floored by the depth and sophistication of many of the articles.  This is not a magazine for short attention spans.  Where most recent video game magazines stop when their articles are just getting interesting, the new EGM appears to kick into another gear.

Some examples of the articles that have kept me reading for the past week are:

  • "Critcal Mass" by Evan Shamoon, a 5 page look at the affect of Metacritic on the game industry.
  • "Taking [Motion] Control" by Kyle Orland : a 2-page analysis of what motion control means to the game industry
  • "The Last Word On Games" by Kevin Gifford : a 4-page history of EGM.
  • "Back From The Second Dimension" by Kris Pigna, a 6-page look at "Retro Evolved" (post-retro) games.
  • "David Jaffe: The EGM Interview" by Brady Fiechter: a massive 8-page interview with game designer/developer David Jaffe
  • "The Case Against The Gaming Press" by Dan Hsu : a 2-page indictment of game journalists and their disregard for the industry that keeps them employed.
  • plus several more interesting one pagers...

I used to beg my inanimate magazines for just one article of this scope an interest in an issue, and here EGM Spring 2010 has a half-dozen.  I was shocked to find this much mature, in-depth analysis in a single publication.

This is not all there is to read in the new EGM.  There are the standards as well: the news, the reviews,and the  previews.  While they  also provide some very good reading, my brain has been trained by so many other magazines to scan these with an eye for bias, shallow genre knowledge, and histrionics, that it was hard to consume them the same way I dove into the other articles.  Hopefully I will be able to get past this "cognitive dissonance" because there are some very good people involved with these sections (including reviews editor Mark Bozon from IGN).

I tested EGMi online as well ,and while it was interesting, I was not completely sold.  However, the print magazine was so vastly superior to anything else, that I'm happy with that for the time being.  If the next issue holds-up as well as the first, I will be an instant subscriber.  I encourage you to pick-up copy, and show your support for a magazine that is really trying to do something special.

Filed under: Book Reviews No Comments
15May/100

HTML 5 Canvas: Creating Gaudy Text Animations…Just Like Flash! (sort of)

Since I have not posted anything about the Canvas in a few weeks I wanted to show some of the experiments I've been working on. Everyone knows that animating text in Flash is very easy and has been around since the technology began. It seems to me, that if the Canvas is going be a "Flash killer", then it must have as robust, if not more-so features than Flash. You can read the Canvas text API here: http://dev.w3.org/html5/2dcontext/#text and see for yourself, but from my view it does not appear to have as many features as Flash at all. Still, I wanted to try it out and see what was possible. Here then is my demo of a HTML5 Canvas text animation.

http://www.8bitrocket.com/wp-content/uploads/2010/07/textblog_movetext.html

Yes, it is true. The HTML 5 Canvas can be used to created some of the same gaudy crap that Flash has been doing for years. Not all of what Flash can do, but some of it. Enough to be dangerous anyway. It's funny, the HTML guys have complained for years about "stupid Flash animations", yet now they have their own tool to do exactly the same thing. Will they practice restraint?

Code Breakdown

Here are the interesting bits of the code. I'm not going to talk about the basics of the canvas, you can get that from here: HTML 5 Canvas For Flash Developers #1: What The #@*! Is The HTML 5 Canvas? or here Exploring The HTML 5 Canvas For Flash Developers #2: Tracking The Mouse To Draw On The Screen.

Animation Loop

It's simple to put text on a Canvas, put animating it is another matter. The Canvas uses an immediate mode drawing paradigm which means he entire screen must be redrawn every time you want to move an object or objects. Unless you are a fan of blitting (we are!) most Flash developers are used to having the player keep track of their objects and redraw them on the screen on each frame. Because of this, they don't need to custom code an animation loop. With the HTML 5 Canvas, you need to create your own loop to have things move on the screen. The code to do this is in the box below. Here are the details of this code:

  • After the page loads (eventWindowLoaded() callback function) we use a setInterval function that should be very familiar to Flash developers (especially those versed in AS2). We set the interval to call appLoop() every 50 milliseconds.
  • The appLoop() only does one thing: calls drawScreen(). This is where you will code all of your "immediate mode" screen manipulations. Remember, there is no display list, so you will be redrawing EVERYTHING on EVERY call to drawScreen().
  • The clearScreen() function is called on every time we are going to redraw. It will perform two functions. It will draw the background, and it will reset and global transformations (i.e. alpha) so that they don't effect the drawing of the background.

[cc lang="javascript" width="550"]function eventWindowLoaded() {

...

setInterval("appLoop()", 50);

...

}

function appLoop() {
drawScreen();
}

function drawScreen() {

clearScreen();
}

function clearScreen() {
context.clearRect(0, 0, 600,400);
context.fillStyle = '#000000';
context.fillRect(0, 0, 600, 400);

}

[/cc]

Moving Text

Now we are going to move some text back and forth across the screen. The steps below describe the code we will create to do this:

  • First, we create a variable named text1Dir that we will use to tell us which direction the text is moving. We want to make sure that we can reverse direction of the text when it reaches the side of the screen.
  • Next we create a variable to hold the calculated x position of the text: text1Xpos;
  • We use a variable named text1 to describe the text that will be displayed: text1 = "Hello Canvas!";
  • In drawScreen() we will start adding code that will redraw the text in text1 every time the function is called.
  • We use the measureText() function of the 2D context to find the width of the text in text1. The function returns an instance of metrics that contain only one property(at this time), width.
  • We use this width to determine if the text has reached the right side of the canvas( (if (text1Xpos > 600-text1Width))) or the left side of the canvas( if (text1Xpos < 10) ).
  • If it has reached either side, we will switch directions using the text1Dir variable ("right" or "left")
  • If we have not reached either side, we will update the position of the text (text1Xpos) based on the direction in text1Dir: "right": (text1Xpos += 10;) or "left": (text1Xpos -= 10;)
  • Finally, we apply the new text to the screen:
    context.fillText ( text1 , text1Xpos, 180);

[cc lang="javascript" width="550"]function eventWindowLoaded() {

...

text1Dir ="right";
text1 = "Hello Canvas!";

...

}
function drawScreen() {

...

metrics = context.measureText(text1)
text1Width = metrics.width;

if (text1Dir == "right") {
text1Xpos += 10;

if (text1Xpos > 600-text1Width) {
text1Dir = "left";
}
} else {
text1Xpos -= 10;

if (text1Xpos < 10) {
text1Dir = "right";
}

}
context.font = '20px _sans';
context.fillStyle = '#FF0000';
context.textBaseline = 'top';
context.fillText ( text1 , text1Xpos, 180);

}

[/cc]

Text Size

We are going to use a similar set of code to that of the movement, for both sizing the text, and for creating the alpha fade on the text. The idea is that we keep track of the direction (for size it will be "up" or "down" instead of "right" and "left" for movement) and reverse accordingly when we reach a limit set in the code.

  • We create a variable to hold the "direction" of the resize: text1SizeDir = "up";
  • We create a variable to hold the font size of the text: text1FontSize=20;
  • In drawScreen() we use text1SizeDir to determine what the next font size for the text will be when we redraw it.
  • We apply the font size to the text like this: context.font = text1FontSize + 'px _sans';, simply appending the font size to the font declaration for context.

[cc lang="javascript" width="550"]function eventWindowLoaded() {

...

text1SizeDir = "up";
text1FontSize=20;

...

}

function drawScreen() {

...

if (text1SizeDir == "up") {

text1FontSize += 2;

if (text1FontSize > 40) {
text1SizeDir = "down";
}
} else {

text1FontSize -= 2;

if (text1FontSize < 20) {
text1SizeDir = "up";
}

}

...

context.font = text1FontSize + 'px _sans';

...

}
[/cc]

Text Alpha Transparency For Fading

Uses an Alpha value for fading the text is very similar to text size and movement except for one major fact: alpha is "global transition" and thus must be used with special care as it will apply to everything on the screen when it is redrawn. For this reason, we will need to add a line of code to the clearScreen() function that resets the alpha before we draw the background. like AS3, alpha is set between the numbers 1 and 0 (AS2 uses a percentage).

  • The text1AlphaDir variable is similar to text1SizeDir as it uses the value "up" and "down", however we will start it with the value "down" which signifies that we will start by fading the text.
  • In drawScreen() we will set context.globalAlpha just before we display the text on the screen. Everything draw after context.globalAlpha will be drawn with the value set for the alpha. It must be reset for anything that does not need the alpha value.
  • We will increment and decrement the alpha value by .1, or 10% each time we redraw the screen.
  • We reset the context.globalAlpha in clearScreen() to 1 so that the background will be drawn with no alpha fade.

[cc lang="javascript" width="550"]function eventWindowLoaded() {

...
text1AlphaDir = "down";
...

}

function drawScreen() {

...

if (text1AlphaDir == 'up') {
text1Alpha +=.1;
if (text1Alpha > .9) {
text1AlphaDir = "down";
}
} else {
text1Alpha -=.1;
if (text1Alpha < .1) {
text1AlphaDir = "up";
}

}
context.globalAlpha = text1Alpha;

...

}

function clearScreen() {

...
context.globalAlpha = 1;
....

}

[/cc]

Text Shadow

Finally, we get to the text shadow. Shadows are fairly easy to create. However, since they are set as part of the global context, you need to be careful how you use them. There are 4 attributes that need to be set to create a shadow:

  • context.shadowColor : The color of the shadow. #XXXXXX hex format is valid.
  • context.shadowOffsetX : The number of pixels to set the shadow on the x axis of the image.
  • context.shadowOffsetY : The number of pixels to set the shadow on the y axis of the image.
  • context.shadowBlur : The number of pixels to spread a blurring effect across both axis

[cc lang="javascript" width="550"] function drawScreen() {

...

context.shadowColor = '#DDDDDD';
context.shadowOffsetX = '2';
context.shadowOffsetY = '2';
context.shadowBlur = '2';

...
}
[/cc]

Full Code Listing

Here is the full code listing for this little gem:

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

Your browser does not support the HTML 5 Canvas.

[/cc]

There are more things that you can do with text, but most of them are manipulations of the global context. I'll report back when I have mastered that aspect of the canvas to make something worth showing. However, the point of this tutorial is to show that while some of the FX you can create with the HTML 5 Canvas are similar to those in Flash, creating them takes a lot more low level code than seems reasonable for a Flash designer. Obviously, tools will be created to build some of these things automatically (you can bet Adobe is on it right now), but those tools will still end-up writing out code much like this...all of it clearly visible in the HTML page.

13May/100

Retro Scan: Original Atari ST Action Interview with Jeff Minter (1988)

Retro Scan: Original Atari ST Action Interview with Jeff Minter (1988)

A couple weeks ago I was hunting around in Steve's garage and found the May 1988 issue of ST Action magazine. I scanned in the review of Dungeon Master in that issue and put it on the site. This issue also contains a great 5 page interview with 80's UK game design icon, Jeff Minter.

minter1_thumb.jpg

The interview was done by David Stewart, a regular contributor to the magazine. I tried to look up David to ask permission to re-print the interview but I met many dead ends on my search. I have heard that there are magazine preservation sites that have been given permission to re-print ST Action articles, but I had no luck in obtaining such permission.

In any case, I have scanned in the 5 pages and they for your reading pleasure. If you own the rights to these are want to taken down please email me at info[at]8bitrocket[dot]com and I will do so. If so own the rights to this interview and have it displayed on the web elsewhere I will delete mine and link to your version. I searched high and low and could not find this article on the info-baun and thought it would be a good read for those interested in games, retro games, llamas, Wales, or psychedelic color/music generators...but especially llamas and camels.

minter1.jpeg

minter2.jpeg

minter3.jpeg

minter4.jpeg

minter5.jpeg

Filed under: Atari Nerd No Comments
11May/100

Virtual Pinball , An LCD Cabinet: My Pinball Dreams (Nearly) Realized?

I love pinball, and the last few years virtual pinball games like Pinball Hall Of Fame: The Williams Collection has satisfied some of my thirst for classic, kinetic, pinball action. However, there is nothing better than standing-up and playing a real pinball machine. However, the days of pinball machines are almost gone. The only remaining pinball manufacture is Stern, and they sell games mostly for people's home game rooms. The Pinball Hall Of Fame in Las Vegas is a great place to see and play dozens of restored pinball games from the days of yore, but the idea of dragging my wife and kids to Las Vegas (a city a absolutely abhor) just to play pinball seems ludicrous although my wife would probably be game, as she loves pinball just as much as I do).

I've thought about buying a single pinball machine, but there are a lot of issues with that idea. The first is that most pinball machines require a lot of maintenance to keep working. While I'm pretty good at software and computer configurations, I'm really not that good with mechanical devices or electronics. If it broke down, I'd buy the manuals, try a couple times to fix it, but when I failed, it would simply gather dust like so many other projects I have 1/2 finished in the garage. The other problem with buying a pinball machine is this: which one do I choose? If I only have the space for one, how do I make that kind of "Sophie's Choice" over classic pinball games? Do I buy Quicksilver, my favorite game from the 80's, The Simpsons, the game my brother and I played obsessively during college, or The Machine Bride Of Pinbot, the game my wife and I played and bonded over when we first started dating?

Well, it seems that I am not alone in this dilemma. There are a lot of pinball fans out there who have been working on (and solving) many of these problems for the past few years. They do not get publicized very often, but their work is nothing short of amazing. First, there are few great, free-ware software programs that allow people to recreate virtual versions of their favorite pinball games on in Windows. Future Pinball is a freeware 3D pinball machine design tool and construction program. It has been used to create nearly perfect versions of classic pinball games. Visual Pinball does a lot of the same thing, but it includes better physics (according to some users/players) and ROM support to help simulate newer machines. Along with the design tools some other useful programs include PinMAME, a version of MAME that supports the (mostly) monochrome video screens of later model pinball games, and Hyperpin, a menu system that supports games developed in both Future Pinball and Visual Pinball. There is a thriving community building these games, and most of them can be found at vpforums.org.

Besides simply playing games on a PC through, menus system Hyperpin have created a brand-new opportunity for pinball fans: the LCD multi-game pinball cabinet. These are home-made "pinball machines" that utilize two LCD screens: a 42" (or so) screen laid-longwise that acts as the pinball table, and a 20" (or so) screen that sits at one one end of the long screen to act as the back glass. Pinball games are simulated using a dual monitor windows configuration, with tables selected using Hyperpin, and played with custom controls on the cabinet including flippers and even a plunger. This is hard to describe, here are a few youtube.com videos of machines that pinball fans have made themselves.

 

 

 

While this is not a perfect solution (yet), it does solve both my dilemmas. It works off a PC computer, which I can probably take apart and put together blindfolded, and it allows for multiple machines to exist in the same physical space. Making the decision that is is a really cool idea is only the first step though. Now I have to figure out how to make it happen. Of course, someone will probably start building these things to sell as a business before I get around to actually making my own, and ultimately, that might be the best option for me.

Filed under: Atari Nerd No Comments
10May/100

The Essential Guide To Flash Games: The Infomerical

I believe this speaks for itself.

8May/100

Fixed Stand-Alone Flash Player 10.1 Will Be Not Be Released Until The Final Version Of 10.1 Player

Earlier this week I found out (and tested) that Adobe had fixed bitmapData.hitTest() in the latest RC2 version of the Flash Player.  However, the stand-alone player delivered with CS5 was not updated.  This means that you still have to test all your code in a browser, and not in the Flash IDE.

Now word had come from Adobe that the stand-alone player will not be updated until the final version of 10.1 is released.  I was just this on the Adobe prerelease forums.

"Flash CS5 released with the beta 3 version of Player 10.1.  We will
release a StandAlone player update once the final version of the Player
ships."

While this is not a huge issue, it does means that until 10.1 is finalized, you will need to download the 10.1 RC2 Flash player, and test all your code in an external browser.  If not, you may still find weird bugs even though you think you have updated to 10.1 RC2.

This site is protected by Comment SPAM Wiper.