- Cuando nos toca un enemigo, ¿perdemos una vida o parte de la energía?
- ¿El enemigo muere también cuando nos toca?
- ¿Cuando se cambia de nivel? ¿Hay que recoger todos los premios? ¿Llegar a alguna puerta?
- ¿Hay tiempo límite para acabar de recorrer un nivel? ¿Al agotar el tiempo perdemos una vida o toda la partida?
- ...
24 diciembre 2010
Creando un juego más modular usando C# y Tao.SDL
04 noviembre 2010
Compilar C# con Geany en Windows
- En Editar / Preferencias / Editor / Sangría: ancho 4 o 2, pero siempre relleno con Espacios en vez de Tabulaciones.
- En Editar / Preferencias / Editor / Mostrar: marcador de líneas largas activado, en la columna 80, para que no descuadre al imprimir; si uso fuentes antiguos o de otros programadores, que quizá usen el carácter de tabulación en vez de espacios, marcaría también la opción de "Mostrar espacio en blanco".
- También me parece cómodo que se cambien tabulaciones por espacios de forma automática y que se borren los espacios al final de cada línea cada vez que se guarda un fichero, algo que se puede conseguir desde Editar / Preferencias / Archivos
23 octubre 2010
El bucle de juego
- Comprobar eventos (pulsaciones de teclas, clics o movimiento de ratón, uso de joystick...)
- Mover los elementos del juego (personaje, enemigos, fondos móviles)
- Comprobar colisiones entre elementos del juego (que pueden suponer perder vidas o energía, ganar puntos, etc)
- Dibujar todos los elementos en pantalla en su estado actual
- Hacer una pausa al final de cada "fotograma", para que la velocidad del juego sea la misma en cualquier ordenador, y, de paso, para ayudar a la multitarea del sistema operativo.
/*---------------------------*/
/* sdl05.cs */
/* */
/* Quinto acercamiento */
/* a SDL */
/* */
/* Por Nacho Cabanes */
/*---------------------------*/
using Tao.Sdl;
using System; // Para IntPtr (puntero: imágenes, etc)
public class Juego
{
short anchoPantalla = 800;
short altoPantalla = 600;
bool terminado = false;
short x = 400;
short y = 300;
short anchoImagen = 50;
short altoImagen = 50;
Sdl.SDL_Event suceso;
int numkeys;
byte[] teclas;
IntPtr pantallaOculta;
IntPtr tipoDeLetra;
IntPtr imagen;
void inicializar()
{
int bitsColor = 24;
int flags = Sdl.SDL_HWSURFACE | Sdl.SDL_DOUBLEBUF | Sdl.SDL_ANYFORMAT
| Sdl.SDL_FULLSCREEN;
// Inicializamos SDL
Sdl.SDL_Init(Sdl.SDL_INIT_EVERYTHING);
pantallaOculta = Sdl.SDL_SetVideoMode(
anchoPantalla,
altoPantalla,
bitsColor,
flags);
// Y SdlTTF, para escribir texto
SdlTtf.TTF_Init();
// Indicamos que se recorte lo que salga de la pantalla oculta
Sdl.SDL_Rect rect2 =
new Sdl.SDL_Rect(0,0, (short) anchoPantalla, (short) altoPantalla);
Sdl.SDL_SetClipRect(pantallaOculta, ref rect2);
// Cargamos una imagen
imagen = SdlImage.IMG_Load("personaje.png");
if (imagen == IntPtr.Zero) {
System.Console.WriteLine("Imagen inexistente: personaje.png!");
Environment.Exit(4);
}
// Y un tipo de letra, en tamano 18
tipoDeLetra = SdlTtf.TTF_OpenFont("FreeSansBold.ttf", 18);
if (tipoDeLetra == IntPtr.Zero) {
System.Console.WriteLine("Tipo de letra inexistente: FreeSansBold.ttf!");
Environment.Exit(5);
}
}
void comprobarTeclas()
{
// Comprobamos sucesos
Sdl.SDL_PollEvent(out suceso);
teclas = Sdl.SDL_GetKeyState(out numkeys);
// Miramos si se ha pulsado alguna flecha del cursor
if (teclas[Sdl.SDLK_UP] == 1)
y -= 2;
if (teclas[Sdl.SDLK_DOWN] == 1)
y += 2;
if (teclas[Sdl.SDLK_LEFT] == 1)
x -= 2;
if (teclas[Sdl.SDLK_RIGHT] == 1)
x += 2;
if (teclas[Sdl.SDLK_ESCAPE] == 1)
terminado = true;
}
void comprobarColisiones()
{
// Todavia no comprobamos colisiones con enemigos
// ni con obstaculos
}
void moverElementos()
{
// Todavia no hay ningun elemento que se mueva solo
}
void dibujarElementos()
{
// Borramos pantalla
Sdl.SDL_Rect origen = new Sdl.SDL_Rect(0,0,
anchoPantalla,altoPantalla);
Sdl.SDL_FillRect(pantallaOculta, ref origen, 0);
// Dibujamos la imagen en sus nuevas coordenadas
dibujarImagenOculta(imagen,x,y, anchoImagen, altoImagen);
// Escribimos el texto, como imagen
escribirTextoOculta("Texto de ejemplo",
/* Coordenadas */ 200,100,
/* Colores */ 50, 50, 255,
tipoDeLetra
);
// Mostramos la pantalla oculta
Sdl.SDL_Flip(pantallaOculta);
}
void pausaFotograma()
{
// Esperamos 20 ms
System.Threading.Thread.Sleep( 20 );
}
void dibujarImagenOculta(IntPtr imagen, short x, short y,
short ancho, short alto)
{
Sdl.SDL_Rect origen = new Sdl.SDL_Rect(0, 0, ancho, alto);
Sdl.SDL_Rect dest = new Sdl.SDL_Rect(x, y, ancho, alto);
Sdl.SDL_BlitSurface(imagen, ref origen, pantallaOculta, ref dest);
}
void escribirTextoOculta(string texto,
short x, short y, byte r, byte g, byte b, IntPtr fuente)
{
// Creamos una imagen a partir de ese texto
Sdl.SDL_Color color = new Sdl.SDL_Color(r, g, b);
IntPtr textoComoImagen = SdlTtf.TTF_RenderText_Solid(
fuente, texto, color);
if (textoComoImagen == IntPtr.Zero){
System.Console.WriteLine("No se puedo renderizar el texto");
Environment.Exit(6);
}
dibujarImagenOculta(textoComoImagen, x,y, (short) (800-x), (short) (600-y));
}
bool partidaTerminada()
{
return terminado;
}
private static void Main()
{
Juego j = new Juego();
j.inicializar();
// Bucle de juego
do {
j.comprobarTeclas();
j.moverElementos();
j.comprobarColisiones();
j.dibujarElementos();
j.pausaFotograma();
} while (! j.partidaTerminada() );
// Finalmente, cerramos SDL
Sdl.SDL_Quit();
}
}
19 octubre 2010
Imágenes PNG y JPG con Tao.SDL
imagen = SdlImage.IMG_Load("personaje.png");
13 octubre 2010
Fuentes TTF con SDL y C#
Debemos incluir el fichero DLL llamado SDL_ttf.DLL en la carpeta del ejecutable de nuestro programa, así como el fichero TTF correspondiente a cada tipo de letra que queramos usar.
Tenemos que declarar un nuevo dato que será nuestro tipo de letra, del tipo genérico "IntPtr":
IntPtr tipoDeLetra;
También tenemos que inicializar SdlTtf después de la inicialización básica de SDL:
SdlTtf.TTF_Init();
Luego preparamos el tipo de letra que queremos usar, indicando a partir de qué fichero TTF y en qué tamaño:
// Un tipo de letra, en tamano 18
tipoDeLetra = SdlTtf.TTF_OpenFont("FreeSansBold.ttf", 18);
if (tipoDeLetra == IntPtr.Zero) {
System.Console.WriteLine("Tipo de letra inexistente: FreeSansBold.ttf!");
Environment.Exit(5);
}
A continuación, podemos crear una imagen a partir de una frase:
// Y creamos una imagen a partir de ese texto
Sdl.SDL_Color colorAzulIntenso = new Sdl.SDL_Color(50, 50, 255);
string texto = "Texto de ejemplo";
IntPtr textoComoImagen = SdlTtf.TTF_RenderText_Solid(
tipoDeLetra, texto, colorAzulIntenso);
if (textoComoImagen == IntPtr.Zero) {
System.Console.WriteLine("No se puedo renderizar el texto");
Environment.Exit(6);
}
Y podríamos dibujar esa imagen en cualquier parte de la pantalla, como cualquier otra imagen:
// Escribimos el texto, como imagen
origen = new Sdl.SDL_Rect(0,0,anchoPantalla,altoPantalla);
dest = new Sdl.SDL_Rect(200,100,anchoPantalla,altoPantalla);
Sdl.SDL_BlitSurface(textoComoImagen, ref origen,
pantallaOculta, ref dest);
Como esta forma de trabajar puede resultar engorrosa, dentro de poco lo mejoraremos, creando una clase "Fuente" que nos oculte todos estos detalles y nos permita escribir texto de forma sencilla.
11 octubre 2010
C#: Una imagen que se mueve con el teclado
/* Ejemplo de acceso a SDL
desde C# (2),
usando Tao.SDL
Por Nacho Cabanes
*/
using Tao.Sdl;
using System; // Para IntPtr (puntero: imágenes, etc)
public class Sdl02
{
private static void Main()
{
short anchoPantalla = 800;
short altoPantalla = 600;
int bitsColor = 24;
int flags = Sdl.SDL_HWSURFACE | Sdl.SDL_DOUBLEBUF | Sdl.SDL_ANYFORMAT
| Sdl.SDL_FULLSCREEN;
IntPtr pantallaOculta;
// Inicializamos SDL
Sdl.SDL_Init(Sdl.SDL_INIT_EVERYTHING);
pantallaOculta = Sdl.SDL_SetVideoMode(
anchoPantalla,
altoPantalla,
bitsColor,
flags);
// Indicamos que se recorte lo que salga de la pantalla oculta
Sdl.SDL_Rect rect2 =
new Sdl.SDL_Rect(0,0, (short) anchoPantalla, (short) altoPantalla);
Sdl.SDL_SetClipRect(pantallaOculta, ref rect2);
// Cargamos una imagen
IntPtr imagen;
imagen = Sdl.SDL_LoadBMP("personaje.bmp");
if (imagen == IntPtr.Zero) {
System.Console.WriteLine("Imagen inexistente!");
Environment.Exit(4);
}
// Parte repetitiva
bool terminado = false;
short x = 400;
short y = 300;
short anchoImagen = 50;
short altoImagen = 50;
Sdl.SDL_Event suceso;
int numkeys;
byte[] teclas;
do
{
// Comprobamos sucesos
Sdl.SDL_PollEvent(out suceso);
teclas = Sdl.SDL_GetKeyState(out numkeys);
// Miramos si se ha pulsado alguna flecha del cursor
if (teclas[Sdl.SDLK_UP] == 1)
y -= 2;
if (teclas[Sdl.SDLK_DOWN] == 1)
y += 2;
if (teclas[Sdl.SDLK_LEFT] == 1)
x -= 2;
if (teclas[Sdl.SDLK_RIGHT] == 1)
x += 2;
if (teclas[Sdl.SDLK_ESCAPE] == 1)
terminado = true;
// Borramos pantalla
Sdl.SDL_Rect origen = new Sdl.SDL_Rect(0,0,
anchoPantalla,altoPantalla);
Sdl.SDL_FillRect(pantallaOculta, ref origen, 0);
// Dibujamos en sus nuevas coordenadas
origen = new Sdl.SDL_Rect(0,0,anchoImagen,altoImagen);
Sdl.SDL_Rect dest = new Sdl.SDL_Rect(x,y,
anchoImagen,altoImagen);
Sdl.SDL_BlitSurface(imagen, ref origen,
pantallaOculta, ref dest);
// Mostramos la pantalla oculta
Sdl.SDL_Flip(pantallaOculta);
// Y esperamos 20 ms
System.Threading.Thread.Sleep( 20 );
} while (!terminado);
// Finalmente, cerramos SDL
Sdl.SDL_Quit();
}
}
- Al inicializar, añadimos una nueva opción, Sdl.SDL_FULLSCREEN, para que el "juego" se ejecute a pantalla completa, en vez de hacerlo en ventana.
- Usamos un bucle "do...while" para repetir hasta que se pulse la tecla ESC.
- SDL_Event es el tipo de datos que se usa para comprobar "sucesos", como pulsaciones de teclas, o de ratón, o el uso del joystick.
- Con SDL_PollEvent forzamos a que se mire qué sucesos hay pendientes de analizar.
- SDL_GetkeyState obtenemos un array que nos devuelve el estado actual de cada tecla. Luego podemos mirar cada una de esas teclas accediendo a ese array con el nombre de la tecla en inglés, así: teclas[Sdl.SDLK_RIGHT]
- SDL_FillRect rellena un rectángulo con un cierto color. Es una forma sencilla de borrar la pantalla o parte de ésta.
13 septiembre 2010
Juegos con C# usando SDL
SDL es una conocida biblioteca para la realización de juegos, que está disponible para diversos sistemas operativos y que permite tanto dibujar imágenes como comprobar el teclado, el ratón o el joystick, así como reproducir sonidos.
Tao.SDL es una adaptación de esta librería, que permite emplearla desde C#. Se puede descargar desde http://www.mono-project.com/Tao
SDL no es una librería especialmente sencilla, y tampoco lo acaba de ser Tao.SDL, así que los fuentes siguientes pueden resultar difíciles de entender, a pesar de realizar tareas muy básicas. Por eso, muchas veces es preferible "ocultar" los detalles de SDL creando nuestras propias clases "Hardware", "Imagen", etc. Lo haremos más adelante, pero de momento v
amos a ver un primer ejemplo, básico pero completo, que muestre cómo entrar a modo gráfico, cargar una imagen, dibujarla en pantalla, esperar cinco segundos y volver al sistema operativo. Tras el fuente comentaré las principales funciones.
/* Ejemplo de acceso a SDL
desde C# (1),
usando Tao.SDL
Por Nacho Cabanes
*/
using Tao.Sdl;
using System; // Para IntPtr (puntero: imágenes, etc)
public class Juego
{
private static void Main()
{
short ancho = 800;
short alto = 600;
int bitsColor = 24;
int flags = (Sdl.SDL_HWSURFACE|Sdl.SDL_DOUBLEBUF|Sdl.SDL_ANYFORMAT);
IntPtr pantallaOculta;
// Inicializamos SDL
Sdl.SDL_Init(Sdl.SDL_INIT_EVERYTHING);
pantallaOculta = Sdl.SDL_SetVideoMode(
ancho,
alto,
bitsColor,
flags);
// Indicamos que se recorte lo que salga de la pantalla oculta
Sdl.SDL_Rect rect2 =
new Sdl.SDL_Rect(0,0, (short) ancho, (short) alto);
Sdl.SDL_SetClipRect(pantallaOculta, ref rect2);
// Cargamos una imagen
IntPtr imagen;
imagen = Sdl.SDL_LoadBMP("personaje.bmp");
if (imagen == IntPtr.Zero) {
System.Console.WriteLine("Imagen inexistente!");
Environment.Exit(4);
}
// Dibujamos la imagen
short x = 400;
short y = 300;
Sdl.SDL_Rect origen = new Sdl.SDL_Rect(0,0,ancho,alto);
Sdl.SDL_Rect dest = new Sdl.SDL_Rect(x,y,ancho,alto);
Sdl.SDL_BlitSurface(imagen, ref origen, pantallaOculta, ref dest);
// Mostramos la pantalla oculta
Sdl.SDL_Flip(pantallaOculta);
// Y esperamos 5 segundos
System.Threading.Thread.Sleep( 5000 );
// Finalmente, cerramos SDL
Sdl.SDL_Quit();
}
}
Algunas ideas básicas:
· SDL_Init es la rutina de inicialización, que entra a modo gráfico, con cierto ancho y alto de pantalla, cierta cantidad de colores y ciertas opciones adicionales.
· El tipo SDL_Rect define un "rectángulo" a partir de su origen (x e y), su ancho y su alto, y se usa en muchas operaciones.
· SDL_SetClipRect indica la zona de recorte (clipping) del tamaño de la pantalla, para que no tengamos que preocuparnos por si dibujamos una imagen parcialmente (o completamente) fuera de la pantalla visible.
· SDL_LoadBMP carga una imagen en formato BMP (si sólo usamos SDL "puro", no podremos emplear otros tipos que permitan menores tamaños, como el JPG, o transparencia, como el PNG). El tipo de dato que se obtiene es un "IntPtr" (del que no daemos más detalles), y la forma de comprobar si realmente se ha podido cargar la imagen es mirando si el valor obtenido es IntPtr.Zero (y en ese caso, no se habría podido cargar) u otro distinto (y entonces la imagen se habría leido sin problemas).
· SDL_BlitSurface vuelca un rectángulo (SDL_Rect) sobre otro, y lo usamos para ir dibujando todas las imágenes en una pantalla oculta, y finalmente volcar toda esa pantalla oculta a la pantalla visible, con lo que se evitan parpadeos (es una técnica que se conoce como "doble buffer").
· SDL_Flip vuelca esa pantalla oculta a la pantalla visible (el paso final de ese "doble buffer").
· Para la pausa no hemos usado ninguna función de SDL, sino Thread.Sleep, que ya habíamos comentado en el apartado sobre temporización.
· SDL_Quit libera los recursos (algo que generalmente haríamos desde un destructor).
Para compilar este ejemplo usando Mono, deberemos:
· Teclear (o copiar y pegar) el fuente.
· Copiar en la misma carpeta los ficheros DLL (Tao.Sdl.Dll y SDL.Dll) y las imágenes (en este caso, "personaje.bmp").
· Compilar con:
mcs sdl01.cs /r:Tao.Sdl.dll
Y si empleamos Visual Studio o SharpDevelop, tendremos que:
· Crear un proyecto de "aplicación de consola".
· Reemplazar nuestro programa principal por éste.
· Copiar el fichero Tao.Sdl.Dll a la carpeta de fuentes, y añadirlo a las referencias del proyecto (normalmente, pulsando el botón derecho del ratón en la vista de clases del proyecto y escogiendo la opción "Agregar referencia").
· Copiar en la carpeta de ejecutables (típicamente bin/debug) los ficheros DLL (Tao.Sdl.Dll y SDL.Dll) y las imágenes (en este caso, "personaje.bmp").
· Compilar y probar.
Si no vamos a usar imágenes comprimidas (PNG o JPG), ni tipos de letra TTF, ni sonidos en formato MP3, ni funciones adicionales de dibujo (líneas, recuadros, círculos, etc)., no necesitaremos ninguna DLL adicional.
Puedes descargar el fuente y el ejecutable, con las DLL y un personaje de ejemplo, aquí:
http://www.nachocabanes.com/fich/descargar.php?nombre=csharp_sdl_01.zip
05 julio 2010
SQLite, C# y DataGridView
1: private void ActualizarListaCiudades()
2: {
3: conexion =
4: new SQLiteConnection
5: ("Data Source=personal.sqlite;Version=3;New=False;Compress=True;");
6: conexion.Open();
7:
8: // Lanzamos la consulta y preparamos la estructura para leer datos
9: string consulta = "select * from ciudad";
10:
11: // Adaptador de datos, DataSet y tabla
12: SQLiteDataAdapter db = new SQLiteDataAdapter(consulta, conexion);
13: DataSet ds = new DataSet();
14: ds.Reset();
15: DataTable dt = new DataTable();
16: db.Fill(ds);
17:
18: //Asigna al DataTable la primer tabla (ciudades)
19: // y la mostramos en el DataGridView
20: dt = ds.Tables[0];
21: dataGridView1.DataSource = dt;
22:
23: // Y ya podemos cerrar la conexion
24: conexion.Close();
25: }
25 junio 2010
SQLite con C# desde Windows Forms
- Crear un nuevo proyecto, que sea una "Aplicación de Windows Forms"
- En la ventana principal, añadir un ListView y un botón.
- Personalizar el ListView usando la pestaña de propiedades, de modo que tenga dos columnas (una para el código y otra para el nombre), y que como modo de visualización ("View") tenga el de "detalles" ("Details").
- Crear una segunda ventana, desde el menú "Proyecto", en la opción "Agregar Windows Forms".
- Añadir a esa ventana dos TextBox para los textos que introducirá el usuario, junto con sus Label para los textos aclaratorios y un botón para confirmar.
- Añadir el fichero DLL a las referencias del proyecto (en la ventana del "Explorador de soluciones", pulsando el botón derecho sobre "References", y escogiendo el fichero System.Data.SQLite.DLL desde la pestaña "Examinar").
- Completar el código fuente del proyecto.
1: private void ActualizarListaCiudades()
2: {
3: conexion =
4: new SQLiteConnection
5: ("Data Source=personal.sqlite;Version=3;New=False;Compress=True;");
6: conexion.Open();
7:
8: lstCiudades.Items.Clear();
9:
10: // Lanzamos la consulta y preparamos la estructura para leer datos
11: string consulta = "select * from ciudad";
12: SQLiteCommand cmd = new SQLiteCommand(consulta, conexion);
13: SQLiteDataReader datos = cmd.ExecuteReader();
14: // Leemos los datos de forma repetitiva
15: while (datos.Read())
16: {
17: string codigo = Convert.ToString(datos[0]);
18: string nombre = Convert.ToString(datos[1]);
19: // Y los mostramos
20: ListViewItem item = new ListViewItem(codigo);
21: item.SubItems.Add(nombre);
22: lstCiudades.Items.Add(item);
23: }
24: conexion.Close();
25: }
1: private void InsertarDatos(string codigo, string nombre)
2: {
3:
4: string insercion; // Orden de insercion, en SQL
5: SQLiteCommand cmd; // Comando de SQLite
6:
7: conexion =
8: new SQLiteConnection
9: ("Data Source=personal.sqlite;Version=3;New=False;Compress=True;");
10: conexion.Open();
11:
12: try
13: {
14: insercion = "INSERT INTO ciudad " +
15: "VALUES ('"+codigo+"','"+nombre+"');";
16: cmd = new SQLiteCommand(insercion, conexion);
17: cmd.ExecuteNonQuery();
18: }
19: catch (Exception e)
20: {
21: MessageBox.Show(
22: "No se ha podido insertar. Posiblemente un codigo esta repetido",
23: "Aviso");
24: }
25: conexion.Close();
26: }
De modo que la acción completa sobre el botón de "Añadir" sería algo como
1: private void btAnadir_Click(object sender, EventArgs e)
2: {
3: ventanaAnadir.Limpiar();
4: ventanaAnadir.ShowDialog();
5: InsertarDatos(ventanaAnadir.GetCodigo(), ventanaAnadir.GetNombre());
6: ActualizarListaCiudades();
7: }
Y aquí puedes descargar el proyecto, con los dos fuentes, los ficheros DLL y el ejecutable: csharp_sqlite2.zip
13 junio 2010
SQLite desde C#
Desde C# no puede usar la DLL de SQLite directamente, pero sí a través de otras como System.Data.Sqlite.Dll, que se puede encontrar en
http://sqlite.phxsoftware.com/
Con esa DLL, junto con la original de SQLite, podremos hacer programas en C# que nos permitan acceder a bases de datos y que sean fáciles de distribuir. SQLite se puede encontrar en
http://www.sqlite.org/
Vamos a ver un pequeño ejemplo de cómo crear una base de datos, cómo introducir datos y cómo mostrarlos. Primero veremos los fragmentos de código, luego un fuente completo, después cómo compilarlo y probarlo, y finalmente incluiré la descarga completa, con fuentes, ejecutable y DLLs.
Para conectar con la base de datos, crearíamos un objeto de tipo "SQLiteConnection":
conexion =
new SQLiteConnection
("Data Source=personal.sqlite;Version=3;New=True;Compress=True;");
conexion.Open();
Para consultas de creación y modificación, crearemos un objeto de tipo SQLiteCommand y lo ejecutaremos con "ExecuteNonQuery()":
string creacion = "CREATE TABLE ciudad "
+"(codigo VARCHAR(2) PRIMARY KEY, nombre VARCHAR(30));";
SQLiteCommand cmd = new SQLiteCommand(creacion, conexion);
cmd.ExecuteNonQuery();
Si se trata de una consulta que sí devuelve datos (un "select"), usaremos "ExecuteReader()" y leeremos datos de forma repetitiva con "while (datos.Read())"
string consulta = "select * from ciudad";
SQLiteCommand cmd = new SQLiteCommand(consulta, conexion);
SQLiteDataReader datos = cmd.ExecuteReader();
// Leemos los datos de forma repetitiva
while (datos.Read())
{
string codigo = Convert.ToString(datos[0]);
string nombre = Convert.ToString(datos[1]);
// Y los mostramos
Console.WriteLine("Codigo: {0}, Nombre: {1}",
codigo, nombre);
}
En los "ExecuteNonQuery", podemos comprobar la cantidad de datos afectados, lo que nos puede ayudar a descubrir errores:
cantidad = cmd.ExecuteNonQuery();
if (cantidad < 1)
Console.WriteLine("No se ha podido insertar");
Aun así, muchos tipos de errores, como una clave duplicada, pueden provocar que salte una excepción y se interrumpa el programa, por lo que sería recomendable incluir las órdenes de inserción dentro de un bloque "try...catch"
En cualquier caso, al terminar de acceder deberemos cerrar la conexión a la base de datos:
conexion.Close();
El fuente completo podría ser así:
// Ejemplo de acceso a SQLite desde C#
// Nacho Cabanes, junio 2010
using System;
using System.IO;
using System.Data.SQLite; //Utilizamos la DLL
public class pruebaSQLite01
{
static SQLiteConnection conexion;
private static void CrearBBDDSiNoExiste()
{
if (!File.Exists("personal.sqlite") )
{
// Creamos la conexion a la BD.
// El Data Source contiene la ruta del archivo de la BD
conexion =
new SQLiteConnection
("Data Source=personal.sqlite;Version=3;New=True;Compress=True;");
conexion.Open();
// Creamos la primera tabla
string creacion = "CREATE TABLE ciudad "
+"(codigo VARCHAR(2) PRIMARY KEY, nombre VARCHAR(30));";
SQLiteCommand cmd = new SQLiteCommand(creacion, conexion);
cmd.ExecuteNonQuery();
// Creamos la segunda tabla
creacion = "CREATE TABLE persona "
+"(codigo VARCHAR(2) PRIMARY KEY, nombre VARCHAR(30),"
+" codigoCiudad VARCHAR(2) );";
cmd = new SQLiteCommand(creacion, conexion);
cmd.ExecuteNonQuery();
}
else
{
// Creamos la conexion a la BD.
// El Data Source contiene la ruta del archivo de la BD
conexion =
new SQLiteConnection
("Data Source=personal.sqlite;Version=3;New=False;Compress=True;");
conexion.Open();
}
}
private static void InsertarDatos()
{
string insercion; // Orden de insercion, en SQL
SQLiteCommand cmd; // Comando de SQLite
int cantidad; // Resultado: cantidad de datos
try
{
insercion = "INSERT INTO ciudad "+
"VALUES ('t','Toledo');";
cmd = new SQLiteCommand(insercion, conexion);
cantidad = cmd.ExecuteNonQuery();
if (cantidad < 1)
Console.WriteLine("No se ha podido insertar");
insercion = "INSERT INTO ciudad "+
"VALUES ('a','Alicante');";
cmd = new SQLiteCommand(insercion, conexion);
cantidad = cmd.ExecuteNonQuery();
if (cantidad < 1)
Console.WriteLine("No se ha podido insertar");
insercion = "INSERT INTO persona "+
"VALUES ('j','Juan','t');";
cmd = new SQLiteCommand(insercion, conexion);
cantidad = cmd.ExecuteNonQuery();
if (cantidad < 1)
Console.WriteLine("No se ha podido insertar");
insercion = "INSERT INTO persona "+
"VALUES ('p','Pepe','t');";
cmd = new SQLiteCommand(insercion, conexion);
cantidad = cmd.ExecuteNonQuery();
if (cantidad < 1)
Console.WriteLine("No se ha podido insertar");
}
catch (Exception e)
{
Console.WriteLine("No se ha podido insertar");
Console.WriteLine("Posiblemente un código está repetido");
Console.WriteLine("Error encontrado: {0} ", e.Message);
}
}
private static void MostrarCiudades()
{
// Lanzamos la consulta y preparamos la estructura para leer datos
string consulta = "select * from ciudad";
SQLiteCommand cmd = new SQLiteCommand(consulta, conexion);
SQLiteDataReader datos = cmd.ExecuteReader();
// Leemos los datos de forma repetitiva
while (datos.Read())
{
string codigo = Convert.ToString(datos[0]);
string nombre = Convert.ToString(datos[1]);
// Y los mostramos
Console.WriteLine("Codigo: {0}, Nombre: {1}",
codigo, nombre);
}
}
private static void MostrarPersonas()
{
// Lanzamos la consulta y preparamos la estructura para leer datos
string consulta = "select * from persona";
SQLiteCommand cmd = new SQLiteCommand(consulta, conexion);
SQLiteDataReader datos = cmd.ExecuteReader();
// Leemos los datos de forma repetitiva
while (datos.Read())
{
string codigo = Convert.ToString(datos[0]);
string nombre = Convert.ToString(datos[1]);
// Y los mostramos
Console.WriteLine("Codigo: {0}, Nombre: {1}",
codigo, nombre);
}
}
private static void MostrarCiudadesYPersonas()
{
// Lanzamos la consulta y preparamos la estructura para leer datos
string consulta =
"select persona.nombre, ciudad.nombre "+
"from persona, ciudad "+
"where persona.codigoCiudad = ciudad.Codigo";
SQLiteCommand cmd = new SQLiteCommand(consulta, conexion);
SQLiteDataReader datos = cmd.ExecuteReader();
// Leemos los datos de forma repetitiva
while (datos.Read())
{
string nombrePersona = Convert.ToString(datos[0]);
string nombreCiudad = Convert.ToString(datos[1]);
// Y los mostramos
Console.WriteLine("{0} vive en {1}",
nombrePersona, nombreCiudad);
}
}
private static void CerrarBBDD()
{
conexion.Close();
}
public static void Main()
{
Console.WriteLine("Accediendo...");
CrearBBDDSiNoExiste();
Console.WriteLine("Añadiendo datos...");
InsertarDatos();
Console.WriteLine("Datos de ciudades:");
MostrarCiudades();
Console.WriteLine("Datos de personas:");
MostrarPersonas();
Console.WriteLine("Datos de personas y ciudades:");
MostrarCiudadesYPersonas();
CerrarBBDD();
}
}
Para compilar este fuente, deberemos incluir "System.Data.SqLite.dll" dentro de las referencias del proyecto. Esto se haría desde el propio entorno visual si usamos herramientas como Visual Studio o SharpDevelop, o bien añadiendo la opción /r si compilamos desde línea de comandos, por ejemplo usando Mono:
gmcs pruebaSQLite.cs /r:System.Data.SqLite.dll
Y aquí puedes descargar el fuente, los ficheros DLL y el ejecutable: csharp_sqlite.zip