20 de Agosto de 2014
Abr
19

.NET Tutorial 2. Sprites, gráficos y bitmaps (Parte I)

Categorías: 

Pues bien, ha llegado el momento de hacer algo más "vistoso".

En esta entrega vamos a ver como es posible mover un "gráfico" sobre un determinado fondo. Tenemos que tener claro una serie de conceptos:

Background: Será la imagen de fondo de nuestro "juego"
Sprite: Serán todos aquellos elementos (en este ejemplo sólo uno) que pueden "moverse" o con los que el jugador puede interaccionar.

Todo esto lo haremos usando el GDI+ del .NET Framework. Ya habrá tiempo de meterse en camisas de once varas con XNA, OpenGL, DirectX, etc. Obviamente los resultados no son ni por asombro parecidos a usar XNA o similares, tanto en calidad como en rendimiento, pero mi idea es ir paso a paso pero con buena letra ;)

Nuestro "Background":

Nuestro "Sprite":

Resultado: (el sprite se va moviendo por la pantalla)

Para usar el GDI+ tendremos que definir dos cosas:

La superficie del GDI+ y el bitmap asociado a dicha superficie.
Básicamente lo que haremos será "copiar cosas" en el bitmap de la superficie para posteriormente copiar la superficie del GDI+ en algun sitio, por ejemplo en un PictureBox, Formulario, etc.

En este caso en particular copiaremos la superficie del GDI+ en un PictureBox, tal y cómo veremos más tarde.

Dicho esto, empecemos.

Crearemos un nuevo proyecto y en nuestro formulario que se crea por defecto insertaremos un control PictureBox, con el nombre PicRender.
Haremos un poco de "trampa" y estableceremos a mano el ancho y el alto de PicRender, en nuestro caso Size = 800; 600, es decir, 800 pixels de ancho y 600 de alto.

El programa funcionará de la siguiente forma:

  • Se ejecuta el Form_Load ()
  • Se cargan los gráficos de nuestro "Background" y de nuestro "Sprite"
  • Se inicializa un Timer que será el que se encarga de la "lógica" del juego

Dentro del Timer de la "lógica del juego" ocurre lo siguiente:

  • Se calculan las nuevas posiciones de nuestro "Sprite"
  • Se llama al método de "Renderizar" o más bien, dibujar las "cosas"

Finalmente en el método de "Renderizar" ocurre lo siguiente:

  • Copiamos nuestro "Background" al bitmap de la superfice del GDI+
  • Copiamos nuestro "Sprite" en la posición calculada en el Timer de la "lógica del juego" al bitmap de la superficie del GDI+
  • Por último, copiamos el bitmap de la superficie del GDI+ en la propiedad Image de PicRender

 

Las variables  que vamos a usar serán las que muestro a continuación.

Private objRender As Graphics      'Nuestra surperficie pricipal del GDI+
Private objBmpRender As Bitmap  'Bitmap que se copiará en la superficie

Private BackGround As Bitmap    'Bitmap con la imagen de fondo

Private Structure sSprite    'Estructura para los sprites
Dim Imagen As Bitmap  'Bitmap del sprite
Dim Posicion As Point     'Posicion (x,y) del sprite en la pantalla
End Structure

Private miSprite1 As sSprite 
 

Creo que las variables están claras pero hare incapié en la estructura sSprite.

Combiene que os acostumbreis a usar estructuras o en su defecto clases, o que oño, usar estructuras de clases ;)

Trabajar con este tipo de construcciones (estructuras, clases, estructuras/clases) facilita enormemente tanto la compresión del código cómo su mantenimiento. En este ejemplo de apenas 100 lineas quizas no tenga mucha importancia, pero cuando tengais códigos de cientos o incluso miles de lineas ya me contareis, ya ;)

Los gráficos los cargamos de la siguiente forma:

BackGround = Image.FromFile(App_Path() & "bitmaps\background1.jpg")
With miSprite1
.Imagen = Image.FromFile(App_Path() & "bitmaps\glow.png")
End With

Cómo veis no tiene mucho misterio, BackGround y miSprite.Imagen son objetos de tipo Bitmap, pues usamos Image.FromFile para cargar dichos "bitmaps".

Los objetos del GDI+ los inicializamos de la siguiente forma, por ejemplo en el Form_Load () :

objRender = Me.CreateGraphics()
objBmpRender =
New Bitmap(PicRender.Width, PicRender.Height)
objRender = Graphics.FromImage(objBmpRender)

En el timer de la "logica del juego" calculamos la nueva posición del sprite y llamamos a la rutina de Renderizado/dibujado:

With miSprite1
'
aqui se hacen cuatro cuentas para calcular la nueva posición del sprite
End With

Render(objRender)

Y finalmente, la rutina que "pinta" es esta:

Private Sub Render(ByVal g As Graphics)
g.DrawImage(BackGround, 0, 0)
   With miSprite1
g.DrawImage(.Imagen, .Posicion)
   End With
PicRender.Image = objBmpRender
End Sub

 

Pues bien, esto es todo por hoy, que ya es mucho, si teneis alguna duda o comentario, ya sabeis lo que toca ;)

 

Saludos.
mov eax,ollydbg; Int 13h 

 

Descargar proyecto .NET Tutorial 2
(147 KB. Visual Studio 2008)

Tutoriales relaccionados:
.NET Tutorial 3. Sprites, gráficos y bitmaps (Parte II)

5
Valoración media: 5 (3 votos)

2 Comentarios:

Asi que lo unico que

Asi que lo unico que sobreescribes del bitmap es el sprite. Sin embargo, que extensión de archivo usas para las imágenes? Porque yo usaba PNG, tenian parte de fondo transparente, pero al cargarlo se veia ese fondo blanco (vease B-Actualizer) Meh

Salu2, Btc

Cómo puedes ver, utilizo

Cómo puedes ver, utilizo un *.jpg para el fondo y un *.png para el sprite. El formato PNG incorpora lo que se conoce como canal Alpha. Hay formatos que no incorporan dicha característica, cómo por ejemplo el formato BMP o JPG. Gracias al canal Alpha el sprite se ve translucido y totalmente transparente donde el valor del canal Alpha es cero. En el siglo pasado (sí, lees bien ;) ) se utilizaban bloques escritos en ensamblador para decidir que pixels de los sprites eran transparentes. Para ello se decidia que por ejemplo el color fucsia o el verde "fosforito" era el color transparente del sprite. La rutina en ensamblador iba leyendo pixel a pixel la imagen del sprite y si encontraba un pixel con el color fucsia o verde "fosforito" no lo copiaba. De esta forma se podian dibujar sprites con partes "transparentes". Para el tema del canal Alpha era muchisimo más complejo. Por suerte (o desgracia, según se mire) actualmente ya no hay que hacer todo eso de escribir rutinas en ensamblador, ya que podemos cargar directamente un archivo *.PNG, *.TGA o incluso *.GIF (los archivos GIF también permiten definir el color "transparente" del sprite).

 Saludos.