Ok! First part of this experiment. For this piece I will use
Drawing an Image to the Canvas with JavaScript. Let me also take a moment to mention how much I detest those sites that use javascript to alter the text you try to copy out of their page. Creepy.
Anyway. This tutorial goes over the basic task of displaying an image to the page and then bouncing it around. I decided to start with this since it was (a) simple and (b) I already know some flex and believe I can accomplish the same task.
Before I start going over my solution, I want to talk a little about tools. I have never felt it was fair to ask people first learning a new technology to also learn a new IDE at the same time, which Flex tutorials are rather heavy on. So for this I stuck to very basic tools.
For Canvas, I used vim and Safari. For Flex I used vim, Safari, mxmlc (the Flex command line compiler) and Adobe's stand alone player.
Secondly, I want to make it clear, I am a newbie to both these technologies. I am sure there are better ways to do things, built in tools, add ons that make things easier, etc..... I do not know any of these things yet. I am still figuring out what things are needed to accomplish a task and which things are simply things some tutorial author did that LOOK necessary but are not.
Now, on to the actual stuff I wrote. Obviously for Canvas I followed the tutorial pretty closely so the files are only a little different from what was on the page. Sadly I am still working out how to post code to blogger, so the formatting is less then stellar.
For canvas I had three files (including the image)
jsplatformer.html
<html lang="en">
<head>
<title>JavaScript Platformer 1</title>
<script type="text/javascript" src="jsplatformer1.js"></script>
</head>
<body>
<canvas id="canvas" width="640" height="480">
<p>Your browser does not support the canvas element.</p>
</canvas>
</body>
</html>
jsplatformer.js
// target frames per second
const FPS = 30;
var x = 0;
var y = 0;
var xDirection = 1;
var yDirection = 1;
var image = null;
var canvas = null;
var context2D = null;
window.onload = init;
function init()
{
image = new Image();
image.src = "file:/./jsplatformer1-smiley.jpg";
canvas = document.getElementById('canvas');
context2D = canvas.getContext('2d');
setInterval(draw, 1000 / FPS);
}
function draw()
{
context2D.clearRect(0, 0, canvas.width, canvas.height);
context2D.drawImage(image, x, y);
x += 1 * xDirection;
y += 1 * yDirection;
if (x >= 450)
{
x = 450;
xDirection = -1;
}
else if (x <= 0)
{
x = 0;
xDirection = 1;
}
if (y >= 250)
{
y = 250;
yDirection = -1;
}
else if (y <= 0)
{
y = 0;
yDirection = 1;
}
}
For Flex, there were a few more files but not many:
Simple1.html
<html lang="en">
<head>
<title>JavaScript Platformer 1</title>
</head>
<body>
<object>
<param name="movie" value="Simple1.swf">
<embed src="Simple1.swf" width="640" height="480">
</embed>
</object>
</body>
</html>
Simple1.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
styleName = "plain"
xmlns="source.*"
layout="absolute"
frameRate="30"
width="640"
height="480"
creationComplete="initApp()"
enterFrame="enterFrame(event)">
<mx:Script>
<![CDATA[
public function initApp():void
{
canvas.init();
}
public function enterFrame(event:Event):void
{
canvas.onTick();
}
]]>
</mx:Script>
<SimpleCanvas id="canvas" width="100%" height="100%" themeColor="#ffffff" />
</mx:Application>
Simple.as
package source {
import mx.core.UIComponent
import flash.display.Bitmap
public class SimpleCanvas extends UIComponent
{
[Embed(source = '../assets/jsplatformer1-smiley.jpg')]
public static const SmileImage:Class
private var SmileBmp:Bitmap = null;
private var xD:int = 1
private var yD:int = 1
public function init():void
{
SmileBmp = new SmileImage()
addChild( SmileBmp )
}
public function onTick():void
{
if (SmileBmp == null)
return;
SmileBmp.x += 1*xD;
SmileBmp.y += 1*yD;
if (SmileBmp.x + SmileBmp.width >= width)
{
xD = -1
}else if (SmileBmp.x <= 0)
{
xD = 1
}
if (SmileBmp.y + SmileBmp.height >= height)
{
yD = -1
}else if (SmileBmp.y <= 0)
{
yD = 1
}
}
}
}
Ok, enough of the raw code, onto some comments. The core logic is the same, which is not surprising. The differences were more in feel.
Simplicity:Canvas won when it came to simplicity. 2 code files to Flex's 3, and information was not as duplicated (for instance, the size of the Flex frame had to be put in multiple locations). Canvas was much more 'start up and go', one had to worry much less about how they were going to do things or how to structure their project.
This also gets into my chief complaint about Flex so far. Flex has many ways to do the same things,.. it feels like a language that has been extended over the years in order to accommodate programmers rather then programmers adjusting to it. This kind of flexibility is good for development, but it makes life for the newbie difficult. I went through 3 different flex tutorials, each one did things sufficiently differently that lessons from one could not easily be applied in others, and figuring out why something did not work was difficult because only a few comments might discuss the way that particular author was doing things.
For instance, loading and image. Canvas seemed to have a way to do it, Image() and then set the source.
Flex, first you have 3 different ways to embed an image, plus there were people talking about a 'loader' API you could also use. Images could be (and in different examples, were) loaded as Bitmap, Sprite, FlexSprite, FlexBitmap, UIComponent, BitmapData, or MovieClip. In various examples they might be added directly to the canvas or immediately embedded in a temp container which in turn was added, with no real explanation of why people were doing this.
There is also the issue of mxml vs as. mxml is for layout and UI, as is for logic.. so you have two different syntaxes for the same functionality, with the intent being the mxml syntax makes layout easier while actionscript makes logic easier, but at first glace figuring out why you have to completely different syntaxes for the same language can be a bit confusing.
Explicitness:Flex was better about explicitness. With Canvas, I guess the whole js file was either converted to a class or processed as some kind of procedural program where it looks for key symbols and links to them. This 'by convention' approach makes things simple, but feels a bit like a big gray room where you are not sure what else might be in there. Flex had things contained within a nice clean class, everything outside language keywords had to be imported (so the split between API and language was much clearer), and entry functions were explicitly defined in the mxml file. You got a much better sense for how things fit into a larger framework.
I admit, I like Flex's explicitness.
Integration:This one is a good example of 'what do you want to use it for?'. Flex produces self contained applications, either for embedding in a web page or running as a desktop application. All interaction with a larger system probably needs to be done via APIs to things like XMLRPC or sockets. However, Flex has no knowledge of the page in which it exists.
Canvas is integrated into the web page, so you can use the main html page for layout and can pass information (like buttons and forms) from the page to the Canvas. I am guessing this also means the Cavans probably has access to other page information so you can adjust what is going on inside the Canvas according to the page, which might contain other technologies like Django linking to a database.
So Canvas feels like a dedicated web technology designed to work with other web technologies... Flex feels more like Java did... it can be run through websites, but is not really 'part' of them.
Asset ManagementCanvas dynamically loads its assets, including pulling them from remote (and remotely managed) locations, and it does this very naturally. Since it is not 'compiled' till someone views the page it can delay as long as possible.
Flex needs to pre-embed images into it's self contained file, so it needs to know ahead of time what each image will be (and seems to convert each asset to a named class?). This brings up the concern of 'what if you do not know till compile time?'... do you need to name EVERY image or is there some way to grab an entire directory? I am guessing there is some kind of html API within Flex for grabbing content off the web and displaying it, but I doubt it is as natural.
So I have concerns about Flex, but these feel like 'newbie/easy' concerns that have solutions later on. Again, Canvas's integration with the rest of a site gives it some clear advantages if you need that kind of structure.
So, this was the very first attempt to compare them. Next up... jsplatformer Part 2!