<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://msmvps.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Search results for 'app:weblogs' matching tags 'ASP.NET MVC', 'Desarrollo de Juegos', and 'Javascript'</title><link>http://msmvps.com/search/SearchResults.aspx?q=app:weblogs&amp;tag=ASP.NET+MVC,Desarrollo+de+Juegos,Javascript&amp;orTags=0&amp;o=DateDescending</link><description>Search results for 'app:weblogs' matching tags 'ASP.NET MVC', 'Desarrollo de Juegos', and 'Javascript'</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 SP2 (Build: 40407.4157)</generator><item><title>Programando Juegos Sociales en L&amp;#237;nea (Parte 5) Nuevo Azure Toolkit</title><link>http://msmvps.com/blogs/lopez/archive/2011/12/01/social_2D00_online_2D00_games_2D00_programming_2D00_part_2D00_5_2D00_new_2D00_azure_2D00_toolkit.aspx</link><pubDate>Thu, 01 Dec 2011 06:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1803114</guid><dc:creator>lopez</dc:creator><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/08/10/social_2D00_online_2D00_games_2D00_programming_2D00_part_2D00_4_2D00_processing_2D00_arbitrary_2D00_game_2D00_actions.aspx"&gt;Anterior Post&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/12/30/social_2D00_games_2D00_programming_2D00_part_2D00_6_2D00_testing_2D00_game_2D00_and_2D00_service_2D00_with_2D00_tdd_2D00_and_2D00_qunit.aspx"&gt;Siguiente Post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Dos semanas atr&amp;aacute;s, fue publicada una nueva versi&amp;oacute;n del &lt;a href="http://watgames.codeplex.com/"&gt;Windows Azure Toolkit for Social Games&lt;/a&gt;. Vean los posts de &lt;a href="http://twitter.com/ntotten"&gt;@ntotten&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ntotten.com/2011/11/windows-azure-toolkit-for-social-games-version-1-1-1/"&gt;Windows Azure Toolkit for Social Games Version 1.1.1&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://ntotten.com/2011/11/windows-azure-toolkit-for-social-games-version-1-1/"&gt;Windows Azure Toolkit for Social Games Version 1.1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;La nueva versi&amp;oacute;n implementa dos juegos simples en HTML5: Ta Te Ti, y Cuatro en Raya, usando vistas ASP.NET MVC, servicios WCF Web API, seguridad federada usando ACS, y Azure Storage. Pueden jugar en l&amp;iacute;nea en:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://watgames4.cloudapp.net/"&gt;http://watgames4.cloudapp.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/watgames04.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Pienso que &amp;eacute;ste es un ejemplo m&amp;aacute;s claro que el anterior (Tankster) que era una gran aplicaci&amp;oacute;n pero algo excesiva ;-). Veamos de entrar en algunos detalles de implementaci&amp;oacute;n de este nuevo ejemplo.&lt;/p&gt;
&lt;p&gt;Totten escribi&amp;oacute;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The biggest change we have made in this release is to separate the core toolkit from the &lt;a href="http://www.tankster.net/"&gt;Tankster&lt;/a&gt; game. After we released the Tankster sample game we received a lot of feedback asking for a simpler game that developers could use to learn. To meet this need we developed two simple games, Tic-Tac-Toe and Four in a Row, and included in the toolkit. The Tankster game is now available separately as a sample built on top of the toolkit.&lt;/p&gt;
&lt;p&gt;&amp;hellip;&lt;/p&gt;
&lt;p&gt;While the new games included in the toolkit are much simpler than Tankster, they still show the same core concepts. You can easily use these samples as a starting point to build out any number of types of games. Additionally, you will find that many of the core components of the game such as the leaderboard services, game command services can be used without any modification to the server side or client side code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;En mi anterior post, mencion&amp;eacute; un peque&amp;ntilde;o pero importante cambio en el proceso de acciones de juego: toda la l&amp;oacute;gica fue removida del c&amp;oacute;digo del servidor. Adoptando este camino, podemos escribir nuevos juegos sin cambiar el c&amp;oacute;digo del servidor. Podemos seguir agregando c&amp;oacute;digo en el servidor si lo necesitamos (por ejemplo, para agregar control al juego, detectar operaciones inv&amp;aacute;lidas enviadas desde alg&amp;uacute;n cliente, etc) pero es interesante tener una base de c&amp;oacute;digo que sea agn&amp;oacute;stica del juego.&lt;/p&gt;
&lt;p&gt;Abriendo la soluci&amp;oacute;n en Visual Studio, encontraremos archivos Javascript usados por los dos juegos. Podemos escribir un nuevo juego, reusando estos archivos sin cambios:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/watgames02.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Los juegos est&amp;aacute;n implementados como &amp;aacute;reas:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/watgames01.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Podr&amp;iacute;amos escribir nuevos juegos y publicarlos como paquetes NuGet. &lt;/p&gt;
&lt;p&gt;Visualmente, el c&amp;oacute;digo Javascript cliente est&amp;aacute; organizado de esta manera:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/watgames03.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Cada juego X (X = Ta Te Ti, Cuatro en Raya, uno nuestro) tiene:&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;XGame&lt;/strong&gt;: la l&amp;oacute;gica del juego&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;XBoard&lt;/strong&gt;: para dibujar el tablero en un elemento canvas de HTML5, y para detectar eventos de click en el mismo.&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;XViewModel&lt;/strong&gt;: contiene el jugador actual y otros datos para ser usandos en el armado de la vista (los ejemplos usan&amp;nbsp; knockout.js, como MVC en Javascript)&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;XController&lt;/strong&gt;: para procesar nuevos eventos y para coordinar los elementos de arriba.&lt;/p&gt;
&lt;p&gt;La parte gen&amp;eacute;rica:&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;UserService&lt;/strong&gt;: m&amp;eacute;todos relacionados a usuarios: login, lista de amigos, etc&amp;hellip;&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;GameService&lt;/strong&gt;:&amp;nbsp; jugar las movidas, recibir movidas de otros jugadores, otras acciones (por ejemplo, se podr&amp;iacute;an enviar mensajes de chat).&lt;/p&gt;
&lt;p&gt;- &lt;strong&gt;ServerInterface&lt;/strong&gt;: Llamadas Ajax (usando GET, POST, JSONP, Azure storage&amp;hellip;.) que son usados por la implementaci&amp;oacute;n de User y Game Service.&lt;/p&gt;
&lt;p&gt;Temas para pr&amp;oacute;ximos posts: analizar el c&amp;oacute;digo Javascript, el uso del Canvas, tests de Javascript usando QUnit, comunicaci&amp;oacute;n con el servidor usando Ajax, cambio del Game Service (en Javascript) para usar un Node.js como servidor que reciba y reparta las acciones de juego.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez    &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt;     &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Programando Juegos Sociales en L&amp;#237;nea (Parte 4) Procesando Acciones De Juego Arbitrarias</title><link>http://msmvps.com/blogs/lopez/archive/2011/08/10/social_2D00_online_2D00_games_2D00_programming_2D00_part_2D00_4_2D00_processing_2D00_arbitrary_2D00_game_2D00_actions.aspx</link><pubDate>Wed, 10 Aug 2011 05:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1797429</guid><dc:creator>lopez</dc:creator><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/08/03/social_2D00_online_2D00_games_2D00_programming_2D00_part_2D00_3_2D00_tankster_2D00_blob_2D00_storage_2D00_and_2D00_jsonp.aspx"&gt;Anterior Post&lt;/a&gt;&amp;nbsp;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/12/01/social_2D00_online_2D00_games_2D00_programming_2D00_part_2D00_5_2D00_new_2D00_azure_2D00_toolkit.aspx"&gt;Siguiente Post&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Hay un nuevo release del Windows Azure Toolkit for Social Games:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://watgames.codeplex.com/releases/view/70342" title="http://watgames.codeplex.com/releases/view/70342"&gt;http://watgames.codeplex.com/releases/view/70342&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Examinemos un cambio clave en esta versi&amp;oacute;n. Hay un nuevo punto de entrada en Tankster.GamePlay\Services\IGameService.cs:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;[WebInvoke(Method = &amp;quot;&lt;span style="color:#8b0000;"&gt;POST&lt;/span&gt;&amp;quot;, UriTemplate = &amp;quot;&lt;span style="color:#8b0000;"&gt;command/{gameId}&lt;/span&gt;&amp;quot;)]
HttpResponseMessage Command(Guid gameId, HttpRequestMessage request);
[WebInvoke(Method = &amp;quot;&lt;span style="color:#8b0000;"&gt;POST&lt;/span&gt;&amp;quot;, UriTemplate = &amp;quot;&lt;span style="color:#8b0000;"&gt;command/v2/{gameId}&lt;/span&gt;&amp;quot;)]
HttpResponseMessage Command2(Guid gameId, HttpRequestMessage request);
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Hay DOS puntos de entrada para enviar comandos de juego desde los clientes. &amp;iquest;Por qu&amp;eacute;? Al tener dos URIs el servidor puede ser usado por los clientes antiguos y por los nuevos. Noten el uso de&amp;nbsp; &amp;ldquo;v2&amp;rdquo; en el UriTemplate. &lt;/p&gt;
&lt;p&gt;El nuevo c&amp;oacute;digo (parcial) de Command2 en su implementaci&amp;oacute;n (GameService.cs):&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#008000;"&gt;// Add gameAction&lt;/span&gt;
var gameAction = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; GameAction
{
    Id = Guid.NewGuid(),
    Type = commandType,
    CommandData = commandData,
    UserId = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.CurrentUserId,
    Timestamp = DateTime.UtcNow
};
&lt;span style="color:#008000;"&gt;// Cleanup game actions lists&lt;/span&gt;
&lt;span style="color:#0000ff;"&gt;for&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; game.GameActions.Count(); i++)
{
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (game.GameActions[i].Timestamp &amp;lt; DateTime.UtcNow.AddSeconds(-10))
    {
        game.GameActions.RemoveAt(i);
        i--;
    }
}
game.GameActions.Add(gameAction);
&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.gameRepository.AddOrUpdateGame(game);
&lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; SuccessResponse;
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Si comparamos &amp;eacute;ste con el viejo c&amp;oacute;digo (que sigue estando en el m&amp;eacute;todo Command) con el c&amp;oacute;digo de arriba, la principal diferencia es:&lt;/p&gt;
&lt;p&gt;- El servidor no maneja la l&amp;oacute;gica de &amp;ldquo;qui&amp;eacute;n es el pr&amp;oacute;ximo jugador en la ronda de turnos&amp;rdquo; 
  &lt;br /&gt;- El servidor no distribuye los comandos recibidos usando un GameActionProcessor&lt;/p&gt;
&lt;p&gt;Y otro cambio: el tipo de una acci&amp;oacute;n de juego es ahora un entero, un int. En la anterior versi&amp;oacute;n del ejemplo era un enum, reflejando un conjunto fijo de tipos.&lt;/p&gt;
&lt;p&gt;Todav&amp;iacute;a actualiza el blob de estado del juego agregando el nuevo comando (un comando puede ser un mensaje de chat, o un disparo). De esta nueva manera, el CODIGO DEL SERVIDOR es m&amp;aacute;s independiente de la l&amp;oacute;gica del juego: el c&amp;oacute;digo cliente tiene la responsabilidad de elegir el pr&amp;oacute;ximo jugador. La noci&amp;oacute;n de turno se deja al desarrollo del c&amp;oacute;digo cliente. Ahora, el c&amp;oacute;digo servidor puede ser usado para OTROS juegos multi-jugador. Y podr&amp;iacute;amos tener nuestro propio &amp;ldquo;Social Game&amp;rdquo;! ;-)&lt;/p&gt;
&lt;p&gt;Entonces, los roles web y worker de Windows Azure est&amp;aacute;n a cargo de la autenticaci&amp;oacute;n federada, la formaci&amp;oacute;n de nuevos juegos (al sumar jugadores que quieran participar), etc. Pero el motor es m&amp;aacute;s &amp;ldquo;game agnostic&amp;rdquo; en este nuevo release.&lt;/p&gt;
&lt;p&gt;Repasando como queda ahora. El c&amp;oacute;digo cliente env&amp;iacute;a comandos:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/tankster08.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Pasos:&lt;/p&gt;
&lt;p&gt;1- El c&amp;oacute;digo cliente env&amp;iacute;a una nueva Game Action en JSON (por ejemplo, informaci&amp;oacute;n de un nuveo disparo (posici&amp;oacute;n, &amp;aacute;ngulo, fuerza)).&lt;/p&gt;
&lt;p&gt;2- Una de las instancias del web role recibe el Game Action y la agrega a la lista de acciones en el correspondiente blobg del juego (guardando solamente las acciones de los &amp;uacute;ltumos 10 segundos)&lt;/p&gt;
&lt;p&gt;3- Los otros jugadores est&amp;aacute;n &amp;ldquo;poleando&amp;rdquo; el estado del juego, notando cu&amp;aacute;ndo una game action implica un cambio de turno. Y si reciben disparos, los van mostrando en cada browser.&lt;/p&gt;
&lt;p&gt;El c&amp;oacute;digo cliente podr&amp;iacute;a manejar tambi&amp;eacute;n el caso de un jugador que pasa a &amp;ldquo;offline&amp;rdquo;, mediante un &amp;ldquo;timeout&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Pros de esta nueva forma de manejar las acciones:&lt;/p&gt;
&lt;p&gt;- El c&amp;oacute;digo del servidor es m&amp;aacute;s gen&amp;eacute;rico, y puede ser usado para otros juegos&lt;/p&gt;
&lt;p&gt;Cons:&lt;/p&gt;
&lt;p&gt;- El c&amp;oacute;digo cliente puede ser enga&amp;ntilde;ado (no hay controles, validaciones en el servidor) 
  &lt;br /&gt;- M&amp;aacute;s complejidad a implementar en el c&amp;oacute;digo cliente: manejo de turnos, &amp;ldquo;timeouts&amp;rdquo;, latencia, control de &amp;ldquo;cheat&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;La prueba &amp;aacute;cida: implementar un nuevo juego usando el mismo c&amp;oacute;digo servidor. Algunos puntos para pulir: el modo Skirmish (cada jugador entra en un juego, esperando a que otros tambi&amp;eacute;n entren) est&amp;aacute; todav&amp;iacute;a &amp;ldquo;hardcodeado&amp;rdquo; a un m&amp;aacute;ximo de 5 jugadores; la ventana de 10 segundos para las acciones es arbitraria. Posibles soluciones: cada cliente de juego crea un nuevo juego (esperando a otros jugadores, o invit&amp;aacute;ndolos) especificando el n&amp;uacute;mero m&amp;iacute;nimo, m&amp;aacute;ximo de jugadores, el &amp;ldquo;timeout&amp;rdquo; en segundos,&amp;nbsp; y la ventana de tiempo para mantener las acciones.&lt;/p&gt;
&lt;p&gt;Pero recuerden: es todav&amp;iacute;a una beta. Una nueva versi&amp;oacute;n est&amp;aacute; en camino.&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez 
  &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; 
  &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Programando Juegos Sociales en L&amp;#237;nea (Parte 3) Tankster, Blob Storage y JSONP</title><link>http://msmvps.com/blogs/lopez/archive/2011/08/03/social_2D00_online_2D00_games_2D00_programming_2D00_part_2D00_3_2D00_tankster_2D00_blob_2D00_storage_2D00_and_2D00_jsonp.aspx</link><pubDate>Wed, 03 Aug 2011 05:00:00 GMT</pubDate><guid isPermaLink="false">d67277c4-116b-43f1-b688-e9ef184ea916:1797128</guid><dc:creator>lopez</dc:creator><description>&lt;p&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/07/22/social_2D00_online_2D00_games_2D00_programming_2D00_part_2D00_2_2D00_tankster_2D00_and_2D00_windows_2D00_azure_2D00_toolkit_2D00_for_2D00_social_2D00_games.aspx"&gt;Anterior Post&lt;/a&gt;&lt;br /&gt;&lt;a href="http://msmvps.com/blogs/lopez/archive/2011/08/10/social_2D00_online_2D00_games_2D00_programming_2D00_part_2D00_4_2D00_processing_2D00_arbitrary_2D00_game_2D00_actions.aspx"&gt;Siguiente Post&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;En mi anterior post escrib&amp;iacute; sobre el Windows Azure Social Gaming Toolkit, y su ejemplo de juego en l&amp;iacute;nea, para varios jugadores. Ver:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://watgames.codeplex.com/"&gt;http://watgames.codeplex.com/&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.tankster.net/"&gt;http://www.tankster.net/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(El lunes 1ro de Agosto, sali&amp;oacute; una nueva beta: &lt;a href="http://watgames.codeplex.com/releases/view/70342" title="http://watgames.codeplex.com/releases/view/70342"&gt;http://watgames.codeplex.com/releases/view/70342&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.ajlopez.com/images/articles2/tankster07.png" alt="" /&gt; &lt;/p&gt;
&lt;p&gt;Hay dos post interesantes de &lt;a href="http://twitter.com/ntotten"&gt;@ntotten&lt;/a&gt; acerca de los &amp;ldquo;internals&amp;rdquo; del juego y las decisiones que se tomaron:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ntotten.com/2011/07/architecture-of-tankster-introduction-to-game-play-part-1/"&gt;Architecture of Tankster &amp;ndash; Introduction to Game Play (Part 1)&lt;/a&gt; &lt;br /&gt;&lt;a href="http://ntotten.com/2011/07/architecture-of-tankster-scale-part-2/"&gt;Architecture of Tankster&amp;ndash; Scale (Part 2)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Vale la pena mencionar ac&amp;aacute; el fragmento de Nathan:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Before we begin with an explanation of the implementation, it is important to know what our goals where for this game. We had three primary goals when building this game.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The game must scale to handle several hundred thousand concurrent users.* &lt;/li&gt;
&lt;li&gt;The architecture must be cost effective. &lt;/li&gt;
&lt;li&gt;The architecture must be flexible enough for different types of games. &lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;* This is the goal, but there are still some known limitations in the current version that would prevent this. I will be writing more about that later.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ahora, en este post, quiero escribir sobre el uso e implementaci&amp;oacute;n de blob storage en Tankster.&lt;/p&gt;
&lt;p&gt;Primero: &amp;iquest;por qu&amp;eacute; usar blob storage? Si jugamos Tankster en modo de pr&amp;aacute;ctica, el cliente Javascript no necesita usar el backend de Azure. El c&amp;oacute;digo Javascript puede acceder al web role y al blob storage usando llamadas Ajax/JSON. Y en juego multi-jugador (en el modo de juego de Tankster llamado Skirmish), cada cliente &amp;ldquo;pollea&amp;rdquo; el blob storage para conseguir el estado del juego (los disparos de los tanques, mensajes de chat, otro estado). Pero de nuevo: &amp;iquest;por qu&amp;eacute; blob storage? Hay razones monetarias (costo de acceder a la Web Role API vs el costo de leer un blob), pero no conozco los precios de Azure (ya saben, &amp;ldquo;el maestro no toca la plata&amp;rdquo; ;-). Pero hay otra raz&amp;oacute;n: repartir el trabajo, dando algo de aire a las instacias de web role. En vez de hacer todo con la API alojada en el web role, se leen blobs desde Azure storage.&lt;/p&gt;
&lt;p&gt;Hay una clase AzureBlobContainer en el proyecto de librer&amp;iacute;a de clases Tankster.Common:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; AzureBlobContainer&amp;lt;T&amp;gt; : IAzureBlobContainer&amp;lt;T&amp;gt;
{
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; CloudBlobContainer container;
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;readonly&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; jsonpSupport;
    &lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; JavaScriptSerializer serializer;
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; AzureBlobContainer(CloudStorageAccount account)
        : &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;(account, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(T).Name.ToLowerInvariant(), &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;)
    {
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; AzureBlobContainer(CloudStorageAccount account, &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; jsonpSupport)
        : &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;(account, &lt;span style="color:#0000ff;"&gt;typeof&lt;/span&gt;(T).Name.ToLowerInvariant(), &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;)
    {
    }
    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; AzureBlobContainer(CloudStorageAccount account, &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; containerName)
        : &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;(account, containerName.ToLowerInvariant(), &lt;span style="color:#0000ff;"&gt;false&lt;/span&gt;)
    { 
    }
	&lt;span style="color:#008000;"&gt;//....&lt;/span&gt;&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;La clase usa generics. El tipo T puede ser un Game, GameQueue u otro tipo .NET. Pueden reusar esta clase en otros proyectos: es &amp;ldquo;game agnostic&amp;rdquo;, no est&amp;aacute; escrita para este proyectos, sino que se puede usar en otros. Los varios constructores le agregan flexibilidad para tests.&lt;/p&gt;
&lt;p&gt;Este es el c&amp;oacute;digo para grabar un objeto tipado en un blob:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Save(&lt;span style="color:#0000ff;"&gt;string&lt;/span&gt; objId, T obj)
{
    CloudBlob blob = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.container.GetBlobReference(objId);
    blob.Properties.ContentType = &amp;quot;&lt;span style="color:#8b0000;"&gt;application/json&lt;/span&gt;&amp;quot;;
    var serialized = &lt;span style="color:#0000ff;"&gt;string&lt;/span&gt;.Empty;
    serialized = serializer.Serialize(obj);
    &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.jsonpSupport)
    {
		serialized = &lt;span style="color:#0000ff;"&gt;this&lt;/span&gt;.container.Name + &amp;quot;&lt;span style="color:#8b0000;"&gt;Callback(&lt;/span&gt;&amp;quot; + serialized + &amp;quot;&lt;span style="color:#8b0000;"&gt;)&lt;/span&gt;&amp;quot;;
    }
    blob.UploadText(serialized);
}
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;El objeto (tipo T) es serializado a JSON. Y no s&amp;oacute;lo JSON: noten que hay un Callback (podr&amp;iacute;amos remover esto, si nuestro proyecto no lo necesita). Entonces, un objeto juego se graba como (he &lt;span style="text-decoration:line-through;"&gt;robado&lt;/span&gt;&amp;hellip;. eh&amp;hellip; tomado prestado ;-) este c&amp;oacute;digo del post de Nathan):&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;gamesCallback(
    {&amp;quot;&lt;span style="color:#8b0000;"&gt;Id&lt;/span&gt;&amp;quot;:&amp;quot;&lt;span style="color:#8b0000;"&gt;620f6257-83e6-4fdc-99e3-3109718934a6&lt;/span&gt;&amp;quot;
    ,&amp;quot;&lt;span style="color:#8b0000;"&gt;CreationTime&lt;/span&gt;&amp;quot;:&amp;quot;&lt;span style="color:#8b0000;"&gt;\/Date(1311617527935)\/&lt;/span&gt;&amp;quot;
    ,&amp;quot;&lt;span style="color:#8b0000;"&gt;Seed&lt;/span&gt;&amp;quot;:1157059416
    ,&amp;quot;&lt;span style="color:#8b0000;"&gt;Status&lt;/span&gt;&amp;quot;:0
    ,&amp;quot;&lt;span style="color:#8b0000;"&gt;Users&lt;/span&gt;&amp;quot;:[
        {&amp;quot;&lt;span style="color:#8b0000;"&gt;UserId&lt;/span&gt;&amp;quot;:&amp;quot;&lt;span style="color:#8b0000;"&gt;MxAb1iZtey732BGsWsoMcwx3JbklW1xSnsxJX9+KanI=&lt;/span&gt;&amp;quot;
        ,&amp;quot;&lt;span style="color:#8b0000;"&gt;UserName&lt;/span&gt;&amp;quot;:&amp;quot;&lt;span style="color:#8b0000;"&gt;MxAb1iZtey732BGsWsoMcwx3JbklW1xSnsxJX9+KanI=&lt;/span&gt;&amp;quot;
        ,&amp;quot;&lt;span style="color:#8b0000;"&gt;Weapons&lt;/span&gt;&amp;quot;:[]
        },
        {&amp;quot;&lt;span style="color:#8b0000;"&gt;UserId&lt;/span&gt;&amp;quot;:&amp;quot;&lt;span style="color:#8b0000;"&gt;ZXjeyzvw7WTdP8/Uio4P6cDZ8jmKvCXCDp7JjWolAOY=&lt;/span&gt;&amp;quot;
        ,&amp;quot;&lt;span style="color:#8b0000;"&gt;UserName&lt;/span&gt;&amp;quot;:&amp;quot;&lt;span style="color:#8b0000;"&gt;ZXjeyzvw7WTdP8/Uio4P6cDZ8jmKvCXCDp7JjWolAOY=&lt;/span&gt;&amp;quot;
        ,&amp;quot;&lt;span style="color:#8b0000;"&gt;Weapons&lt;/span&gt;&amp;quot;:[]
        }]
    ,&amp;quot;&lt;span style="color:#8b0000;"&gt;ActiveUser&lt;/span&gt;&amp;quot;:&amp;quot;&lt;span style="color:#8b0000;"&gt;MxAb1iZtey732BGsWsoMcwx3JbklW1xSnsxJX9+KanI=&lt;/span&gt;&amp;quot;
    ,&amp;quot;&lt;span style="color:#8b0000;"&gt;GameRules&lt;/span&gt;&amp;quot;:[]
    ,&amp;quot;&lt;span style="color:#8b0000;"&gt;GameActions&lt;/span&gt;&amp;quot;:[]
    })&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;&amp;iquest;Por qu&amp;eacute; el callback? Para soportar JSONP:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/JSONP" title="http://en.wikipedia.org/wiki/JSONP"&gt;http://en.wikipedia.org/wiki/JSONP&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;JSONP&lt;/b&gt; or &amp;quot;JSON with padding&amp;quot; is a complement to the base &lt;a href="http://en.wikipedia.org/wiki/JSON"&gt;JSON&lt;/a&gt; data format, a &lt;i&gt;pattern of usage&lt;/i&gt; that allows a page to request data from a server in a different domain. As a solution to this problem, JSONP is an alternative to a more recent method called &lt;a href="http://en.wikipedia.org/wiki/Cross-Origin_Resource_Sharing"&gt;Cross-Origin Resource Sharing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Under the &lt;a href="http://en.wikipedia.org/wiki/Same_origin_policy"&gt;same origin policy&lt;/a&gt;, a web page served from server1.example.com cannot normally connect to or communicate with a server other than server1.example.com. An exception is the &lt;a href="http://en.wikipedia.org/wiki/HTML"&gt;HTML&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/HTML_element#script_tag"&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;&lt;/a&gt; element. Taking advantage of the open policy for &lt;a href="http://en.wikipedia.org/wiki/HTML_element#script_tag"&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt;&lt;/a&gt; elements, some pages use them to retrieve Javascript code that operates on dynamically-generated JSON-formatted data from other origins. This usage pattern is known as JSONP. Requests for JSONP retrieve not JSON, but arbitrary JavaScript code. They are evaluated by the JavaScript interpreter, not parsed by a JSON parser.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Si Ud. no conoce JSON y JSONP, ac&amp;aacute; hay un tutorial con ejemplo usando JQuery (la misma librer&amp;iacute;a usada por el c&amp;oacute;digo de Tankster):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.ibm.com/developerworks/library/wa-aj-jsonp1/"&gt;Cross-domain communications with JSONP, Part 1: Combine JSONP and jQuery to quickly build powerful mashup&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Pero (ya saben, siempre hay un &amp;ldquo;pero&amp;rdquo; en todo proyecto de software) el blob storage de Azure no soporta el uso de JSONP URLs (que tienen un par&amp;aacute;metro indicando el id de un callback generado al azar):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://stackoverflow.com/questions/5489481/query-json-data-from-azure-blob-storage-with-jquery"&gt;Query JSON data from Azure Blob Storage with jQuery&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Hay una soluci&amp;oacute;n propuesta en un hilo de Stack Overflow. El agente Maxwell Smart dir&amp;iacute;a: ah! el &amp;ldquo;viejo truco&amp;rdquo; de tener el callback ya especificado en el blob!&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;dataCallback({&amp;quot;&lt;span style="color:#8b0000;"&gt;Name&lt;/span&gt;&amp;quot;:&amp;quot;&lt;span style="color:#8b0000;"&gt;Valeriano&lt;/span&gt;&amp;quot;,&amp;quot;&lt;span style="color:#8b0000;"&gt;Surname&lt;/span&gt;&amp;quot;:&amp;quot;&lt;span style="color:#8b0000;"&gt;Tortola&lt;/span&gt;&amp;quot;})&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Pueden leer una m&amp;aacute;s detallada descripci&amp;oacute;n del problema y soluci&amp;oacute;n con c&amp;oacute;digo de ejemplo en el post de &lt;a href="http://twitter.com/woloski"&gt;@woloski&lt;/a&gt;&amp;rsquo;s post (Buen pr&amp;aacute;ctica Mat&amp;iacute;as! escribir un post con c&amp;oacute;digo!):&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blogs.southworks.net/mwoloski/2011/07/02/ajax-cross-domain-jquery-wcf-web-api-or-mvc-windows-azure"&gt;Ajax, Cross Domain, jQuery, WCF Web API or MVC, Windows Azure&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Un problema a tener en cuenta: vean que el nombre del callback est&amp;aacute; &amp;ldquo;hardcodeado&amp;rdquo; en el blob. El gamesCallback presente en el blob de Game Status debe ser el nombre de una funci&amp;oacute;n global. Pero pueden cambiar el texto del blob a cualquier Javascript v&amp;aacute;lido.&lt;/p&gt;
&lt;p&gt;&amp;iquest;Y del lado cliente? Pueden estudiar el c&amp;oacute;digo de &lt;a href="http://gskinner.com/blog"&gt;gskinner&lt;/a&gt; en el proyecto Tankster.GamePlay, en src\ui\net\ServerDelegate.js:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;(&lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; (&lt;span style="color:#0000ff;"&gt;window&lt;/span&gt;) {
    goog.provide(&amp;#39;net.ServerDelegate&amp;#39;);
    goog.require(&amp;#39;net.ServerRequest&amp;#39;);
    
    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; ServerDelegate = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; () {
        &lt;span style="color:#0000ff;"&gt;throw&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; Error(&amp;#39;ServerDelegate cannot be instantiated.&amp;#39;);
    };
    
    &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; p = ServerDelegate;
    
    p.BASE_API_URL = &amp;quot;&lt;span style="color:#8b0000;"&gt;/&lt;/span&gt;&amp;quot;;
    p.BASE_BLOB_URL = &amp;quot;&lt;span style="color:#8b0000;"&gt;http://tankster.blob.core.windows.net/&lt;/span&gt;&amp;quot;;
    p.BASE_ASSETS_URL = &amp;quot;&lt;span style="color:#8b0000;"&gt;&lt;/span&gt;&amp;quot;;
    p.load = &lt;span style="color:#0000ff;"&gt;function&lt;/span&gt; (type, data, loadNow) {        
        &lt;span style="color:#0000ff;"&gt;var&lt;/span&gt; req;
        &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt; (p.CLIENT_URL == &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;) {
            p.CLIENT_URL = &lt;span style="color:#0000ff;"&gt;window&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;location&lt;/span&gt;.&lt;span style="color:#0000ff;"&gt;toString&lt;/span&gt;();
        }
&lt;span style="color:#008000;"&gt;//....&lt;/span&gt;
&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;There is an interesting switch:&lt;/p&gt;
&lt;pre&gt;&lt;pre style="background-color:#ffffff;margin:0em;width:100%;font-family:consolas,courier,monospace;font-size:12px;"&gt;&lt;span style="color:#0000ff;"&gt;switch&lt;/span&gt; (type) {
    &lt;span style="color:#008000;"&gt;//Local / config calls&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;strings&amp;#39;:
        req = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ServerRequest(&amp;#39;locale/en_US/strings.js&amp;#39;, 
		   &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;jsonp&amp;#39;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;stringsCallback&amp;#39;); &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    &lt;span style="color:#008000;"&gt;//Game calls&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;endTurn&amp;#39;:
        req = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ServerRequest(apiURL+&amp;#39;Game/EndTurn/&amp;#39;, 
		    &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;xml&amp;#39;); &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;leaveGame&amp;#39;:
        req = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ServerRequest(apiURL+&amp;#39;Game/Leave/&amp;#39;+data.id, 
		    {reason:data.reason}, &amp;#39;xml&amp;#39;, ServerRequest.POST); &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;playerDead&amp;#39;:
        req = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ServerRequest(apiURL+&amp;#39;Game/PlayerDead/&amp;#39;, 
		    &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;json&amp;#39;); &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;gameCreate&amp;#39;:
        req = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ServerRequest(apiURL+&amp;#39;Game/Queue&amp;#39;, data, 
		    &amp;#39;xml&amp;#39;, ServerRequest.POST); &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;usersGame&amp;#39;:
        req = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ServerRequest(blobURL+&amp;#39;sessions/&amp;#39;+data, 
		    &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;jsonp&amp;#39;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;sessionsCallback&amp;#39;); &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;gameStatus&amp;#39;:
        req = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ServerRequest(blobURL+&amp;#39;games/&amp;#39;+data, 
		    &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;jsonp&amp;#39;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;gamesCallback&amp;#39;); &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;gameQueueStatus&amp;#39;:
        req = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ServerRequest(blobURL+&amp;#39;gamesqueues/&amp;#39;+data, 
		    &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;jsonp&amp;#39;, &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;gamesqueuesCallback&amp;#39;); &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;notifications&amp;#39;:
        req = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ServerRequest(blobURL+&amp;#39;notifications/&amp;#39;+data, 
		    &lt;span style="color:#0000ff;"&gt;null&lt;/span&gt;, &amp;#39;jsonp&amp;#39;); &lt;span style="color:#0000ff;"&gt;break&lt;/span&gt;;
    
    &lt;span style="color:#008000;"&gt;//User calls&lt;/span&gt;
    &lt;span style="color:#0000ff;"&gt;case&lt;/span&gt; &amp;#39;verifyUser&amp;#39;:
&lt;span style="color:#008000;"&gt;//...&lt;/span&gt;&lt;/pre&gt;
&lt;/pre&gt;
&lt;p&gt;Vean el &amp;lsquo;gameStatus&amp;rsquo;: usa &amp;lsquo;jsonp&amp;rsquo; como formato. Pienso que el&amp;nbsp; &amp;lsquo;gamesCallback&amp;rsquo; como par&amp;aacute;metro no es necesario: pueden usar cualquier otro nombre, la funci&amp;oacute;n a llamar reside en el contenido del blob. &lt;/p&gt;
&lt;p&gt;Yo pienso que hay alternativas a esta forma de mantener el estado del juego. El blob refleja a la entidad Game (ver Tankster.Core\Entities\Game.cs). Pero podr&amp;iacute;a ser implementado en dos blobs por juego:&lt;/p&gt;
&lt;p&gt;- Uno de los blobs, conteniendo el estado inicial (jugadores, posiciones, armas&amp;hellip;) y la lista de TODA la historia del juego (pienso que todo esto se puede reusar para juegos de tablero, como ajedrez o go, donde puede ser interesante tener la historia de las movidas del juego).&lt;/p&gt;
&lt;p&gt;- Otro blob, conteniendo las &amp;ldquo;novedades&amp;rdquo; (los &amp;uacute;ltimos 10 segundos de las acciones del juego). De esta forma, los clientes &amp;ldquo;pollean&amp;rdquo; este blob, que deber&amp;iacute;a ser m&amp;aacute;s corto que el actual.&lt;/p&gt;
&lt;p&gt;El precio a pagar: el servicio en el Web Role que atiende las acciones de los juegos DEBE actualizar LOS DOS blobs. Pero esta actualizaci&amp;oacute;n s&amp;oacute;lo ocurren cuando un jugador env&amp;iacute;a una movida (disparo, chat..). La consulta reiterada desde cada cliente se dispara, digamos, cada un segundo. Actualmente, el blob del juego mantiene los &amp;uacute;ltimos 10 segundos de las acciones Y ADEMAS el estado inicial, jugadores, armas, etc&amp;hellip; CADA CLIENTE lee reiteradamente esa informaci&amp;oacute;n. En la implementaci&amp;oacute;n que sugiero, los datos a leer cada vez son menos. En el caso que un cliente se desconecte y reconecte, podr&amp;iacute;a leer el blob que contiene el juego completo, para volver a sincronizar su estado.&lt;/p&gt;
&lt;p&gt;La separaci&amp;oacute;n de esta informaci&amp;oacute;n en dos blobs podr&amp;iacute;a mejorar la escalabilidad de la soluci&amp;oacute;n. Pero ya saben: &lt;a href="http://c2.com/cgi/wiki?PrematureOptimization"&gt;premature optimization is the root of all evil&lt;/a&gt; ;-). Si tomamos ese camino para almacenar y recuperar los juegos, deber&amp;iacute;amos ejecutar algunos tests de carga para realmente conocer las consecuencias de esa decisi&amp;oacute;n.&lt;/p&gt;
&lt;p&gt;Tengo que seguir con m&amp;aacute;s an&amp;aacute;lisis de c&amp;oacute;digo de Tankster, patrones y desarrollo de juegos sociales en general.&lt;/p&gt;
&lt;p&gt;Algunos enlaces:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://channel9.msdn.com/coding4fun/blog/WAT-is-to-Social-Gaming-as-Windows-Azure-is-to"&gt;WAT is to Social Gaming, as Windows Azure is to... | Coding4Fun Blog | Channel 9&lt;/a&gt; &lt;br /&gt;Gracias! &amp;ldquo;Vieron a luz&amp;rdquo; y mencionan mi post ;-) &lt;br /&gt;&lt;a href="http://channel9.msdn.com/Shows/Cloud+Cover/Episode-52-Tankster-and-the-Windows-Azure-Toolkit-for-Social-Games"&gt;Episode 52 - Tankster and the Windows Azure Toolkit for Social Games | Cloud Cover | Channel 9&lt;/a&gt; &lt;br /&gt;&lt;a href="http://venturebeat.com/2011/07/19/microsoft-tailors-windows-azure-for-social-game-developers/"&gt;Microsoft tailors Azure cloud services to social game developers | VentureBeat&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.ditii.com/2011/07/20/windows-azure-toolkit-for-social-games-released-to-codeplex-tankster-social-game-built-for-windows-azure/"&gt;Windows Azure Toolkit for Social Games Released to CodePlex &amp;ndash; &amp;lsquo;Tankster&amp;rsquo; Social Game Built for Windows Azure&lt;/a&gt; &lt;br /&gt;&lt;a href="http://channel9.msdn.com/Series/Social-Gaming-on-Windows-Azure/Tankster-a-Social-Game-Built-for-Windows-Azure"&gt;Tankster, a Social Game Built for Windows Azure | Social Gaming on Windows Azure | Channel 9&lt;/a&gt; &lt;br /&gt;&lt;a href="http://channel9.msdn.com/Series/Social-Gaming-on-Windows-Azure"&gt;Social Gaming on Windows Azure | Channel 9&lt;/a&gt; &lt;br /&gt;&lt;a href="http://blogs.msdn.com/b/windowsazure/archive/2011/07/20/build-your-next-game-with-the-windows-azure-toolkit-for-social-games.aspx"&gt;Build Your next Game with the Windows Azure Toolkit for Social Games&lt;/a&gt; &lt;br /&gt;&lt;a href="http://www.zdnet.com/blog/microsoft/microsoft-delivers-early-build-of-windows-azure-toolkit-for-social-game-developers/10115"&gt;Microsoft delivers early build of Windows Azure toolkit for social-game developers | ZDNet&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.delicious.com/ajlopez/tankster" title="http://www.delicious.com/ajlopez/tankster"&gt;http://www.delicious.com/ajlopez/tankster&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Nos leemos!&lt;/p&gt;
&lt;p&gt;Angel &amp;ldquo;Java&amp;rdquo; Lopez &lt;br /&gt;&lt;a href="http://www.ajlopez.com"&gt;http://www.ajlopez.com&lt;/a&gt; &lt;br /&gt;&lt;a href="http://twitter.com/ajlopez"&gt;http://twitter.com/ajlopez&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>