Anterior | Índice | Siguiente
Capítulo 7: Recorrer un Fondo con Teclado (Scrolling Surface)
Lenguaje: C#
Para: VS2003 / VS2005 / VS2008
Por Dark-N: hernaldog@gmail.com
Visita mi Blog


http://darknromhacking.com



Objetivo: A partir de una pantalla chica, vamos a recorrer una imagen mas grande de fondo con el teclado, y que a la vez, se vea una flecha indicando que nos movemos hacia allá.

Lo primero es descargar las 2 imágenes que usaremos (la imagen de fondo y una imagen con 4 flechas):



Estas imágenes las debes dejar en el directorio bin/Debug una vez compilado el proyecto. Ahora el tema es simple ya que lo primero es definir una enumeración con las 4 direcciones posibles:

private enum enumTeclas : int
{
  Up = 0,
  Down = 1,
  Left = 2,
  Right = 3
}

También creamos un arreglo llamado teclas que contendrá los movimientos y cuando se presione el teclado se almacene allí un numero:

private static bool[] teclas = new bool[4];
...
case Key.UpArrow:
  teclas[(int)enumTeclas.Up] = args.Down;
  break;
case Key.DownArrow:
  teclas[(int)enumTeclas.Down] = args.Down;
  break;
...

Debemos tener antes el game-loop la carga de las 2 imágenes:

srf_cursor = new Surface( @"cursor.PNG").Convert(srf_videoScreen, true, false );
srf_cursor.TransparentColor = Color.FromArgb( 255, 255, 255 ); 
srf_fondo = new Surface( @"paisaje.PNG" ).Convert(srf_videoScreen, true, false );

Aquí dejamos transparente el blanco de fondo de la imagen con las flechas (imagen cursor.png), para esto usamos Color.FromArgb(Red=255, Green=255, Blue=255) = Blanco.

Finalmente en el evento Tick creamos 2 Arraylist (un Arraylist es un colección de objetos, a grandes rasgos es parecido a un arreglo pero con mas atributos). El ArrayList puntosFlechaDestino tendrán las posiciones a mover y recanguloFlechaOrigen contendrá el objeto Rectángulo de Sdl.Net con las posiciones de la imagen (flecha) a mostrar de cursor.png.

ArrayList recanguloFlechaOrigen = new ArrayList();
ArrayList puntosFlechaDestino = new ArrayList();

Ahora veamos que pasa cuando presionamos con el teclado la fecha arriba o abajo

...
if( teclas[(int) enumTeclas.Up] )
{
    puntosFlechaDestino.Add( new Point( srf_videoScreen.Width/2 - 50, srf_videoScreen.Height/2 - 150 ));
    recanguloFlechaOrigen.Add( new Rectangle( 0, 0, 95, 95 ));
    if( y > 0 )
        y -= 5;
}

if( teclas[(int) enumTeclas.Down] )
{
    puntosFlechaDestino.Add( new Point( srf_videoScreen.Width/2 - 50, srf_videoScreen.Height/2 + 50 ));
    recanguloFlechaOrigen.Add( new Rectangle( 100, 100, 95, 95 ));
    if( y < srf_fondo.Height - srf_videoScreen.Height )
        y += 5;
}

if( teclas[(int) enumTeclas.Left] )
...

if( teclas[(int) enumTeclas.Right] )
...
Si se presiona arriba:

Se guardan la posiciones a movernos en puntosFlechaDestino tomando el centro de la imagen como referencia y le restamos 50 pixels hacia arriba y 150 de largo.
Dentro de recanguloFlechaOrigen guardamos el rectángulo con las posiciones 0, 0, 95, 95 de la imagen cursor.png
La variable y que maneja el eje Y se resta 5 pixels (si subes con el teclado Y se resta, si bajas Y se sube)

Y así con las otras direcciones.

Finalmente tenemos el render de los objetos, para esto como siempre usamos la propiedad Blit:

srf_videoScreen.Blit( srf_fondo, new Point( 0, 0 ), new Rectangle ( x, y, srf_videoScreen.Width, srf_videoScreen.Height ));

for( int index = 0; index < puntosFlechaDestino.Count; index ++ )
{
   srf_videoScreen.Blit(srf_cursor, (Point) puntosFlechaDestino[index], (Rectangle) recanguloFlechaOrigen[index]);
}

srf_videoScreen.Update();
Con srf_videoScreen.Blit( superficie, punto donde pintar, rectangulo) pintamos la imagen de fondo, pero le delimitamos que no sea completo, sino solo el largo y ancho de la superficie de video solamente. El rectángulo tiene los parámetros x,y que son calculados en el cuadro anterior. Estas variables son las encargadas de dar el efecto que se mueve le fondo.

Con el ciclo For lo que hacemos es pintar tantas veces el cursor como puntosFlechaDestino hayan. De esta forma solo se ve las fechas que corresponde al movimiento. Si presionas derecha, se ve una fecha apuntando a la derecha y a la vez, se mueve la imagen hacia allá.


Código fuente para VS 2003:

/*
  Ejemplo usando SDL.NET 4.0 y VS 2003 con C#
  Lo que haremos ser? un scrolling de una imagen, permitiendo mover el fondo usando el teclado 
  Recomendado usar PNG en vez de JPG o BMP ya que soporta Alpha Channels para aplicar Transparencia
  
  Autor: Dark-N (basado en el codigo de: Egon A. Rath)
  Fecha: 11-05-2009 
*/

using System;
using System.Drawing;
using SdlDotNet;
using SdlDotNet.Sprites;
using System.IO;
using System.Collections;


namespace Scrolling
{

    public class Superficie
    {
        private static Surface srf_videoScreen;
        private static Surface srf_cursor;
        private static Surface srf_fondo;
        private static bool[] teclas = new bool[4];
        private static int x = 0, y = 0;
        

        private enum enumTeclas : int
        {
            Up = 0,
            Down = 1,
            Left = 2,
            Right = 3
        }

        public static void Main()
        {
             
            srf_videoScreen = Video.SetVideoModeWindow(300, 300, 32);    
            Video.WindowCaption = "Scrolling de una Superficie";

            CargaImagenes();

            Events.Quit += new QuitEventHandler(Evento_Salir);
            Events.Tick += new TickEventHandler(Evento_Tick);
            Events.KeyboardDown +=new KeyboardEventHandler(TecladoManejador);
            Events.KeyboardUp +=new KeyboardEventHandler(TecladoManejador);            
            Events.Run();        
        }


        private static void Evento_Salir(object sender, SdlDotNet.QuitEventArgs e)
        {
            Events.QuitApplication();
        }
        

        private static void CargaImagenes()
        {                      
            srf_cursor = new Surface( @"cursor.PNG").Convert(srf_videoScreen, true, false );
            srf_cursor.TransparentColor = Color.FromArgb( 255, 255, 255 ); //Blanco (Red=255, Green=255, Blue=255)
            srf_fondo = new Surface( @"paisaje.PNG" ).Convert(srf_videoScreen, true, false );
        }

        
        private static void TecladoManejador( object sender, KeyboardEventArgs args )
        {
            switch( args.Key )
            {
                case Key.UpArrow:
                    teclas[(int)enumTeclas.Up] = args.Down;
                    break;
                case Key.DownArrow:
                    teclas[(int)enumTeclas.Down] = args.Down;
                    break;
                case Key.LeftArrow:
                    teclas[(int)enumTeclas.Left] = args.Down;
                    break;
                case Key.RightArrow:
                    teclas[(int)enumTeclas.Right] = args.Down;
                    break;
                case Key.Escape:
                    Events.QuitApplication();
                    break;
            }
        }


        private static void Evento_Tick( object sender, TickEventArgs args )
        {
            ArrayList recanguloFlechaOrigen = new ArrayList();
            ArrayList puntosFlechaDestino = new ArrayList();
            
            if( teclas[(int) enumTeclas.Up] )
            {
                puntosFlechaDestino.Add( new Point( srf_videoScreen.Width/2 - 50, srf_videoScreen.Height/2 - 150 ));
                recanguloFlechaOrigen.Add( new Rectangle( 0, 0, 95, 95 ));
                if( y > 0 )
                    y -= 5;
            }

            if( teclas[(int) enumTeclas.Down] )
            {
                puntosFlechaDestino.Add( new Point( srf_videoScreen.Width/2 - 50, srf_videoScreen.Height/2 + 50 ));
                recanguloFlechaOrigen.Add( new Rectangle( 100, 100, 95, 95 ));
                if( y < srf_fondo.Height - srf_videoScreen.Height )
                    y += 5;
            }

            if( teclas[(int) enumTeclas.Left] )
            {
                puntosFlechaDestino.Add( new Point( srf_videoScreen.Width/2 - 150, srf_videoScreen.Height/2 - 50 ));
                recanguloFlechaOrigen.Add( new Rectangle( 0, 100, 95, 95 ));
                if( x > 0 )
                    x -= 5;
            }

            if( teclas[(int) enumTeclas.Right] )
            {
                puntosFlechaDestino.Add( new Point( srf_videoScreen.Width / 2 + 50, srf_videoScreen.Height / 2 - 50 ));
                recanguloFlechaOrigen.Add( new Rectangle( 100, 0, 95, 95 ));
                if( x < srf_fondo.Width - srf_videoScreen.Width )
                    x += 5;
            }        
        

            //Mostramos imagen de fondo (la seccion que que alcanza a verse)
            srf_videoScreen.Blit( srf_fondo, new Point( 0, 0 ), new Rectangle ( x, y, srf_videoScreen.Width, srf_videoScreen.Height ));

            //Mostramos cursor. (la seccion del cursor ya que se saca una parte de la imagen para mostrar 1 de las 4 direcciones)
            for( int index = 0; index < puntosFlechaDestino.Count; index ++ )
            {
                srf_videoScreen.Blit(srf_cursor, (Point) puntosFlechaDestino[index], (Rectangle) recanguloFlechaOrigen[index]);
            }            

            srf_videoScreen.Update();
        }
    }
}



Código fuente para VS 2005/2008. Antes recuerda:
  • Agregar las referencias: SDL.Net 6.0 y System.Drawing.
  • En las propiedades del Proyecto, en Output Type dejarlo como Windows Application
  • Copiar las imagenes que coloqué en la carpeta bin/Debug del proyecto.

    //Archivo: Superficie.cs
    //Autor: Dark-N (basado en el codigo de: Egon A. Rath)
    //fecha: 25-05-2009
    
    using System;
    using System.Collections.Generic; //para eventos y otras cosas
    using System.Collections; //para ArrayList
    using System.Drawing; //colores
    
    using SdlDotNet.Graphics; //para sprites y surfaces
    using SdlDotNet.Core; //Eventos
    using SdlDotNet.Input; //keyborad
    namespace ScrollingSurface
    {
        public class Superficie
        {
            private static Surface srf_videoScreen;
            private static Surface srf_cursor;
            private static Surface srf_fondo;
            private static bool[] teclas = new bool[4];
            private static int x = 0, y = 0;
    
            private enum enumTeclas : int
            {
                Up = 0,
                Down = 1,
                Left = 2,
                Right = 3
            }
    
            public static void Main()
            {
    
                srf_videoScreen = Video.SetVideoMode(320, 280, false, false, false, true);
                Video.WindowCaption = "Scrolling de una Superficie";
    
                CargaImagenes();
    
                SdlDotNet.Core.Events.KeyboardDown += new EventHandler < KeyboardEventArgs >(Evento_Teclado);
                SdlDotNet.Core.Events.KeyboardUp += new EventHandler < KeyboardEventArgs >(Evento_Teclado);
                SdlDotNet.Core.Events.Tick += new EventHandler < TickEventArgs >(Evento_Tick);
                SdlDotNet.Core.Events.Quit += new EventHandler < QuitEventArgs >(Evento_Salir);
                Events.Run();        
            }
    
    
            private static void CargaImagenes()
            {
                srf_cursor = new Surface(@"cursor.PNG").Convert(srf_videoScreen, true, false);
                srf_cursor.Transparent = true;
                srf_cursor.TransparentColor = Color.FromArgb(255, 255, 255); //Blanco (Red=255, Green=255, Blue=255)
                srf_fondo = new Surface(@"paisaje.PNG").Convert(srf_videoScreen, true, false);
            }
    
            private static void Evento_Salir(object sender, QuitEventArgs e)
            {
                Events.QuitApplication();
            }
    
            private static void Evento_Teclado( object sender, KeyboardEventArgs args )
            {
                switch( args.Key )
                {
                    case Key.UpArrow:
                        teclas[(int)enumTeclas.Up] = args.Down;
                        break;
                    case Key.DownArrow:
                        teclas[(int)enumTeclas.Down] = args.Down;
                        break;
                    case Key.LeftArrow:
                        teclas[(int)enumTeclas.Left] = args.Down;
                        break;
                    case Key.RightArrow:
                        teclas[(int)enumTeclas.Right] = args.Down;
                        break;
                    case Key.Escape:
                        Events.QuitApplication();
                        break;
                }          
            }
    
            private static void Evento_Tick(object sender, TickEventArgs args)
            {
                ArrayList recanguloFlechaOrigen = new ArrayList();
                ArrayList puntosFlechaDestino = new ArrayList();
    
                if (teclas[(int)enumTeclas.Up])
                {
                    puntosFlechaDestino.Add(new Point(srf_videoScreen.Width / 2 - 50, srf_videoScreen.Height / 2 - 150));
                    recanguloFlechaOrigen.Add(new Rectangle(0, 0, 95, 95));
                    if (y > 0)
                        y -= 5;
                }
    
                if (teclas[(int)enumTeclas.Down])
                {
                    puntosFlechaDestino.Add(new Point(srf_videoScreen.Width / 2 - 50, srf_videoScreen.Height / 2 + 50));
                    recanguloFlechaOrigen.Add(new Rectangle(100, 100, 95, 95));
                    if (y < srf_fondo.Height - srf_videoScreen.Height)
                        y += 5;
                }
    
                if (teclas[(int)enumTeclas.Left])
                {
                    puntosFlechaDestino.Add(new Point(srf_videoScreen.Width / 2 - 150, srf_videoScreen.Height / 2 - 50));
                    recanguloFlechaOrigen.Add(new Rectangle(0, 100, 95, 95));
                    if (x > 0)
                        x -= 5;
                }
    
                if (teclas[(int)enumTeclas.Right])
                {
                    puntosFlechaDestino.Add(new Point(srf_videoScreen.Width / 2 + 50, srf_videoScreen.Height / 2 - 50));
                    recanguloFlechaOrigen.Add(new Rectangle(100, 0, 95, 95));
                    if (x < srf_fondo.Width - srf_videoScreen.Width)
                        x += 5;
                }
    
                srf_videoScreen.Blit(srf_fondo, new Point(0, 0), new Rectangle(x, y, srf_videoScreen.Width, srf_videoScreen.Height));
    
                for (int index = 0; index < puntosFlechaDestino.Count; index++)
                {
                    srf_videoScreen.Blit(srf_cursor, (Point)puntosFlechaDestino[index], (Rectangle)recanguloFlechaOrigen[index]);
                }
    
                srf_videoScreen.Update();
            }
        }
    }
    
    

    Una vez codificado, si al compilar no arroja errores, debe aparecerte algo como esto:



    Bajar proyecto para VS 2003 desde aquí.

    Bajar proyecto para VS 2008 desde aquí.

    Anterior | Índice | Siguiente
    Volver a Página Principal

    blog comments powered by Disqus
    2003 - 2018    La Web de Dark-N