domingo, 24 de marzo de 2019

Creando videojuegos en Rust lang (Parte 6)

Antes de continuar con el ejemplo de "Hello ggez" me gustaría crear ejemplos que muestren las funcionalidades de Rust y el léxico de Rust que nos permitan entender más fácilmente lo que estaremos haciendo en el ejemplo "Hello ggez". Estas funcionalidades, que tenemos que saber cómo codificarlas y cómo usarlas, son las siguientes:
Crearemos programas simples para mostrar estas funcionalidades. Los nombres de archivo que utilizaré serán "pre_hello_ggez" y el número del ejemplo.

Para crear todos estos "main.rs" de forma rápida descargué la versión más reciente del programa "Notepad++". La versión más reciente muestra la opción "Rust" en la selección de lenguaje y esta opción resalta la sintaxis de Rust. Usamos el comando "cargo new <nombre>" para crear cada uno de los proyectos.

Navegación:
Primera parte
Siguiente parte
Parte anterior

Creando videojuegos en Rust lang (parte 5)

Aprendiendo a trabajar con Rust se facilita más usando dos herramientas que ayudan para el formato del código y que sugieran patrones recomendados. Así podremos compartir nuestro código o identificar formas de escribir nuestro programa de mejor manera, aprovechando las características del idioma.

Para este objetivo tenemos los paquetes rustfmt y clippy. Para instalarlos y utilizarlos sólo ejecutamos las instrucciones correspondientes:
  1. Asegurar tener rustup installado y actualizado; para hacer esto ejecutamos el comando rustup update.
  2. Ejectuamos el comando rustup component add clippy.
  3. Ejecutamos el comando rustup component add rustfmt.
  4. Y para ejecutarlos simplemente nos vamos a nuestro proyecto y ejecutamos cargo clippy y cargo fmt
Resultado de los comandos para instalar Clippy y Rustfmt
Por ejemplo si lo ejecutamos con en el siguiente código de ejemplo:

1
2
3
4
fn main() {
    let VARIABLE = 1i32;
    println!("Hello, world!, {}", VARIABLE);
}

Nos muestra como resultado lo siguiente:
Resultado de correr 'cargo clippy'
Con estos comentarios podemos mejorar el formato de nuestro programa. Por alguna razón ejecutar el comando 'cargo fmt' no me regresa nada, aunque no sé si esto es normal al menos podré utilizar clippy.

Navegación:
Primera parte
Siguiente parte
Parte anterior

Fuente (inglés):

miércoles, 20 de marzo de 2019

Creando videojuegos en Rust lang (Parte 4)

Para nuestro "Hola mundo" en un motor de juegos usaremos el motor de juegos ggez. Las razones por las cuales escogí ggez en vez de las otras opciones (principalmente Amethyst o Piston) son las siguientes:
  • ggez es relativamente reciente. Por otra parte Piston es más estable y cuenta con más tiempo. Para Piston ya hay varios vídeos de ejemplo disponibles en Youtube. Piston parece ser muy modular y quisiera ver como se manejaría un motor de juegos más reciente, menos modular y más simplificado. 
  • Amethyst cuenta con un "Entity-Component-System" llamado specs. Estos sistemas de entidades-componentes es una forma de programar videojuegos en una forma orientada a datos de forma eficiente. A pesar que esto facilita la escala del juego de vídeo, creo que esto será demasiado para ejemplos simples ("Hola mundo", "Snake", etc.) Puede que mientras empiece a dominar estos juegos simples necesite implementar un modelo ECS y eventualmente utilizar el ECS de Amethyst
  • ggez está enfocado a gráficos 2D, mientras que Amethyst está enfocado a ambos: 2D y 3D.
Seguiremos la guía que proporciona ggez en su página de Github: https://github.com/ggez/ggez/blob/master/docs/guides/HelloGgez.md

La guía anterior nos guía a crear un programa simple que use ggez:
  1. Primero nos pide instalar Rust, estos pasos ya los realizamos. 
  2. Luego Nos pide crear un "crate" para nuestro proyecto en este caso ya sabemos como hacerlo cargo new hello_ggez01 y cd hello_ggez01
  3. Luego nos pide abrir el archivo Cargo.toml y agregamos ggez como una dependencia. En el archivo podemos actualizar nuestros metadatos. Básicamente el archivo Cargo.toml es una archivo TOML ("Tom's Obvious, Minimal Language") que guarda los metadatos de las dependencias y versiones usadas para compilar el proyecto. Este es el Cargo.toml que utilicé, cambié ligeramente la versión: 
    1
    2
    3
    4
    5
    6
    7
    8
    [package]
    name = "hello_ggez01"
    version = "0.1.0"
    authors = ["MiUsuario <micorreo@correo.com>"]
    edition = "2018"
    
    [dependencies]
    ggez = "0.5.0-rc.1"
    
  4. Nos pide luego ejecutar el comando cargo run para que descargue y haga la compilación de ggez. Después de unos momentos debería de salir el "Hello world!" predeterminado como se ve en las captura siguientes.
"cargo run" ejecutándose y descargando todas las dependencias.
Se muestra también el Cargo.toml abierto en Visual Studio Code.
Resultado después de esperar a que se descarguen y se compilen las dependencias.
Como no modificamos el archivo obtenemos el "Hola, mundo!" predeterminado.
Este tiempo de espera que tardó en descargar y copilar se lo ahorra al ejecutar el comando "cargo run" nuevamente. Cargo detecta las versiones ya descargadas y compiladas de las dependencias y usa estas. De la misma forma Cargo puede detectar si cambió algún archivo fuente o podemos forzar a Cargo a hacer las descargas o compilaciones.

Navegación:
Primera parte
Siguiente parte
Parte anterior

Fuentes para ggez (inglés):
Fuentes para Piston (inglés):
Fuentes para Amethyst (inglés):

martes, 19 de marzo de 2019

Creando videojuegos en Rust lang (Parte 3)

Antes de usar un paquete de un motor de juegos decidí realizar un pequeño "Hola mundo" usando sólo herramientas básicas de Rust. También sirve como una prueba para ver si puedo mostrar código de Rust en el Blog. Para generar el formato usaré la página hilite.me que me genera el código HTML que tengo que pegar al Blog para que se vea con formato.

Este es un pequeño programa que lee un número de la consola y lo imprime de vuelta. Está basado en la primera parte del tutorial donde se guía a crear un juego de adivina el número en el libro de Rust: https://doc.rust-lang.org/book/ch02-00-guessing-game-tutorial.html

Hice un directorio llamado "demo_guess_game" usando cargo new. Y el código que usé y modifiqué en el "main.rs" es el siguiente:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
use std::io;

fn main() {
    println!("¡Adivina el número!");

    println!("Por favor, inserte el número que desea adivinar.");

    let mut guess = String::new();

    io::stdin().read_line(&mut guess)
        .expect("Hubo un fallo al leer la línea");

    println!("El número que intentó es: {}", guess);
}

Desde la última entrada descubrí que la razón por la que no se podía ejecutar bien el "cargo build" era porque mi antivirus lo marcaba como amenaza y lo escaneaba. Resolví esto ajustando mi antivirus para que no lo marque como amenaza. Entonces, el resultado de ejecutar cargo build y cargo run fue el siguiente:
Demostración del resultado de correr el código anterior
Hay muchas características de Rust que se demuestran en este simple programa. Estas características se explican con más detalle en el vínculo. A fin que estos conceptos no causen problema más adelante este es un resumen de algunos de las características importantes del código:
  • use std::io; está linea sirve para llamar la librería estándar y obtener los métodos de entrada y salida (input/output, io). En este caso la función "read_line" que usamos en la línea 10.
  • fn main() { es una declaración del método "main". La ejecución del código siempre empieza en el método "main".
  • println!("¡Adivina el número!"); la parte que dice println! es una macro. Las macros es una forma poderosa de escribir código que se desdobla en más código. Durante la compilación se convierten en líneas de código separadas, es decir usar una macro es un atajo para ahorrarnos escribir líneas de código individuales. Otra cosa que resaltar es que Rust nos aceptó los caracteres en español "¡" y "ú"; y también está mostrando estos correctamente en la consola.
  • let mut guess = String::new(); esta línea crea/declara ("let") una variable modificable ("mut") llamada "guess" y esta se liga a un objecto String modificable. De forma predeterminada en Rust todos los tipos básicos son fijos y no se pueden modificar
  • io::stdin().read_line(&mut guess).expect("Hubo un fallo al leer la línea"); es la línea más complicada porque llama la función "stdin" del paquete "io", llama el método "read_line" para leer una línea. Este método "read_line" requiere que le prestemos una referencia mutable a la variable "guess" para que la actualice y nos la regrese a "main" (el dueño de la variable). Esto se tiene que hacer de esta forma por la lógica de Rust en donde de forma predeterminada las variables no son modificables/mutables. Finalmente la parte final de ".expect" sirve para regresar el resultado o imprimir el error "Hubo un fallo al leer la línea" en caso que falle el método del sistema que llamamos. 
  • println!("El número que intentó es: {}", guess); esta línea usa "{}" para indicar donde se colocarán las variables, en este caso "guess" es la única variable. En este caso está macro nos ayuda a imprimir la variable.
Para entender más detalles de como funciona Rust recomiendo buscar más ejemplos en línea o buscar libros de Rust. Pueden de hecho usar el libro virtual gratuito: https://doc.rust-lang.org/book. Sin embargo, para fines de este blog intentaré dar un resumen de todos los nuevos componentes en la medida que se vallan introduciendo y en la medida que me enfrente a errores al intentar correr estos ejemplos.

Navegación:
Primera parte
Siguiente parte
Parte anterior

domingo, 10 de marzo de 2019

Creando videojuegos en Rust lang (Parte 2)

En la parte anterior instalamos Rust. Ahora para crear el videojuego podemos decidir crear nuestro propio motor de juegos o usar alguno existente. De estas opciones la opción más rápida es la segunda.

La página http://arewegameyet.com/ muestra una lista de varios recursos que podemos utilizar para hacer juegos. De esta lista nos limitaremos a crear un juego 2D sin audio como nuestro "hola mundo".

AreWeGameYet muestra una lista algunos motores de juegos existentes. Resalto estos 4 motores de juegos/interfaces por su número de descargas al momento de esta publicación:
  • ggez: Al momento de esta publicación cuenta con 14 mil descargas. Es un framework de peso ligero para crear juegos 2D de forma rápida, puede servir bien para "Game Jams". Esta es una opción reciente y al momento de escribir esta entrada se encuentra en desarrollo activo. Esta opción está inspirada en LÖVE que es un Framework para hacer juegos 2D en Lua. Algunos juegos mostrados en la página de AreWeGameYet son "Llamassacre" y "Zemeroth". Contiene herramientas para dibujos 2D, sonido, cargar recursos y manejar eventos. Estos son algunos videos que usan ggez "Flappy Bird Game in Rust!", "RustFest Zürich 2017 - Create Rust games easily by Lisa" y "Writing a simple game in Rust - Willian Molinari".
  • Amethyst: Al momento de esta publicación cuenta con 15 mil descargas. Esta es una opción  reciente (al tiempo de publicación) y parece estar en constante desarrollo por una compañía sin ánimo de lucro. Encontré el video "Everpuzzle - using the Amethyst Engine with Rust for Games" donde explica un juego desarrollado en Amethyst. También está el vídeo "Amethyst Showcase Q1 2019" donde muestra varios juegos y prototipos hechos en Amethyst. 
  • Piston: Al momento de esta publicación cuenta con 131 mil descargas. Esta opción planea ser un motor de juegos modular. Esta creo que es la opción más vieja, más estable y mejor documentada. Algunos juegos hechos con Piston mostrados en la página de AreWeGameYet son "Vigilant Steel" y "hematite". En la página de Piston vemos también "Piston 2048", "Playform" y "Rustyhex". En la plática de Lisa Passing ella comenta utilizó Piston para su juego 2D pero que tuvo problema al incorporar sonido. Al parecer Pison no incluye framework para manejar sonido. En "Making a Snake Game in Rust" se muestra como crear un juego 2D de snake (sin sonido) utilizando Piston. En "Rust For Game Development" se utiliza Pison como ejemplo para mostrar un demo 2D simple.
  • sdl2: Al momento de esta publicación cuenta con 164 mil descargas. "Chucklefish" (creadores de Starbound) actualmente tienen un proyecto con nombre código "Spellbound" que están desenrollando en Rust y otros idiomas. "Chucklefish" esta usando sdl2 según una publicación en el foro de Rust de Reddit.
Hablando de estudios medianos utilizando Rust tenemos que mencionar que"Chucklefish" está siguiendo la opción de desarrollar su propio motor de juego para manejar la funcionalidad precisa del que van a realizar, usando SDL2 para correrlo en computadoras. También Andrea Pessino de "Ready At Dawn" Studios expresó en Twitter comentarios sobre uso de Rust en lugar de C/C++ para desarrollar juegos.

Antes de hacer un Hola mundo en uno de los motores de juegos de arriba hay que hacer un Hola mundo de Rust para confirmar que podemos compilar Rust correctamente. También necesitamos tener listo el editor de nuestro código de Rust.

Descargaremos y instalaremos "Visual Studio Code" (VSCode) que es el Editor más usado para Rust en este momento según los resultados de una encuesta de "The Rust Blog" en 2018. "Visual Studio Code" tiene la extension "Rust (rls)" que podemos instalar. En esta entrada nos concentraremos en instalar esto siguiendo siguiendo el ejemplo del vídeo "Rust For Game Development" https://www.youtube.com/watch?v=aKLntZcp27M

Resultado al ejecutar el comando 'cargo'
  1. Descargar el instalador de Visual Studio Code correspondiente del vínculo https://code.visualstudio.com/Download. En mi caso sería el vínculo siguiente: https://go.microsoft.com/fwlink/?LinkID=534107
  2. Una vez descargado tenemos que correr el instalador descargado. En este caso al tiempo de escribir esta entrada es "VSCodeUserSetup-x64-1.32.1.exe" que corresponde a Windows 64 bits.
  3. Navegamos las pantallas del instalador siguiendo los pasos que nos indica. Cerramos otras aplicaciones para que no interfieran con la instalación.
  4. Al final estará palomeada la opción de Ejecutar Visual Studio Code, seleccionamos "Finalizar" y ahora se abrirá VSCode.
  5. Damos click a la opción "Extensions" en el menú de la izquierda en VisualStudio Code. 
  6. En la barra de búsqueda buscamos "Rust".
  7. En los resultados debería aparecer la opción "Rust (rls)".
  8. Le damos click en el botón "Install" a la opción "Rust (rls)".
  9. Esperamos un momento mientras se instala.
  10. Una vez instalado el icono en el panel debería decir "Installed". 
  11. Cerramos Visual Studo Code por ahora.
  12. Reiniciamos la computadora, ya que hay variables que se actualizan al reiniciar la computadora.
  13. Abrimos una terminal / línea de comandos / cmd de Windows.
  14. Escribimos el comando "cargo" y presionamos la tecla Enter. Esto nos permitirá ver si Rust y "Cargo" están instalados correctamente. Instalar Rust y "Cargo" fue lo que se hizo en automático con el instalador de la parte anterior. Si está instalado correctamente verán algo como la imagen de arriba.
  15. Creamos una carpeta donde guardaremos nuestro proyecto. Puede ser en un folder llamado  "Rust" dentro de "Mis documentos". Este caso usaré la siguiente estructura "C:\Users\<MiUsuario>\Documents\Rust\HolaMundo", donde <MiUsuario> correponde al nombre de mi usuario en Windows.
  16. Ahora navegamos a un directorio de proyectos usando el comando "cd C:\Users\<MiUsuario>\Documents\Rust\HolaMundo".
  17. Una vez ejecutado el comando ejecutamos el comando "cargo new demo_hello_world_en_rust". Este comando hace que cargo cree la estructura de una nuevo proyecto.
  18. Podemos entrar a esta carpeta con el comando "cd demo_hello_world_en_rust".
  19. Ejecutamos el comando "dir" para ver las carpetas y archivos que generó. En este caso hizo un archivo ".gitignore", un "Cargo.toml" y una carpeta "src".
  20. Abrimos esto en VS Code usando el comando "code ."
  21. Expandimos "src" en el panel derecho y vemos que tiene un archivo "main.rs" que es un archivo simple de Hola Mundo.  
  22. Damos un click en "main.rs" para abrirlo en el panel derecho.
  23. Una vez abierto me salieron algunos errores en el cual mencionan que no se pudo iniciar "RLS". Ignoraré estos errores por ahora ya que creo que es para habilitar "intellisense" (autocompletado) con el código de Rust. Investigaré y arreglaré este problema más adelante si es necesario pero no debería detenernos en nuestro Hola, mundo! 
  24. Intentando ejecutar el comando "cargo run" en la línea de comando (cmd) en la carpeta correspondiente ("demo_hello_world_en_rust") me muestra un error que no encuentra el "link.exe". Buscando un poco en línea encuentro que esto se debe a que se pudo haber instalado incorrectamente el Visual Studio Tools. Puede ser que se haya instalado sin algún SDK o que simplemente no instaló todos los componentes. Entonces intentaré instalar el SDK de Windows 10.
  25. Para instalar Windows 10 SDK hay que ir a la página correspondiente y darle click en "Download the installer" https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk
  26. Se descarga "winsdksetup.exe". Lo ejecutamos y seguimos las indicaciones del instalador. Cerramos todas las ventanas para que no afecten en la instalación. 
  27. Seguía sin funcionar. Así que volví a seguir los pasos de la parte 1 para instalar Visual Studio Tools (https://aka.ms/buildtools). Al ejecutar el exe me da opción de instalar diversos componentes. Esta vez me aseguré de palomear 4 opciones "Windows 10 SDK (10.0.17763.0)", "Herramientas de C++ para CMake", "Características principales de las herramientas d..." y "SDK de Windows 8.1 y SDK de URT". La captura de como se ve esto se muestra en las imágenes de abajo.
  28. Una vez terminada la instalación volvemos a abrir una línea de comandos (cmd) y nos dirigimos a nuestro folder "demo_hello_world_en_rust" y ejecutamos "cargo run". Ahora se ejecuta correctamente.
  29. En mi caso se quedó la ventana abierta, creo que por problemas con el antivirus. Desactivé el antivirus y abrí otra ventana y ahora "cargo run" funcionó correctamente y pude ver mi "Hola mundo". Las capturas de las pantallas principales de muestran abajo.
Captura de pantalla de las líneas ejecutadas para crear los archivos de un nuevo proyecto de Cargo

Como se ven las opciones al instalar nuevamente Visual Studio Build Tools. Estas son las opciones que seleccioné para que funcione bien

"cargo run" mostrando mi "Hola, mundo!" de Rust ("Hello, world!") funcionando. Funcionó bien después de desactivar mi antivirus que estaba detectando el ".exe" como sospechoso.

Si llegan a ver la pantalla de arriba significa que están compilando en Rust en su computadora. También demuestra que Cargo está funcionando. Con esto estamos un paso más cerca a crear nuestro juego en Rust.

Navegación:
Siguiente parte
Parte anterior

Fuentes (inglés):

viernes, 8 de marzo de 2019

Creando videojuegos en Rust lang (Parte 1)

Este blog documentará mi intento de crear un juego en el lenguaje de Programación "Rust". "Rust" es óxido en inglés, por eso el nombre del blog "Desoxidando la mente".

Rust es un lenguaje de programación relativamente nuevo que intenta ser de bajo nivel (similar a C/C++). Las razones por las que escogí Rust:
  • El idioma es nuevo e interesante. Quisiera aprender este lenguaje y parece que hay una comunidad interesada en el lenguaje.
  • El ambiente para videojuegos en Rust todavía no es muy maduro, no hay juegos grandes escritos en "Rust" sólo proyectos pequeños o medianos.
  • Hay necesidad de que haya documentación en español.
  • Siempre he querido crear un videojuego (aunque sea simple). Nota: Crear videojuegos comerciales es complicado. Crear al nivel para competir con otros requiere de un equipo y recursos. Pero poniendo objetivos simples y avanzando lentamente puede ser factible como pasatiempo y como aprendizaje. 
  • Quisiera programar un juego en un lenguaje de bajo nivel para tener más control para que pueda correr rápido en computadoras de gama baja o media. En este caso serán puros juegos 2D.
  • Rust tiene el sistema de "Cargo" que facilitan el manejo de paquetes, versiones de paquetes y compilaciones de paquetes. Con este sistema es fácil descargar las dependencias.
El primer paso es instalar Rust. Para esto seguí los pasos descritos en la documentación de Rust:
  1. Ir a https://www.rust-lang.org/install.html
  2. Descargar "RUSTUP-INIT.exe". En este caso el sitio detectó que estoy usando Windows y me puso el vínculo para descargar este archivo.
  3. Una vez descargado darle doble click para instalar. Si te sale la ventana emergente de "Windows Defender" selecciona que confías en el programa.
  4. Me salió una ventana como la que se muestra en la derecha. La ventana menciona que tengo que instalar Microsoft Visual C++ Build Tools 2017. Y me proporciona el vínculo https://aka.ms/buildtools 
  5. Selecciono "N" para parar la instalación.
  6. Voy a https://aka.ms/buildtools
  7. Selecciono descargar "Build Tools for Visual Studio 2017"
  8. Una vez descargado ejecuto el .exe para que se instalen las herramientas.
  9. Navego las pantallas dándole "Siguiente"/"Continuar". Llegará a un punto donde descarga e instala lo que necesitamos.
  10. Se abrió una ventana de Visual Studio que decía "Preparándose". Una vez que esperé un tiempo la ventana mencionó que no encuentra "Visual Studio". Eso es porque no lo tengo instalado en mi sistema. Entonces cerré esa ventana.
  11. Ahora ejecutamos nuevamente el .exe descargado originalmente ("RUSTUP-INIT.exe"). 
  12. Nuevamente me salió la ventana de arriba a la derecha. Esta vez selecciono "Y".
  13. Ahora me da 3 opciones. Selecciono la primera opción: "Proceed with installation (default)" para proseguir con la instalación con las opciones predeterminadas. 
  14. Si todo salió bien ahora descargará los archivos necesarios e instalará el compilador y la herramienta "Cargo" que usaremos para manejar varios paquetes en Rust. La recomendación es cerrar todos los programas y navegadores de internet para que no interrumpan la instalación.
  15. Una vez terminada la instalación la ventana se cierra.
  16. Podemos confirmar la instalación abriendo una línea de comando (Símbolo de sistema / cmd) y ejecutando el comando "rustc --version".

Con esto se confirma esta parte de la instalación, en las siguientes entradas crearemos las carpetas de mi primer proyecto, empezaremos a hacer pruebas y comenzaremos a usar "Cargo".

Navegación:
Siguiente parte

Fuentes (inglés):