Archive

Posts Tagged ‘javascript’

twitter-node https fix

November 1st, 2011 No comments
nodejs twitter-node

nodejs twitter-node

twitter streaming api

twitter streaming api

Como muchos sabran, hace un tiempo el steaming api de twitter solo funciona con https.

Para nodejs existe el modulo twitter-node, que permitia consumir este streaming, pero dejo de funcionar por el tema del https.

Aca adjunto el index.js de ese modulo (el codigo js que lo hace funcionar) fixeado para que trabajo con https.

Como fix extra, también deje habilitado el debug (propiedad que existía pero no hacia nada).

 

//Fixed by Cesar Casas (lortmorris@gmail.com)
var https         = require('https'),
    query        = require('querystring'),
    Parser       = require('./parser'),
    EventEmitter = require('events').EventEmitter,
    Buffer       = require('buffer').Buffer;

// process.mixin is gone, a function for replacement
function extend(a, b) {
  Object.keys(b).forEach(function (key) {
    a[key] = b[key];
  });
  return a;
}

// Creates a streaming connection with twitter, and pushes any incoming
// statuses to a tweet event.
//
// options - optional Object that specifies custom configuration values.
//
// Valid option keys:
//
// port      - Integer of proxy port
// host      - String or ip address of the proxy server.  Defaults to 'stream.twitter.com'.
// path      - String of the base path for the request.
// action    - String part of the URL that specifies what to query for.
// track     - Array of keywords to filter.  See track()
// following - Array of userIDs to filter.  See follow()
// locations - Array of lat/long tuples.  See location()
// params    - Extra HTTP params Object to send with the request.
// user      - String Twitter login name or email.
// password  - String Twitter password.
//
// Returns TwitterNode instance.
var TwitterNode = exports.TwitterNode = function(options) {
  EventEmitter.call(this);
  if(!options) options = {};
  var self           = this;
  this.port          = options.port      || 80;
  this.host          = options.host      || 'stream.twitter.com';
  this.path          = options.path      || '/1/statuses/';
  this.action        = options.action    || 'filter';
  this.trackKeywords = options.track     || [];
  this.following     = options.follow    || [];
  this.locations     = options.locations || [];
  this.params        = options.params    || {};
  this.user          = options.user;
  this.password      = options.password;
  this.headers       = { "User-Agent": 'Twitter-Node' };
  this.debug         = options.debug || false;
  this.parser        = new Parser();
  this.parser.addListener('object', processJSONObject(this));
  this.parser.addListener('error', function (error) {
    self.emit('error', new Error('TwitterNode parser error: ' + error.message));
  });
  if (options.headers) {
    extend(this.headers, options.headers);
  }
}

TwitterNode.prototype = Object.create(EventEmitter.prototype);

// Track the following keyword.  If called multiple times, all words are sent
// as a comma-separated parameter to Twitter.
//
// See: http://apiwiki.twitter.com/Streaming-API-Documentation#track
//
// word - String word to track.
//
// Returns nothing.
TwitterNode.prototype.track = function track(word) {
  this.trackKeywords.push(word);
  return this;
};

// Follow the given twitter user (specified by their userID, not screen name)
// If called multiple times, all userIDs are sent as a comma-separated
// parameter to Twitter.
//
// See: http://apiwiki.twitter.com/Streaming-API-Documentation#follow
//
// userID - Integer userID to track.
//
// Returns nothing.
TwitterNode.prototype.follow = function follow(userId) {
  this.following.push(userId);
  return this;
};

// Match tweets in the given bounding box.
//
// See: http://apiwiki.twitter.com/Streaming-API-Documentation#locations
//
// Example: location(-122.75, 36.8, -121.75, 37.8) // SF
//
// lng1, lat1 - southwest corner of the bounding box.
// lng2, lat2 - northeast corner.
//
// Returns nothing.
TwitterNode.prototype.location = function location(lng1, lat1, lng2, lat2) {
  this.locations.push(lng1, lat1, lng2, lat2)
  return this;
};

TwitterNode.prototype.stream = function stream() {
  if (this._clientResponse && this._clientResponse.connection) {
    this._clientResponse.socket.end();
  }

  if (this.action === 'filter' && this.buildParams() === '') return;

	var headers = extend({}, this.headers),
      twit    = this,
      request;

  headers['Host'] = this.host;

  if (this.user) {
    headers['Authorization'] = basicAuth(this.user, this.password);
  }

var options = {
  host: this.host,
  port: this.port,
  path: this.requestUrl(),
  method: 'GET',
  headers : headers
};

if(this.debug) console.log(options);

var req = https.request(options, function(res) {

if(this.debug)  console.log("statusCode: ", res.statusCode);
if(this.debug)  console.log("headers: ", res.headers);

  res.on('data', function(d) {
    twit._receive(d);
    if(this.debug) process.stdout.write(d);
  });

  res.on('response', function(d) {
	    twit._clientResponse = d;
	    if(this.debug) process.stdout.write(d);
	  });

  res.on('end', function() {
      twit.emit('end', this);
      twit.emit('close', this);
    });

});

req.end();

req.on('error', function(e) {
  console.error(e);
});

  return this;
};

// UTILITY METHODS

// Passes the received data to the streaming JSON parser.
//
// chunk - String data received from the HTTP stream.
//
// Returns nothing.
TwitterNode.prototype._receive = function(chunk) {
  this.parser.receive(chunk);
  return this;
};

// Builds the URL for the streaming request.
//
// Returns a String absolute URL.
TwitterNode.prototype.requestUrl = function() {
  var url =  this.path + this.action + ".json" + this.buildParams();
	console.log('make url: ', url);

	return url;
};

// Builds the GET params for the streaming request.
//
// Returns URI encoded string: "?track=LOST"
TwitterNode.prototype.buildParams = function() {
  var options = {};
  extend(options, this.params);
  if (this.trackKeywords.length > 0) options.track = this.trackKeywords.join(",");
  if (this.following.length > 0)     options.follow = this.following.join(",");
  if (this.locations.length > 0)     options.locations = this.locations.join(",");
  if (options.track || options.follow || options.locations) {
    return "?" + query.stringify(options);
  }
  return "";
};

// Base64 encodes the given username and password.
//
// user - String Twitter screen name or email.
// pass - String password.
//
// Returns a Basic Auth header fit for HTTP.
var basicAuth = function basicAuth(user, pass) {
  return "Basic " + new Buffer(user + ":" + pass).toString('base64');
};

// Creates a callback for the object Event of the JSON Parser.
//
// twit - an instance of this TwitterNode.
//
// Returns a function to be passed to the addListener call on the parser.
var processJSONObject = function processJSONObject(twit) {
  return function(tweet) {
    if (tweet.limit) {
      twit.emit('limit', tweet.limit);
    } else if (tweet['delete']) {
      twit.emit('delete', tweet['delete']);
    } else {
      twit.emit('tweet', tweet);
    }
  };
};

Utilidades para el manejo del flujo asincrónico en NodeJS

nodejs

nodejs

Los que programan en NodeJS seguramente habrán notado lo dificil que es seguir el flujo del programa cuando tenemos varias llamadas a funciones que realizan operaciones asincronicas.
Los casos mas comunes que se suelen dar son donde tenemos que realizar 2 o mas operaciones asincrónicas en serie o en paralelo y debemos determinar cuando se han finalizado de procesar.
Para ello hay varias librerías que nos ayudan a escribir código mas legible y ahorrarnos un poco de indentación, pero la verdad es que, en mi opinión, la mayoría son demasiado complejas y tienen demasiados “features” para resolver problemas sencillos.
Basandome en algunas de estas librerías y algunos conceptos que leí por ahí, desarrollé unas utilidades simples.

1) forEachAsync: Permite realizar una operación asincrónica en cada iteración y continuar a la siguiente al finalizarla.

 

Array.prototype.forEachAsync = function(iterator, then) {
	var self = this;
	var loop = function(i) {
		if (i < self.length) {
			iterator(self[i], function() {
				loop(i+1);
			});
		}
		else {
			then();
		}
	};
	loop(0);
};

Ejemplo:

[1,2,3,4,5].forEachAsync(function(item, next) {
	console.log('item ' + item);
	setTimeout(function() {
		next(); // avanzamos al siguiente item, alias ‘continue’
	}, 500);
}, function() {
	console.log('end');
});

2) forEachAsyncParallel: Parecido a la versión anterior pero permite n cantidad de operaciones simultaneas.

Array.prototype.forEachAsyncParallel = function(iterator, max, then) {
	var self = this;
	var count = 0, index = 0;
	var loop = function() {
		if (index == self.length && count == 0) then();
		else if (index < self.length) {
			count++;
			iterator(self[index++], function() {
				count--;
				loop();
			});
		}
	};
	if (self.length == 0) then();
	for (var i = 0, len = Math.min(max, self.length); i < len && index < self.length; i++) loop();
};

Ejemplo:

[1,2,3,4,5].forEachAsyncParallel(function(item, next) {
	console.log('item ' + item);
	setTimeout(function() {
		next();
	}, 500);
}, 2, function() {
	console.log('end');
});

3) Futuros / continuaciones
Podemos aplicar el concepto de “currying” y hacer una función que nos ayude a encapsular una operación asincrónica para recuperar el resultado mas adelante.
Este concepto consiste en derivar una funcion de n parámetros en una que solo acepte un parámetro. Si aplicamos esto al callback podemos hacer lo siguiente:

function searchApi(url, callback) {
	// async op...
}
function readFile(path, callback) {
	// async op...
}

// creamos funciones especializadas
function curriedSearchApi(url) {
	return future(searchApi, arguments, 1);
}
function curriedReadFile(path) {
	return future(readFile, arguments, 1);
}

// iniciamos las operaciones...
var apiSearch = curriedSearchApi('http://google.com?q=lalala');
var fileReader = curriedReadFile('/etc/passwd');

// mas adelante...
apiSearch(function(err, result) {
	fileReader(function(err, result) {
		// terminaron ambas operaciones, hacemos algo con ambos resultados
	});
});

Y aquí está la implementación de “future”:

function future(fn, args, i) {
	var done, err, result;
	var cb = function(e, r) {
		done = true;
		err = e,
		result = r;
	};
	args = Array.prototype.slice.call(args);
	args[i || 1] = function(e, r) {
		cb(e, r);
	};
	fn.apply(this, args);
	return function(_) {
		if (done) _(err, result);
		else cb = _;
	};
}

Como se ve, lo que hacemos es llamar a la funcion fn con los argumentos recibidos. i indica el índice que ocupa el callback en el objeto arguments.
Creamos nuestro propio callback que va a almacenar el resultado y retornamos una función cuyo único parámetro es un callback.
Si al momento de llamar esta función ya teníamos el resultado, simplemente lo devolvemos, caso contrario se reemplaza el callback por el nuevo.

Hay varias formas de resolver los casos anteriores, algunas tan sencillas como usar contadores y otras algo rebuscadas pero que en definitiva ayudan a mantener legible el código.
Pueden ver la lista de módulos que ayudan a resolver este tipo de problemas aquí: https://github.com/joyent/node/wiki/modules#async-flow

Espero les haya gustado, hasta la próxima! :D

Javascript bible gold edition download pdf free

May 15th, 2011 2 comments
biblia de javascript download

Descargar La biblia de JavaScript en formato PDF

La biblia de JavaScript Gold Edition para bajar en PDF.

Este libro pasado a PDF es sin duda una de las mas importantes referencias de javascript.

A toda aquella persona que quiera perfeccionarse en javascript o quiera aprender de cero el lenguaje que dominara la tecnologia en los proximos anios, les recomiendo intentar darle una lectura al libro.

En el libro se cubren basicamente la totalidad de los aspectos mas importante del lenguaje JavaScript, desde los conceptos mas simples (incluso conceptos basicos de programacion) hasta lo mas avanzado, dejando al lector un conocimiento realmente importante, con el cual se sentira libre de desarrollar cualquier aplicacion, tanto web como desktop.

Recomiendo tambien la lectura no solo para los que desean aprender javascript para el lado del cliente, sino tambien para aquellos que inician en la novedosa y poderosa tecnologia NodeJS.

biblia de javascript gold edition download

Qbasic en javascript

May 13th, 2011 1 comment
qbasic javascript codigo en basic

qbasic javascript codigo en basic

Sin dudas algunas JavaScript es el lenguaje mas flexible del cual disponemos hoy en dia.

Su capacidad de estar presente tanto del lado del Cliente (mas que nada por frameworks como mootools, jquery, etc) y actualmente del lado del servidor (enter ellos el incomparable NodeJS) lo convierte en una opcion de potencial practicamente infinito, y hoy presentaremos algo que demuestra lo que decimos.

Navegando en internet en busqueda de nuevas tendencias o novedades de JavaScript me he topado con algo que realmente me parecio brillante, y es nada mas y nada menos que un interprete (con editor y todo) de QBasic.

Para los que no sepan (mas que nada los jovenes) QBasic era un lenguaje de progamacion bastante usado para aprender a hacer los primeros sistemitas, usado para juegos y poco para tareas administrativas, QBasic fue sin duda en la primer pasion de los que hoy son denominados “Sr. en programacion o Ninjas”.

Bien, entendamos que necesitamos (en forma muy grosera obvio) para tener un lenguaje de programacion (mas que nada si tiene editor).

Primero que nada, el editor en si, es decir, una “gui” o “pantalla” donde podamos escribir nuestro codigo, que nos advierta de alguna mala sintaxis, o que nos sugiera correciones.

Por otro lado, necesitamos un “compilador” que no presisamente pase nuestro codigo fuente a codigo maquina, puede simplemente hacer un paso intermedio, como por ejemplo generar bytecode, es decir, un grupo de instrucciones que seran interpretados por una maquina virtual.

Si hablamos de una maquina virtual, necesitamos “algo” que interprete los bytecodes y en base a los mismos “haga algo”.

Bueno, lo que hoy les traigo son todos esos pasos, desde el editor hasta la maquina virtual, 100% escrito en JavaScript.

El unico requisito para que todo esto funcione correctamente es contar con un navegador que soporte Canvas… y obviamente se recomienda chrome o firefox.

qbasic javascript bytecode editor

qbasic javascript bytecode editor

Para verlo funcionando hacer click aca

qbasic javascript demo game

qbasic javascript demo game

Aca les dejo los archivos JS para que vean de que se trata por separado.

CodeGenerator

console

GlrParser

qbasic

RuleParser

RuleSet

Tokenizer

TypeChecker

types

virtualmachine

 

Tambien para que todo funcione, necesitan una imagen de mapa de caracteres y les paso el ejemplo (archivo.bas).

test.bas

charmap qbasic javascript

charmap qbasic javascript

Sintetizador con html5 via PCM

April 7th, 2011 No comments

Nunca dejamos de descubrir nuevas cosas que podemos hacer con JavaScript, HTML5, css3, etc.

En esta oportunidad les presento riffwave, una libreria en JavaScript que genera usando el tag audio de html5 sonidos por medio de PCM (MIC en Castellano).

Aca va el ejemplo de como se usa la libreria.

 

var data = []; // just an array
for (var i=0; i<10000; i++) data[i] = Math.round(255 * Math.random()); // fill data with random samples
var wave = new RIFFWAVE(data); // create the wave file
var audio = new Audio(wave.dataURI); // create the HTML5 audio element
audio.play(); // some noise

aca les dejo la web de la libreria http://www.codebase.es/riffwave/ riffwave

Aca dejo el codigo de la libreria para los que quieran copiar y pega directamente.

/*
 * RIFFWAVE.js v0.02 - Audio encoder for HTML5 

Arkanoid en javascript con jquery

April 7th, 2011 No comments

Aca les presentamos una seria de proyectos personales (experimentos) del site http://hakim.se/experiments

La verdad es que el que mas me gusto fue el Arkanoid escrito con jquery, muy simpatico y original.

 

arkanoid en jquery

arkanoid en jquery

Otro que esta realmente copado es el siguiente: http://hakim.se/experiments/html5/core/01/#

Es un lindo juego, muy adictivo!.

Mas ejemplos de lindos juegos en javascript con modelos matematicos interesantes: http://sinuousgame.com/

 

ThreadsTabs for Mootools 1.2 o Mootools 1.3

January 27th, 2011 No comments

Por una necesidad de un cliente, escribi esta clase simple y rapida, que permite saber cuantos tabs estan instanciados con el mismo site.

Tambien podemos saber si los cierra por accion de usuario o por timeout.

Estare subiendo las actualizaciones.

/**
Threads v1.0

Manejo de mensajes entre distintos tabs del navegador para un mismo Site.

@Autor Cesar Casas
@Version 1.0
@WebSite http://cesarcasas.com.ar

**/

var Threads={};

/** Conf Class settings **/

Threads.keyThread=12312123; //la key unica de cada tab, con new Date() y el metodo que nos guste la podemos armar
Threads.keyGroupThread="__ThreadGroupKEY"; //el nombre de la cookie con el que manejamos todo

/** Source
 *
 *
 */

Threads.CookieOptions={
		domain:window.location.hostname
		,duration: 0

	};

Threads.cookieSetFunction = function(c_name,value,expiredays){

	Cookie.write(c_name, value, Threads.CookieOptions);
	return ;

}

Threads.cookieReadFunction = function(name) {

	var myCookie = Cookie.read(name);
	if(myCookie == null) return "";
	return myCookie;

}

Threads.getAllThreads=function(){
	var actual=Threads.cookieReadFunction(Threads.keyGroupThread);

	var empty={};
	if(actual=="" || actual==undefined || actual=="undefined") {

		return empty;
	}
	else {

		return JSON.decode(actual);
	}
}

Threads.removeOldInstances=function(instanceID){
	Threads.Notify();
	var instanceID = instanceID || '';
	var allThreads=Threads.getAllThreads();
	var CurrentTime=new Date().getTime();

 	//Threads.cookieSetFunction(Threads.keyGroupThread, "{}");

	 for (var key in allThreads) {

		var diff=(CurrentTime-allThreads[key].time);

		if(diff > 5000 || allThreads[key].id==instanceID){
			Threads.callThreadClose(allThreads[key]);
			delete(allThreads[key]);

		}
	};
	Threads.cookieSetFunction(Threads.keyGroupThread, JSON.encode(allThreads));

};

Threads.count=function(){
	var all=Threads.getAllThreads();

	var x=0;
	for (var key in all) {
		x++;
	};
	return x;
}

Threads.existInstance=function(data){
	var allThreads=Threads.getAllThreads();

	var exist=false;
	 for (var key in allThreads) {
		if(allThreads[key].id==Threads.keyThread) {
			exist=true;

		}
	};

	if(!exist) Threads.callThreadOpen(data);
};

Threads.Notify=function(instanceID){
	var instanceID = instanceID || Threads.keyThread
	var data={
			'id': instanceID
			,'time':new Date().getTime()

	};

	Threads.existInstance(data);
	var allThreads=Threads.getAllThreads();

	var str="allThreads._"+(Threads.keyThread)+" = data";

	eval(str);

	Threads.cookieSetFunction(Threads.keyGroupThread, JSON.encode(allThreads));

}

Threads.pingThreadRequest=function(){
	Threads.removeOldInstances();
}

Threads.callThreadClose=function(thread){
	Threads.isThreadClose(thread);
}

Threads.callThreadOpen=function(thread){
	Threads.isThreadOpen(thread);
}

/**
override functions body for callbacks 

*/

Threads.isThreadClose=function(){};
Threads.isThreadOpen=function(){};

window.addEvent("domready", function(){
		Threads.pingThreadRequest.periodical(1000);

		Threads.isThreadClose=function(th){
			//console.log("se cerro un tabs por timeout", th);
		};

		Threads.isThreadOpen=function(th){
			//console.log("se abrio un tab nuevo", th);
		};

});

node.js vs php & apache

October 6th, 2010 1 comment

En la investigacion de node.js, obviamente busque algunas comparaciones con el viejo y poco querido PHP.

Obviamente intuia que el server de node.js era mucho mas rapido que apache, pero no tenia tiempo de hacer las pruebas, es por eso que busque en internet que se habia hecho al respecto, y aca dejo los datos.

Primero una comparativa de las tecnologias

Apache, PHP node.js
syntax Additional language to web standard ECMA script
try to use common structures
One language to rule them all = reuse parts of your framework on the client side
strings ‘line
line’
‘line\nline’ or “line\n\
line”
templates <code><?php // code ?></code> var s = ‘<code>’;
// code
s += ‘</code>’;
// send response
http://github.com/creationix/microtemplates
database interface PDO + prepared Statements (includes class instance support) Still no prepared statements, 1.5 – 3x slower
Driver update
performance faster
unicode PCRE no Unicode Character Properties / Scripts / Blocks in RegExp (only \w, \W consider Unicode whitespace)
add chars manually to regexp
order no namespaces up to 5.3
simple modules / namespaces
serving files Apache serves static files Overhead to serve static files
Use additional webserver (nginx) or included in web framework
access Only synchronous access
… but easier code
Asynchronous access via closures
… highly nested code
http://github.com/creationix/step
OOP implicit memoization via __get() and reuse of requested key getters (/setters) must access key with other name, bad for iteration or JSON notation
platform many reliable extensions many extensions still experimental
… but the community is dynamic
PostGIS/Postgres MongoDB CouchDB
GIS functionality rich just stuff based on points few
stable yes yes probably
GIS standards full OpenGIS support (except for GeomColl in relational functions, workaround functions) no OpenGIS at all, just points full excepting for GeomColl
GIS indexing no GeomColl
index single geoms
yes yes
GIS performance fast

Fuente: https://docs.google.com/View?id=dfzvhszt_30drxqrvhk

Comparativa de rendimiento

Number of requests performed: 2000
Number of multiple requests made: 50

node.js vs php y apache, request por segundo

node.js vs php y apache, request por segundo

Number of requests performed: 2000Number of multiple requests made: 100

node.js vs php y apache, request por segundo

node.js vs php y apache, request por segundo

Number of requests performed: 2000
Number of multiple requests made: 150

node.js vs php y apache, request por segundo

node.js vs php y apache, request por segundo

Fuente: http://ricallinson.com/nodejs-ash-vs-php-symfony-vs-php-codeigniter

Seguire mi investigacon, cada vez me convenso mas de que node.js tiene un gran futuro.

Primeras pruebas con nodejs – javascript server side

October 3rd, 2010 No comments

nodejs javascript server side

nodejs javascript server side

Evaluando Node.js

Node.js es una aplicacion que permite correr JS desde el lado del servidor.

Si bien es un proyecto muy nuevo, segun se ha podido apreciar cuenta con mucho potecial, y lo mas interesante, podemos meter frameworks en JS como modulos, y programar en forma mas “comoda” en javascript.

Para los que andan en la busqueda de un nuevo lenguaje (en especial los programadores PHP que siempre andan buscando cambiar, pero no encuentran un lenguaje comodo) es quizas la mejor opcion.

JavaScript es un lenguaje muy simple de comprender, orientado a objetos, y con infinitas posibilidades. Sin lugar a dudas, hay que poner mucho trabajo para node.js siga creciendo.

Bueno, manos a la obra, vamos por parte.

Estas pruebas las hice en Ubuntu, pero mas adelante veremos lo mismo sobre FreeBSD.

Instalacion.

Primero que nada bajamos node.js http://nodejs.org/#download

Despues tenemos que instalar algunos paquetes para poder compilar

#apt-get install build-essential libssl-dev

Ahora si, vamos a compilar.

Descomprimimos:

#tar -zxvf node-v0.2.3.tar.gz

vamos al directorio:

#cd node-v0.2.3

Configuramos:

#./configure

Compilamos:

#make

Instalamos:

#make install

Primeras pruebas

Bueno, ya con node.js instalado, solamente tenemos que ejecutar “node” y veremos la consola.

#node

Para salir de la consola, solamente tenemos que precionar ctrl+D

La consola en si no va  a ser tema de estudio, pero si queremos hacer una prueba, podemos ejecutar

var a="hola mundo";
a;

Como siempre, lo ideal es leer la documentacio, pero vamos a hacer algunas pruebas mas.

Creamos un archivo llamado server.js con nuestro editor preferido para programar y ponemos este codigo

var http = require('http');

http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
}).listen(8124);

console.log('Server running at http://127.0.0.1:8124/');

Guardamos y ejecutamos escribiendo

#node server.js

Ahora comprobamos si efectivamente funciona abriendo nuestro navegador favorito y poniendo como url

http://127.0.0.1:8124

Bueno, por el momento ha sido todo, pero seguire escribiendo articulos sobre node.js ya que me parece un proyecto apacionado.

Portal de juegos en HTML 5

August 15th, 2010 No comments

En esta ocasion les presentamos un portal de juegos totalmente escritos en html5.

Para los que no esten familiarizados con el termino html5, viene a ser asi como la evolucion y el futuro web, y segun mucho lo que desplaza a flash para siempre.

Les dejo el link, asi ustedes mismo pueden apreciar las posibilidades de html5. http://html5games.com/