19 febrero 2023

Introduction to Game Design, Prototyping, and Development: From Concept to Playable Game with Unity and C#

Introduction to Game Design, Prototyping, and Development: From Concept to Playable Game with Unity and C# de Jeremy Gibson Bond es un buen libro para iniciarse en el desarrollo de juegos. A diferencia de otros que se centran en cómo desarrollar en Unity, Bond pone en práctica su experiencia como profesor universitario adoptando un enfoque global que abarca tanto conceptos teóricos como prácticos y técnicos. Es cierto que su estructura ordenada y formal huele a libro de texto, pero este es de los buenos, de los que de verdad te aportan conocimientos que no se evaporarán cuando pasen un par de años y cinco versiones del engine de turno.

La primera parte del libro se centra en aspectos teóricos empezando a un gran nivel de abstracción y bajando poco a poco al detalle. De hecho comienza describiendo lo que se entiende por un juego y cuales son los elementos y la estructura que los caracterizan. Fíjate que he dicho juego, no juego de ordenador. Tan generales son los conceptos de esta parte, que el autor anima a ponerlos en práctica en una mesa con lápiz y papel. Se nota también que Bond es un gran fan de los juegos de mesa y rol, empezando por D&D, por las numerosas referencias a ellos y a sus mecánicas. El objetivo de esta parte es que el lector sea capaz de modelar el juego en su cabeza, centrándose en elaborar las mecánicas que lo hagan atractivo de jugar. En esta parte me ha resultado especialmente sugerente la estructuración por capas de los distintos tipos de juego que hay dentro de un mismo juego: está el juego que prentendían diseñar sus creadores al fijar sus reglas, el juego que surge en la mesa según  lo juegan los jugadores y finalmente el juego que surge cuando la gente lo hace suyo y empieza a modificarlo y a hacerlo evolucionar al margen de los creadores originales (cualquier aficionado a los mods disfrutará con esta formulación teórica).

La segunda parte se zambulle en el diseño de un juego. Partiendo de los conceptos teóricos se trata de dar forma a las piezas que conformarán el juego, primero con prototipos en papel jugados por sucesivos grupos de testers. Aquí me resultó muy interesante la parte en la que te enseña las formas sutiles que tienen los juegos para guiar al jugador hacia donde quiere el diseñador. En esta parte hay sitio incluso para un breve baño de Agile y Scrum. 

Creo que estas dos primeras partes serán las que más gusten a los que ya tengan cierta experiencia con Unity.

La tercera parte se encarga de llevar los prototipos en papel a prototipos técnicos, más cercanos a la forma final del juego. Aquí es donde empieza con los conceptos básicos de Unity. Empieza desde cero, incluso desde cómo ordenar el layout de paneles del editor de Unity y luego va avanzando por la programación en C# para Unity. Los que ya sepan de C# y hayan hecho sus pinitos de Unity probablemente pasen rápido las hojas de esta parte, aunque no recomiendo saltárselas del todo porque hay algunos trucos interesantes. Yo mismo he aprendido un par de cosillas a pesar de tener ya bastante experiencia programando tanto en otros lenguajes, como en C# para Unity.

La cuarta parte se centra en desarrollar una serie de prototipos que cubren algunos de los tipos básicos de juegos. Son como minitutoriales, cubriendo cada uno de ellos un tipo diferente de juegos. Los que estén empezando con Unity encontrarán aquí una excelente manera de soltarse aprendiendo además buenas prácticas.

Se trata por tanto de un libro muy completo, bien estructurado y tremendamente didáctico, con un montón de enlaces y referencias a otros libros con los que continuar al terminar este. Lo recomiendo tanto a los que ya sepan de Unity y quieran empezar con el diseño de juegos, como a aquellos que estén empezando y quieran coger confianza con Unity empezando desde cero. 


18 febrero 2023

Cómo usar PackageCloud para distribuir tus paquetes RPM y DEB

Hace un tiempo escribí artículo explicando cómo configurar una cuenta de JFrog Artifactory para hospedar repositorios Debian y RPM. 

Desde entonces, mi interés por Artifactory se ha difuminado porque tienen la política de monitorizar que mantienes una actividad constante para mantener tu cuenta viva. Si tienes periodos sin subidas o descargas de paquetes te suspende la cuenta y tienes que reactivarla manualmente. Esto es muy desagradable e incómodo y ocurre con demasiada frecuencia cuando eres un desarrollador aficionado como yo, que desarrolla en su tiempo libre y no puede mantener un ritmo constante en sus proyectos. Eso y la complejidad de la configuración de Artifactory me hizo buscar otras opciones.

Buscando por Internet he encontrado PackageCloud y hasta ahora ha resultado una alternativa excelente a Artifactory. PackagedCloud tiene una gama gratuita de 2 GB de almacenamiento 1 10 GB de transferencia mensual. Para aficionados como yo creo que es más que suficiente. 

Creación de un repositorio

Una vez que te registras en PackageCloud accedes a un panel de control muy claro. Comparado con Artifactory todo es simple e intuitivo. En la esquina superior derecha de la página "Home" tienes un gran botón que reza: "Create a repository". Puedes usarlo para crear un repositorio para cada aplicación que tengas. 

 


Una característica estupenda de PackageCloud es que un único repositorio puede hospedar múltiples paquetes simultaneamente. Así que no necesitas crear un repositorio por cada tipo de paquete que quieras hospedar de tu aplicación, en vez de eso tienes un único repositorio para tu aplicación y subes a él lo paquetes deb, rpm, gem o de otro tipo que generes.

Subir paquetes

Cuando usa PackageCloud te das cuenta de que sus desarrolladores han hecho un gran esfuerzo para guiarte paso a paso. Una vez que creas tu repositorio te guían para subir paquetes a través de tu consola de comandos (aunque tembién hay un bonito botón azul para subir los paquetes a través de un interfaz web si así lo prefieres):

Como primera aproximación vamos a probar primero el interfaz web para subir un paquete y luego probaremos la opción de la consola de comandos.

Si seleccionas un repositorio recién creado en la página "Home" rn trarás en la página de la figura anterior. Para usar el interfaz web para subir paquetes pulsa el botón "Upload a package". Ese botón hará aparecer la siguiente ventana emergente:

Como se puede ver en la última captura, he pulsado el botón "Select a package" y he seleccionado vdist_2.1.0:amd64.deb. Después tienes que seleccionar tu distribución objetivo en en campo combo. Te sugiero que elijas una distribución lo más generalizada posible para ampliar tu audiencia. Por ejemplo, yo uso un equipo con Linux Mint y aunque Linux Mint aparece en el campo combo prefiero seleccionar Ubuntu Focal como un equivalente mucho más común (partiendo de que mi Linux Mint Uma en realidad se basa en Ubuntu Focal). Después de seleccionar un paquete y una distribución objetivo, el botón "upload" se habilitará. La subida comenzará cuando pulses ese botón. Sabrás que la subida ha finalizado exitosamente cuando aparezca una caja verde con el mensaje "Upload Successful!".

Si prefieres usar la consola, puedes tirar de la aplicación para consola de PackageCloud. Es una aplicación basada en Ruby, así que tienes que asegurarte de tener su intérprete instalado:

dante@Camelot:~/$ sudo apt install ruby ruby-dev g++
[sudo] password for dante:
[...]

dante@Camelot:~$

El paquete de Ruby te ofrece el comando "gem" para instalar la aplicación de PackageCloud:

dante@Camelot:~/$ sudo gem install package_cloud
Building native extensions. This could take a while...
Successfully installed unf_ext-0.0.8
Successfully installed unf-0.1.4
Successfully installed domain_name-0.5.20190701
Successfully installed http-cookie-1.0.4
Successfully installed mime-types-data-3.2021.0901
Successfully installed mime-types-3.3.1
Successfully installed netrc-0.11.0
Successfully installed rest-client-2.1.0
Successfully installed json_pure-1.8.1
Building native extensions. This could take a while...
Successfully installed rainbow-2.2.2
Successfully installed package_cloud-0.3.08
Parsing documentation for unf_ext-0.0.8
Installing ri documentation for unf_ext-0.0.8
Parsing documentation for unf-0.1.4
Installing ri documentation for unf-0.1.4
Parsing documentation for domain_name-0.5.20190701
Installing ri documentation for domain_name-0.5.20190701
Parsing documentation for http-cookie-1.0.4
Installing ri documentation for http-cookie-1.0.4
Parsing documentation for mime-types-data-3.2021.0901
Installing ri documentation for mime-types-data-3.2021.0901
Parsing documentation for mime-types-3.3.1
Installing ri documentation for mime-types-3.3.1
Parsing documentation for netrc-0.11.0
Installing ri documentation for netrc-0.11.0
Parsing documentation for rest-client-2.1.0
Installing ri documentation for rest-client-2.1.0
Parsing documentation for json_pure-1.8.1
Installing ri documentation for json_pure-1.8.1
Parsing documentation for rainbow-2.2.2
Installing ri documentation for rainbow-2.2.2
Parsing documentation for package_cloud-0.3.08
Installing ri documentation for package_cloud-0.3.08
Done installing documentation for unf_ext, unf, domain_name, http-cookie, mime-types-data, mime-types, netrc, rest-client, json_pure, rainbow, package_cloud after 8 seconds
11 gems installed


dante@Camelot:~$

Ese comando te permite hacer muchas cosas, incluso crear repositorios desde la consola, pero enfoquémonos en subir paquetes. Para subir un paquete sólo hay que incluir el verbo "push":

dante@Camelot:~/$ package_cloud push dante-signal31/vdist/ubuntu/focal vdist_2.2.0post1_amd64.deb 
Email:
dante.signal31@gmail.com
Password:

/var/lib/gems/2.7.0/gems/json_pure-1.8.1/lib/json/common.rb:155: warning: Using the last argument as keyword parameters is deprecated
Got your token. Writing a config file to /home/dante/.packagecloud... success!
/var/lib/gems/2.7.0/gems/json_pure-1.8.1/lib/json/common.rb:155: warning: Using the last argument as keyword parameters is deprecated
Looking for repository at dante-signal31/vdist... /var/lib/gems/2.7.0/gems/json_pure-1.8.1/lib/json/common.rb:155: warning: Using the last argument as keyword parameters is deprecated
success!
Pushing vdist_2.2.0post1_amd64.deb... success!

dante@Camelot:~$

La URL que se le pasa a "package_cloud push" siempre tiene la forma: <username>/<repository>/<distribution>/<distribution version>.

Después de eso, el nuevo apaquete aparecerá registrado en el interfaz web:

Instalación de paquetes

Hasta ahora hemos visto todo lo que necesitas saber desde el punto de vista del publicador de paquetes, pero ahora nos vamos a poner en el lugar de los usuarios que van a instalar nuestros paquetes.

La cosa no puede ser más sencilla. Cada repositorio tienen un botón la sección de paquetes llamado  "Quick install instructions for:". Pulsa ese botón y te saldrá una ventana emergente como esta:


Sólo copia el comando, o usa el botón de copia, y haz que el usuario pegue lo pegue en su consola (dicho de otra manera: incluye en tus instrucciones de instalación que el usuario ejecute el comando):

dante@Camelot:~/$ curl -s https://packagecloud.io/install/repositories/dante-signal31/vdist/script.deb.sh | sudo bash
[sudo] password for dante:
Detected operating system as LinuxMint/uma.
Checking for curl...
Detected curl...
Checking for gpg...
Detected gpg...
Running apt-get update... done.
Installing apt-transport-https... done.
Installing /etc/apt/sources.list.d/dante-signal31_vdist.list...done.
Importing packagecloud gpg key... done.
Running apt-get update... done.

The repository is setup! You can now install packages.

dante@Camelot:~$

El comando registró al repositorio de PackageCloud como una de las fuentes de paquetes autorizadas para tu sistema. En teoría, ahora el usuario debería poder hacer un "sudo apt update" y tu debería salir listado pero en la práctica aquí hay que tener cierto cuidado. ¿Recuerdas cuando te dije que mi equipo es un Linux Mint pero que el repositorio lo fijo a Ubuntu/Focal? la cuestión es que el comando detectó mi sistema y fijó automáticamente la fuente del repositorio como si esta fuese a servir a los Linux Mint: 

dante@Camelot:~/$ cat /etc/apt/sources.list.d/dante-signal31_vdist.list 
# this file was generated by packagecloud.io for
# the repository at https://packagecloud.io/dante-signal31/vdist

deb https://packagecloud.io/dante-signal31/vdist/linuxmint/ uma main
deb-src https://packagecloud.io/dante-signal31/vdist/linuxmint/ uma main


dante@Camelot:~$

He marcado en rojo la parte incorrecta. Si aún así insistimos en actualizar nos saldrá un error:

dante@Camelot:~/$ sudo apt update
Hit:1 http://archive.canonical.com/ubuntu focal InRelease
Hit:2 https://download.docker.com/linux/ubuntu focal InRelease
Hit:3 http://archive.ubuntu.com/ubuntu focal InRelease
Get:4 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Ign:5 http://packages.linuxmint.com uma InRelease
Get:6 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:7 http://archive.ubuntu.com/ubuntu focal-backports InRelease [101 kB]
Hit:8 http://packages.linuxmint.com uma Release
Ign:11 https://packagecloud.io/dante-signal31/vdist/linuxmint uma InRelease
Hit:10 https://packagecloud.io/dante-signal31/cifra-rust/ubuntu focal InRelease
Err:12 https://packagecloud.io/dante-signal31/vdist/linuxmint uma Release
404 Not Found [IP: 52.52.239.191 443]
Reading package lists... Done
E: The repository 'https://packagecloud.io/dante-signal31/vdist/linuxmint uma Release' does not have a Release file.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.


dante@Camelot:~$

Como el repositorio está configurado para servir a los Ubuntu/Focal, tengo que corregir manualmente  la entrada en mi lista de repositorios, de la siguiente manera: 

dante@Camelot:~/$ cat /etc/apt/sources.list.d/dante-signal31_vdist.list 
# this file was generated by packagecloud.io for
# the repository at https://packagecloud.io/dante-signal31/vdist

deb https://packagecloud.io/dante-signal31/vdist/ubuntu/ focal main
deb-src https://packagecloud.io/dante-signal31/vdist/ubuntu/ focal main

dante@Camelot:~$

Ahora "apt update" funcionará y encontrarás el paquete:

dante@Camelot:~/$ sudo apt update
Hit:1 https://download.docker.com/linux/ubuntu focal InRelease
Hit:2 http://archive.ubuntu.com/ubuntu focal InRelease
Hit:3 http://archive.canonical.com/ubuntu focal InRelease
Get:4 http://archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB]
Ign:5 http://packages.linuxmint.com uma InRelease
Get:6 http://security.ubuntu.com/ubuntu focal-security InRelease [114 kB]
Get:7 http://archive.ubuntu.com/ubuntu focal-backports InRelease [101 kB]
Hit:8 http://packages.linuxmint.com uma Release
Hit:10 https://packagecloud.io/dante-signal31/cifra-rust/ubuntu focal InRelease
Get:11 https://packagecloud.io/dante-signal31/vdist/ubuntu focal InRelease [24,4 kB]
Get:12 https://packagecloud.io/dante-signal31/vdist/ubuntu focal/main amd64 Packages [963 B]
Fetched 353 kB in 3s (109 kB/s)
Reading package lists... Done
Building dependency tree
Reading state information... Done
All packages are up to date.
dante@Camelot:~/Downloads$ sudo apt show vdist
Package: vdist
Version: 2.2.0post1
Priority: extra
Section: net
Maintainer: dante.signal31@gmail.com
Installed-Size: 214 MB
Depends: libssl1.0.0, docker-ce
Homepage: https://github.com/dante-signal31/vdist
Download-Size: 59,9 MB
APT-Sources: https://packagecloud.io/dante-signal31/vdist/ubuntu focal/main amd64 Packages
Description: vdist (Virtualenv Distribute) is a tool that lets you build OS packages from your Python applications, while aiming to build an isolated environment for your Python project by utilizing virtualenv. This means that your application will not depend on OS provided packages of Python modules, including their versions.

N: There is 1 additional record. Please use the '-a' switch to see it

dante@Camelot:~$

Como es obvio, si el tu equipo o el equipo del usuario es del mismo tipo que el fijado como objetivo en el repositorio, entonces no habrá nada que corregir. De todos modos, no descartes que los usuarios estén usando distribuciones derivadas de la que uses de objetivo, por lo que conviene que documentes este tema para que se fijen bien al configurar los repositorios.

Llegados a este punto, tus usuarios serán capaces de instalar tu paquete como cualquier otro:

dante@Camelot:~/$ sudo apt install vdist
[...]

dante@Camelot:~$

Conclusión

PackageCloud hace extremadamente fácil desplegar tus paquetes. Conparado con Bintray o Artifactory, su configuración es una gozada. Tengo que ver como evoluciona, pero a primera vista parece un servicio prometedor.