<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9153989234387817345</id><updated>2012-02-02T19:20:23.341-08:00</updated><category term='visual studio'/><category term='C#'/><category term='csharp'/><category term='programacion desarrollo lenguajes'/><category term='gamelab'/><category term='programación'/><category term='java'/><category term='hilos'/><category term='noticias'/><category term='tutorial'/><category term='feria'/><category term='windows'/><category term='gamlab'/><category term='gijon'/><category term='xbox'/><category term='comparativa'/><category term='thread'/><category term='videojuegos'/><category term='XNA'/><category term='drag and drop'/><category term='threading'/><title type='text'>The Code Crab</title><subtitle type='html'>Blog orientado a la programación en diferentes lenguajes y plataformas</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>13</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-6945760865251666129</id><published>2010-07-08T02:44:00.001-07:00</published><updated>2010-09-22T03:55:09.399-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XNA'/><category scheme='http://www.blogger.com/atom/ns#' term='videojuegos'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><category scheme='http://www.blogger.com/atom/ns#' term='windows'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='xbox'/><category scheme='http://www.blogger.com/atom/ns#' term='programación'/><title type='text'>Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 5</title><content type='html'>&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/TDWd1Gy2XzI/AAAAAAAAAM8/BS7CABEH5hU/s1600-h/crabiconballc4.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" title="crab-icon ball c#" alt="crab-icon ball c#" align="left" src="http://lh4.ggpht.com/_OESoGgtnthw/TDWd172nf5I/AAAAAAAAANA/1VaNX76_Wg4/crabiconballc_thumb2.png?imgmax=800" width="48" height="68" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;¿Que tal pequeños cangrejillos? Disculpad la tardanza de esta quinta parte del tutorial, pero me ha dado mas problemas de los que me esperaba, y además he andado algo ocupadillo. En esta parte de tutorial vamos a aprender a manejar detección de colisiones, parte fundamental de prácticamente cualquier videojuego, así que nos ponemos serios, que empieza lo difícil. Empecemos por la teoría.&lt;/p&gt;  &lt;p&gt;Existen numerosas técnicas de detección de colisiones entre sprites (no exclusivas de XNA, son comunes en el mundo del desarrollo de videojuegos). Lo más fácil y eficiente (de cara a procesamiento y obtención de buenos resultados de performance) es utilizar rectángulos, detectando colisión cuando estos se intersecan.&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jbosch/colision_5F00_rectangulo.png"&gt;&lt;img border="0" alt="" src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/jbosch/colision_5F00_rectangulo.png" /&gt;&lt;/a&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jbosch/colision_5F00_rectangulo2.png"&gt;&lt;img border="0" alt="" src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/jbosch/colision_5F00_rectangulo2.png" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;El problema obvio es la imprecisión en la detección de la colisión. Según esto, un impreciso acercamiento entre los dos objetos ya supondría una colisión, como se puede ver en las imágenes anteriores.&lt;/p&gt;  &lt;p&gt;En muy pocas ocasiones, pues, esta técnica tan simple nos valdrá. Aunque existen otras variantes más precisas, y todavía eficientes, basadas en la detección de colisiones mediante rectángulos. Una de ellas sería dividir cada uno de los sprites en rectángulos más pequeños, y englobarlos todos en uno más grande. Entonces, primero intentaríamos detectar la colisión mediante los rectángulos grandes, y solo si esta es afirmativa, intentaríamos detectar la colisión entre los rectángulos más pequeños (y estos son los que decidirían si hay colisión o no).&lt;/p&gt;  &lt;p align="center"&gt;&lt;a href="http://geeks.ms/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/jbosch/colision_5F00_rectangulo3.png"&gt;&lt;img border="0" alt="" src="http://geeks.ms/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/jbosch/colision_5F00_rectangulo3.png" /&gt;&lt;/a&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;img alt="colisiones1" src="http://juank.black-byte.com//Blog/Content/colisiones2d/Colisiones1.gif" width="164" longdesc="Colision entre objetos circulares" height="143" /&gt;&lt;/p&gt;  &lt;p&gt;Como esta existen muchas variantes de la misma técnica, basadas en diferentes formas geométricas, y si bien esta técnica es mucho mas precisa que la anterior, aun puede ser más precisa, aplicando la detección de colisiones denominada “Perfecta” o Pixel a Pixel, en la cual se obtendrá precisión perfecta, activándose solo cuando se colisione a nivel de pixel.&lt;/p&gt;  &lt;p&gt;La principal desventaja de esta técnica es que es más complicada que las anteriores, y por tanto tiene un coste computacional mucho mayor. Sin embargo en nuestro caso vamos a adoptar una solución intermedia, comprobando solo la colisión pixel a pixel solo si se detecta colisión con rectángulos. Evidentemente el rendimiento no es igual que con las técnicas más simples, pero se mejorará muchísimo.&lt;/p&gt;  &lt;p&gt;Fuente: &lt;a title="http://geeks.ms/blogs/jbosch/archive/2009/08/08/xna-pixel-perfect-collision-con-xna-en-base-a-un-mapa-de-colisiones-2d.aspx" href="http://geeks.ms/blogs/jbosch/archive/2009/08/08/xna-pixel-perfect-collision-con-xna-en-base-a-un-mapa-de-colisiones-2d.aspx"&gt;http://geeks.ms/blogs/jbosch/archive/2009/08/08/xna-pixel-perfect-collision-con-xna-en-base-a-un-mapa-de-colisiones-2d.aspx&lt;/a&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TDWd2PJZpfI/AAAAAAAAANE/ENzVL-la_0Q/s1600-h/EnemigoBasico4.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="EnemigoBasico" border="0" alt="EnemigoBasico" align="right" src="http://lh5.ggpht.com/_OESoGgtnthw/TDWd25HIuOI/AAAAAAAAANI/YV-t33Y-wS4/EnemigoBasico_thumb2.png?imgmax=800" width="40" height="57" /&gt;&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Pues explicado esto, vamos al tema. Lo primero que habrá que hacer es una clase para crear enemigos. Esta parte voy rápido que no hay nada nuevo. Añadimos la imagen del enemigo como siempre (metiéndola en la carpeta content y arrastrándola al VS). Una vez esta esto, creamos la clase Enemigo1, algo así:&lt;/p&gt;  &lt;pre style="display: none" class="csharp" name="code"&gt;    class Enemigo1&lt;br /&gt;    {&lt;br /&gt;        private const int anchoImagen = 40;&lt;br /&gt;        private const int altoImagen = 57;&lt;br /&gt;        private Texture2D imagen;&lt;br /&gt;        public Texture2D Imagen&lt;br /&gt;        {&lt;br /&gt;            get { return imagen; }&lt;br /&gt;        }&lt;br /&gt;        private Rectangle bounds;&lt;br /&gt;        public Rectangle Bounds&lt;br /&gt;        {&lt;br /&gt;            get { return bounds; }&lt;br /&gt;        }&lt;br /&gt;        private Vector2 posicion;&lt;br /&gt;        public Vector2 Posicion&lt;br /&gt;        {&lt;br /&gt;            get { return posicion; }&lt;br /&gt;        }&lt;br /&gt;        int altoVentana;&lt;br /&gt;        int anchoVentana;&lt;br /&gt;        public event EventHandler FueraDePantalla;&lt;br /&gt;        public Enemigo1(Vector2 posicion, int altoVentana, int anchoVentana, ContentManager Content)&lt;br /&gt;        {&lt;br /&gt;            this.altoVentana = altoVentana;&lt;br /&gt;            this.anchoVentana = anchoVentana;&lt;br /&gt;            this.posicion = posicion;&lt;br /&gt;            //Ya que los disparos pueden surgir en cualquier momento, y no al principio de la ejecución no tiene sentido tener un método&lt;br /&gt;            //LoadContent que cargue las imágenes. En vez de eso las cargaremos en el constructor.&lt;br /&gt;            imagen = Content.Load&amp;lt;Texture2D&amp;gt;(&amp;quot;EnemigoBasico&amp;quot;);&lt;br /&gt;        }&lt;br /&gt;        public void Update()&lt;br /&gt;        {&lt;br /&gt;            posicion.Y += 3;&lt;br /&gt;            bounds = new Rectangle((int)posicion.X, (int)posicion.Y, anchoImagen, altoImagen);&lt;br /&gt;            if (posicion.Y &amp;gt;= altoVentana)&lt;br /&gt;                FueraDePantalla(this, null);&lt;br /&gt;        }&lt;br /&gt;        public void Draw(SpriteBatch spbtch)&lt;br /&gt;        {&lt;br /&gt;            spbtch.Draw(imagen, posicion, new Rectangle(0,0,anchoImagen, altoImagen), Color.White);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Imagino que a estas alturas sabréis por donde van los tiros. 40 y 57 son las dimensiones de la imagen. Además de los atributos de siempre vemos que tenemos un Rectangle, llamado bounds, en el que almacenamos el rectángulo que representa la imagen dibujada en pantalla y lo mantenemos actualizado (en update). Además añadimos varias propiedades para poder acceder a imagen, _posicion y bounds sin necesidad de implementar un método get (Gracias a esto se podra acceder simplemente con &lt;em&gt;enemigo.Imagen &lt;/em&gt;o&lt;em&gt; enemigo.Bounds. &lt;/em&gt;Este nuevo atributo, así como las diferentes propiedades también tienen que ser añadidas a las clases Nave y Disparo, pues nos hará falta para la detección de colisiones:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="display: none" class="csharp" name="code"&gt;    class Disparo&lt;br /&gt;    {&lt;br /&gt;        private const int anchoImagen = 6;&lt;br /&gt;        private const int altoImagen = 22;&lt;br /&gt;        private Texture2D imagen;&lt;br /&gt;        public Texture2D Imagen&lt;br /&gt;        {&lt;br /&gt;            get { return imagen; }&lt;br /&gt;        }&lt;br /&gt;        private Rectangle bounds;&lt;br /&gt;        public Rectangle Bounds&lt;br /&gt;        {&lt;br /&gt;            get { return bounds; }&lt;br /&gt;        }&lt;br /&gt;        private Vector2 posicion;&lt;br /&gt;        public Vector2 Posicion&lt;br /&gt;        {&lt;br /&gt;            get { return posicion; }&lt;br /&gt;        }&lt;br /&gt;        public event EventHandler FueraDePantalla;&lt;br /&gt;        &lt;br /&gt;        public Disparo(Vector2 posicion, int anchoNave, ContentManager Content)&lt;br /&gt;        {&lt;br /&gt;            this.posicion = posicion;&lt;br /&gt;            //movemos un poco la posicion del disparo, para que salga desde el centro de la nave y no desde una esquina&lt;br /&gt;            posicion.X += (anchoNave / 2);&lt;br /&gt;            //lo que acabamos de centrar es la esquina superior izquierda del disparo. Así situaremos el centro alineado con el centro de la imagen&lt;br /&gt;            //los 3 pixeles extra es por que la imagen del disparo no esta perfectamente centrada.&lt;br /&gt;            posicion.X -= (anchoImagen / 2)+3;&lt;br /&gt;            //Ya que los disparos pueden surgir en cualquier momento, y no al principio de la ejecución no tiene sentido tener un método&lt;br /&gt;            //LoadContent que cargue las imágenes. En vez de eso las cargaremos en el constructor.&lt;br /&gt;            imagen = Content.Load&amp;lt;Texture2D&amp;gt;(&amp;quot;weapons&amp;quot;);&lt;br /&gt;        }&lt;br /&gt;        public void Update()&lt;br /&gt;        {&lt;br /&gt;            posicion.Y-=5;&lt;br /&gt;            bounds = new Rectangle((int)posicion.X, (int)posicion.Y, anchoImagen, altoImagen);&lt;br /&gt;            if (posicion.Y &amp;lt;= 0)&lt;br /&gt;                FueraDePantalla(this, null);&lt;br /&gt;        }&lt;br /&gt;        public void Draw(SpriteBatch spbtch)&lt;br /&gt;        {&lt;br /&gt;            spbtch.Draw(imagen, posicion, new Rectangle(0,0,anchoImagen, altoImagen), Color.White);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="display: none" class="csharp" name="code"&gt;    class Nave&lt;br /&gt;    {&lt;br /&gt;        private Rectangle rectangulo;&lt;br /&gt;        private const int anchoImagen = 42;&lt;br /&gt;        private const int altoImagen = 44;&lt;br /&gt;        private Texture2D imagen;&lt;br /&gt;        public Texture2D Imagen&lt;br /&gt;        {&lt;br /&gt;            get { return imagen; }&lt;br /&gt;        }&lt;br /&gt;        //Este rectangulo representa la posicion dentro de la ventana, mientras que el que ya teniamos&lt;br /&gt;        //representa la posición dentro de la imagen.&lt;br /&gt;        private Rectangle bounds;&lt;br /&gt;        public Rectangle Bounds&lt;br /&gt;        {&lt;br /&gt;            get { return bounds; }&lt;br /&gt;        }&lt;br /&gt;        private Vector2 posicion;&lt;br /&gt;        public Vector2 Posicion&lt;br /&gt;        {&lt;br /&gt;            get { return posicion; }&lt;br /&gt;        }&lt;br /&gt;        private int altoVentana;&lt;br /&gt;        private int anchoVentana;&lt;br /&gt;        private List&lt;disparo&gt;disparos;&lt;br /&gt;        public List&lt;disparo&gt; Disparos&lt;br /&gt;        {&lt;br /&gt;            get { return disparos; }&lt;br /&gt;        }&lt;br /&gt;        private int frameCounter = 0;&lt;br /&gt;        private ContentManager content;&lt;br /&gt;        public Nave(int altoVentana, int anchoVentana)&lt;br /&gt;        {&lt;br /&gt;            this.altoVentana = altoVentana;&lt;br /&gt;            this.anchoVentana = anchoVentana;&lt;br /&gt;            posicion = new Vector2(altoVentana - altoImagen * 2, (anchoVentana - anchoImagen) / 2);&lt;br /&gt;            CrearRectangulo(anchoImagen, altoImagen * 2);&lt;br /&gt;            disparos = new List&amp;lt;Disparo&amp;gt;();&lt;br /&gt;        }&lt;br /&gt;        public void LoadContent(ContentManager Content)&lt;br /&gt;        {&lt;br /&gt;            this.content = Content;&lt;br /&gt;            imagen = Content.Load&amp;lt;Texture2D&amp;gt;(&amp;quot;battleship&amp;quot;);&lt;br /&gt;        }&lt;br /&gt;        public void Update()&lt;br /&gt;        {&lt;br /&gt;            UpdateShots();&lt;br /&gt;            UpdatePosition();&lt;br /&gt;            UpdateRectangle();            &lt;br /&gt;        }&lt;br /&gt;        private void UpdateShots()&lt;br /&gt;        {&lt;br /&gt;            frameCounter++;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Z) &amp;amp;&amp;amp; disparos.Count &amp;lt; 6 &amp;amp;&amp;amp; frameCounter &amp;gt; 7)&lt;br /&gt;            {&lt;br /&gt;                Disparo s = new Disparo(posicion, anchoImagen, content);&lt;br /&gt;                disparos.Add(s);&lt;br /&gt;                s.FueraDePantalla += new EventHandler(FueraDePantallaHandler);&lt;br /&gt;                frameCounter = 0;&lt;br /&gt;            }&lt;br /&gt;            disparos.ForEach(x =&amp;gt; x.Update());        &lt;br /&gt;        }&lt;br /&gt;        private void UpdatePosition()&lt;br /&gt;        {&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Left) &amp;amp;&amp;amp; posicion.X &amp;gt; 5)&lt;br /&gt;                posicion.X -= 5;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Right) &amp;amp;&amp;amp; posicion.X &amp;lt; (anchoVentana - anchoImagen))&lt;br /&gt;                posicion.X += 5;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Up) &amp;amp;&amp;amp; posicion.Y &amp;gt; 5)&lt;br /&gt;                posicion.Y -= 5;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Down) &amp;amp;&amp;amp; posicion.Y &amp;lt; (altoVentana - altoImagen))&lt;br /&gt;                posicion.Y += 5;&lt;br /&gt;            bounds = new Rectangle((int)Posicion.X, (int)Posicion.Y, anchoImagen, altoImagen);&lt;br /&gt;        }&lt;br /&gt;        private void UpdateRectangle()&lt;br /&gt;        {&lt;br /&gt;            //a partir de aquí escojemos la parte de imagen que queremos dibujar y la almacenamos en rectangle,&lt;br /&gt;            // en funcion de la combinaion de botones que se esten pulsando.&lt;br /&gt;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Left) &amp;amp;&amp;amp; Keyboard.GetState().IsKeyDown(Keys.Up))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(0, altoImagen);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Right) &amp;amp;&amp;amp; Keyboard.GetState().IsKeyDown(Keys.Up))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen * 2, altoImagen);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Up))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen, altoImagen);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Left) &amp;amp;&amp;amp; Keyboard.GetState().IsKeyDown(Keys.Down))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(0, 0);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Right) &amp;amp;&amp;amp; Keyboard.GetState().IsKeyDown(Keys.Down))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen * 2, 0);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Down))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen, 0);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Left))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(0, altoImagen * 2);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Right))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen * 2, altoImagen * 2);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen, altoImagen * 2);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        private void CrearRectangulo(int x, int y)&lt;br /&gt;        {&lt;br /&gt;            rectangulo = new Rectangle(x, y, anchoImagen, altoImagen);&lt;br /&gt;        }&lt;br /&gt;        public void Draw(SpriteBatch spbtch)&lt;br /&gt;        {&lt;br /&gt;            spbtch.Draw(imagen, posicion, rectangulo, Color.White);&lt;br /&gt;            DrawShots(spbtch);&lt;br /&gt;        }&lt;br /&gt;        private void DrawShots(SpriteBatch spbtch)&lt;br /&gt;        {&lt;br /&gt;            foreach (Disparo s in disparos)&lt;br /&gt;            {&lt;br /&gt;                s.Draw(spbtch);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        private void FueraDePantallaHandler(Object sender, EventArgs args)&lt;br /&gt;        {&lt;br /&gt;            disparos.Remove((Disparo)sender);&lt;br /&gt;        }&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Solo muestro las partes que cambio por evitar hacer un post enorme, así que cuidado si copiáis pegáis. Con esto añadimos las nuevas propiedades, el nuevo atributo, y mantenemos actualizado este atributo. Es importante darse cuenta de la diferencia entre este rectángulo (bounds) que muestra el rectángulo ocupado por la imagen en la ventana, y el otro rectángulo que ya teníamos en Nave, que representa que parte de la imagen se va a dibujar.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ahora que esta todo preparado, lo primero que hay que hacer es mostrar los enemigos por pantalla. Esto lo manejaremos en la clase Game1 de momento (En la próxima parte del tutorial se hará una pequeña reestructuración).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="display: none" class="csharp" name="code"&gt;        public class Game1 : Microsoft.Xna.Framework.Game&lt;br /&gt;        {&lt;br /&gt;            private GraphicsDeviceManager graphics;&lt;br /&gt;            private SpriteBatch spriteBatch;&lt;br /&gt;            private Nave nave;&lt;br /&gt;            private Fondo fondo;&lt;br /&gt;            private int frameCounter = 0;&lt;br /&gt;            private List&amp;lt;Enemigo1&amp;gt; enemigos;&lt;br /&gt;&lt;br /&gt;            public Game1()&lt;br /&gt;            {&lt;br /&gt;                graphics = new GraphicsDeviceManager(this);&lt;br /&gt;                enemigos = new List&amp;lt;Enemigo1&amp;gt;();&lt;br /&gt;                Content.RootDirectory = &amp;quot;Content&amp;quot;;            &lt;br /&gt;            }&lt;br /&gt;	...&lt;br /&gt;            protected override void Update(GameTime gameTime)&lt;br /&gt;            {&lt;br /&gt;                // Cuidado con esto, no usamos mando.&lt;br /&gt;                if (Keyboard.GetState().IsKeyDown(Keys.Escape))&lt;br /&gt;                    this.Exit();&lt;br /&gt;                fondo.Update();&lt;br /&gt;                nave.Update();&lt;br /&gt;                UpdateEnemigos();&lt;br /&gt;                base.Update(gameTime);&lt;br /&gt;            }&lt;br /&gt;            private void UpdateEnemigos()&lt;br /&gt;            {&lt;br /&gt;                frameCounter++;&lt;br /&gt;                if (frameCounter &amp;gt; 60)&lt;br /&gt;                {&lt;br /&gt;                    Random r = new Random();&lt;br /&gt;                    Enemigo1 e = new Enemigo1(&lt;br /&gt;                        new Vector2(r.Next(graphics.PreferredBackBufferWidth), -57),&lt;br /&gt;                        graphics.PreferredBackBufferHeight,&lt;br /&gt;                        graphics.PreferredBackBufferWidth,&lt;br /&gt;                        Content&lt;br /&gt;                        );&lt;br /&gt;                    enemigos.Add(e);&lt;br /&gt;                    e.FueraDePantalla += new EventHandler(FueraDePantallaHandler);&lt;br /&gt;                    frameCounter = 0;&lt;br /&gt;                }&lt;br /&gt;                enemigos.ForEach(x =&amp;gt; x.Update());  &lt;br /&gt;            }&lt;br /&gt;            private void FueraDePantallaHandler(Object sender, EventArgs args)&lt;br /&gt;            {&lt;br /&gt;                enemigos.Remove((Enemigo1)sender);&lt;br /&gt;            }&lt;br /&gt;            protected override void Draw(GameTime gameTime)&lt;br /&gt;            {&lt;br /&gt;                GraphicsDevice.Clear(Color.Black);&lt;br /&gt;&lt;br /&gt;                spriteBatch.Begin();&lt;br /&gt;                fondo.Draw(spriteBatch);&lt;br /&gt;                nave.Draw(spriteBatch);&lt;br /&gt;                foreach (Enemigo1 e in enemigos)&lt;br /&gt;                {&lt;br /&gt;                    e.Draw(spriteBatch);&lt;br /&gt;                }&lt;br /&gt;                spriteBatch.End();&lt;br /&gt;&lt;br /&gt;                base.Draw(gameTime);&lt;br /&gt;            }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Añadimos a los atributos una lista de enemigos, que luego instanciamos en el constructor, además de un int para contar los frames (ahora veréis para que). Después, en Update, añadimos UpdateEnemigos, que hará varias cosas. Lo primero será aumentar &lt;em&gt;frameCounter&lt;/em&gt; para así saber cuando pasan 60 frames.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Si el contador es mayor que 60 procederemos a añadir un nuevo enemigo (Con esto evitamos añadir sabedioscuantos enemigos por segundo). Para ello, instanciamos un objeto Random, y creamos un enemigo con una coordenada X aleatoria (Con la anchura de la pantalla de máximo) y –57 de coordenada Y para que entre poco a poco a la pantalla. Añadimos este enemigo recién creado a la lista enemigos, controlamos el evento &lt;em&gt;FueraDePantalla&lt;/em&gt; (De igual manera que lo hacemos con los disparos, para borrar los enemigos que se salgan de la pantalla). Por ultimo ponemos el contador de frames a 0.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Después, fuera del If (esto se tiene que ejecutar siempre, no solo cada 60 frames) se invocara a Update de todos los enemigos. Una vez más no utilizamos foreach por que es posible que se dispare &lt;em&gt;FueraDePantalla &lt;/em&gt;y que cambie enemigos, lo que haría que un foreach diese un error en tiempo de ejecución, pero la expresión lambda utilizada en esencia hace lo mismo.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TDWd33bNdJI/AAAAAAAAANM/PhqUxBNdtWk/s1600-h/image%5B6%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh5.ggpht.com/_OESoGgtnthw/TDWd4uNJYuI/AAAAAAAAANQ/duw8nCXJZSs/image_thumb%5B4%5D.png?imgmax=800" width="496" height="323" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto podemos probar a ejecutar y veremos que ya tenemos una serie de enemigos en pantalla cada X tiempo. ¿Va cogiendo forma no?. Ahora que ya está todo preparado podemos empezar con la detección de colisiones, manejada una vez mas desde Game1 temporalmente:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre style="display: none" class="csharp" name="code"&gt;            protected override void Update(GameTime gameTime)&lt;br /&gt;            {&lt;br /&gt;                // Cuidado con esto, no usamos mando.&lt;br /&gt;                if (Keyboard.GetState().IsKeyDown(Keys.Escape))&lt;br /&gt;                    this.Exit();&lt;br /&gt;                fondo.Update();&lt;br /&gt;                nave.Update();&lt;br /&gt;                UpdateEnemigos();&lt;br /&gt;                UpdateColisiones();&lt;br /&gt;                base.Update(gameTime);&lt;br /&gt;            }&lt;br /&gt;	...&lt;br /&gt;            private void UpdateColisiones()&lt;br /&gt;            {&lt;br /&gt;                //eliminamos cualquier enemigo que haya colisionado contra cualquier disparo en la pantalla&lt;br /&gt;                bool colision = false;&lt;br /&gt;                Enemigo1 enemigoABorrar = null;&lt;br /&gt;                Disparo disparoABorrar = null;&lt;br /&gt;&lt;br /&gt;                foreach (Enemigo1 e in enemigos)&lt;br /&gt;                {&lt;br /&gt;                    foreach (Disparo d in nave.Disparos)&lt;br /&gt;                    {&lt;br /&gt;                        if(ColisionEnemigoDisparo(e, d))&lt;br /&gt;                        {&lt;br /&gt;                            //si hay colision ponemos el tag a true, almacenamos el disparo y el enemigo y rompemos el primer bucle&lt;br /&gt;                            colision = true;&lt;br /&gt;                            enemigoABorrar = e;&lt;br /&gt;                            disparoABorrar = d;&lt;br /&gt;                            break;                            &lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                    //si el tag esta activo rompemos el segundo bucle&lt;br /&gt;                    if (colision)&lt;br /&gt;                        break;&lt;br /&gt;                }&lt;br /&gt;                //si el tag esta activo borramos el enemigo y el disparo&lt;br /&gt;                if (colision)&lt;br /&gt;                {&lt;br /&gt;                    enemigos.Remove(enemigoABorrar);&lt;br /&gt;                    nave.Disparos.Remove(disparoABorrar);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            private bool ColisionEnemigoDisparo(Enemigo1 e, Disparo d)&lt;br /&gt;            {&lt;br /&gt;                //Si los rectangle de e y de d se intersectan comprobamos la colision.&lt;br /&gt;                if(e.Bounds.Intersects(d.Bounds))&lt;br /&gt;                    return ColisionPixel(d.Imagen, e.Imagen, d.Posicion, e.Posicion);&lt;br /&gt;                return false;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            public static bool ColisionPixel(Texture2D texturaA, Texture2D texturaB, Vector2 posicionA, Vector2 posicionB)&lt;br /&gt;            {&lt;br /&gt;                bool colisionPxAPx = false;&lt;br /&gt;&lt;br /&gt;                uint[] bitsA = new uint[texturaA.Width * texturaA.Height];&lt;br /&gt;                uint[] bitsB = new uint[texturaB.Width * texturaB.Height];&lt;br /&gt;&lt;br /&gt;                Rectangle rectanguloA = new Rectangle(Convert.ToInt32(posicionA.X), Convert.ToInt32(posicionA.Y), texturaA.Width, texturaA.Height);&lt;br /&gt;                Rectangle rectanguloB = new Rectangle(Convert.ToInt32(posicionB.X), Convert.ToInt32(posicionB.Y), texturaB.Width, texturaB.Height);&lt;br /&gt;                //almacenamos los datos de los pixeles en las variables locales bitsA y bitsB&lt;br /&gt;                texturaA.GetData&lt;uint&gt;(bitsA);&lt;br /&gt;                texturaB.GetData&lt;uint&gt;(bitsB);&lt;br /&gt;                &lt;br /&gt;                //almacenamos las coordenadas que delimitaran la zona en la que trabajaremos&lt;br /&gt;                int x1 = Math.Max(rectanguloA.X, rectanguloB.X);&lt;br /&gt;                int x2 = Math.Min(rectanguloA.X + rectanguloA.Width, rectanguloB.X + rectanguloB.Width);&lt;br /&gt;&lt;br /&gt;                int y1 = Math.Max(rectanguloA.Y, rectanguloB.Y);&lt;br /&gt;                int y2 = Math.Min(rectanguloA.Y + rectanguloA.Height, rectanguloB.Y + rectanguloB.Height);&lt;br /&gt;&lt;br /&gt;                for (int y = y1; y &amp;lt; y2; ++y)&lt;br /&gt;                {&lt;br /&gt;                    for (int x = x1; x &amp;lt; x2; ++x)&lt;br /&gt;                    {&lt;br /&gt;                        if (((bitsA[(x - rectanguloA.X) + (y - rectanguloA.Y) * rectanguloA.Width] &amp;amp; 0xFF000000) &amp;gt;&amp;gt; 24) &amp;gt; 20 &amp;amp;&amp;amp;&lt;br /&gt;                            ((bitsB[(x - rectanguloB.X) + (y - rectanguloB.Y) * rectanguloB.Width] &amp;amp; 0xFF000000) &amp;gt;&amp;gt; 24) &amp;gt; 20)&lt;br /&gt;                        {&lt;br /&gt;                            //Se comprueba el canal alpha de las dos imagenes en el mismo pixel. Si los dos son visibles hay colision.&lt;br /&gt;                            colisionPxAPx = true;&lt;br /&gt;                            break;&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    // Rompe el bucle si la condicion ya se ha cumplido.&lt;br /&gt;                    if (colisionPxAPx)&lt;br /&gt;                    {&lt;br /&gt;                        break;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                return colisionPxAPx;&lt;br /&gt;            }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Añadimos a Update otro método en el cual manejaremos las colisiones. Como ya mencionamos anteriormente no se puede eliminar la lista que se este iterando dentro de un iterador foreach, pero esta vez no podremos usar una expresión lambda, así que utilizaremos un tag y unas variables locales para saber cuando se encuentra una colisión y borrar tanto el disparo como el enemigo después de salir del bucle.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En el método colisión enemigo disparo, usado por el método anterior, comprobamos si hay una colisión rectangular, y en caso de que sea así pasamos a ver si hay colisión pixel a pixel. En caso de que sea así devolvemos true y si no devolvemos false.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En cuanto al método estático ColisionPixel, almacenamos los datos de los pixeles en los arrays bitsA y bitsB, buscamos los limites del espacio que vamos a manejar, con las coordenadas x1, x2, y1 y y2. Con todo esto recorremos los arrays bitsA y bitsB con dos bucles for en los cuales comprobamos en cada iteración el canal Alpha de transparencia de las dos imágenes en un punto concreto. Por esto en caso de que ninguna de las dos imágenes sea transparente en cualquier punto significa que hay colisión, por lo que devolveremos true.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TDWd5p_qomI/AAAAAAAAANU/W0N2PdV89Qo/s1600-h/image%5B15%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh3.ggpht.com/_OESoGgtnthw/TDWd6lpLWJI/AAAAAAAAANY/g-ZovrbDJlE/image_thumb%5B9%5D.png?imgmax=800" width="518" height="334" /&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TDWd7u237gI/AAAAAAAAANc/RIGxXn9bem4/s1600-h/image%5B21%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh6.ggpht.com/_OESoGgtnthw/TDWd8ePH34I/AAAAAAAAANg/NP7XAyK68RA/image_thumb%5B13%5D.png?imgmax=800" width="104" height="146" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Con esto la detección de colisiones esta completa, y lo podemos ver ejecutando el juego, aunque no se aprecie en la captura :P La colisión de los enemigos con las nave la pondremos mas adelante, cuando se añadan las vidas y la pantalla de gameover. No obstante esto empieza a coger forma ya, ¿no? Podéis bajar el código hasta ahora en el siguiente enlace:&amp;#160; &lt;a title="http://www.megaupload.com/?d=OE6KUY4S" href="http://www.megaupload.com/?d=OE6KUY4S"&gt;http://www.megaupload.com/?d=OE6KUY4S&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En la próxima entrega del tutorial menú, pantalla de pausa y pantalla de gameover. No os lo perdáis y ¡Sed buenos cangrejos!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; He cambiado algunas cosas en el código respecto a la parte 5 del tutorial original con la intención de obtener un código más limpio. Quite todas las _ de las variables, y me asegure de que todas las propiedades estaban en mayúscula. A parte de esto también cambie algunos puntos donde se accedía a las variables mediante las propiedades desde dentro de la misma clase.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Para los que hagan el tutorial a partir de ahora (22/09/2010) no lo notarán, pues ya esta actualizado, pero los que ya han hecho el tutorial que se bajen mi código, ya que esta corregido. Es posible que se me colase alguna errata, en tal caso hacédmelo saber.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-6945760865251666129?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/6945760865251666129/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/07/programando-videojuegos-tutorial-xna.html#comment-form' title='27 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/6945760865251666129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/6945760865251666129'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/07/programando-videojuegos-tutorial-xna.html' title='Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 5'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_OESoGgtnthw/TDWd172nf5I/AAAAAAAAANA/1VaNX76_Wg4/s72-c/crabiconballc_thumb2.png?imgmax=800' height='72' width='72'/><thr:total>27</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-2405416765012721974</id><published>2010-07-03T04:39:00.001-07:00</published><updated>2010-07-03T04:39:25.756-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gijon'/><category scheme='http://www.blogger.com/atom/ns#' term='gamelab'/><category scheme='http://www.blogger.com/atom/ns#' term='videojuegos'/><category scheme='http://www.blogger.com/atom/ns#' term='feria'/><title type='text'>GameLab 2010: Tercer día</title><content type='html'>&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TC8hQ4w4YCI/AAAAAAAAAME/htmYYHVAdNE/s1600-h/image003200x2504.jpg"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" title="image003--200x250" alt="image003--200x250" align="left" src="http://lh6.ggpht.com/_OESoGgtnthw/TC8hRbkBhJI/AAAAAAAAAMI/9eU-M6wXVto/image003200x250_thumb2.jpg?imgmax=800" width="88" height="100" /&gt;&lt;/a&gt; Un día más en The Code Crab hemos asistido al &lt;a href="http://www.gamelab.es/"&gt;GameLab 2010&lt;/a&gt;, y aquí estoy resumiendo el día. Lo primero es decir que hoy viernes, ultimo día, la feria concluía a las 2 del mediodía, y por tanto había menos actividades que los otros días, y una vez más no hay nada nuevo que probar por lo que me centrare en las charlas. Además de esto no he podido asistir a todas las charlas, por lo que resumiré las que pude ver. &lt;/p&gt;  &lt;p&gt;A primera hora hubo una mesa redonda sobre las nuevas plataformas, y el modo en que afectan estas a los creadores. Por desgracia no pude asistir, pero mi sorpresa fue grande al ver que la siguiente conferencia, iPad, una oportunidad para los creadores, no fue en realidad una conferencia como indicaba el programa, sino &lt;strong&gt;otra mesa redonda en la que apenas se mencionó el iPad&lt;/strong&gt;. De hecho no asistí a la primera mesa redonda, pero el titulo que tenia encaja definitivamente mucho mas en la mesa redonda que vi (Y no me equivoque de charla yo, que pregunté y todo).&lt;/p&gt;  &lt;p&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh3.ggpht.com/_OESoGgtnthw/TC8hR8OUjvI/AAAAAAAAAMM/cQLI9sZQVdw/image_thumb%5B13%5D.png?imgmax=800" width="240" height="160" /&gt; &lt;/p&gt;  &lt;p&gt;En esta improvisada mesa redonda pudimos ver a &lt;a href="http://www.gamelab.es/ponentes/xavier-carrillo/"&gt;Xavier Carrillo&lt;/a&gt;, Director General de &lt;a href="http://www.digital-legends.com/"&gt;Digital Legends Entertainment&lt;/a&gt;, el supuesto ponente, junto con &lt;a href="http://www.gamelab.es/ponentes/gonzalo-suarez-girard/"&gt;Gonzo Suárez&lt;/a&gt; y &lt;a href="http://www.gamelab.es/ponentes/igor-pusenjak/"&gt;Igor Pusenjak&lt;/a&gt; (No estoy seguro al 100% de que eran ellos, pues como reitero una vez más esta mesa redonda estaba fuera del programa). Se habló de los nuevos medios, y de la importancia de los juegos sociales, descubiertos mediante facebook. ¿Que nos deparara el futuro? Desde luego hay que aprovechar al máximo todos los nuevos medios, cambiando radicalmente la formula tradicional del desarrollo de los videojuegos.&lt;/p&gt;  &lt;p&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh3.ggpht.com/_OESoGgtnthw/TC8hSq9xHQI/AAAAAAAAAMQ/CVY-DRbiJyY/image_thumb%5B16%5D.png?imgmax=800" width="240" height="228" /&gt; &lt;/p&gt;  &lt;p&gt;Tras esta mesa redonda, hubo otra sobre las diferentes plataformas en el mercado de los juegos móviles, pero tras el desastre(esto es mi opinión, claro) de la supuesta conferencia del iPad no estaba de humor para otra mesa redonda, así que no asistí.&lt;/p&gt;  &lt;p&gt;Tras esto &lt;a href="http://www.gamelab.es/ponentes/juancho-carrillo/"&gt;Juancho Carrillo&lt;/a&gt;, Lead Designer de &lt;a href="http://tonika.es/"&gt;Tonika Games&lt;/a&gt;, junto con &lt;a href="http://www.gamelab.es/ponentes/roberto-lopez-yeste/"&gt;Roberto López Yeste&lt;/a&gt; y &lt;a href="http://www.gamelab.es/ponentes/richard-brown/"&gt;Richard Brown&lt;/a&gt; nos ofrecieron una interesante conferencia en la cual se nos presento PlayEnglish.&lt;/p&gt;  &lt;div style="padding-bottom: 0px; padding-left: 0px; width: 425px; padding-right: 0px; display: block; float: none; margin-left: auto; margin-right: auto; padding-top: 0px" id="scid:5737277B-5D6D-4f48-ABFC-DD9C333F4C5D:fa5d4834-374d-4e2a-98be-81fa229eaa33" class="wlWriterEditableSmartContent"&gt;&lt;div id="1666c952-cd27-4c41-a540-f2af8938c549" style="margin: 0px; padding: 0px; display: inline;"&gt;&lt;div&gt;&lt;a href="http://www.youtube.com/watch?v=IQ-19XB2u8E&amp;amp;hl=es_ES&amp;amp;fs=1" target="_new"&gt;&lt;img src="http://lh3.ggpht.com/_OESoGgtnthw/TC8hTOVrTUI/AAAAAAAAAM0/YATBPZEeVQU/video0d91e459c0c5%5B5%5D.jpg?imgmax=800" style="border-style: none" galleryimg="no" onload="var downlevelDiv = document.getElementById('1666c952-cd27-4c41-a540-f2af8938c549'); downlevelDiv.innerHTML = &amp;quot;&amp;lt;div&amp;gt;&amp;lt;object width=\&amp;quot;425\&amp;quot; height=\&amp;quot;355\&amp;quot;&amp;gt;&amp;lt;param name=\&amp;quot;movie\&amp;quot; value=\&amp;quot;http://www.youtube.com/v/IQ-19XB2u8E&amp;amp;hl=es_ES&amp;amp;fs=1&amp;amp;hl=en\&amp;quot;&amp;gt;&amp;lt;\/param&amp;gt;&amp;lt;embed src=\&amp;quot;http://www.youtube.com/v/IQ-19XB2u8E&amp;amp;hl=es_ES&amp;amp;fs=1&amp;amp;hl=en\&amp;quot; type=\&amp;quot;application/x-shockwave-flash\&amp;quot; width=\&amp;quot;425\&amp;quot; height=\&amp;quot;355\&amp;quot;&amp;gt;&amp;lt;\/embed&amp;gt;&amp;lt;\/object&amp;gt;&amp;lt;\/div&amp;gt;&amp;quot;;" alt=""&gt;&lt;/a&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;  &lt;p&gt;Tras un rato de publicidad de Sony (y es que tenemos muy claro que los chicos de Sony se encantan a si mismos) nos mostraron el trailer que podéis ver encima (nada exclusivo, es el anuncio de TV).&lt;/p&gt;  &lt;p&gt;Este juego es bastante innovador, según nos contaron, pues pese a ser un juego educativo esta más centrado en la diversión que en el aprendizaje, haciendo así que el aprender ingles sea progresivamente, de forma natural y divertida. El jugador tendrá que encarar una serie de pruebas, dignas de cualquier aventura gráfica, en las cuales tendrá que aplicar conocimientos de ingles y adquirir conocimientos nuevos de forma practica. Además de esto el juego cuenta con varios &lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/TC8hUHJNZnI/AAAAAAAAAMY/wW4C69HaJFI/s1600-h/image%5B30%5D.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" title="image" alt="image" align="right" src="http://lh5.ggpht.com/_OESoGgtnthw/TC8hUxmCMjI/AAAAAAAAAMc/evDgwHn3uIo/image_thumb%5B22%5D.png?imgmax=800" width="142" height="129" /&gt;&lt;/a&gt;niveles de dificultad, y &lt;strong&gt;se centra en las partes que dan problemas al jugador&lt;/strong&gt;, ofreciendo una experiencia personalizada.&lt;/p&gt;  &lt;p&gt;Todo esto hace de PlayEnglish un juego bastante interesante y digno de probar, para de paso repasar esos Phrasal&amp;#160; Verbs que tanto dolor de cabeza nos dieron en su día. Tras esto se declaro en exclusiva que el próximo desarrollo del estudio iba a ser… Patito Feo, que pese a lo mal que pueda sonar, seguro que es un gran éxito (orientado a un publico mas concreto claro).&lt;/p&gt;  &lt;p&gt;Por ultimo, la ultima conferencia fue de la mano de Gilberto Sánchez, Director Editorial de &lt;a href="http://www.virtualtoys.net/"&gt;Virtual Toys&lt;/a&gt;, estudio responsable de títulos como Horsez y Imagina Ser. La conferencia hablaba del proceso intermedio que hay entre la finalización de un juego y la publicación del mismo, y se dejo claro que &lt;strong&gt;hacer un buen juego solo es un 40% del trabajo&lt;/strong&gt;.&lt;/p&gt;  &lt;p&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh6.ggpht.com/_OESoGgtnthw/TC8hVqF0jjI/AAAAAAAAAMg/7ZhIYkGPPNA/image_thumb%5B26%5D.png?imgmax=800" width="240" height="89" /&gt; &lt;/p&gt;  &lt;p&gt;Tras un rato hablando de temas de publicidad, mercados, y demás cosas aburridas, se nos anuncio que el estudio ahora mismo estaba trabajando en Torrente Online 2, el cual dispone de muchas novedades frente al primero, y cuya beta ya estará disponible el próximo 19 de julio.&lt;/p&gt;  &lt;p&gt;Con esto (y con un sorteo de una ps3 y una psp go) concluye el GameLab 2010. En cuanto mis impresiones generales del evento, creo que este año se ha batido un record de visitas, pues ha estado algo más orientado al publico que otras veces, más pensado para diseñadores y empresas.&lt;/p&gt;  &lt;p&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh5.ggpht.com/_OESoGgtnthw/TC8hWFt9e_I/AAAAAAAAAMk/wAozhz8EVzo/image_thumb%5B30%5D.png?imgmax=800" width="520" height="203" /&gt; &lt;/p&gt;  &lt;p&gt;La presencia de Sony no dejo nada que desear, ofreciéndonos varias novedades como el 3D, el Castlevania LOS, el nuevo SingStar, el Gran Turismo 5 y PlayStation Move, pero sin embargo la presencia de Nintendo fue bastante ligera, en cuanto a que tenia cosas para probar pero &lt;strong&gt;ninguna novedad&lt;/strong&gt;, mientras que Microsoft ni siquiera patrocinaba, solo colaboraba, por lo que ofreció conferencias interesantes pero &lt;strong&gt;nada para probar&lt;/strong&gt;. Con esto quiero decir, que GameLab se está convirtiendo en un pequeño E3, y vamos por buen camino, pero aun no es suficiente, y si Nintendo y Microsoft hubiese colaborado tanto como lo hizo Sony el evento hubiese sido mucho mejor.&lt;/p&gt;  &lt;p&gt;En cuanto a las conferencias (y esto es, una vez más, mi opinión, y no un hecho universal), una vez mas se mezclan conferencias muy interesantes, como presentaciones en exclusiva de juegos (Como Castlevania o Kinect), con otras que se repiten año tras año sin ninguna clase de novedad, como una serie de mesas redondas. En mi opinión para seguir avanzando el GameLab debe centrarse más en las novedades. Conferencias sobre diferentes plataformas, presentaciones de juegos, nuevas tecnologías y que nos depara el futuro. Todo esto lo hubo este año, pero por desgracia, solo fue entorno al 50% de las conferencias, siendo el resto bastante menos interesantes. &lt;/p&gt;  &lt;p&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh6.ggpht.com/_OESoGgtnthw/TC8hWtwsMAI/AAAAAAAAAMo/FVls2UQsiks/image_thumb%5B34%5D.png?imgmax=800" width="386" height="153" /&gt; &lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/TC8hXFAwu7I/AAAAAAAAAMs/PWfrQ0Nco3I/s1600-h/image%5B12%5D.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; margin-left: 0px; border-top: 0px; margin-right: 0px; border-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh4.ggpht.com/_OESoGgtnthw/TC8hXhtOUlI/AAAAAAAAAMw/ijo9mG1DStU/image_thumb%5B10%5D.png?imgmax=800" width="90" height="77" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Por tanto en mi opinión, GameLab, algún año será un pequeño E3 en Asturias, pero aún nos queda un largo camino por recorrer. Sin embargo, ese día cada vez esta más cerca, estoy seguro de que el próximo año estará aún mejor, ¡Lo esperamos con impaciencia Lobo!. Tras la vuelta a la normalidad me pondré a trabajar de nuevo en el tutorial de XNA, así que estad atentos. ¡¡Sed unos cangrejos pacientes!!&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-2405416765012721974?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/2405416765012721974/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/07/gamelab-2010-tercer-dia.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/2405416765012721974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/2405416765012721974'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/07/gamelab-2010-tercer-dia.html' title='GameLab 2010: Tercer día'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_OESoGgtnthw/TC8hRbkBhJI/AAAAAAAAAMI/9eU-M6wXVto/s72-c/image003200x250_thumb2.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-5590037401026177149</id><published>2010-07-01T08:57:00.001-07:00</published><updated>2010-07-01T12:57:19.077-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gijon'/><category scheme='http://www.blogger.com/atom/ns#' term='gamelab'/><category scheme='http://www.blogger.com/atom/ns#' term='videojuegos'/><category scheme='http://www.blogger.com/atom/ns#' term='feria'/><title type='text'>GameLab 2010: Segundo día</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_OESoGgtnthw/TCzws7qe-JI/AAAAAAAAALE/boMfTGgzEJI/s1600/Cangre.png"&gt;&lt;/a&gt;  &lt;div style="text-align: center"&gt;   &lt;br /&gt;&lt;/div&gt; &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_OESoGgtnthw/TCy7ij2oHvI/AAAAAAAAAK8/TPSJhODa-ZQ/s1600/image003--200x250.jpg"&gt;&lt;img style="margin: 0px 10px 10px 0px; width: 88px; float: left; height: 100px; cursor: hand" id="BLOGGER_PHOTO_ID_5488968248272101106" border="0" alt="" src="http://1.bp.blogspot.com/_OESoGgtnthw/TCy7ij2oHvI/AAAAAAAAAK8/TPSJhODa-ZQ/s320/image003--200x250.jpg" /&gt;&lt;/a&gt;Un día más en The Code Crab hemos asistido al &lt;a href="http://www.gamelab.es/"&gt;GameLab 2010&lt;/a&gt;, y aquí estoy ofreciendo mi experiencia de nuevo. Dado que no hubo nada más nuevo que poder probar, por desgracia. Por esto hoy me centraré más en las conferencias.  &lt;div&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/TCzy-WDGe4I/AAAAAAAAALM/HSQV9cSUEIY/s1600-h/P010710_13.44%5B4%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="P010710_13.44" border="0" alt="P010710_13.44" src="http://lh6.ggpht.com/_OESoGgtnthw/TCzy-zT6BJI/AAAAAAAAALQ/5Ps-SLsuj5w/P010710_13.44_thumb%5B2%5D.jpg?imgmax=800" width="260" height="200" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;/div&gt;  &lt;div&gt;A primera hora, Alon Shtruzman, vicepresidente de &lt;a href="http://www.playcast-media.com/"&gt;Playcast Media&lt;/a&gt;, nos ha ofrecido una conferencia sobre los videojuegos sin consola y la importancia de los medios, así como la influencia que estos tienen en el contenido. Como ya sabréis es un tema importante estos días, debido al lanzamiento no hace tiempo de &lt;a href="http://www.onlive.com/"&gt;OnLive&lt;/a&gt;.&lt;/div&gt;  &lt;div&gt;El ponente ha previsto un importante cambio en el mercado de los videojuegos, especialmente los casual, abriendo camino para los juegos en la nube o juegos sin consola. Todo este cambio de mercado, según Alon, viene dado por la reciente proliferación de los juegos sociales y familiares, siendo el paso a los juegos sin consolas el próximo paso lógico, acercando más aún los juegos a nuestro salón y al de todo el mundo.&lt;/div&gt;  &lt;div&gt;   &lt;br /&gt;&lt;/div&gt;  &lt;div&gt;Tras esta interesante charla he asistido a una serie de conferencias sobre XNA, de varias horas de duración que era en paralelo con otras charlas que me perdí. Por desgracia para mi, el 80% de las charlas eran similares a unas que se habían dado en mi facultad hace unos meses. El propósito de las charlas es la presentación de &lt;a href="http://www.windowsphone7.com/"&gt;Windows Phone 7&lt;/a&gt;, así como una introducción al desarrollo de videoconsola para este valiéndose de XNA, pero que os voy a contar de XNA ya a estas alturas :)&lt;/div&gt;  &lt;div&gt;También se anuncio el &lt;a href="http://www.imaginemobile.es/"&gt;Imagine Mobile&lt;/a&gt;, el cual es un concurso interesante que presenta una gran oportunidad, os aconsejo que si tenéis tiempo participéis.&lt;/div&gt;  &lt;div&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TCzy_8zXczI/AAAAAAAAALU/fLu9yV_AYhQ/s1600-h/image%5B4%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh5.ggpht.com/_OESoGgtnthw/TCzzAjpKw2I/AAAAAAAAALY/phzTqTIJ2pk/image_thumb%5B2%5D.png?imgmax=800" width="240" height="145" /&gt;&lt;/a&gt;     &lt;br /&gt;&lt;/div&gt;  &lt;div&gt;Después de comer al fin llego el momento que todo el mundo estaba esperando, la presentación de Castlevania Lords of Shadow. El juego, se presento en exclusiva en el GameLab solo presentado antes en el E3. Como ya he mencionado antes también hay disponible una demo, a la que tuve la suerte de probar (un par de veces :).&lt;/div&gt;  &lt;div&gt;Este juego ha sido diseñado por Mercury Steam, un estudio español anteriormente pequeño, en colaboración con Kojima. El ponente, Enric Álvarez, declaró que cuando recibieron la llamada de Kojima no se lo creían. La conferencia comenzó mostrándonos el vídeo de presentación, ya mostrado en el E3, que podéis ver a continuación.&lt;/div&gt;  &lt;div align="center"&gt;&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/-QShgAQSk_A&amp;amp;hl=es_ES&amp;amp;fs=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/-QShgAQSk_A&amp;amp;hl=es_ES&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;    &lt;br /&gt;&lt;/div&gt;  &lt;div&gt;¿Habéis notado la canción de Vampire Killer al final del vídeo?&lt;/div&gt;  &lt;div&gt;Tras este vídeo, Enric declaro que se intento cuidar al máximo los detalles para procurar una máxima inmersión por parte de los jugadores, con cosas como una gran banda sonora, y una ambientación oscura y sangrienta, de acuerdo con los estándares de los juegos clásicos de la saga, pero con gráficos de ultima generación, así como un arte gráfico impresionante.&lt;/div&gt;  &lt;div&gt;Tras varias declaraciones se procedió a enseñarnos dos niveles del juego inéditos (Nada que ver con la demo, que ofrecía un tutorial y dejaba ver un sistema de combate similar a God of War).&lt;/div&gt;  &lt;div&gt;En el primero de ellos, vemos una de las partes iniciales del castillo en el cual se deja entrever diferentes aspectos del juego, como un mapa abierto, y un elaborado componente de exploración. Tenemos 2 barras de magia, una roja para hechizos de ataque y otra azul para hechizos defensivos, a parte de los clásicos objetos, y combinaciones entre objetos y magias.&lt;/div&gt;  &lt;div align="center"&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TCzzBbQgFgI/AAAAAAAAALc/ZPExQM3XpKo/s1600-h/P010710_16.33%5B3%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="P010710_16.33" border="0" alt="P010710_16.33" src="http://lh4.ggpht.com/_OESoGgtnthw/TCzzB5ZcTOI/AAAAAAAAALg/8ejku64doPg/P010710_16.33_thumb%5B1%5D.jpg?imgmax=800" width="260" height="200" /&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TCzzCcrxKdI/AAAAAAAAALk/muouQ8PiUT0/s1600-h/P010710_16.20%5B6%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="P010710_16.20" border="0" alt="P010710_16.20" src="http://lh3.ggpht.com/_OESoGgtnthw/TCzzDF0-n0I/AAAAAAAAALo/0-lepBjRr3s/P010710_16.20_thumb%5B2%5D.jpg?imgmax=800" width="260" height="200" /&gt;&lt;/a&gt; &lt;/div&gt;  &lt;div&gt;Enric nos prometió una gran cantidad de secretos, con los cuales podremos obtener entre otras cosas mejoras de salud y magia, y para muchos de los cuales tendremos que volver a una parte anterior del castillo después de conseguir algún poder.&lt;/div&gt;  &lt;div&gt;En cuanto a los enemigos, vemos una gran diferencia al pasar de un enemigo a otro, convirtiendo la lucha en algo dinámico. Tras todo esto, se llego a un jefe final, el carnicero del castillo, y vemos que la dificultad, al menos en los jefes, es bastante elevada, ¡Enric no se lo pasó hasta el tercer intento y valiéndose de trampas!&lt;/div&gt;  &lt;div&gt;Después observamos la torre del reloj, lo que nos permitió observar un elaborado plataformeo, el cual cambia a lo largo del juego, evitando así una experiencia monótona. Si nos caemos mientras escalamos la torre volveremos a un punto inmediatamente anterior pero perdiendo algo de vida, y por un error de Enric hemos visto el doble salto (con alas, estilo Alucard).&lt;/div&gt;  &lt;div&gt;En conclusión, el nuevo Castlevania parece, por fin, una gran adaptación de la saga al entorno 3D, con un juego muy innovador, atractivo y entretenido, pero fiel a los orígenes al mismo tiempo.&lt;/div&gt;  &lt;div align="center"&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TCzzDtinIbI/AAAAAAAAALs/in0x-mAxwr0/s1600-h/P010710_17.43%5B4%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="P010710_17.43" border="0" alt="P010710_17.43" src="http://lh3.ggpht.com/_OESoGgtnthw/TCzzEDRumsI/AAAAAAAAALw/Y2AY19lcziM/P010710_17.43_thumb%5B2%5D.jpg?imgmax=800" width="311" height="241" /&gt;&lt;/a&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/TCzzElBSJ8I/AAAAAAAAAL0/Sj75-fzPCQg/s1600-h/image%5B10%5D.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" title="image" alt="image" src="http://lh5.ggpht.com/_OESoGgtnthw/TCzzF9eZBQI/AAAAAAAAAL4/0-paDe7TuXI/image_thumb%5B6%5D.png?imgmax=800" width="221" height="240" /&gt;&lt;/a&gt;&amp;#160; &lt;br /&gt;&lt;/div&gt;  &lt;div&gt;Una vez concluida esta sorprendente presentación, pudimos ver en acción a Kinect (o Proyect Natal, como se conocía hasta ahora), de la mano de David Darnés, Productor de Ubisoft Barcelona, aunque por desgracia no lo pudimos probar, excepto un par de afortunados.&lt;/div&gt;  &lt;div&gt;Tras un poco mas de la cantidad de publicidad de Ubisoft recomendada por las autoridades sanitarias, se presento Kinect junto con Motion Sports, un juego lanzado junto al dispositivo de la mano de Ubisoft, evidentemente.&lt;/div&gt;  &lt;div align="center"&gt;&lt;object width="640" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/qPqxEpIMkOo&amp;amp;hl=es_ES&amp;amp;fs=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/qPqxEpIMkOo&amp;amp;hl=es_ES&amp;amp;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;    &lt;br /&gt;&lt;/div&gt;  &lt;div&gt;&amp;#160;&lt;/div&gt;  &lt;div&gt;Motion Sports ofrece una serie de pequeños juegos de deportes (no me suena de nada esto tampoco), ideales para jugar con amigos, y la principal innovación es el uso de Kinect, por lo que no hace falta ninguna clase de controlador, se controla todo con la voz y el movimiento.&lt;/div&gt;  &lt;div&gt;En la demo estaban disponibles los juegos de rugby y esquí, y parecía funcionar bastante bien en general, aunque tenía algunos problemas con los brazos. Además parece fácil salirse del radio, parando el juego. Esto puede suponer alguna molestias para juegos moviditos, pero nada serio.&lt;/div&gt;  &lt;div&gt;   &lt;br /&gt;&lt;/div&gt;  &lt;div&gt;Tras estas dos geniales conferencias, el evento continuó con una conferencia sobre Basket Dudes y el modelo de micro pagos, de la mano de Fernando Piquer, Fundador y CEO de &lt;a href="http://www.bitoon.com/"&gt;Bitoon Entertainment&lt;/a&gt;, en la cual se nos dejo claro que el modelo se centra en ofrecer una experiencia completa de juego a todos los usuarios, estén dispuestos a pagar o no, pero ofreciendo una serie de ventajas a los jugadores que paguen.&lt;/div&gt;  &lt;div&gt;&amp;#160;&lt;img style="text-align: center; margin: 0px auto 10px; width: 150px; display: block; height: 68px; cursor: pointer" border="0" alt="" src="http://www.playstationportable.de/images/db/22407_150.jpg" /&gt;&lt;/div&gt;  &lt;div&gt;Por último, Daniel Sánchez-Crespo, Director General y Jefe de Diseño de &lt;a href="http://www.novarama.com/"&gt;Novarama &lt;/a&gt;(Empresa desarrolladora del exitoso juego Invizimals) expuso una interesante charla sobre la manera de innovar en el sector del desarrollo de videojuegos.&lt;/div&gt;  &lt;div&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/TCzzG4PsqtI/AAAAAAAAAL8/fz6stbSQp7I/s1600-h/P010710_19.18%5B4%5D.jpg"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px" title="P010710_19.18" border="0" alt="P010710_19.18" src="http://lh5.ggpht.com/_OESoGgtnthw/TCzzHd-nTNI/AAAAAAAAAMA/vOxyXOiyM70/P010710_19.18_thumb%5B2%5D.jpg?imgmax=800" width="260" height="200" /&gt;&lt;/a&gt;&lt;span style="color: rgb(0,0,238); -webkit-text-decorations-in-effect: underline" class="Apple-style-span"&gt;&lt;/span&gt;&lt;/div&gt;  &lt;div&gt;Después de esto nos presento en exclusiva Invizimals Shadow Zone, la continuación del exitoso juego Invizimals, del cual no consigo encontrar imágenes y aún no hay trailer, pero pudimos observar muchas novedades con respecto al primero, en cuanto a nuevos Invizimals, nuevas maneras de capturar y un nuevo sistema de rankings online. Por cierto, que Invizimals se estrenará pronto en USA, seguro que es un gran éxito, igual que aquí :)&lt;/div&gt;  &lt;div&gt;   &lt;br /&gt;&lt;/div&gt;  &lt;div&gt;Una vez más me detendré antes de lo que me gustaría por que vuelvo a llevar escrito más de lo que debería (Si es que me emociono con el Castlevania). Mañana concluiré con el ultimo día del GameLab, una vez mas resumiendo las conferencias a las que pueda asistir. ¿Que os parece el lavado de cara del blog? Yo creo que sobretodo ahora se lee mejor independientemente de la resolución usada.&lt;/div&gt; &lt;span style="color: rgb(0,0,238); -webkit-text-decorations-in-effect: underline" class="Apple-style-span"&gt;&lt;img style="margin: 0px 0px 10px 10px; width: 129px; float: right; height: 102px; cursor: pointer" id="BLOGGER_PHOTO_ID_5489026700578584722" border="0" alt="" src="http://4.bp.blogspot.com/_OESoGgtnthw/TCzws7qe-JI/AAAAAAAAALE/boMfTGgzEJI/s320/Cangre.png" /&gt;&lt;/span&gt;  &lt;div&gt;&lt;span style="-webkit-text-decorations-in-effect: underline" class="Apple-style-span"&gt;&lt;/span&gt;&lt;span style="color: #0000ee" class="Apple-style-span"&gt;     &lt;br /&gt;&lt;/span&gt;    &lt;div&gt;     &lt;br /&gt;&lt;/div&gt;    &lt;div&gt;Gracias por leer The Code Crab una vez más, y ¡Sed unos cangrejos pacientes!, ¡Mañana más!&lt;/div&gt;    &lt;div&gt;Gracias a Sara por el cangrejo una vez más :)&lt;/div&gt; &lt;/div&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;&lt;/p&gt;  &lt;p&gt;PD: Perdón por la calidad de las fotos, las hago con mi móvil y sacar fotos a un proyector no es la mejor idea.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-5590037401026177149?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/5590037401026177149/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/07/gamelab-2010-segundo-dia.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/5590037401026177149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/5590037401026177149'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/07/gamelab-2010-segundo-dia.html' title='GameLab 2010: Segundo día'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_OESoGgtnthw/TCy7ij2oHvI/AAAAAAAAAK8/TPSJhODa-ZQ/s72-c/image003--200x250.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-7854628514974674010</id><published>2010-06-30T09:09:00.000-07:00</published><updated>2010-06-30T15:59:27.984-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gijon'/><category scheme='http://www.blogger.com/atom/ns#' term='videojuegos'/><category scheme='http://www.blogger.com/atom/ns#' term='feria'/><category scheme='http://www.blogger.com/atom/ns#' term='gamlab'/><title type='text'>GameLab 2010: Primer día</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_OESoGgtnthw/TCullzIETpI/AAAAAAAAAJk/zst2LTHJdi4/s1600/Cangre.png"&gt;&lt;/a&gt;  &lt;div style="text-align: center"&gt;   &lt;br /&gt;&lt;/div&gt; &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_OESoGgtnthw/TCtwffYEjCI/AAAAAAAAAJU/IQTI2pBtimY/s1600/image003--200x250.jpg"&gt;&lt;img style="margin: 0px 10px 10px 0px; width: 88px; float: left; height: 100px; cursor: hand" id="BLOGGER_PHOTO_ID_5488604257181797410" border="0" alt="" src="http://3.bp.blogspot.com/_OESoGgtnthw/TCtwffYEjCI/AAAAAAAAAJU/IQTI2pBtimY/s200/image003--200x250.jpg" /&gt;&lt;/a&gt;   &lt;br /&gt;Hoy ha sido el primer día del GameLab 2010, la feria internacional del videojuego y el ocio interactivo. El evento se celebra en Gijón, dentro del palacio de congresos, en el interior del recinto ferial.   &lt;div&gt;   &lt;div&gt;     &lt;div style="text-align: center"&gt;&lt;img style="text-align: center; margin: 0px auto 10px; width: 262px; display: block; height: 135px; cursor: hand" id="BLOGGER_PHOTO_ID_5488655176971629826" border="0" alt="" src="http://3.bp.blogspot.com/_OESoGgtnthw/TCuezaYAtQI/AAAAAAAAAJc/uu6oi7sC4HY/s320/gamelab.png" /&gt;&lt;/div&gt;      &lt;div&gt;He podido observar tras recoger mi acreditación que este año hay más gente que otros años, y hay mayor cantidad de asistentes informales y menos empresas. Esto se debe a que como mencionaron en el acto de presentación, por primera vez este año se ha intentado orientar a todo tipo de asistentes, y no sólo a desarrolladores.&lt;/div&gt;      &lt;div&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/TCur45aW5dI/AAAAAAAAAJs/F88FP0xeoos/s1600-h/P300610_09.58%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="P300610_09.58" border="0" alt="P300610_09.58" src="http://lh4.ggpht.com/_OESoGgtnthw/TCur5bAT4dI/AAAAAAAAAJw/udOeUV9AMcg/P300610_09.58_thumb%5B3%5D.jpg?imgmax=800" width="430" height="331" /&gt;&lt;/a&gt;&lt;/div&gt;      &lt;div&gt;Una vez dentro lo primero que observamos es la zona de Sony, que no deja nada que desear. En ella he podido probar muchas cosas interesantes, gran cantidad de las cuales aún no están en el mercado.&lt;/div&gt;      &lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/TCur5_UVW_I/AAAAAAAAAJ0/eTyopS8GQxE/s1600-h/P300610_10.30%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="P300610_10.30" border="0" alt="P300610_10.30" src="http://lh5.ggpht.com/_OESoGgtnthw/TCur6dOAnZI/AAAAAAAAAJ4/Jk2hrbN_VaY/P300610_10.30_thumb%5B3%5D.jpg?imgmax=800" width="293" height="229" /&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TCur7AOXjoI/AAAAAAAAAJ8/2Gc31IrSLyk/s1600-h/P300610_10.30%5B01%5D%5B9%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="P300610_10.30[01]" border="0" alt="P300610_10.30[01]" src="http://lh3.ggpht.com/_OESoGgtnthw/TCur7g65IwI/AAAAAAAAAKA/N9O54FleYRs/P300610_10.30%5B01%5D_thumb%5B7%5D.jpg?imgmax=800" width="289" height="231" /&gt;&lt;/a&gt;         &lt;br /&gt;&lt;/div&gt;      &lt;div&gt;La primera de ellas y la mas llamativa es el poder probar PlayStation Move, con un juego de eye toy play o algo parecido, así como un juego de varios deportes (No nos suena de absolutamente nada). No estaba mal, era algo parecido a los juegos de minijuegos típicos de la wii. El sistema move es definitivamente mas preciso que la consola de nintendo, pero personalmente yo no he notado tanta diferencia como sony nos prometía, aunque quizás otros juegos lo exploten mejor, por lo que no hablare demasiado antes de tiempo.&lt;/div&gt;      &lt;div&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="P300610_10.47" border="0" alt="P300610_10.47" src="http://lh6.ggpht.com/_OESoGgtnthw/TCur8KtSYfI/AAAAAAAAAKE/-CfIcgpAc9Y/P300610_10.47_thumb%5B3%5D.jpg?imgmax=800" width="324" height="250" /&gt; &lt;/div&gt;      &lt;div&gt;También llamaba la atención el 3D de PS3, el cual me ha resultado bastante satisfactorio, dando la misma sensación que en el cine, aunque evidentemente no es lo mismo en una tele que en una pantalla de cine. De todos modos funciona genial, y pese al ligero mareo al empezar a usarlo, una vez se acostumbran tus ojos la sensación de profundidad esta muy lograda.&lt;/div&gt;      &lt;div&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TCur8kq9B8I/AAAAAAAAAKI/1sjn20Z1lYQ/s1600-h/P300610_17.25%5B5%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="P300610_17.25" border="0" alt="P300610_17.25" src="http://lh3.ggpht.com/_OESoGgtnthw/TCur9LzzqQI/AAAAAAAAAKM/UWFkflimisw/P300610_17.25_thumb%5B3%5D.jpg?imgmax=800" width="335" height="259" /&gt;&lt;/a&gt; &lt;/div&gt;      &lt;div&gt;La tercera gran sorpresa que tuvimos fue una demo de Castlevania Lord of Shadows. Tras una larga cola he podido jugar la demo completa, y he de decir que la demo ofrecida deja ver un sistema de combate que no tiene nada que envidiar a God of war, por no hablar de la ambientación y de la historia que tiene al ser un Castlevania. En mi opinión, si el resto del juego mantiene la exploración y el plataformeo de los Castlevania clásicos va a ser un juego estupendo.&lt;/div&gt;      &lt;div&gt;Además de esto en la sala de Sony podemos encontrar juegos que aún no han salido como Gran Turismo 5 y el SingStar nuevo (con guitarra), y otros que ya están en venta como Heavy Rain, God of War 3 y Play english para la psp.&lt;/div&gt;      &lt;div&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="P300610_10.50" border="0" alt="P300610_10.50" src="http://lh3.ggpht.com/_OESoGgtnthw/TCur9kJ5B8I/AAAAAAAAAKQ/EikOTyhDaJw/P300610_10.50_thumb%5B3%5D.jpg?imgmax=800" width="357" height="275" /&gt;&lt;/div&gt;      &lt;div&gt;Por desgracia, la parte de Nintendo no estaba ni por asomo tan bien como la de Sony, no hemos podido ver la 3DS, ni nada nuevo, sólo una exposición de Shigueru Miyamoto, donde pudimos probar algunos juegos nuevos como el Mario Galaxy 2 y el Smash Bros Brawl y algunos juegos clásicos, como el donkey kong y el super mario bros, pero por desgracia nada que aun no se haya lanzado aún.&lt;/div&gt;      &lt;div&gt;       &lt;br /&gt;&lt;/div&gt;      &lt;div&gt;En cuanto a la presencia de Microsoft, aún no hay nada, aunque se que mañana organizarán algunos talleres y otras actividades, y corren rumores de que se podrá ver Kinect (Proyect Natal) antes de terminar la feria. Esperemos que sea cierto.        &lt;br /&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="P300610_12.13" border="0" alt="P300610_12.13" src="http://lh6.ggpht.com/_OESoGgtnthw/TCur-BxSQgI/AAAAAAAAAKU/d-tldRrIDWA/P300610_12.13_thumb%5B3%5D.jpg?imgmax=800" width="356" height="275" /&gt; &lt;/div&gt;      &lt;div&gt;También encontramos otras zonas donde podemos probar juegos en el iPad, así como un sensor que mide las ondas cerebrales para saber tu concentración y tu relajación, de la mano de la empresa &lt;a href="http://www.neurosky.com/"&gt;Neurosky&lt;/a&gt;.&lt;/div&gt;      &lt;div&gt;       &lt;br /&gt;&lt;/div&gt;      &lt;div&gt;En cuanto a las conferencias del primer día, empezamos con una feria sobre la situación actual de los juegos online (MMO), un poco orientada a empresas, a la cual asistí durante solo un rato, por lo que no me entere mucho.&lt;/div&gt;      &lt;div&gt;&amp;#160;&lt;/div&gt;      &lt;div&gt;Tras esto, tuvimos al fin la inauguración de la feria, donde nos explicaron que el desarrollo de videojuegos es un sector en aumento en España, que no tiene tantas ventajas como otros sectores, pese a su importancia, pero que poco a poco va ganándose el reconocimiento que merece.&lt;span style="white-space: pre" class="Apple-tab-span"&gt; &lt;/span&gt;También se explico que es el primer intento para abrir la feria al publico global y no sólo para desarrolladores, ya mencionado anteriormente.&lt;/div&gt;      &lt;div align="center"&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TCur-kwgflI/AAAAAAAAAKY/Xi7TtsXxB64/s1600-h/P300610_16.10%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="P300610_16.10" border="0" alt="P300610_16.10" src="http://lh3.ggpht.com/_OESoGgtnthw/TCur_B-vBoI/AAAAAAAAAKc/YHzXtDwHXk0/P300610_16.10_thumb%5B2%5D.jpg?imgmax=800" width="284" height="220" /&gt;&lt;/a&gt; &lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/TCur_i4_qzI/AAAAAAAAAKg/TlEvD5_upao/s1600-h/P300610_13.05%5B6%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="P300610_13.05" border="0" alt="P300610_13.05" src="http://lh4.ggpht.com/_OESoGgtnthw/TCur_9Pt5JI/AAAAAAAAAKk/XObiVIMOxnE/P300610_13.05_thumb%5B4%5D.jpg?imgmax=800" width="276" height="218" /&gt;&lt;/a&gt;         &lt;br /&gt;&lt;/div&gt;      &lt;div&gt;Después de esto, se pasó a una mesa redonda, donde varios ponentes, como Gonzo Suárez y Enric Álvarez, hablaron de la situación internacional del desarrollo de videojuegos en España a nivel Histórico.        &lt;br /&gt;&lt;/div&gt;      &lt;div&gt;       &lt;div&gt;Después de comer, tuvo lugar la charla que a mí, personalmente, más me ha llamado la atención: Controladores mentales, de la mano del vicepresidente de Neurosky. Se habló de las diferentes generaciones de controladores, siendo los controladores tradicionales la primera generación y los controladores cinéticos, como Wii, Move y Kinect, la segunda generación. Siguiendo este orden según las generaciones avanzan se va estrechando la distancia entre el juego y el cuerpo del jugador.Por ello, la tercera generación de controladores de los videojuegos serían los sensores biológicos. Podemos ver un ejemplo de esto en el futuro sensor para la wii, Wii Vitality Sensor. Neurosky ofrece un sensor, bastante cómodo y accesible que detecta el estado del cuerpo, en concreto, la concentración, la tranquilidad y el parpadeo. Esto es una herramienta enormemente potente a la hora de hacer videojuegos bastante creativos, pudiendo medir en un juego de terror si el jugador esta asustado, por poner un pequeño ejemplo.&lt;/div&gt;     &lt;/div&gt;      &lt;div align="center"&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TCusAmiox1I/AAAAAAAAAKo/M8YwKGOFZq8/s1600-h/P300610_11.47%5B6%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="P300610_11.47" border="0" alt="P300610_11.47" src="http://lh4.ggpht.com/_OESoGgtnthw/TCusBFdY3JI/AAAAAAAAAKs/qluHbbkN33A/P300610_11.47_thumb%5B4%5D.jpg?imgmax=800" width="289" height="227" /&gt;&lt;/a&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/TCusB9UOddI/AAAAAAAAAK0/s8IFfbRA7PQ/s1600-h/P300610_11.47%5B01%5D%5B4%5D.jpg"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" title="P300610_11.47[01]" border="0" alt="P300610_11.47[01]" src="http://lh4.ggpht.com/_OESoGgtnthw/TCusCBosUOI/AAAAAAAAAK4/vUMmeYCW-5Y/P300610_11.47%5B01%5D_thumb%5B2%5D.jpg?imgmax=800" width="294" height="228" /&gt;&lt;/a&gt;         &lt;br /&gt;&lt;/div&gt;      &lt;div&gt;Tras esto, hubo varias charlas más, sobre los modelos de desarrollo adecuados para lanzar un juego de móvil exitoso, una charla sobre la administración como fuente de apoyo al desarrollo de proyectos de ocio interactivo, y otra sobre los juegos online, descargables vs juegos en la web.&lt;/div&gt;      &lt;div&gt;       &lt;br /&gt;&lt;/div&gt;      &lt;div&gt;No me entretengo más, siento no haber explicado tanto como me gustaría algunas charlas, pero ya es un post bien largo y además tengo algo de prisa. Mañana actualizaré las charlas que se den más a fondo ya que no tendré que volver a explicar las distintas salas.&lt;/div&gt;      &lt;div&gt;       &lt;br /&gt;&lt;/div&gt;      &lt;div&gt;&lt;img style="margin: 0px 0px 10px 10px; width: 150px; float: right; height: 112px; cursor: pointer" id="BLOGGER_PHOTO_ID_5488662639678869138" border="0" alt="" src="http://1.bp.blogspot.com/_OESoGgtnthw/TCullzIETpI/AAAAAAAAAJk/zst2LTHJdi4/s320/Cangre.png" /&gt;&lt;/div&gt;      &lt;div&gt;En cuanto al tutorial de XNA lamento mi tardanza, pero la detección de colisiones me está dando&lt;/div&gt;      &lt;div&gt;más problemas de lo que me esperaba, os prometo que en cuanto acabe el GameLab subo la quinta parte. ¡Sed buenos cangrejos!&lt;/div&gt;      &lt;div&gt;PD: Gracias a Sara por el cangrejo ;)&lt;/div&gt;      &lt;div&gt;       &lt;br /&gt;&lt;/div&gt;   &lt;/div&gt; &lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-7854628514974674010?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/7854628514974674010/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/06/gamelab-2010-primer-dia.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/7854628514974674010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/7854628514974674010'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/06/gamelab-2010-primer-dia.html' title='GameLab 2010: Primer día'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_OESoGgtnthw/TCtwffYEjCI/AAAAAAAAAJU/IQTI2pBtimY/s72-c/image003--200x250.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-8729223960400953632</id><published>2010-06-22T11:57:00.001-07:00</published><updated>2010-06-22T15:47:54.592-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='XNA'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><title type='text'>Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 4</title><content type='html'>&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TCEHiM7Zk-I/AAAAAAAAAIc/JTljlSi5xlg/s1600-h/crab-icon%20ball%20c%23%5B4%5D.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px;" title="crab-icon ball c#" alt="crab-icon ball c#" src="http://lh6.ggpht.com/_OESoGgtnthw/TCEHi6a5pDI/AAAAAAAAAIg/aUGRcdu4fpE/crab-icon%20ball%20c%23_thumb%5B2%5D.png?imgmax=800" align="left" width="48" height="68" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Hoy en The Code Crab vamos a poner un fondo animado para nuestro futuro superventas. La técnica que vamos a seguir es bien sencilla: Tendremos una imagen que tenga el mismo ancho que la pantalla pero mucho mas alta, y la empezaremos a dibujar por abajo, subiendo poco a poco, hasta llegar a la parte superior que será similar a la parte inferior. Cuando pasa esto volvemos a la parte de abajo y ya tenemos efecto de scroll.&lt;/p&gt;  &lt;p&gt;Dado que XNA solo soporta imágenes de resolución X x Y, donde ni X ni Y rebasan los 2000 y pico pixeles (no se cuantos exactamente) es posible que para un scroll largo haga falta dividir el fondo en diferentes imágenes. No vamos a dar un ejemplo de ese caso, pero que sepáis que sería exactamente lo mismo pero un poco mas complicado. Lo más importante es que si tenemos 3 imágenes A, B y C, para hacer una transición fluida de una a otra la ultima parte que se dibuje de una tiene que ser equivalente a la primera de la siguiente, esto es, el final de A y el principio de B coinciden, el final de B y el principio de C coinciden y el final de C y el principio de A coinciden.&lt;/p&gt;  &lt;p&gt;Una vez tenemos claro lo que queremos hacer, necesitamos saber la resolución de nuestra ventana para preparar la imagen. Para ello, como recordareis, tenemos las propiedades &lt;em&gt;PreferredBackBufferHeight&lt;/em&gt; y &lt;em&gt;PreferredBackBufferWidth&lt;/em&gt; de &lt;em&gt;graphics&lt;/em&gt;. Aunque si queréis se pueden alterar, yo no lo voy a hacer, voy a dejar la resolución por defecto. Como no la altero, voy a imprimir estos datos por pantalla, para saber que resolución tiene nuestra ventana:&lt;/p&gt;  &lt;pre class="csharp" name="code"&gt; protected override void Initialize()&lt;br /&gt;       {&lt;br /&gt;           Console.WriteLine(graphics.PreferredBackBufferHeight + "x" + graphics.PreferredBackBufferWidth);&lt;br /&gt;           _fondo = new Fondo(graphics.PreferredBackBufferHeight, graphics.PreferredBackBufferWidth);&lt;br /&gt;           _nave = new Nave(graphics.PreferredBackBufferHeight, graphics.PreferredBackBufferWidth);&lt;br /&gt;           this.Window.Title="Space Burst";&lt;br /&gt;           base.Initialize();           &lt;br /&gt;       }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Con esto, ejecutamos nuestro proyecto, y no ha cambiado nada, pero si vamos a la ventana de resultados veremos algo así:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/TCEHjJAa42I/AAAAAAAAAIk/MxKg63GfguY/s1600-h/image%5B5%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://lh5.ggpht.com/_OESoGgtnthw/TCEHjxLsfYI/AAAAAAAAAIo/_npiRMbiWRg/image_thumb%5B3%5D.png?imgmax=800" width="471" height="182" /&gt;&lt;/a&gt; No os olvidéis de borrar la línea ahora que ya sabéis el tamaño de la ventana. Con esto ya sabemos la resolución de la ventana, 480x800, con lo que ahora necesitamos una imagen loquesea x 800 donde los primeros y los últimos 480 px sean iguales. A partir de una imagen real del espacio, algo de photoshopeo cutre (se me da fatal) y algo de paciencia, yo he conseguido esto, aunque si os apetece podéis haceros vuestro propio fondo.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://img294.imageshack.us/img294/4605/spacebackgr.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="spaceBackgr" alt="spaceBackgr" src="http://lh3.ggpht.com/_OESoGgtnthw/TCEHky9uPJI/AAAAAAAAAIw/nlK6Bp6sNgY/spaceBackgr_thumb%5B3%5D.jpg?imgmax=800" width="152" height="312" /&gt;&lt;/a&gt; Con esto, tenemos ya un fondo de 1700x800 con el principio y el final igual (Hay que pinchar en la imagen para verla completa). Lo metemos en la carpeta y lo agregamos a los recursos del proyecto, como venimos haciendo con todas las imágenes. Tras esto ya estamos preparados para crear la clase Fondo (esta es bastante sencillita):&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt; private const int anchoImagen = 800;&lt;br /&gt;       private const int altoImagen = 1700;&lt;br /&gt;       private int altoVentana;&lt;br /&gt;       private Texture2D imagen;&lt;br /&gt;       private Rectangle rectangulo;&lt;br /&gt;       public Fondo(int altoVentana, int anchoVentana)&lt;br /&gt;       {           &lt;br /&gt;           rectangulo = new Rectangle(0, altoImagen - altoVentana, anchoVentana, altoVentana);&lt;br /&gt;           this.altoVentana = altoVentana;&lt;br /&gt;       }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En cuanto a las propiedades, a estas alturas no os sorprenderá mucho, así que iré rápido. Guardamos el ancho y el alto de la imagen, así como el alto de la ventana (para saber cuanto tiene que medir el rectángulo) que será pasado en el constructor. También almacenamos un rectángulo con la sección de la imagen que se dibujara, empezando por la parte inferior de la imagen y un Texture2D con la imagen en sí.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;        public void LoadContent(ContentManager Content)&lt;br /&gt;       {&lt;br /&gt;           imagen = Content.Load&lt;texture2d&gt;("spaceBackgr");&lt;br /&gt;       }&lt;br /&gt;       public void Update()&lt;br /&gt;       {&lt;br /&gt;           rectangulo.Y -= 1;&lt;br /&gt;           if (rectangulo.Y &amp;lt;= 0)&lt;br /&gt;               rectangulo.Y = ((altoImagen - altoVentana) -15);&lt;br /&gt;       }&lt;br /&gt;       public void Draw(SpriteBatch spbtch)&lt;br /&gt;       {&lt;br /&gt;           spbtch.Draw(imagen, new Vector2(0, 0), rectangulo, Color.White);&lt;br /&gt;       }&lt;/texture2d&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;  En cuanto a los métodos, tendremos los 3 tradicionales de XNA que ya conoceréis. &lt;em&gt;LoadContent&lt;/em&gt; y &lt;em&gt;Draw&lt;/em&gt; son iguales que en Nave, por lo que no merece mucho la pena pararse (en cuanto a &lt;em&gt;Draw&lt;/em&gt; la única diferencia es que lo dibujamos en (0,0), ya que queremos que ocupe toda la pantalla).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Lo importante aquí (relativamente, pues es bastante simple en realidad) es el método &lt;em&gt;Update&lt;/em&gt;, en el cual disminuimos en 1 la coordenada Y de rectángulo, para subir hacia arriba el rectángulo y crear un efecto scroll. A mi personalmente me gusta el efecto que queda al disminuir en 1 cada &lt;em&gt;Update&lt;/em&gt;, pero si se aumenta el numero aumentara la velocidad del scroll. Eso queda a gusto de cada uno. También controlamos que si Y es 0 o menos, volvemos al principio, volviendo a mostrar la parte de abajo de la imagen, que como ya mencioné anteriormente debería ser igual. Ese –15 extra se debe a que si ponemos las coordenadas iniciales sin mas se apreciara un rebote, dado a que la imagen se esta moviendo constantemente, y que probablemente la parte de arriba y la de abajo no sean exactamente iguales pixel a pixel. A base de prueba y error para el caso de esta imagen he sacado que el numero apropiado son 15 px, pero si usáis otra imagen esto cambiara.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ahora que ya tenemos lista la clase Fondo, solo nos queda agregar una instancia en la clase principal &lt;em&gt;Game1&lt;/em&gt;, y las invocaciones a todos los métodos necesarios:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;    public class Game1 : Microsoft.Xna.Framework.Game&lt;br /&gt;   {&lt;br /&gt;       GraphicsDeviceManager graphics;&lt;br /&gt;       SpriteBatch spriteBatch;&lt;br /&gt;       Nave _nave;&lt;br /&gt;       Fondo _fondo;&lt;br /&gt;&lt;br /&gt;       public Game1()&lt;br /&gt;       {&lt;br /&gt;           graphics = new GraphicsDeviceManager(this);&lt;br /&gt;           Content.RootDirectory = "Content";           &lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void Initialize()&lt;br /&gt;       {&lt;br /&gt;     //Recordar comentar la siguiente linea&lt;br /&gt;           //Console.WriteLine(graphics.PreferredBackBufferHeight + "x" + graphics.PreferredBackBufferWidth);&lt;br /&gt;           _fondo = new Fondo(graphics.PreferredBackBufferHeight, graphics.PreferredBackBufferWidth);&lt;br /&gt;           _nave = new Nave(graphics.PreferredBackBufferHeight, graphics.PreferredBackBufferWidth);&lt;br /&gt;           this.Window.Title="Space Burst";&lt;br /&gt;           base.Initialize();           &lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void LoadContent()&lt;br /&gt;       {&lt;br /&gt;           // Create a new SpriteBatch, which can be used to draw textures.&lt;br /&gt;           spriteBatch = new SpriteBatch(GraphicsDevice);&lt;br /&gt;           _fondo.LoadContent(Content);&lt;br /&gt;           _nave.LoadContent(Content);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void UnloadContent()&lt;br /&gt;       {&lt;br /&gt;           // TODO: Unload any non ContentManager content here&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void Update(GameTime gameTime)&lt;br /&gt;       {&lt;br /&gt;           // Cuidado con esto, no usamos mando.&lt;br /&gt;           if (Keyboard.GetState().IsKeyDown(Keys.Escape))&lt;br /&gt;               this.Exit();&lt;br /&gt;           _fondo.Update();&lt;br /&gt;           _nave.Update();&lt;br /&gt;&lt;br /&gt;           base.Update(gameTime);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void Draw(GameTime gameTime)&lt;br /&gt;       {&lt;br /&gt;           GraphicsDevice.Clear(Color.Black);&lt;br /&gt;&lt;br /&gt;           spriteBatch.Begin();&lt;br /&gt;           _fondo.Draw(spriteBatch);&lt;br /&gt;           _nave.Draw(spriteBatch);&lt;br /&gt;           spriteBatch.End();&lt;br /&gt;&lt;br /&gt;           base.Draw(gameTime);&lt;br /&gt;       }&lt;br /&gt;   }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; Es importante recordar, que como se menciono anteriormente, para que la imagen A se dibuje por encima de la imagen B, hay que dibujar primero B y luego A. Por tanto, el Fondo debe ser lo primero en dibujarse, o sino tapara el resto de objetos. Por lo demás, nada nuevo.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TCEHl-BhnPI/AAAAAAAAAI0/rL2VMjQWkT4/s1600-h/image%5B12%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://lh4.ggpht.com/_OESoGgtnthw/TCEHmpSAQdI/AAAAAAAAAI4/_4jcSuMEkoQ/image_thumb%5B8%5D.png?imgmax=800" width="566" height="369" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras ejecutar vemos el efecto obtenido. ¿Que os parece? Yo creo que no esta mal, queda un poco raro la nave pixelada con la imagen real del espacio, pero bueno, siempre podéis cambiar vuestro fondo por otro :P&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Podéis descargaros el código fuente del tutorial hasta este momento en el siguiente enlace: &lt;a title="http://www.megaupload.com/?d=RB2TYYLJ" href="http://www.megaupload.com/?d=RB2TYYLJ"&gt;http://www.megaupload.com/?d=RB2TYYLJ&lt;/a&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/TCEHnAVG6sI/AAAAAAAAAI8/jbgBsgpjsrY/s1600-h/cangrejus%20guaperus%5B6%5D.png"&gt;&lt;img style="border: 0px none; display: inline; margin-left: 0px; margin-right: 0px;" title="cangrejus guaperus" alt="cangrejus guaperus" src="http://lh4.ggpht.com/_OESoGgtnthw/TCEHnuDIb-I/AAAAAAAAAJA/9FLEfz4t5cc/cangrejus%20guaperus_thumb%5B4%5D.png?imgmax=800" align="right" border="0" width="137" height="85" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Con esto concluye esta parte del tut orial. En la siguiente parte nos ponemos serios, introduciendo enemigos y detección de colisiones, no os lo perdáis. ¡Sed buenos cangrejos!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;PD: ¡¡Gracias a Sara por el aporte del cangrejo!!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="padding: 0px; margin: 0px; display: inline; float: none;" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:7e7b0fac-c0ac-4f2a-8d3e-1131f1e13d60" class="wlWriterEditableSmartContent"&gt;Etiquetas de Technorati: &lt;a href="http://technorati.com/tags/programaci%c3%b3n" rel="tag"&gt;programación&lt;/a&gt;,&lt;a href="http://technorati.com/tags/juegos" rel="tag"&gt;juegos&lt;/a&gt;,&lt;a href="http://technorati.com/tags/xna" rel="tag"&gt;xna&lt;/a&gt;,&lt;a href="http://technorati.com/tags/windows" rel="tag"&gt;windows&lt;/a&gt;,&lt;a href="http://technorati.com/tags/xbox" rel="tag"&gt;xbox&lt;/a&gt;,&lt;a href="http://technorati.com/tags/C%23" rel="tag"&gt;C#&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-8729223960400953632?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/8729223960400953632/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/06/programando-videojuegos-tutorial-xna_22.html#comment-form' title='13 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/8729223960400953632'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/8729223960400953632'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/06/programando-videojuegos-tutorial-xna_22.html' title='Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 4'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_OESoGgtnthw/TCEHi6a5pDI/AAAAAAAAAIg/aUGRcdu4fpE/s72-c/crab-icon%20ball%20c%23_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-7244776196344148359</id><published>2010-06-19T07:40:00.001-07:00</published><updated>2010-06-19T07:44:54.714-07:00</updated><title type='text'>Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 3</title><content type='html'>&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TBzWqmpk0iI/AAAAAAAAAH8/bP4Sp24fJZ8/s1600-h/crab-icon%20ball%20c%23%5B4%5D.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" title="crab-icon ball c#" alt="crab-icon ball c#" align="left" src="http://lh5.ggpht.com/_OESoGgtnthw/TBzWrE7gwDI/AAAAAAAAAIA/xhlhNPvJctU/crab-icon%20ball%20c%23_thumb%5B2%5D.png?imgmax=800" width="48" height="68" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Bueno, tras un pequeño intervalo de tiempo volvemos con el tutorial sobre XNA, pues ya va siendo hora que nuestra navecita pueda disparar. Lo primero que necesitamos es un sprite del disparo. En mi caso voy a utilizar este, pero bueno, este es un país libre. &lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TBzWrl1YLJI/AAAAAAAAAIE/OfdNNsgji2E/s1600-h/weapons%5B4%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="weapons" alt="weapons" src="http://lh4.ggpht.com/_OESoGgtnthw/TBzWr7KgRbI/AAAAAAAAAII/hZFAHIlCZLY/weapons_thumb%5B2%5D.png?imgmax=800" width="70" height="22" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Para introducirlo en el proyecto tenemos que repetir lo que ya aprendimos en la primera parte del tutorial. Copiamos la imagen a la carpeta del proyecto y la arrastramos a &lt;em&gt;Content&lt;/em&gt; en el VS.&lt;/p&gt;  &lt;p&gt;Una vez que tenemos la imagen dentro de &lt;em&gt;Content&lt;/em&gt; necesitaremos crear una nueva clase que almacene toda la información de cada disparo, como por ejemplo la clase &lt;em&gt;Disparo&lt;/em&gt;.&lt;/p&gt;  &lt;p&gt;¿Que atributos necesita esta clase? Necesita los siguientes:&lt;/p&gt;  &lt;pre class="csharp" name="code"&gt;	private const int anchoImagen = 6;&lt;br /&gt;        private const int altoImagen = 22;&lt;br /&gt;        private Texture2D imagen;&lt;br /&gt;        private Vector2 _posicion;&lt;br /&gt;        public event EventHandler FueraDePantalla;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Como podéis ver, ya que Disparo va a representar a un Sprite que se moverá por la pantalla tiene atributos bastante similares a Nave, excepto por el Rectangle (Los disparos no tendrán animación). El único atributo nuevo es el evento FueraDePantalla, que se disparará cuando el disparo se salga de la pantalla, para avisar a la clase que contenga los disparos (Estarán almacenados dentro de una lista en Nave) de que debe borrar el disparo. ¿Por que? Es sencillo, si a lo largo del juego vamos añadiendo cada vez mas disparos, aunque se salgan de la pantalla seguirán existiendo, por lo que estarán consumiendo recursos inútilmente. Este evento se disparará en el método Update que definiremos mas adelante. En cuanto al resto de atributos, son equivalentes a los de Nave, si tenéis dudas podéis mirar atrás.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Necesitamos un constructor acorde con estos atributos, algo parecido a esto:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;	public Disparo(Vector2 posicion, int anchoNave, ContentManager Content)&lt;br /&gt;        {&lt;br /&gt;            _posicion = posicion;&lt;br /&gt;            //movemos un poco la posicion del disparo, para que salga desde el centro de la nave y no desde una esquina&lt;br /&gt;            _posicion.X += (anchoNave / 2);&lt;br /&gt;            //lo que acabamos de centrar es la esquina superior izquierda del disparo. Así situaremos el centro alineado con el centro de la imagen&lt;br /&gt;            //los 3 pixeles extra es por que la imagen del disparo no esta perfectamente centrada.&lt;br /&gt;            _posicion.X -= (anchoImagen / 2)+3;&lt;br /&gt;            //Ya que los disparos pueden surgir en cualquier momento, y no al principio de la ejecución no tiene sentido tener un método&lt;br /&gt;            //LoadContent que cargue las imágenes. En vez de eso las cargaremos en el constructor.&lt;br /&gt;            imagen = Content.Load&lt;texture2d&gt;(&amp;quot;weapons&amp;quot;);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En el constructor vemos como se inicializa la posición del disparo en función de la posición de la nave (pasada por parámetro) Además utilizamos el ContentManager pasado para inicializar la imagen. Recordad que no hay que poner terminación. Más tarde habrá que modificar la clase nave para que almacene ContentManager, y así poder pasar el parámetro al crear los disparos.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Además de esto necesitaremos un método Update que haga avanzar el disparo y un método Draw que lo dibuje por pantalla:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;	public void Update()&lt;br /&gt;        {&lt;br /&gt;            _posicion.Y-=5;&lt;br /&gt;            if (_posicion.Y &amp;lt;= 0)&lt;br /&gt;                FueraDePantalla(this, null);&lt;br /&gt;        }&lt;br /&gt;        public void Draw(SpriteBatch spbtch)&lt;br /&gt;        {&lt;br /&gt;            spbtch.Draw(imagen, _posicion, new Rectangle(0,0,anchoImagen, altoImagen), Color.White);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Como se puede observar en el método Update disminuimos 5 puntos el eje Y de la posición. Variando esto se podrá modificar la velocidad de los disparos (Recordad que la posición se expresa en pixeles). Además de esto si la posición se hace menor que 0 lanzara el evento antes mencionado, que será manejado por Nave para borrar el disparo.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En cuanto a Draw, nada nuevo.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto ya tenemos lista la clase Disparo. Deberemos añadir una lista de disparos a los atributos de Nave y inicializarla en el constructor:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;        private Rectangle rectangulo;&lt;br /&gt;        private const int anchoImagen = 42;&lt;br /&gt;        private const int altoImagen = 44;&lt;br /&gt;        private Texture2D imagen;&lt;br /&gt;        private Vector2 posicion;&lt;br /&gt;        private int altoVentana;&lt;br /&gt;        private int anchoVentana;&lt;br /&gt;        private List&amp;lt;Disparo&amp;gt; disparos;&lt;br /&gt;        private int frameCounter = 0;&lt;br /&gt;        private ContentManager _content;&lt;br /&gt;        public Nave(int altoVentana, int anchoVentana)&lt;br /&gt;        {&lt;br /&gt;            this.altoVentana = altoVentana;&lt;br /&gt;            this.anchoVentana = anchoVentana;&lt;br /&gt;            posicion = new Vector2(altoVentana - altoImagen * 2, (anchoVentana - anchoImagen) / 2);&lt;br /&gt;            CrearRectangulo(anchoImagen, altoImagen * 2);&lt;br /&gt;            disparos = new List&amp;lt;Disparo&amp;gt;();&lt;br /&gt;        }&lt;br /&gt;        public void LoadContent(ContentManager Content)&lt;br /&gt;        {&lt;br /&gt;            this._content = Content;&lt;br /&gt;            imagen = Content.Load&amp;lt;texture2d&amp;gt;(&amp;quot;battleship&amp;quot;);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Como podemos ver hay varias cosas nuevas. En cuanto a la lista antes mencionada, podemos ver que se inicializa en el constructor. También almacenamos el ContentManager que obtenemos en el método LoadContent por que lo necesitaremos para inicializar los disparos. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En cuanto al int frameCounter, lo utilizaremos para que no se pueda disparar demasiado rápido. Me explico. Si no ponemos ninguna clase de restricción de este estilo al crear los disparos, si mantenemos pulsado el botón se creara un disparo cada vez que se pulse el botón Update. Esto serán una cantidad enorme de disparos. Si tenemos un contador, que cada vez que se llame a Update se le suma 1, y que cada vez que creamos un disparo se ponga a 0 podemos decir que si el contador esta mas bajo que 7 no se cree ningún disparo, haciendo así que los disparos se creen mucho mas lentos. Yo he puesto 7, pero el numero se puede alterar al gusto, claro. &lt;strong&gt;Esta técnica es indispensable aplicarla a cualquier botón que se utilice que no sean los de movimiento&lt;/strong&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Una vez explicado esto, veremos como queda nuestro método Update tras manejar los disparos:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;        public void Update()&lt;br /&gt;        {&lt;br /&gt;            UpdateShots();&lt;br /&gt;            UpdatePosition();&lt;br /&gt;            UpdateRectangle();            &lt;br /&gt;        }&lt;br /&gt;        private void UpdateShots()&lt;br /&gt;        {&lt;br /&gt;            frameCounter++;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Z) &amp;amp;&amp;amp; disparos.Count &amp;lt; 6 &amp;amp;&amp;amp; frameCounter &amp;gt; 7)&lt;br /&gt;            {&lt;br /&gt;                Disparo s = new Disparo(posicion, anchoImagen, _content);&lt;br /&gt;                disparos.Add(s);&lt;br /&gt;                s.FueraDePantalla += new EventHandler(FueraDePantallaHandler);&lt;br /&gt;                frameCounter = 0;&lt;br /&gt;            }&lt;br /&gt;            disparos.ForEach(x =&amp;gt; x.Update());        &lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Como se puede ver, hemos añadido un método mas a Update donde se manejan los disparos. Lo primero que se hace es aumentar frameCounter, tras lo cual si la tecla está pulsada, hay menos de 6 disparos y framecounter está a 7 o más crearemos un nuevo disparo. Lo de la limitación de 6 disparos en la pantalla es totalmente opcional, depende del poder que le queráis dar a vuestra nave :). &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Una vez se cumplen todas estas condiciones se crea un nuevo disparo, se añade a la lista y frameCounter se pone a 0. Además de esto también empezamos la escucha del evento, con lo cual, una vez se dispare el evento FueraDePantalla se invocará automáticamente al método FueraDePantallaHandler, que definiremos ahora, en el cual se eliminara el disparo que ha enviado el evento por que este se ha salido de la pantalla.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En cuanto a la última línea del método es una expresión lambda que básicamente recorre disparos y llama a Update de cada disparo. Lo más intuitivo sería hacer un foreach para que realice esto, pero dado que durante la ejecución del bucle puede cambiar el tamaño de disparos, si usamos foreach saltara una excepción, mientras que usando esta expresión Lambda no pasara. Otra solución sería recorrer la lista manualmente valiéndose de un bucle convencional como for.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En cuanto al manejador de eventos que borrara los disparos sobrantes, será algo tan sencillo como esto:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;	private void FueraDePantallaHandler(Object sender, EventArgs args)&lt;br /&gt;        {&lt;br /&gt;            disparos.Remove((Disparo)sender);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Por ultimo, solo nos queda llamar al método Draw de cada disparo dentro del método Draw de Nave:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;        public void Draw(SpriteBatch spbtch)&lt;br /&gt;        {&lt;br /&gt;            spbtch.Draw(imagen, posicion, rectangulo, Color.White);&lt;br /&gt;            DrawShots(spbtch);&lt;br /&gt;        }&lt;br /&gt;        private void DrawShots(SpriteBatch spbtch)&lt;br /&gt;        {&lt;br /&gt;            foreach (Disparo s in disparos)&lt;br /&gt;            {&lt;br /&gt;                s.Draw(spbtch);&lt;br /&gt;            }&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto, podemos probar a ejecutar el programa, y veremos que nuestra nave ya esta dotada de un armamento temible.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/TBzWsbUr5DI/AAAAAAAAAIM/HD0iOKfQxMw/s1600-h/image%5B12%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh4.ggpht.com/_OESoGgtnthw/TBzWs6UU1CI/AAAAAAAAAIQ/dmu8gy1fLbk/image_thumb%5B8%5D.png?imgmax=800" width="571" height="372" /&gt;&lt;/a&gt;Y eso es todo por hoy. Podéis bajaros el código fuente de lo que tenemos hasta ahora en el siguiente enlace:&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TBzWvMnumNI/AAAAAAAAAIU/-8X6PT-82lY/s1600-h/image%5B22%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh4.ggpht.com/_OESoGgtnthw/TBzWv7jE19I/AAAAAAAAAIY/GXP-nQ9_lkI/image_thumb%5B16%5D.png?imgmax=800" width="122" height="81" /&gt;&lt;/a&gt;&amp;#160;&lt;a title="http://www.megaupload.com/?d=SQ0VIX0T" href="http://www.megaupload.com/?d=SQ0VIX0T"&gt;http://www.megaupload.com/?d=SQ0VIX0T&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En la próxima parte del tutorial veremos como añadir a nuestro juego un fondo animado con scroll. No os lo perdáis y ¡¡Sed unos cangrejos pacientes!! &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:c58a8f02-8e94-4486-9a3d-d867e2bdc10a" class="wlWriterEditableSmartContent"&gt;Etiquetas de Technorati: &lt;a href="http://technorati.com/tags/programaci%c3%b3n" rel="tag"&gt;programaci&amp;#243;n&lt;/a&gt;,&lt;a href="http://technorati.com/tags/juegos" rel="tag"&gt;juegos&lt;/a&gt;,&lt;a href="http://technorati.com/tags/xna" rel="tag"&gt;xna&lt;/a&gt;,&lt;a href="http://technorati.com/tags/windows" rel="tag"&gt;windows&lt;/a&gt;,&lt;a href="http://technorati.com/tags/xbox" rel="tag"&gt;xbox&lt;/a&gt;,&lt;a href="http://technorati.com/tags/C%23" rel="tag"&gt;C#&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-7244776196344148359?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/7244776196344148359/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/06/programando-videojuegos-tutorial-xna_19.html#comment-form' title='6 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/7244776196344148359'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/7244776196344148359'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/06/programando-videojuegos-tutorial-xna_19.html' title='Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 3'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_OESoGgtnthw/TBzWrE7gwDI/AAAAAAAAAIA/xhlhNPvJctU/s72-c/crab-icon%20ball%20c%23_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-5354271569852879443</id><published>2010-06-18T02:56:00.000-07:00</published><updated>2010-06-18T03:18:11.320-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='gamelab'/><category scheme='http://www.blogger.com/atom/ns#' term='noticias'/><category scheme='http://www.blogger.com/atom/ns#' term='tutorial'/><title type='text'>Noticias</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_OESoGgtnthw/TBtDehoNFyI/AAAAAAAAAH0/FR0JDpOm1XI/s1600/crab-icon+etc.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 48px; height: 68px;" src="http://1.bp.blogspot.com/_OESoGgtnthw/TBtDehoNFyI/AAAAAAAAAH0/FR0JDpOm1XI/s320/crab-icon+etc.png" alt="" id="BLOGGER_PHOTO_ID_5484051162955847458" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Hoy en the code crab aprovecharemos para anunciar varias cosas. La primera de todas es que (por fin) he terminado la carrera, por lo que ya soy un Ingeniero informático en toda regla ^^. Gracias a esto tendré mucho más tiempo para dedicar al blog, por lo que ya mismo me pongo a trabajar en el tutorial de XNA, que se que estáis ansiosos de más.&lt;br /&gt;&lt;br /&gt;En otra línea de sucesos, aprovecho para anunciar que asistiré al &lt;a href="http://www.gamelab.es/"&gt;GameLab 2010&lt;/a&gt;, una feria del videojuego que se celebra en mi provincia (Asturias), por lo que tendré la oportunidad de asistir. Intentare realizar resúmenes de las conferencias a las que asista y ponerlas en el blog, aunque no prometo nada de la calidad, pues soy informático y no periodista. No me hace mucha gracia que se me entremezcle las entradas del GameLab con las de XNA (Que parece que va para largo), pero para compensar, tras terminar todas las partes del tutorial, las recopilare en un PDF y subiré el archivo en una entrada.&lt;br /&gt;&lt;br /&gt;Pues no os aburro más con esta entrada sin contenido. La tercera parte del tutorial &lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://icons.mysitemyway.com/wp-content/gallery/blue-chrome-rain-icons-animals/011337-blue-chrome-rain-icon-animals-animal-crab2.png"&gt;&lt;img style="float: right; margin: 0pt 0pt 10px 10px; cursor: pointer; width: 73px; height: 73px;" src="http://icons.mysitemyway.com/wp-content/gallery/blue-chrome-rain-icons-animals/011337-blue-chrome-rain-icon-animals-animal-crab2.png" alt="" border="0" /&gt;&lt;/a&gt;saldrá en unos días (esta vez sí), ¡Sed unos cangrejos pacientes!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-5354271569852879443?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/5354271569852879443/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/06/noticias.html#comment-form' title='0 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/5354271569852879443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/5354271569852879443'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/06/noticias.html' title='Noticias'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_OESoGgtnthw/TBtDehoNFyI/AAAAAAAAAH0/FR0JDpOm1XI/s72-c/crab-icon+etc.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-8138270259603388138</id><published>2010-06-08T06:50:00.001-07:00</published><updated>2010-06-14T06:51:14.996-07:00</updated><title type='text'>Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 2</title><content type='html'>&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TA1avCMsQsI/AAAAAAAAAG0/CV7Loo7SbWM/s1600-h/crab-icon%20ball%20c%23%5B5%5D.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" title="crab-icon ball c#" alt="crab-icon ball c#" src="http://lh5.ggpht.com/_OESoGgtnthw/TA1avkBJvtI/AAAAAAAAAG4/uUjSqua-EDs/crab-icon%20ball%20c%23_thumb%5B3%5D.png?imgmax=800" width="48" height="68" /&gt;&lt;/a&gt; Un día después, en The Code Crab, continuamos lo que hemos dejado a medias.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/TA0nh1ecx9I/AAAAAAAAAGU/3bwEWi6KEyQ/s1600-h/image%5B4%5D.png"&gt;&lt;img style="display: inline" title="image" alt="image" src="http://lh6.ggpht.com/_OESoGgtnthw/TA0nibb3Z9I/AAAAAAAAAGY/k2QV9zGM_t4/image_thumb%5B2%5D.png?imgmax=800" width="591" height="384" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Tenemos nuestra navecita, que ya se ve en la pantalla (preciosa ella), y nuestro código perfectamente organizado, con una clase Game1 que llama a los respectivos métodos de cada objeto que tiene (es decir de la nave de momento) y con una clase nave que maneja todo lo relativo a la navecita. Es hora de implementar el Update de la clase Nave para poder moverla por la pantallita, pero antes necesitaremos preparar unos cuantos atributos mas:&lt;/p&gt;  &lt;pre class="csharp" name="code"&gt;        private const int anchoImagen = 42;&lt;br /&gt;        private const int altoImagen = 44;&lt;br /&gt;        private Texture2D imagen;&lt;br /&gt;        private Vector2 posicion;&lt;br /&gt;        private int altoVentana;&lt;br /&gt;        private int anchoVentana;&lt;br /&gt;        public Nave(int altoVentana, int anchoVentana)&lt;br /&gt;        {&lt;br /&gt;            this.altoVentana = altoVentana;&lt;br /&gt;            this.anchoVentana = anchoVentana;&lt;br /&gt;            posicion = new Vector2(altoVentana - altoImagen * 2, (anchoVentana - anchoImagen) / 2);&lt;br /&gt;            CrearRectangulo(anchoImagen, altoImagen * 2);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Añadimos 4 enteros: en anchoImagen y altoImagen almacenaremos el tamaño en pixels de la imagen, lo cual simplificara bastante las cosas a la hora de mostrarlo por pantalla (y de paso si cambias de imagen no te tienes que volver loco buscando todos los 42 y 44 que pusiste). En height y width almacenamos el tamaño de la ventana en pixels, el cual ya pasábamos como parámetro, pero esta vez lo almacenamos, pues lo necesitaremos para que la nave no se salga de la pantalla.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Con todo esto ya estamos listos para implementar Update, donde manejaremos la nave en función de las teclas que se pulsen:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;        public void Update()&lt;br /&gt;        {&lt;br /&gt;            UpdatePosition();            &lt;br /&gt;        }&lt;br /&gt;        private void UpdatePosition()&lt;br /&gt;        {&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Left) &amp;amp;&amp;amp; posicion.X &amp;gt; 5)&lt;br /&gt;                posicion.X -= 5;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Right) &amp;amp;&amp;amp; posicion.X &amp;lt; (anchoVentana - anchoImagen))&lt;br /&gt;                posicion.X += 5;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Up) &amp;amp;&amp;amp; posicion.Y &amp;gt; 5)&lt;br /&gt;                posicion.Y -= 5;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Down) &amp;amp;&amp;amp; posicion.Y &amp;lt; (altoVentana - altoImagen))&lt;br /&gt;                posicion.Y += 5;&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Que es todo esto, os preguntareis. Pues bien, es bastante sencillo. Con el método estático &lt;em&gt;Keyboard.GetState()&lt;/em&gt; obtenemos el estado actual del teclado, y con el método &lt;em&gt;IsKeyDown(Keys.X) &lt;/em&gt;sabemos si una tecla X esta pulsada o no. Una vez sabemos esto es fácil intuir que lo que hacemos es cambiar la posición en función de que tecla se pulse, aumentando X si se pulsa derecha, reduciéndolo si se pulsa izquierda, aumentando Y si se pulsa abajo y reduciéndolo si se pulsa Up. Yo tengo puesto un aumento/disminución de 5, pero si cambiáis el numerito estaréis cambiando la velocidad de la nave.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;En cuanto a la otra condición se trata de comprobar que la imagen no se salga de los bordes (Para esto necesitábamos el tamaño de la ventana). Cuando se comprueba que no se salga de los bordes inferior y derecho, hay que restarle al tamaño de la ventana el tamaño de la imagen por un motivo simple: La posición que le indicamos a la imagen es la coordenada de su esquina superior izquierda, por lo que si dejamos que esta coordenada llegue a ser el ancho o el alto de la ventana, la imagen se saldrá de la pantalla.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto si probamos a ejecutar, ya podemos mover nuestra nave (divertido, ¿No?), pero aquí falta algo. Para que tener varias imágenes distintas para la nave en función de hacia donde se este moviendo si no lo utilizamos. Pues bien, vamos a ello. Una vez mas lo primero que hay que hacer será añadir un nuevo atributo para representar el estado.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;¿Como representamos el estado de la nave? Podemos usar prácticamente cualquier cosa, siempre que tengamos claro lo que estamos usando, como un string o incluso un int, pero la opción mas sencilla sera almacenar un objeto Rectangle con la sección de la imagen que dibujaremos, para no tener que complicarnos la vida en el Draw. También tendremos que modificar el constructor para inicializar la variable:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;       private Rectangle rectangulo;&lt;br /&gt;       private int ancho = 42;&lt;br /&gt;       private int alto = 44;&lt;br /&gt;       private Texture2D imagen;&lt;br /&gt;       private Vector2 posicion;&lt;br /&gt;       private int height;&lt;br /&gt;       private int width;&lt;br /&gt;       public Nave(int height, int width)&lt;br /&gt;       {&lt;br /&gt;           this.height = height;&lt;br /&gt;           this.width = width;&lt;br /&gt;           posicion = new Vector2(height-alto*2, (width-ancho)/2);&lt;br /&gt;           estado = Estado.Normal;&lt;br /&gt;       }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ya que nuestra imagen es una cuadricula de cuadros 42x44, &lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TA0ni83yLTI/AAAAAAAAAGc/BxqPzZK7Nxg/s1600-h/image%5B9%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh5.ggpht.com/_OESoGgtnthw/TA0njT4S33I/AAAAAAAAAGg/hsyZSHf5Gwk/image_thumb%5B5%5D.png?imgmax=800" width="125" height="133" /&gt;&lt;/a&gt; tenemos que fijarnos en que imagen queremos dibujar según hacia donde este la nave avanzando. Si enumeramos las diferentes imágenes que tenemos vemos que de 1 a 3 son las diferentes imágenes retrocediendo (Sin propulsión), de 4 a 6 son las imágenes avanzando (Mucha propulsión) y de 7 a 9 son las imágenes normales (Poca propulsión). Entonces ¿Como hacemos que nuestra imagen cambie según en que dirección avance la nave?. &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Es fácil, ¿Recordáis los parámetros de &lt;em&gt;SpriteBatch.draw&lt;/em&gt;? El primer parámetro es la imagen a dibujar, el siguiente las coordenadas donde se debe dibujar, y el tercero un objeto Rectangle que indique que parte de la imagen se dibujara, cuyo constructor pide como parámetros la coordenada de donde tiene que empezar a coger la imagen (esquina superior izquierda, como siempre) y la altura y la anchura de esta. La altura y la anchura serán siempre las mismas, mientras que la coordenada variara en función de que imagen queremos. Como sabemos la dirección en la que avanza la nave es fácil saber estas coordenadas utilizando múltiplos de la anchura y altura, ya que es una cuadricula (Por ejemplo, si queremos la coordenada de la imagen 3 tiene que ser (anchura*2, 0), mientras que para la imagen 8 sería (anchura, altura*2)). Lo único que nos hace falta es almacenar estas coordenadas en la variable rectangulo, definida anteriormente, y actualizarla en función de que teclas se estén pulsando.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Con esto tenemos una variable estado en la cual almacenamos que sección de la imagen queremos dibujar. Tras esto, lo que tenemos que hacer es añadir mas cosas al método Update, para que en función de hacia que dirección se este moviendo cambie el rectángulo:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;        public void Update()&lt;br /&gt;        {&lt;br /&gt;            UpdatePosition();&lt;br /&gt;            UpdateRectangle();            &lt;br /&gt;        }&lt;br /&gt;        private void UpdatePosition()&lt;br /&gt;        {&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Left) &amp;amp;&amp;amp; posicion.X &amp;gt; 5)&lt;br /&gt;                posicion.X -= 5;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Right) &amp;amp;&amp;amp; posicion.X &amp;lt; (anchoVentana - anchoImagen))&lt;br /&gt;                posicion.X += 5;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Up) &amp;amp;&amp;amp; posicion.Y &amp;gt; 5)&lt;br /&gt;                posicion.Y -= 5;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Down) &amp;amp;&amp;amp; posicion.Y &amp;lt; (altoVentana - altoImagen))&lt;br /&gt;                posicion.Y += 5;&lt;br /&gt;        }&lt;br /&gt;        private void UpdateRectangle()&lt;br /&gt;        {&lt;br /&gt;            //a partir de aquí escojemos la parte de imagen que queremos dibujar y la almacenamos en rectangle,&lt;br /&gt;            // en funcion de la combinaion de botones que se esten pulsando.&lt;br /&gt;&lt;br /&gt;            if (Keyboard.GetState().IsKeyDown(Keys.Left) &amp;amp;&amp;amp; Keyboard.GetState().IsKeyDown(Keys.Up))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(0, altoImagen);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Right) &amp;amp;&amp;amp; Keyboard.GetState().IsKeyDown(Keys.Up))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen * 2, altoImagen);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Up))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen, altoImagen);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Left) &amp;amp;&amp;amp; Keyboard.GetState().IsKeyDown(Keys.Down))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(0, 0);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Right) &amp;amp;&amp;amp; Keyboard.GetState().IsKeyDown(Keys.Down))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen * 2, 0);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Down))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen, 0);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Left))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(0, altoImagen * 2);&lt;br /&gt;            }&lt;br /&gt;            else if (Keyboard.GetState().IsKeyDown(Keys.Right))&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen * 2, altoImagen * 2);&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;                CrearRectangulo(anchoImagen, altoImagen * 2);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;	private void CrearRectangulo(int x, int y)&lt;br /&gt;        {&lt;br /&gt;            rectangulo = new Rectangle(x, y, anchoImagen, altoImagen);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ya que también necesitamos saber si la nave se esta desplazando en diagonal no podemos usar los if utilizados para modificar la posición, y por esto mismo es muy importante el orden de los if (Pues no podemos comprobar si la nave esta Retrocediendo hasta que no hayamos comprobado que no este retrocediendo hacia la derecha ni hacia la izquierda, pues en ambos casos si comprobamos si esta retrocediendo antes obtendremos un falso positivo).&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto ya tenemos actualizado el estado de la nave, y sabemos que parte de la imagen debemos dibujar. Ahora solo resta dibujar el Sprite, con lo que tendremos que modificar el método Draw de la clase nave, quedándonos así:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;	public void Draw(SpriteBatch spbtch)&lt;br /&gt;        {&lt;br /&gt;            spbtch.Draw(imagen, posicion, rectangulo, Color.White);&lt;br /&gt;        }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras todo esto, y como ya invocábamos a todos los métodos en la parte anterior del tutorial (Incluso Update que antes no hacía nada, si me habéis hecho caso) ya debería funcionar todo correctamente, y nuestra preciosa nave se podrá mover con libertad por la pantalla sin salirse y con una animación bastante chula.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TA0nj65NCpI/AAAAAAAAAGk/UyFRatgUr6Q/s1600-h/image%5B16%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="image" alt="image" src="http://lh4.ggpht.com/_OESoGgtnthw/TA0nka1pmtI/AAAAAAAAAGo/g-ReW6vnwrc/image_thumb%5B10%5D.png?imgmax=800" width="591" height="385" /&gt;&lt;/a&gt;Ya va cogiendo forma el juego, ¿No? Con esto termina la segunda parte del tutorial, estad atentos para la tercera parte, la haré en unos días. Podéis descargaros el código fuente de la aplicación hasta ahora en el siguiente enlace: &lt;a href="http://www.megaupload.com/?d=LN7C0R0J"&gt;http://www.megaupload.com/?d=LN7C0R0J&lt;/a&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/TA0nlJThVLI/AAAAAAAAAGs/2GGjK4n0oQQ/s1600-h/image%5B26%5D.png"&gt;&lt;img style="border-right-width: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; margin-left: 0px; border-left-width: 0px; margin-right: 0px" title="image" border="0" alt="image" align="right" src="http://lh5.ggpht.com/_OESoGgtnthw/TA0nl2qse8I/AAAAAAAAAGw/IbK-lEUnAqs/image_thumb%5B18%5D.png?imgmax=800" width="102" height="72" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Eso es todo por hoy, espero que os este gustando el megatutorial. Hasta otra y ¡¡Sed buenos Cangrejos!! &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:85b85c80-e464-402f-99d4-15b5e9c7f01d" class="wlWriterEditableSmartContent"&gt;Etiquetas de Technorati: &lt;a href="http://technorati.com/tags/programaci%c3%b3n" rel="tag"&gt;programaci&amp;#243;n&lt;/a&gt;,&lt;a href="http://technorati.com/tags/juegos" rel="tag"&gt;juegos&lt;/a&gt;,&lt;a href="http://technorati.com/tags/xna" rel="tag"&gt;xna&lt;/a&gt;,&lt;a href="http://technorati.com/tags/windows" rel="tag"&gt;windows&lt;/a&gt;,&lt;a href="http://technorati.com/tags/xbox" rel="tag"&gt;xbox&lt;/a&gt;,&lt;a href="http://technorati.com/tags/C%23" rel="tag"&gt;C#&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-8138270259603388138?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/8138270259603388138/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/06/programando-videojuegos-tutorial-xna_08.html#comment-form' title='11 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/8138270259603388138'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/8138270259603388138'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/06/programando-videojuegos-tutorial-xna_08.html' title='Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 2'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_OESoGgtnthw/TA1avkBJvtI/AAAAAAAAAG4/uUjSqua-EDs/s72-c/crab-icon%20ball%20c%23_thumb%5B3%5D.png?imgmax=800' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-4871800109740275330</id><published>2010-06-06T09:38:00.001-07:00</published><updated>2010-06-10T01:19:20.080-07:00</updated><title type='text'>Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 1</title><content type='html'>&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TAvO8rhotnI/AAAAAAAAAFk/1DME-sz_wN4/s1600-h/crab-icon%20ball%20c%23%5B4%5D.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px;" title="crab-icon ball c#" alt="crab-icon ball c#" src="http://lh6.ggpht.com/_OESoGgtnthw/TA6i-0QslWI/AAAAAAAAAG8/JphmOuZD4yo/crab-icon%20ball%20c%23%5B4%5D.png?imgmax=800" align="left" width="48" height="68" /&gt; &lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Antes de nada quiero disculparme por la ausencia de las ultimas semanas, he estado demasiado ocupado como para poner ninguna entrada, pero ya estoy de vuelta, y empiezo fuerte.&lt;/p&gt;  &lt;p&gt;En las próximas entradas, vamos a trabajar sobre &lt;span id="SPELLING_ERROR_3" class="blsp-spelling-error"&gt;XNA&lt;/span&gt;, un entorno de desarrollo proporcionado por Microsoft para el desarrollo de juegos 2D y 3D. Tiene un montón de ventajas, pero en mi opinión la mas importante es la portabilidad del código a la hora de trasladar un juego entre las diferentes plataformas soportadas (&lt;span id="SPELLING_ERROR_4" class="blsp-spelling-error"&gt;PC&lt;/span&gt;, &lt;span id="SPELLING_ERROR_5" class="blsp-spelling-error"&gt;XBox&lt;/span&gt; 360 y &lt;span id="SPELLING_ERROR_6" class="blsp-spelling-error"&gt;Windows&lt;/span&gt; &lt;span id="SPELLING_ERROR_7" class="blsp-spelling-error"&gt;Phone&lt;/span&gt;). &lt;span id="SPELLING_ERROR_8" class="blsp-spelling-error"&gt;Evidentemente&lt;/span&gt; no es lo mismo trabajar con la pantalla de un móvil que con una &lt;span id="SPELLING_ERROR_9" class="blsp-spelling-error"&gt;tele&lt;/span&gt;, pero las diferencias en cuanto a código se reducen a eso y a los controles del juego.&lt;/p&gt;  &lt;p&gt;Quiero mencionar que este &lt;span id="SPELLING_ERROR_10" class="blsp-spelling-error"&gt;tutorial&lt;/span&gt; esta orientado tanto a gente que nunca ha programado &lt;span id="SPELLING_ERROR_11" class="blsp-spelling-error"&gt;videojuegos&lt;/span&gt; como a gente que nunca ha utilizado &lt;span id="SPELLING_ERROR_12" class="blsp-spelling-error"&gt;XNA&lt;/span&gt;. Solo se requieren conocimientos básicos de C#, e intentare ir paso por paso y explicarlo todo con detalle.&lt;/p&gt;  &lt;p&gt;Para este &lt;span id="SPELLING_ERROR_13" class="blsp-spelling-error"&gt;tutorial&lt;/span&gt;, dividido en varias partes, vamos a desarrollar un juego para &lt;span id="SPELLING_ERROR_14" class="blsp-spelling-error"&gt;Windows&lt;/span&gt; (Un juego de naves en 2D), pero no es nada difícil trasladar este código a cualquiera las plataformas anteriormente mencionadas. ¿Que necesitamos para empezar a programar en &lt;span id="SPELLING_ERROR_15" class="blsp-spelling-error"&gt;XNA&lt;/span&gt; &lt;span id="SPELLING_ERROR_16" class="blsp-spelling-error"&gt;game&lt;/span&gt; &lt;span id="SPELLING_ERROR_17" class="blsp-spelling-error"&gt;studio&lt;/span&gt;? Pues simplemente, un visual &lt;span id="SPELLING_ERROR_18" class="blsp-spelling-error"&gt;studio&lt;/span&gt; y una versión de &lt;span id="SPELLING_ERROR_19" class="blsp-spelling-error"&gt;XNA&lt;/span&gt; &lt;span id="SPELLING_ERROR_20" class="blsp-spelling-error"&gt;Game&lt;/span&gt; &lt;span id="SPELLING_ERROR_21" class="blsp-spelling-error"&gt;Studio&lt;/span&gt; compatible con este. Yo voy a utilizar &lt;span id="SPELLING_ERROR_22" class="blsp-spelling-error"&gt;VS&lt;/span&gt; 2010 y &lt;span id="SPELLING_ERROR_23" class="blsp-spelling-error"&gt;XNA&lt;/span&gt; &lt;span id="SPELLING_ERROR_24" class="blsp-spelling-error"&gt;GS&lt;/span&gt; 4.0 por ser las ultimas versiones de ambos, pero las diferencias en cuanto al código deberían ser mínimas.&lt;/p&gt;  &lt;p&gt;¿Donde conseguimos &lt;span id="SPELLING_ERROR_25" class="blsp-spelling-error"&gt;XNA&lt;/span&gt; &lt;span id="SPELLING_ERROR_26" class="blsp-spelling-error"&gt;Game&lt;/span&gt; &lt;span id="SPELLING_ERROR_27" class="blsp-spelling-error"&gt;Studio&lt;/span&gt;? Muy fácil, aquí mismo: &lt;a title="http://creators.xna.com/es-ES/downloads" href="http://creators.xna.com/es-ES/downloads"&gt;http://creators.xna.com/es-ES/downloads&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Una vez tenemos todo instalado podemos comenzar a programar. Lo primero que haremos será crear un nuevo proyecto de &lt;span id="SPELLING_ERROR_28" class="blsp-spelling-error"&gt;XNA&lt;/span&gt; para &lt;span id="SPELLING_ERROR_29" class="blsp-spelling-error"&gt;Windows&lt;/span&gt; &lt;span id="SPELLING_ERROR_30" class="blsp-spelling-error"&gt;Games&lt;/span&gt;.&lt;/p&gt;  &lt;p&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://lh5.ggpht.com/_OESoGgtnthw/TA6i_uucLqI/AAAAAAAAAHA/uMPfH9DNqUE/image%5B6%5D.png?imgmax=800" width="531" height="373" /&gt;Tras esto veremos que nos &lt;span id="SPELLING_ERROR_32" class="blsp-spelling-error"&gt;autogenera&lt;/span&gt; ya bastantes cosas. La clase principal es la que nos habrá llamado &lt;span id="SPELLING_ERROR_33" class="blsp-spelling-error"&gt;Game&lt;/span&gt;1 y tiene los siguientes métodos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;&lt;span id="SPELLING_ERROR_34" class="blsp-spelling-error"&gt;Initialize&lt;/span&gt;&lt;/strong&gt; se llama al principio de la ejecución del juego. En principio lo utilizaremos para crear instancias de los objetos que vamos a necesitar y para cambiar cosas como el titulo de la ventana. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;span id="SPELLING_ERROR_35" class="blsp-spelling-error"&gt;LoadContet&lt;/span&gt; &lt;/strong&gt;se llama después de &lt;span id="SPELLING_ERROR_36" class="blsp-spelling-error"&gt;Initialize&lt;/span&gt;. Este &lt;span id="SPELLING_ERROR_37" class="blsp-spelling-error"&gt;método&lt;/span&gt; creara una instancia de &lt;span id="SPELLING_ERROR_38" class="blsp-spelling-error"&gt;SpriteBatch&lt;/span&gt;, la cual usaremos para dibujar cosas por pantalla mas adelante. Además es aquí donde debemos cargar las imágenes de nuestro juego. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;span id="SPELLING_ERROR_39" class="blsp-spelling-error"&gt;Update&lt;/span&gt; &lt;/strong&gt;se llamara varias veces por segundo a lo largo de la ejecución del juego, y aquí deberemos insertar la lógica del juego. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;&lt;span id="SPELLING_ERROR_40" class="blsp-spelling-error"&gt;Draw&lt;/span&gt; &lt;/strong&gt;se llamara varias veces por segundo también y se encargara de dibujar cosas por pantalla valiéndose del antes mencionado &lt;span id="SPELLING_ERROR_41" class="blsp-spelling-error"&gt;SpriteBatch&lt;/span&gt;. Es importante tener en cuenta de que si una cosa se dibuja mas tarde que otra, la que mas tarde se dibuje quedara por encima de la otra. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Si probamos a ejecutar veremos una pantalla en azul.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/TA6jAeNt1LI/AAAAAAAAAHE/OvjKlZ0iJZw/s1600-h/image%5B12%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://lh6.ggpht.com/_OESoGgtnthw/TA6jA9PAfQI/AAAAAAAAAHI/NXwp1N6q8pg/image_thumb%5B3%5D.png?imgmax=800" width="469" height="303" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;No es gran cosa, pero es el comienzo de nuestro juego. Lo primero que debemos notar es que ese fondo azul no nos sirve (si alguien quiere hacer un juego de una piscina quizás sirva, pero nosotros vamos a hacer un juego de naves) así que cambiaremos el color de fondo por negro. Para ello habrá que modificar el método &lt;span id="SPELLING_ERROR_43" class="blsp-spelling-error"&gt;Draw&lt;/span&gt;:&lt;/p&gt;  &lt;pre class="csharp" name="code"&gt;protected override void Draw(GameTime gameTime)&lt;br /&gt;    {&lt;br /&gt;        GraphicsDevice.Clear(Color.Black);&lt;br /&gt;&lt;br /&gt;        // TODO: Add your drawing code here&lt;br /&gt;&lt;br /&gt;        base.Draw(gameTime);&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Con esto el fondo de nuestra aplicación ya será negro. En partes posteriores de este &lt;span id="SPELLING_ERROR_57" class="blsp-spelling-error"&gt;tutorial&lt;/span&gt; se explicara como cambiar el fondo e incluso animarlo. El próximo paso para que la ventana sea mas adecuada a nuestras necesidades es cambiar el titulo. Esto lo insertamos dentro del método &lt;span id="SPELLING_ERROR_58" class="blsp-spelling-error"&gt;Initialize&lt;/span&gt;:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;protected override void Initialize()&lt;br /&gt;    {&lt;br /&gt;        // TODO: Add your initialization logic here&lt;br /&gt;        this.Window.Title="Space Burst";&lt;br /&gt;        base.Initialize();        &lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto la ventana ya esta preparada para nuestro juego, con un fondo negro y &lt;span id="SPELLING_ERROR_72" class="blsp-spelling-error"&gt;Space&lt;/span&gt; &lt;span id="SPELLING_ERROR_73" class="blsp-spelling-error"&gt;Burst&lt;/span&gt; de titulo,&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/TA6jCZz5VXI/AAAAAAAAAHU/sy0BLKPjvgI/s1600-h/battleship%5B4%5D.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px;" title="battleship" alt="battleship" src="http://lh4.ggpht.com/_OESoGgtnthw/TA6jC-2-bJI/AAAAAAAAAHY/NAa56Di17Wc/battleship_thumb%5B2%5D.png?imgmax=800" align="right" width="125" height="133" /&gt;&lt;/a&gt; el próximo &lt;span id="SPELLING_ERROR_74" class="blsp-spelling-error"&gt;exitazo&lt;/span&gt; de ventas esta preparado para arrancar :P. Ahora toca preguntarnos que es lo que  falta en nuestro juego? Es un juego de naves, así que es bueno tener alguna. Yo voy a utilizar la siguiente imagen, que es un &lt;span id="SPELLING_ERROR_75" class="blsp-spelling-error"&gt;sprite&lt;/span&gt; con varias posiciones de una nave &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Para añadir la imagen a nuestro proyecto la copiamos en la carpeta del proyecto y la añadimos (arrastrándola &lt;span id="SPELLING_ERROR_76" class="blsp-spelling-error"&gt;mismamente&lt;/span&gt;) a &lt;span id="SPELLING_ERROR_77" class="blsp-spelling-error"&gt;Content&lt;/span&gt; de nuestro proyecto. Esto será una especie de proyecto a parte para los que usen &lt;span id="SPELLING_ERROR_78" class="blsp-spelling-error"&gt;XNA&lt;/span&gt; &lt;span id="SPELLING_ERROR_79" class="blsp-spelling-error"&gt;GS&lt;/span&gt; 4.0 o una carpeta en caso de usar versiones anteriores.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ahora crearemos la clase Nave. &lt;span id="SPELLING_ERROR_80" class="blsp-spelling-error"&gt;Podríamos&lt;/span&gt; poner todo dentro de la clase &lt;span id="SPELLING_ERROR_81" class="blsp-spelling-error"&gt;Game&lt;/span&gt;1, pero el código resultante no sería nada elegante. Añadimos la nueva clase al proyecto &lt;em&gt;&lt;span id="SPELLING_ERROR_82" class="blsp-spelling-error"&gt;Click&lt;/span&gt; derecho&amp;gt;Añadir&amp;gt;Clase &lt;/em&gt;y comenzamos con nuestra nave. Antes de nada y para evitar futuros &lt;span id="SPELLING_ERROR_85" class="blsp-spelling-error"&gt;problemillas&lt;/span&gt; añadiremos los diferentes &lt;span id="SPELLING_ERROR_86" class="blsp-spelling-error"&gt;imports&lt;/span&gt; necesarios:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;using Microsoft.Xna.Framework.Graphics;&lt;br /&gt;using Microsoft.Xna.Framework;&lt;br /&gt;using Microsoft.Xna.Framework.Content;&lt;br /&gt;using Microsoft.Xna.Framework.Input;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;¿Que atributos necesitamos que tenga? Pues vamos a ir poco a poco, así que empezaremos con 2: un objeto &lt;em&gt;&lt;span id="SPELLING_ERROR_91" class="blsp-spelling-error"&gt;Texture&lt;/span&gt;2D&lt;/em&gt; donde se almacenara la imagen y un objeto &lt;em&gt;Vector2&lt;/em&gt; donde se almacenara la posición.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;&lt;br /&gt;        private Texture2D imagen;&lt;br /&gt;        private Vector2 posicion;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Además de esto, tendremos que añadir a la clase nave los métodos importantes de la clase &lt;span id="SPELLING_ERROR_96" class="blsp-spelling-error"&gt;Game&lt;/span&gt;1: &lt;span id="SPELLING_ERROR_97" class="blsp-spelling-error"&gt;LoadContent&lt;/span&gt;, &lt;span id="SPELLING_ERROR_98" class="blsp-spelling-error"&gt;Update&lt;/span&gt; y &lt;span id="SPELLING_ERROR_99" class="blsp-spelling-error"&gt;Draw&lt;/span&gt;, y así en la clase &lt;span id="SPELLING_ERROR_100" class="blsp-spelling-error"&gt;Game&lt;/span&gt;1 solo tendremos que llamar en cada método a los métodos &lt;span id="SPELLING_ERROR_101" class="blsp-spelling-error"&gt;correspondientes&lt;/span&gt; de todos los objetos que tengamos en la pantalla.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Debemos crear la instancia de posición dentro del constructor de la clase y la de imagen dentro de &lt;span id="SPELLING_ERROR_102" class="blsp-spelling-error"&gt;LoadContent&lt;/span&gt;. Como algo opcional podremos pasar al constructor de nave el ancho y alto de la ventana, para saber donde dibujar &lt;span id="SPELLING_ERROR_103" class="blsp-spelling-error"&gt;inicialmente&lt;/span&gt; la nave y que no quede demasiado descentrada:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt; public Nave(int altoVentana, int anchoVentana)&lt;br /&gt;    {&lt;br /&gt;        posicion = new Vector2(altoVentana-100, (anchoVentana)/2);&lt;br /&gt;    }&lt;br /&gt;    public void LoadContent(ContentManager Content)&lt;br /&gt;    {&lt;br /&gt;        imagen = Content.Load&amp;lt;Texture2D&amp;gt;;("battleship");&lt;br /&gt;    }&lt;br /&gt;    public void Update()&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;    }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;El parámetro &lt;span id="SPELLING_ERROR_126" class="blsp-spelling-error"&gt;ContentManager&lt;/span&gt; es necesario para cargar imágenes, y lo pasamos al invocar el método desde la clase principal. Hay que notar que el nombre de la imagen se escribe sin terminación. Esto es importante, por que sino no te encontrara tu imagen. También añadimos ya el &lt;span id="SPELLING_ERROR_127" class="blsp-spelling-error"&gt;método&lt;/span&gt; &lt;span id="SPELLING_ERROR_128" class="blsp-spelling-error"&gt;Update&lt;/span&gt; de la clase nave, aunque aún no haga nada.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Aprovecho para explicar el sistema de coordenadas utilizado por &lt;span id="SPELLING_ERROR_129" class="blsp-spelling-error"&gt;XNA&lt;/span&gt;. Las medidas son en &lt;span id="SPELLING_ERROR_130" class="blsp-spelling-error"&gt;pixeles&lt;/span&gt; y al contrario que el sistema cartesiano el eje (0,0) esta situado en la parte superior izquierda de la ventana. Así por ejemplo si tenemos una ventana de 800x600 el punto (800, 600) sería la esquina inferior derecha, (800, 0) sería la esquina superior derecha y (0, 600) la esquina inferior izquierda.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto &lt;span id="SPELLING_ERROR_131" class="blsp-spelling-error"&gt;implementamos&lt;/span&gt; el método &lt;span id="SPELLING_ERROR_132" class="blsp-spelling-error"&gt;Draw&lt;/span&gt; de Nave, que dibujara la imagen en la posición adecuada:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;public void Draw(SpriteBatch spbtch)&lt;br /&gt;{&lt;br /&gt; spbtch.Draw(imagen, posicion, new Rectangle(42, 88, 42, 44), Color.White);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Que es todo esto, os &lt;span id="SPELLING_ERROR_144" class="blsp-spelling-error"&gt;preguntareis&lt;/span&gt;. Lo primero es el parámetro, el objeto &lt;span id="SPELLING_ERROR_145" class="blsp-spelling-error"&gt;SpriteBatch&lt;/span&gt; &lt;span id="SPELLING_ERROR_146" class="blsp-spelling-error"&gt;anteriormente&lt;/span&gt; comentado, que se encarga de dibujar cosas por pantalla. Lo utilizamos para llamar al &lt;span id="SPELLING_ERROR_147" class="blsp-spelling-error"&gt;metodo&lt;/span&gt; &lt;span id="SPELLING_ERROR_148" class="blsp-spelling-error"&gt;Draw&lt;/span&gt;. Pide varios parámetros: con imagen le pasamos la imagen que debe dibujar, con posición le pasamos donde debe dibujarla (hasta ahí espero que lo entendáis bien), pero ¿que es ese &lt;span id="SPELLING_ERROR_149" class="blsp-spelling-error"&gt;Rectangle&lt;/span&gt;? Pues muy sencillo. Nuestra imagen tiene varias imágenes de la nave en diferentes posiciones, y ese &lt;span id="SPELLING_ERROR_150" class="blsp-spelling-error"&gt;Rectangle&lt;/span&gt; indica que parte de la imagen hay que dibujar. En caso de que la imagen fuese una sola no haría falta este parámetro. Los números que necesita para crearse son las coordenadas donde empieza a dibujar, x e y por ese orden, y el ancho y alto de la imagen. Nuestra imagen consta de 9 imágenes de 42x44, así que con esos parámetros debería dibujar la imagen central.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto solo queda crear una instancia de Nave y llamar a los métodos necesarios en la clase &lt;span id="SPELLING_ERROR_151" class="blsp-spelling-error"&gt;Game&lt;/span&gt;1:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;    public class Game1 : Microsoft.Xna.Framework.Game&lt;br /&gt;   {&lt;br /&gt;       GraphicsDeviceManager graphics;&lt;br /&gt;       SpriteBatch spriteBatch;&lt;br /&gt;       Nave _nave;&lt;br /&gt;&lt;br /&gt;       public Game1()&lt;br /&gt;       {&lt;br /&gt;           graphics = new GraphicsDeviceManager(this);&lt;br /&gt;           Content.RootDirectory = "Content";           &lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void Initialize()&lt;br /&gt;       {&lt;br /&gt;           // TODO: Add your initialization logic here&lt;br /&gt;&lt;br /&gt;           _nave = new Nave(graphics.PreferredBackBufferHeight, graphics.PreferredBackBufferWidth);&lt;br /&gt;           this.Window.Title="Space Burst";&lt;br /&gt;           base.Initialize();           &lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void LoadContent()&lt;br /&gt;       {&lt;br /&gt;           // Create a new SpriteBatch, which can be used to draw textures.&lt;br /&gt;           spriteBatch = new SpriteBatch(GraphicsDevice);&lt;br /&gt;           _nave.LoadContent(Content);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void UnloadContent()&lt;br /&gt;       {&lt;br /&gt;           // TODO: Unload any non ContentManager content here&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void Update(GameTime gameTime)&lt;br /&gt;       {&lt;br /&gt;           // Cuidado con esto, no usamos mando.&lt;br /&gt;           if (Keyboard.GetState().IsKeyDown(Keys.Escape))&lt;br /&gt;               this.Exit();&lt;br /&gt;           _nave.Update();&lt;br /&gt;&lt;br /&gt;           base.Update(gameTime);&lt;br /&gt;       }&lt;br /&gt;&lt;br /&gt;       protected override void Draw(GameTime gameTime)&lt;br /&gt;       {&lt;br /&gt;           GraphicsDevice.Clear(Color.Black);&lt;br /&gt;&lt;br /&gt;           spriteBatch.Begin();&lt;br /&gt;           _nave.Draw(spriteBatch);&lt;br /&gt;           spriteBatch.End();&lt;br /&gt;&lt;br /&gt;           base.Draw(gameTime);&lt;br /&gt;       }&lt;br /&gt;   }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Como &lt;span id="SPELLING_ERROR_234" class="blsp-spelling-error"&gt;veréis&lt;/span&gt;, en el método &lt;span id="SPELLING_ERROR_235" class="blsp-spelling-error"&gt;LoadContent&lt;/span&gt; pasamos a Nave la anchura y la altura de nuestra ventana. En &lt;span id="SPELLING_ERROR_236" class="blsp-spelling-error"&gt;Update&lt;/span&gt; hay que tener cuidado, puesto que al menos a mi, en el código &lt;span id="SPELLING_ERROR_237" class="blsp-spelling-error"&gt;autogenerado&lt;/span&gt; comprobaba que estuviese pulsado el botón Atrás dentro de un &lt;span id="SPELLING_ERROR_238" class="blsp-spelling-error"&gt;gamepad&lt;/span&gt; (&lt;em&gt;GamePad.GetState(PlayerIndex.One).Buttons.Back == &lt;span id="SPELLING_ERROR_239" class="blsp-spelling-error"&gt;ButtonState&lt;/span&gt;.&lt;span id="SPELLING_ERROR_240" class="blsp-spelling-error"&gt;Pressed&lt;/span&gt;&lt;/em&gt;), y como &lt;span id="SPELLING_ERROR_241" class="blsp-spelling-error"&gt;probablemente&lt;/span&gt; nosotros usaremos teclado, tenemos que cambiar eso por la tecla escape, como se puede ver en el código. Además de esto llamamos al método &lt;span id="SPELLING_ERROR_242" class="blsp-spelling-error"&gt;Update&lt;/span&gt; de nave que aunque no haga nada, pronto lo hará. También llamamos a _nave.&lt;span id="SPELLING_ERROR_243" class="blsp-spelling-error"&gt;Draw&lt;/span&gt; dentro del &lt;span id="SPELLING_ERROR_244" class="blsp-spelling-error"&gt;metodo&lt;/span&gt; &lt;span id="SPELLING_ERROR_245" class="blsp-spelling-error"&gt;Draw&lt;/span&gt; principal, pasando como &lt;span id="SPELLING_ERROR_246" class="blsp-spelling-error"&gt;parametro&lt;/span&gt; el &lt;span id="SPELLING_ERROR_247" class="blsp-spelling-error"&gt;SpriteBatch&lt;/span&gt;.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras todo esto, si probamos a ejecutar, veremos algo similar a esto:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/TA6jDV2yalI/AAAAAAAAAHc/lYPIZypvIYE/s1600-h/image%5B34%5D.png"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="image" alt="image" src="http://lh6.ggpht.com/_OESoGgtnthw/TA6jDx2E57I/AAAAAAAAAHg/NtKJ4tHlyzc/image_thumb%5B19%5D.png?imgmax=800" width="539" height="348" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Aún no se mueve, ni hace nada, pero que esperabais, Roma no se construyo en un día. ¿Ha sido largo? No mucho. ¿Ha sido difícil? para nada.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/TA6j_mF7jJI/AAAAAAAAAHs/2DX0qAG8VYs/s1600-h/image%5B48%5D.png"&gt;&lt;img style="border: 0px none; display: inline; margin-left: 0px; margin-right: 0px;" title="image" alt="image" src="http://lh5.ggpht.com/_OESoGgtnthw/TA6kAKtiyoI/AAAAAAAAAHw/nSU13bW--IA/image_thumb%5B29%5D.png?imgmax=800" align="right" border="0" width="77" height="77" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Con esto concluyo esta titánica entrada que se me ha alargado bastante mas de lo que esperaba. Muy pronto sacare la segunda parte, para que nuestra &lt;span id="SPELLING_ERROR_249" class="blsp-spelling-error"&gt;navecita&lt;/span&gt; ya pueda hacer cosas. ¡Sed unos cangrejos pacientes!  &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt; &lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="padding: 0px; margin: 0px; display: inline; float: none;" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:193068df-40e0-4067-afe0-c93a2f54852f" class="wlWriterEditableSmartContent"&gt;Etiquetas de Technorati: &lt;a href="http://technorati.com/tags/programaci%c3%b3n" rel="tag"&gt;programación&lt;/a&gt;,&lt;a href="http://technorati.com/tags/juegos" rel="tag"&gt;juegos&lt;/a&gt;,&lt;a href="http://technorati.com/tags/xna" rel="tag"&gt;xna&lt;/a&gt;,&lt;a href="http://technorati.com/tags/windows" rel="tag"&gt;windows&lt;/a&gt;,&lt;a href="http://technorati.com/tags/xbox" rel="tag"&gt;xbox&lt;/a&gt;,&lt;a href="http://technorati.com/tags/C%23" rel="tag"&gt;C#&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-4871800109740275330?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/4871800109740275330/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/06/programando-videojuegos-tutorial-xna.html#comment-form' title='17 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/4871800109740275330'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/4871800109740275330'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/06/programando-videojuegos-tutorial-xna.html' title='Programando videojuegos: Tutorial XNA Game Studio 4.0 parte 1'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_OESoGgtnthw/TA6i-0QslWI/AAAAAAAAAG8/JphmOuZD4yo/s72-c/crab-icon%20ball%20c%23%5B4%5D.png?imgmax=800' height='72' width='72'/><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-149098431276945485</id><published>2010-05-16T04:08:00.001-07:00</published><updated>2010-05-17T05:16:33.517-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='java'/><category scheme='http://www.blogger.com/atom/ns#' term='thread'/><category scheme='http://www.blogger.com/atom/ns#' term='comparativa'/><category scheme='http://www.blogger.com/atom/ns#' term='C#'/><category scheme='http://www.blogger.com/atom/ns#' term='threading'/><category scheme='http://www.blogger.com/atom/ns#' term='programación'/><category scheme='http://www.blogger.com/atom/ns#' term='hilos'/><title type='text'>Ejecutando Hilos, comparativa Java y C#</title><content type='html'>&lt;p&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/S-_SJemLYPI/AAAAAAAAAE8/cL8F_ugKXG8/s1600-h/crabiconjava3.png"&gt;&lt;img style="display: inline;" title="crab-icon java" alt="crab-icon java" src="http://lh5.ggpht.com/_OESoGgtnthw/S-_SJwqO-6I/AAAAAAAAAFA/kLxzIclpT_k/crabiconjava_thumb1.png?imgmax=800" width="48" height="68" /&gt;&lt;/a&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/S-_SKBN4jRI/AAAAAAAAAFE/8JjzI2h2gSA/s1600-h/crabiconballc3.png"&gt;&lt;img style="display: inline;" title="crab-icon ball c#" alt="crab-icon ball c#" src="http://lh6.ggpht.com/_OESoGgtnthw/S-_SKhtwZSI/AAAAAAAAAFI/KCaax1CLFC0/crabiconballc_thumb1.png?imgmax=800" width="48" height="68" /&gt;&lt;/a&gt;  Hoy en The Code Crab vamos a ver como se ejecutan hilos, comparando el código en C# para ello con el código en Java. No obstante, no vamos a profundizar mucho en el tema, para mas información consultad las siguientes fuentes:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;C#: &lt;a title="http://msdn.microsoft.com/en-us/library/aa645740%28VS.71%29.aspx" href="http://msdn.microsoft.com/en-us/library/aa645740%28VS.71%29.aspx"&gt;http://msdn.microsoft.com/en-us/library/aa645740%28VS.71%29.aspx&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;Java: &lt;a title="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Thread.html" href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Thread.html"&gt;http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Thread.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt;Java: &lt;span style="text-decoration: underline;"&gt; &lt;a href="http://blog.davidmogar.es/2010/04/thread-pools-en-java/"&gt;http://blog.davidmogar.es/2010/04/thread-pools-en-java/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Pues sin mas preámbulos, empecemos con C#.&lt;/p&gt;  &lt;p&gt;Ejecutar un metodo en un hilo paralelo es muy sencillo. Lo primero es que no se nos debe olvidar la instrucción using: “&lt;em&gt;using System.Threading;”.&lt;/em&gt; Una vez tenemos el using definido correctamente debemos hacer el método que queremos que se ejecute en un hilo separado. No tiene por que ir en una clase separada, ni llevar nada especial, simplemente un método normal y corriente:&lt;/p&gt;  &lt;pre class="csharp" name="code"&gt; public void HelloThread()&lt;br /&gt;     {&lt;br /&gt;         while (true)&lt;br /&gt;         {&lt;br /&gt;             Console.WriteLine("Hola desde el hilo " + Thread.CurrentThread.ManagedThreadId);&lt;br /&gt;             Thread.Sleep(300);&lt;br /&gt;         }&lt;br /&gt;     }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto definiremos e invocaremos los hilos. Puede ser en cualquier método que se ejecute que tenga acceso al método que acabamos de definir. En mi caso, estoy haciendo un programa simple de ejemplo así que pondré el código en el constructor:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="csharp" name="code"&gt;&lt;br /&gt;public Program()&lt;br /&gt;     {&lt;br /&gt;         //Creamos y lanzamos un hilo&lt;br /&gt;         Thread thr1 = new Thread(HelloThread);&lt;br /&gt;         thr1.Start();&lt;br /&gt;         //Creamos y lanzamos un segundo hilo&lt;br /&gt;         Thread thr2 = new Thread(HelloThread);&lt;br /&gt;         thr2.Start();&lt;br /&gt;         //Esperamos 5 segundos a que hagan cosas&lt;br /&gt;         Thread.Sleep(5000);&lt;br /&gt;         //Cerramos el primer hilo&lt;br /&gt;         thr1.Abort();&lt;br /&gt;         //Join une el hilo con el principal, haciendo así que se espere a que termine ordenadamente&lt;br /&gt;         thr1.Join();&lt;br /&gt;         //Cerramos y esperamos por el segundo hilo&lt;br /&gt;         thr2.Abort();&lt;br /&gt;         thr2.Join();&lt;br /&gt;         Console.WriteLine("Programa terminado ordenadamente");&lt;br /&gt;     }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Compilamos, ejecutamos, y … tachaaaaaaaaaan, funciona!&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/S-_SLIlaAeI/AAAAAAAAAFM/bSpGv5RLvbg/s1600-h/hilos14.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="hilos1" alt="hilos1" src="http://lh3.ggpht.com/_OESoGgtnthw/S-_SLgEx7sI/AAAAAAAAAFQ/QfKbhVJAXw8/hilos1_thumb2.jpg?imgmax=800" width="240" height="121" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Ha sido fácil, ¿verdad? Mucho, diría yo. Ahora veremos como seria hacer en Java este mismo programa.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Lo primero que tenemos que hacer es crear una clase que herede de Thread, implementando el método run, donde habrá que poner la lógica del hilo:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class ThreadClass extends Thread {&lt;br /&gt;private boolean thrbool = true;&lt;br /&gt;public void run(){&lt;br /&gt;//Repetimos el bucle hasta que thrbool este puesto a false&lt;br /&gt;while(thrbool){&lt;br /&gt;System.out.println("Hello from thread "+super.getId());&lt;br /&gt;//Hay que hacer try catch para poder usar thread.sleep()&lt;br /&gt;try{&lt;br /&gt; Thread.sleep(300);&lt;br /&gt;}catch(Exception e){}&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;//Metodo para poner thrbool a false&lt;br /&gt;//Se podria utilizar el metodo .stop para forzar a cerrarse el hilo&lt;br /&gt;//Pero esta deprecated, asi que mejor terminarlo todo ordenadamente&lt;br /&gt;public void stopThread(){&lt;br /&gt;thrbool = false;&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tras esto debemos hacer una clase principal que instancie los hilos:&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre class="java" name="code"&gt;public class MainClass{&lt;br /&gt;public static void main(String args[]){&lt;br /&gt;//Creamos y arrancamos 2 hilos diferentes&lt;br /&gt;ThreadClass thr1 = new ThreadClass();&lt;br /&gt;ThreadClass thr2 = new ThreadClass();&lt;br /&gt;thr1.start();&lt;br /&gt;thr2.start();&lt;br /&gt;try{&lt;br /&gt;Thread.sleep(5000);&lt;br /&gt;}catch(Exception e){}&lt;br /&gt;//Hacemos que se cierren ordenadamente.&lt;br /&gt;thr1.stopThread();&lt;br /&gt;thr2.stopThread();&lt;br /&gt;}&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Tenemos el método stop() equivalente a Abort() de C#, pero esta deprecated, así que deberíamos crear nuestro propio método para cerrar el hilo. Tras esto ya tenemos nuestro programa funcionando con diferentes hilos.&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh6.ggpht.com/_OESoGgtnthw/S-_SMPwO59I/AAAAAAAAAFU/fAtlbwkILJg/s1600-h/hilos2%5B4%5D.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="hilos2" alt="hilos2" src="http://lh4.ggpht.com/_OESoGgtnthw/S-_SMvH6nxI/AAAAAAAAAFY/6w5K1uB8fLw/hilos2_thumb%5B2%5D.jpg?imgmax=800" width="240" height="180" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;edit&gt; &lt;/edit&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;EDIT:&lt;/span&gt; Dado que Java no permite herencia multiple, el uso de la clase base Thread no esta aconsejado, puesto que si queremos utilizar en otro hilo una clase que ya hereda de algo no podriamos. La solución a esto es implementar la interfaz &lt;span style="font-style: italic;"&gt;Runnable&lt;/span&gt;, siendo por lo demas exactamente igual que heredar de Thread.&lt;br /&gt;&lt;p&gt;¿Que os ha parecido? Siendo sincero, es bastante fácil de hacer en ambos lenguajes, pero definitivamente en caso de tener que escoger definitivamente es mas fácil en C#, pues lo mas intuitivo es lanzar un método cualquiera en un hilo distinto, sin necesidad de crear una clase a parte. Así que esa es mi conclusión. ¡¡Hasta otra y sed buenos cangrejos!! &lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/S-_SNJohvvI/AAAAAAAAAFc/ui3Gy1LMTlU/s1600-h/image%5B4%5D.png"&gt;&lt;img style="border: 0px none; display: inline;" title="image" alt="image" src="http://lh4.ggpht.com/_OESoGgtnthw/S-_SNsY6FUI/AAAAAAAAAFg/pfA2y7bJN_w/image_thumb%5B2%5D.png?imgmax=800" width="48" border="0" height="48" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-149098431276945485?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/149098431276945485/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/05/ejecutando-hilos-comparativa-java-y-c.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/149098431276945485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/149098431276945485'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/05/ejecutando-hilos-comparativa-java-y-c.html' title='Ejecutando Hilos, comparativa Java y C#'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_OESoGgtnthw/S-_SJwqO-6I/AAAAAAAAAFA/kLxzIclpT_k/s72-c/crabiconjava_thumb1.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-2137766980981695318</id><published>2010-05-09T13:23:00.001-07:00</published><updated>2010-05-09T14:33:09.830-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='visual studio'/><category scheme='http://www.blogger.com/atom/ns#' term='drag and drop'/><category scheme='http://www.blogger.com/atom/ns#' term='programación'/><category scheme='http://www.blogger.com/atom/ns#' term='csharp'/><title type='text'>Guía simple: Drag-and-Drop en Windows Forms</title><content type='html'>&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/S-cZsH-dScI/AAAAAAAAAEU/g9DT2CbY1SU/s1600-h/crab-icon%20ball%20c%23%5B4%5D.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px;" title="crab-icon ball c#" alt="crab-icon ball c#" src="http://lh3.ggpht.com/_OESoGgtnthw/S-cZsePKIbI/AAAAAAAAAEY/P2HZG60-gsM/crab-icon%20ball%20c%23_thumb%5B2%5D.png?imgmax=800" align="left" width="48" height="68" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Hoy en The Code Crab vamos a empezar a picar un poco de código, que siendo un blog de programación como que ya va tocando. Vamos a implementar Drag-and-Drop paso a paso, de forma sencilla con un pequeño ejemplo que os podréis descargar, pero no será nada difícil añadirlo a vuestro programas grandes.&lt;/p&gt;  &lt;p&gt;Drag-and-Drop es una propiedad que tienen algunas interfaces graficas que permite mover objetos de un lugar a otro tan solo arrastrándolos con el ratón.&lt;/p&gt;  &lt;p&gt;En mi caso utilizare visual studio 2010, pero esto funciona en cualquier versión de VS sin ningún problema (os dará problemas los archivos de solución quizás, pero el código en principio no). Con esto abrimos el VS, creamos un nuevo proyecto (Aplicación de windows forms en c#) y creamos una interfaz grafica simple para el ejemplo, que constara de dos listBox, aunque con un par de transformaciones el código debería funcionar sin muchos problemas para otros contenedores similares.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/S-cZtB6AFXI/AAAAAAAAAEc/kqWe7Lcx2ms/s1600-h/elefantes1%5B4%5D.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="elefantes1" alt="elefantes1" src="http://lh4.ggpht.com/_OESoGgtnthw/S-cZtqaenLI/AAAAAAAAAEg/S2rccxRYWdo/elefantes1_thumb%5B2%5D.jpg?imgmax=800" width="240" height="207" /&gt;&lt;/a&gt;Es importante que busquéis en  las propiedades de los listBox la propiedad enableDrop y que la pongáis a True, sin esto el programa no funcionara. Después de esto nos metemos a modificar el código (Ver-&amp;gt;Código)&lt;/p&gt;  &lt;p&gt;Aquí tendremos que crear varios métodos para hacer funcionar el Drag-and-Drop. Necesitaremos dos métodos para poder coger objetos de un listBox y otros dos para poder soltar objetos en un listBox. Como queremos que se pueda cojer objetos de ambos vamos a implementar los 4 métodos una vez para cada listBox. No los repetiré por aquí pero si tenéis alguna duda podéis consultar el código que hay al final.&lt;/p&gt;  &lt;p&gt;El primer método se llama Mouse Down, y es el evento que se dispara al pulsar sobre un elemento del listBox. Hace falta para poder sacar objetos de un componente.&lt;/p&gt;  &lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt; /// &lt;summary&gt;&lt;br /&gt;       /// Evento disparado cuando se pincha sobre un objeto de un listBox, se empieza el drag and drop&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       private void listBox1_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)&lt;br /&gt;       {&lt;br /&gt;           int indexOfItem = listBox1.IndexFromPoint(e.X, e.Y);&lt;br /&gt;           //se almacena la posición donde esta colocado el objeto que vamos a mover&lt;br /&gt;           if (indexOfItem &amp;gt;= 0 &amp;amp;&amp;amp; indexOfItem &amp;lt; listBox1.Items.Count)&lt;br /&gt;           {&lt;br /&gt;               //Escojemos que tipo de Drag and Drop queremos. Mi consejo es usar Copia aunque quieras mover, y quitar los objetos&lt;br /&gt;               //manualmente una vez que se pose el objeto, así evitaremos que si el usuario suelta el objeto fuera de un listBox,&lt;br /&gt;               //este se pierda.&lt;br /&gt;               listBox1.DoDragDrop(listBox1.Items[indexOfItem], DragDropEffects.Copy);&lt;br /&gt;           }&lt;br /&gt;       }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;El siguiente método se dispara cuando se suelta un objeto en el mismo componente que se cogió, provocando así una reorganización. Se llama DragOver&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt; &lt;br /&gt; /// &lt;summary&gt;&lt;br /&gt;       /// Evento disparado al soltar un objeto en el mismo sitio donde se ha cojido&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       private void listBox1_DragOver(object sender, System.Windows.Forms.DragEventArgs e)&lt;br /&gt;       {&lt;br /&gt;&lt;br /&gt;           indice =&lt;br /&gt;               listBox1.IndexFromPoint(listBox1.PointToClient(new Point(e.X, e.Y)));&lt;br /&gt;           //Cambiamos el objeto seleccionado de posición, en funcion de donde se suelte&lt;br /&gt;           listBox1.SelectedIndex = indice;&lt;br /&gt; }&lt;br /&gt;           &lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Con esto concluyen los eventos para cojer objetos de un listBox. Ahora vamos con los necesarios para soltar un objeto en un componente, empezamos con DragDrop, evento que se dispara al soltar un objeto en un listBox&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt; /// &lt;summary&gt;&lt;br /&gt;       /// Evento disparado al soltar un objeto en un listBox distinto al que se cojio&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       private void listBox1_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)&lt;br /&gt;       {&lt;br /&gt;           //Podemos cambiar el formato en funcion del objeto que tengamos en listBox.Items, pero hay que tener cuidado&lt;br /&gt;           //por que aunque items acepte cualquier objeto, no hay formatos de Drag and Drop para todo.&lt;br /&gt;           listBox1.Items.Remove(e.Data.GetData(DataFormats.Text));&lt;br /&gt;           if (indice &amp;gt;= 0 &amp;amp;&amp;amp; indice &amp;lt; listBox1.Items.Count)&lt;br /&gt;           {&lt;br /&gt;               //Si se solto en la parte alta se pone el objeto donde corresponde&lt;br /&gt;               listBox1.Items.Insert(indice, e.Data.GetData(DataFormats.Text));&lt;br /&gt;           }&lt;br /&gt;           else&lt;br /&gt;           {&lt;br /&gt;               //Sino se pone en el fondo&lt;br /&gt;               listBox1.Items.Add(e.Data.GetData(DataFormats.Text));&lt;br /&gt;           }&lt;br /&gt;           //quitamos el objeto en el listBox2, para conseguir manualmente el efecto mover (explicado anteriormente)&lt;br /&gt;           listBox2.Items.Remove(e.Data.GetData(DataFormats.Text));&lt;br /&gt;       }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Y por ultimo hacemos un método mas, DragEnter, disparando cuando se entra con el ratón a un listBox arrastrando un objeto&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;       /// Evento disparado al arrastrar un objeto dentro del listBox&lt;br /&gt;       /// &lt;/summary&gt;&lt;br /&gt;       public void listBox1_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)&lt;br /&gt;       {&lt;br /&gt;&lt;br /&gt;           // Cambiamos el cursor del raton para indicar que el objeto arrastrado se puede soltar aquí&lt;br /&gt;           e.Effect = DragDropEffects.Copy;&lt;br /&gt;&lt;br /&gt;       }&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Para que nuestro programa funcione bien debemos tener estos métodos 2 veces, uno para listBox1 y otro para listBox2, con cuidado de cambiar las referencias a estos. Tras esto solo nos queda añadir los eventos a las listBox, que lo haremos en el constructor de la clase, después de la llamada al método InitializeComponent();&lt;/p&gt;&lt;br /&gt;&lt;pre name="code" class="csharp"&gt;&lt;br /&gt;//No hay que olvidarse de agregar todos los metodos que hicimos o no servira de nada&lt;br /&gt;           listBox1.MouseDown += new System.Windows.Forms.MouseEventHandler(listBox1_MouseDown);&lt;br /&gt;           listBox1.DragOver += new System.Windows.Forms.DragEventHandler(listBox1_DragOver);&lt;br /&gt;           listBox1.DragDrop += new System.Windows.Forms.DragEventHandler(listBox1_DragDrop);&lt;br /&gt;           listBox1.DragEnter += new System.Windows.Forms.DragEventHandler(listBox1_DragEnter);&lt;br /&gt;&lt;br /&gt;           listBox2.MouseDown += new System.Windows.Forms.MouseEventHandler(listBox2_MouseDown);&lt;br /&gt;           listBox2.DragOver += new System.Windows.Forms.DragEventHandler(listBox2_DragOver);&lt;br /&gt;           listBox2.DragDrop += new System.Windows.Forms.DragEventHandler(listBox2_DragDrop);&lt;br /&gt;           listBox2.DragEnter += new System.Windows.Forms.DragEventHandler(listBox2_DragEnter);&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Y voila, tras todo esto ya tenemos nuestro programa funcionando con Drag-and-Drop. ¿No ha sido tan difícil, no?&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/S-cZuO-3CyI/AAAAAAAAAEk/v7TbDPA1f9w/s1600-h/elefantes2%5B4%5D.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto;" title="elefantes2" alt="elefantes2" src="http://lh6.ggpht.com/_OESoGgtnthw/S-cZuoR88gI/AAAAAAAAAEo/SPG0Ci3U_CE/elefantes2_thumb%5B2%5D.jpg?imgmax=800" width="240" height="147" /&gt;&lt;/a&gt;Podéis descargar aquí el código fuente en caso de que os halla quedado alguna duda:  &lt;a title="http://www.megaupload.com/?d=GM4O9V65" href="http://www.megaupload.com/?d=GM4O9V65"&gt;http://www.megaupload.com/?d=GM4O9V65&lt;/a&gt;&lt;/p&gt;&lt;br /&gt;&lt;br /&gt;&lt;p&gt;Pues eso es todo por hoy, muchas gracias por leerme y ¡Sed buenos cangrejos!&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/S-cZvDF_1YI/AAAAAAAAAEs/kVIq0dtn1OI/s1600-h/565%5B2%5D.gif"&gt;&lt;img style="border: 0px none; display: inline;" title="565" alt="565" src="http://lh6.ggpht.com/_OESoGgtnthw/S-cZv_Aj9fI/AAAAAAAAAEw/zl2tnUrMx_I/565_thumb.gif?imgmax=800" border="0" width="64" height="64" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-2137766980981695318?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/2137766980981695318/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/05/guia-simple-drag-and-drop-en-windows.html#comment-form' title='1 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/2137766980981695318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/2137766980981695318'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/05/guia-simple-drag-and-drop-en-windows.html' title='Guía simple: Drag-and-Drop en Windows Forms'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_OESoGgtnthw/S-cZsePKIbI/AAAAAAAAAEY/P2HZG60-gsM/s72-c/crab-icon%20ball%20c%23_thumb%5B2%5D.png?imgmax=800' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-3501533103309600444</id><published>2010-05-08T04:06:00.001-07:00</published><updated>2010-05-08T04:06:32.624-07:00</updated><title type='text'>Utilizando librerías dll desde C++</title><content type='html'>&lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/S-VFl_sso3I/AAAAAAAAAC8/Mn_X2j349BM/s1600-h/crab-icon%20cpp%5B7%5D.png"&gt;&lt;img style="display: inline; margin-left: 0px; margin-right: 0px" title="crab-icon cpp" alt="crab-icon cpp" align="left" src="http://lh5.ggpht.com/_OESoGgtnthw/S-VFmt-ttVI/AAAAAAAAADA/093iXO5mMC8/crab-icon%20cpp_thumb%5B5%5D.png?imgmax=800" width="48" height="68" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Bueno, aquí vamos con mi primer post, y para ir a contracorriente no vamos a empezar precisamente con algo fácil. Toca manejarse con &lt;strong&gt;C++&lt;/strong&gt;, ese lenguaje maligno que tiene la habilidad en convertir lo sencillo en complicado (No es mi lenguaje favorito como habréis adivinado).&lt;/p&gt;  &lt;p&gt;Pues en este post vamos a aprender como utilizar desde &lt;strong&gt;C++&lt;/strong&gt; una librería de linkado dinámico, mas conocidas como &lt;strong&gt;dlls&lt;/strong&gt;. En cualquier otro lenguaje hacer esto es el pan de cada día, por ejemplo en C# basta con ir al apartado referencias, click derecho, agregar referencia y ya está. Sin embargo en C++ no es tan sencillo.&lt;/p&gt;  &lt;p&gt;Para este ejemplo utilizaremos Visual Studio 2010, que esta nuevito y recién salido del horno, y no os preocupes si usáis una versión anterior que explicare las diferencias. Y para los aventados, se que utilizar una dll compilando desde línea de comandos no es nada difícil, pero tengo la extraña manía de utilizar IDEs (Lo se, soy terrible).&lt;/p&gt;  &lt;p&gt;Bueno, pues para empezar, por algún motivo C++ no solo utiliza el archivo dll como otros lenguajes, necesitamos el archivo lib asociado y además los archivos .h de todas las clases que compone el dll. Sabiendo esto, creamos nuestro proyecto en Visual Studio, en caso de que no lo tengamos ya y vamos a la carpeta del proyecto. Para tener a mano todo esto que necesitamos crearemos aquí dos carpetas, import y lib, y metemos los archivos .h de la libreria en import y el archivo .lib en la carpeta lib.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/S-VFnFPHksI/AAAAAAAAADE/oeQ5Wkziv-4/s1600-h/shot1%5B9%5D.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="shot1" alt="shot1" src="http://lh4.ggpht.com/_OESoGgtnthw/S-VFn3ELI6I/AAAAAAAAADI/nBshD9f7pKk/shot1_thumb%5B7%5D.jpg?imgmax=800" width="240" height="176" /&gt;&lt;/a&gt;¿Y que hacemos con el archivo dll? Pues la mejor opción será meterlo en una carpeta donde el Linker no tenga problemas para encontrarlo, la mejor opción es&amp;#160; &lt;em&gt;C:\Windows\System32 &lt;/em&gt;donde se encuentran los dll que utilizan otros programas.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/S-VFoaNs3EI/AAAAAAAAADM/wwYj8GS30BM/s1600-h/shot2%5B5%5D.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="shot2" alt="shot2" src="http://lh6.ggpht.com/_OESoGgtnthw/S-VFo9zpP-I/AAAAAAAAADQ/XxUqkHf5rUo/shot2_thumb%5B3%5D.jpg?imgmax=800" width="240" height="183" /&gt;&lt;/a&gt; Tras esto abrimos el Visual Studio, y una vez abrimos el proyecto, vamos a &lt;em&gt;Herramientas-&amp;gt;Opciones&lt;/em&gt; (&lt;em&gt;Tools-&amp;gt;Options&lt;/em&gt; en ingles) y aquí en proyectos y soluciones buscamos &lt;em&gt;Directorios de VC++(VC++ Directories):&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/S-VFpgNXp3I/AAAAAAAAADU/lfaMAfD9s9Y/s1600-h/shot3%5B4%5D.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="shot3" alt="shot3" src="http://lh3.ggpht.com/_OESoGgtnthw/S-VFqIep27I/AAAAAAAAADY/p2W-bnlIKAg/shot3_thumb%5B2%5D.jpg?imgmax=800" width="240" height="139" /&gt;&lt;/a&gt; Ups, ¿Que es esto? Me explicare. Aquí podremos encontrar las opciones de configuración de directorios en versiones mas antiguas de VS, pero por algún motivo en VS 2010 nos encontramos con esto. Puedes pulsar ? todo lo que quieras que no sale ninguna ayuda, y la hoja de propiedades que menciona, yo personalmente no la encuentro por ningún lado. ¿Donde esta esto entonces?&lt;/p&gt;  &lt;p&gt;En el explorador de soluciones, hacemos click derecho en el proyecto y entramos en propiedades, y ahí lo encontramos (¿Que sentido tiene quitar una cosa para dejarla en otro sitio? Aunque no tenia sentido quitarla para empezar, en fin…):&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh3.ggpht.com/_OESoGgtnthw/S-VFqidzMfI/AAAAAAAAADc/Rd9tFUerkpc/s1600-h/shot4%5B4%5D.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="shot4" alt="shot4" src="http://lh3.ggpht.com/_OESoGgtnthw/S-VFqzwi8dI/AAAAAAAAADg/QB3HmDIi8eI/shot4_thumb%5B2%5D.jpg?imgmax=800" width="240" height="170" /&gt;&lt;/a&gt;Aquí en&amp;#160; &lt;em&gt;Include Directories&lt;/em&gt; y en &lt;em&gt;Library Directories &lt;/em&gt;añadimos nuestras carpetas &lt;em&gt;Include&lt;/em&gt; y &lt;em&gt;lib&lt;/em&gt; respectivamente, separándolas de lo que ya hay por ; y intentando no cargarnos nada.&lt;/p&gt;  &lt;p&gt;Tras esto buscamos en la misma pantalla &lt;em&gt;Vinculador-&amp;gt;Entrada(Linker-&amp;gt;Input):&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/S-VFrWhGSqI/AAAAAAAAADk/r_qSzdfN7r8/s1600-h/shot5%5B4%5D.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="shot5" alt="shot5" src="http://lh6.ggpht.com/_OESoGgtnthw/S-VFrwJtbUI/AAAAAAAAADo/v1JRBlE4gSU/shot5_thumb%5B2%5D.jpg?imgmax=800" width="240" height="170" /&gt;&lt;/a&gt;Aquí añadimos en &lt;em&gt;Dependencias Adicionales(Aditional Depencences) &lt;/em&gt;el nombre de nuestro archivo .lib (solo el archivo, sin ruta) y una vez mas separándolo con ; y con cuidado de no cargarnos nada. Le damos a aceptar y &lt;em&gt;¡&lt;/em&gt;V&lt;em&gt;oila!&lt;/em&gt; Si todo ha ido bien nuestro programa ya debería compilar y ejecutar (¡No os olvidéis de poner los include!)&lt;/p&gt;  &lt;p&gt;&lt;a href="http://lh4.ggpht.com/_OESoGgtnthw/S-VFsds51MI/AAAAAAAAADs/G43qio4ImOw/s1600-h/shot6%5B4%5D.jpg"&gt;&lt;img style="display: block; float: none; margin-left: auto; margin-right: auto" title="shot6" alt="shot6" src="http://lh3.ggpht.com/_OESoGgtnthw/S-VFsxDqHYI/AAAAAAAAADw/3v_eJzKcYHw/shot6_thumb%5B2%5D.jpg?imgmax=800" width="240" height="134" /&gt;&lt;/a&gt;¿Conclusiones? Pues yo personalmente creo que esto es algo básico que debería ser muchísimo mas sencillo, y aunque explicado parezca hasta evidente os reto a intentar esto solos sin seguir ningún tutorial (Incluso podéis probar a buscar en google, que lo que yo me encontré no hizo mas que liarme).&lt;/p&gt;  &lt;p&gt;En cuanto a lo de el Visual Studio 2010 de quitar una pantalla de configuración, cambiarla por una hoja de propiedades aparentemente inexistente y sin embargo dejar la pantalla de configuración si se accede desde otro sitio… En fin, corramos un estúpido velo, lo dejare a vuestro criterio.&lt;/p&gt;  &lt;p&gt;Un saludo, y ¡Sed buenos cangrejos! &lt;a href="http://lh5.ggpht.com/_OESoGgtnthw/S-VFtWOuvjI/AAAAAAAAAD0/U77P925-fEw/s1600-h/emoti-crab5%5B2%5D.gif"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="emoti-crab5" border="0" alt="emoti-crab5" src="http://lh5.ggpht.com/_OESoGgtnthw/S-VFt_bwXqI/AAAAAAAAAD4/X9IML5uvzwY/emoti-crab5_thumb.gif?imgmax=800" width="33" height="15" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:74ed301a-f6ef-4b6c-9bd6-9c3e6d1ef40c" class="wlWriterEditableSmartContent"&gt;Etiquetas de Technorati: &lt;a href="http://technorati.com/tags/c%2b%2b" rel="tag"&gt;c++&lt;/a&gt;,&lt;a href="http://technorati.com/tags/cpp" rel="tag"&gt;cpp&lt;/a&gt;,&lt;a href="http://technorati.com/tags/dll" rel="tag"&gt;dll&lt;/a&gt;,&lt;a href="http://technorati.com/tags/programaci%c3%b3n" rel="tag"&gt;programaci&amp;#243;n&lt;/a&gt;,&lt;a href="http://technorati.com/tags/libreria" rel="tag"&gt;libreria&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-3501533103309600444?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/3501533103309600444/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/05/utilizando-librerias-dll-desde-c.html#comment-form' title='2 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/3501533103309600444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/3501533103309600444'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/05/utilizando-librerias-dll-desde-c.html' title='Utilizando librerías dll desde C++'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_OESoGgtnthw/S-VFmt-ttVI/AAAAAAAAADA/093iXO5mMC8/s72-c/crab-icon%20cpp_thumb%5B5%5D.png?imgmax=800' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9153989234387817345.post-1128642684674351091</id><published>2010-05-06T06:39:00.001-07:00</published><updated>2010-05-06T07:29:08.700-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='programacion desarrollo lenguajes'/><title type='text'>Hello World</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_OESoGgtnthw/S-LSLHXcPGI/AAAAAAAAACE/ovLy3XSCqu0/s1600/crab-icon+etc.png"&gt;&lt;img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 48px; height: 68px;" src="http://1.bp.blogspot.com/_OESoGgtnthw/S-LSLHXcPGI/AAAAAAAAACE/ovLy3XSCqu0/s320/crab-icon+etc.png" alt="" id="BLOGGER_PHOTO_ID_5468163985978965090" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Últimamente me he tenido que enfrentar a serios problemas en cuanto a la programación, el principal de ellos el desarrollo de mi proyecto de fin de carrera.&lt;br /&gt;&lt;br /&gt;Con esto me he dado cuenta de la cantidad de cosas que están mal documentadas en cuanto a la programación: Apis insuficiente, blogs con pocos detalles y hablando de versiones de lenguajes realmente atrasadas y posts en foros que hablan y hablan pero no resuelven la duda que preguntan al principio.&lt;br /&gt;&lt;br /&gt;Tras esto me dio por pensar que quizás debiera poner mi grano de arena al mundo de la programación haciendo mi propio blog dedicado a este tema, y actualizarlo con los problemas que me hayan encontrado los cuales sean difíciles de encontrar por internet.&lt;br /&gt;&lt;br /&gt;En este blog se trataran varios lenguajes de programación, pero probablemente me centre en C# y Java, viendo ocasionalmente cosas de C++, C, Ruby y Python. Si con mis posts consigo ayudar a alguien, mi blog habrá cumplido su cometido. ¡Hola Mundo!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9153989234387817345-1128642684674351091?l=codecrab.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://codecrab.blogspot.com/feeds/1128642684674351091/comments/default' title='Enviar comentarios'/><link rel='replies' type='text/html' href='http://codecrab.blogspot.com/2010/05/hello-world.html#comment-form' title='4 comentarios'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/1128642684674351091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9153989234387817345/posts/default/1128642684674351091'/><link rel='alternate' type='text/html' href='http://codecrab.blogspot.com/2010/05/hello-world.html' title='Hello World'/><author><name>Wardamo</name><uri>http://www.blogger.com/profile/00726109849185439898</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://2.bp.blogspot.com/_OESoGgtnthw/S-HPvEr-DNI/AAAAAAAAABI/vFevyDiNXtc/S220/gatoGrande.png'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_OESoGgtnthw/S-LSLHXcPGI/AAAAAAAAACE/ovLy3XSCqu0/s72-c/crab-icon+etc.png' height='72' width='72'/><thr:total>4</thr:total></entry></feed>
