class_18-cf42052b

La App Makers

Hola chicos!!!
Hoy hablaremos del módulo WGET de Python, el cual es una utilidad para hacer descargas de archivos desde un servidor o host. El objetivo final de este post, será el integrar dentro de un juego Ren’Py un sistema de descarga, lo que puede servir, por ejemplo, para entregar actualizaciones, o regalar activos a los jugadores.
Sin más nada que acotar, ve a buscar tu PC, siéntate en un lugár cómodo, ¡y a codificar se ha dicho!


1. INTRODUCCIÓN AL SISTEMA DE DESCARGAS IN-GAME : ¿QUÉ ES “WGET”?

[SCREENSHOT : Sistema de descarga de recursos de “ElectroBasics Electronic Quiz!”, aún en desarrollo.]

WGET es una utilidad de descargas que se encuentra mayormente montado en lenguaje C (GitHub). También hay una variante que está montada en Python, que por cierto, será la que ocuparemos en este tutorial.

En este post pretendemos integrar WGET en un juego Ren’Py para ejecutar descargas de archivos según sea necesario.
Esto puede ser útil en caso de que queramos hacer DLCs para nuestro juego, o bien, regalar archivos a los jugadores.

Condiciones de funcionamiento de WGET en general :

  • Servidor propio : Es necesario que dispongas de algún host para almacenar los archivos. Las nubes de almacenamiento como MEGA o MediaFire lamentablemente no nos sirven porque no entregan una respuesta límpia del archivo.
  • Rango de Solicitudes : Puedes ejecutar solicitudes de URL que sean de rango HTTP y HTTPS. Si tu servidor o host no posee certificados de seguridad, puedes ejecutar la descarga escribiendo la URL solo como HTTP.

Itinerario de este tutorial :

  • Integración del Procesamiento en hilos (Threading).
  • Crear objeto class() para agrupar funciones y ejecutar una descarga con WGET.
  • Preparación de la UI que mostrará el progreso de la descarga.

2. ¡VAMOS A HACER QUE WGET ENCAJE EN EL ENTORNO DE UN JUEGO REN’PY!

Antes de empezar, debemos obtener el módulo ya que no es un módulo que venga en los archivos de Python. Sigue el paso a paso :


  • Paso 1 : Descarga del módulo WGET.

Si señor, por más increíble que suene, todo lo necesario para ejecutar descargas, está codificado en un solo script de Python titulado como wget.py. Descarga el script desde el siguiente link :


  • Paso 2 : Preparar carpeta para módulos de Python.


[Screenshot Paso 2]

Abre la carpeta /game de tu proyecto (donde tienes tus Assets) y en el interior, haz una carpeta llamada python-packages. Si ya lo tenias creado dentro de la carpeta /game, puedes omitir este paso y continuar en el siguiente.


  • Paso 3 : Colocación del módulo.


[Screenshot Paso 3]

Una vez creada la carpeta python-packages, coloca en su interior el archivo wget.py.
Después de hacer estos 3 pasos, ya podrás utilizar a WGET dentro del código sin problemas.

Si estás listo o lista, pues… ¡Vamos a codificar de una vez! xD.


3. CREACIÓN DEL SISTEMA DE DESCARGAS [PYTHON]

Agárrate del asiento y sujeta tu tostadora porque esto va a estar un poco turbulento. Aconsejo cinturones de seguridad para mejor estabilidad xD.

Ok, vamos directo al grano. La dinámica de funcionamiento obligatoria para WGET en Ren’Py, será el usar la lógica del procesamiento en hilos (Threading). ¿Por qué lo haremos de esa forma? Pues la descarga, es un proceso más en nuestro programa o juego, entonces si usamos a WGET sin hacer uso del Multithreading, Ren’Py (el juego) sufrirá una interrupción con el típico mensaje “No responde”.

Para hacer funcionar las descargas con hilos, usaremos el módulo por defecto de Python llamado “Threading”. No necesitarás descargarlo puesto que viene ya dentro de los recursos de Ren’Py.

En cuanto a estructura del código, crearemos una clase que se encargará de ejecutar, controlar y evaluar el progreso de la descarga. Todo esto será implementado para que WGET y tu juego puedan trabajar de forma amigable y en paralelo, evitando errores en el funcionamiento.

Mira el código a continuación (Mucho texto xD) :

[SCREENSHOTS : Código que ejecuta descargas con WGET, mismo código implementado en “ElectroBasics Electronic Quiz!”]

El Screenshot que acabas de ver, es el código que ejecuta las descargas. En el, se aprecian un grupo de funciones reunidas dentro de un objeto class().
Para que entiendas la utilidad de cada función, haré un desglose del código para la clase y cada una de las funciones en su interior :

  • WGET_Assets_Downloader(threading.Thread) [Clase] : Esta clase es un objeto que empaqueta las funciones que conforman al sistema de descargas.
  •  __init__(self, url, out=None) [Función / Método] : Esta función es un método que inicializa todos los atributos de la clase WGET_Assets_Downloader(), y recibe los datos necesarios para realizar las descargas. Cuando la clase es llamada, recibe dos parámetros externos : el url (La URL del archivo a descargar) y el out (la ruta del disco donde se descargará el archivo)
  • status(self) [Función / Método] : Esta función retorna el porcentaje de progreso en la descarga del archivo. Esto es calculado en base a los Bytes descargados y a los Bytes totales del archivo a descargar.
  • MB_Actual(self) [Función / Método] : Esta función retorna los Megabytes descargados.
  • MB_Target(self) [Función / Método] : Esta función retorna los Megabytes totales del archivo.
  • _filename(self) [Función / Método] : Esta función retorna el nombre asignado al archivo. El nombre asignado se obtiene desde la llamada a wget.download() y a su vez, desde el parámetro out de __init__.
  • download_is_finished(self) [Función / Método] : Esa función retorna True cuando la descarga finaliza. De lo contrario retorna False por defecto.
  • _has_exception(self) [Función / Método] : Cuando ocurre un error, sin importar si el error ocurrió antes o durante la descarga, esta función retorna True. Si no ocurre ningún error, retorna False.
  •  _raise_from_thread(self) [Función / Método] : En caso de que ocurra un error, esta función permite rastrear el error si así se desea. En el código completo de este post, dejaré comentado el fragmento que permite rastrear el error con un botón de texto.
  • _callback_func(…..) [Función / Método] : Esta función se encarga de calcular el progreso de la descarga. La variable __download_status calcula el porcentaje de descarga, __actual se dedica a convertir los bytes descargados en Megabytes dividiendo los bytes descargados en 1048576, y por último, __target convierte también en Megabytes, los bytes totales del archivo a descargar.

NOTA : Muchos dicen que 1 MB (Megabyte) corresponde a 1.000.000 B (Bytes), pero en realidad 1 MB corresponde a 1.048.576 Bytes.

  • run(self) [Función / Método] : Esta función es la que da inicio a la descarga del archivo. La descarga se ejecuta usando wget.download() dentro de bloques try/except, lo que permite detectar un error y no detener el programa o juego por completo.

¡Waaaaaaaah! ¿Has visto todo este desmadre eh?
Créeme, el desglose quizá fue un poco caótico, pero esta madre funciona al 100%.
Con esto ya terminado, podemos proceder a la parte más liviana del tutorial : el crear la UI. Vamos para allá.


4. CREACIÓN DE LA UI DE DESCARGAS [REN’PY + PYTHON]

Aquí estamos en la parte más relajada del tutorial, pero es una de las cosas más importantes para las descargas ya que, además de mostrar el progreso de forma gráfica, es la parte que actuará como intermediario entre el código del ítem anterior y el código convencional de Ren’Py.
Como ya hemos trabajado con el Lenguaje de Pantallas, agregaré el código completo de la UI y haré su respectivo desglose para entender su estructura. Mira a continuación :

El inicio de la Screen y el fragmento que aparecerá en caso de un error…

El fragmento que aparece cuando la descarga termina…

El fragmento que muestra el progreso de descarga como barras y cifras numéricas…

Y el botón para iniciar la descarga.

[SCREENSHOTS : Código de Ren’Py para mostrar y ejecutar la descarga de un archivo mediante el código del ítem 3]

Bien, bien, empezaremos a desglosar las cosas más importantes del código :

  • download_screen(url, out=None) [Screen] : Esta pantalla es la responsable de iniciar la descarga. Recibe como argumentos a 2 strings, las que contienen la URL del archivo, y ruta de salida del archivo.
  • Download_Action [Variable] : Esta variable posee la llamada a la clase que se encarga de ejecutar la descarga. La clase recibe como argumento a los dos parámetros de la Screen.
  •  _Download_Activity [Variable] : Esta variable se encarga de “avisar” cuando la descarga haya iniciado. Por defecto es False, pero cuando inicia la descarga cambia a True, mostrando a los objetos de UI que están en el interior de su bloque.
  • showif _Download_Activity [Condicional] : La condición evalúa a la variable _Download_Activity para mostrar los objetos de UI, ya sea el progreso de descarga, o un mensaje de error. Si se evalúa como False, mostrará el botón “Iniciar Descarga”.
  • showif Download_Action.download_is_finished [Condicional] : La condicional evalúa a la clase en cuanto al método download_is_finished(). ¿Recuerdas que esa función retorna True cuando termina la descarga? Cuando se evalúa como True, muestra el mensaje de que la descarga ha finalizado, de lo contrario, seguirá mostrando la barra de progreso.
  • showif Download_Action._has_exception [Condicional] : Esta condicional evalúa a la clase en cuanto al método _has_exception(). Si ocurre un error, mostrará el mensaje de error, de lo contrario, mostrará la UI del progreso de descarga.
  • Function(Download_Action._raise_from_thread) [Acción] : Esta acción evalúa a la clase en cuando al método _raise_from_thread(), el cual sirve para rastrear el error a voluntad. Al presionar el textbutton en la pantalla, ejecutará esta acción mostrando una pantalla con los detalles completos del error. Es opcional añadirlo a la UI del juego. Recomiendo añadirlo solo en caso de querer depurar errores asociados al sistema de descargas.
  • .format(Download_Action.status) [Formato de texto] : Esto entrega a la propiedad text, el progreso de descarga en forma de porcentaje.
  • .format(Download_Action.MB_Actual) [Formato de texto] : Esto entrega a la propiedad text, los Megabytes descargados.
  • .format(Download_Action.MB_Target) [Formato de texto] : Esto entrega a la propiedad text, los Megabytes totales del archivo.

Vaya. Es impresionante que hayas llegado a este punto del post. ¿Sabes por qué lo digo? Pues porque lo feo ya pasó. El entorno de descargas está completamente terminado, así que ahora solo debo indicarte el como ejecutar las descargas.

La Screen de más arriba es ideal para que sea llamado dentro de un label. Mira el ejemplo de uso a continuación :

[SCREENSHOT : Código de Ren’Py llamando a la Screen para ejecutar la descarga de un archivo.]

El código anterior inicializará dos variables con datos y llamará a la Screen que efectúa la descarga. Desglosemos este código :

  • link [Variable] : Contiene una string con la URL del archivo ubicado en el servidor.
  • path [Variable] : Contiene una string con el nombre del archivo para almacenar en el disco. El archivo de ejemplo es un archivo de audio llamado “Snow_Halation.mp3”.

#OffTopic : “Love Live!” no debilita la masculinidad de nadie. Por el contrario, la duplica de forma exhorbitante xD.

  • download_screen() [Screen] : Es la pantalla que hace de intermediario con el sistema de descargas. Recibe dos argumentos de string, siendo el primer argumento la URL del archivo y el segundo argumento la ruta de salida o el nombre del archivo a guardar en el disco.

Ahora que he terminado completamente con el sistema de descarga, pasaremos a la parte más placentera del tutorial, donde vemos funcionar a todo este desmadre xD.


Cuando pulses el botón de “Comenzar” en el menú principal, te aparecerá lo siguiente en la pantalla de tu PC :

Al hacer click en el botón de texto que pone “Iniciar descarga”, sucederá lo siguiente :

Cuando termine la descarga, verás este delicioso mensaje xD :

Y en el caso de que ocurra un error, antes o durante una descarga, aparecerá este mensaje :

El código de este tutorial, descarga los archivos en la carpeta raíz del motor Ren’Py. Este es un Screenshot en la carpeta de Ren’Py en mi PC :

[SCREENSHOT : Archivo de audio “Snow_Halation.mp3” descargado en la carpeta del motor y reproduciéndose.]

NOTA 1 : Si quieres comprobar de que este código realmente funciona con una red real de internet, puedes usar esta URL que contiene la versión v7.3.5 de Ren’Py : https://www.renpy.org/dl/7.3.5/renpy-7.3.5-sdk.7z.exe

NOTA 2 : La tipografía que se ve en los Screenshots, la puse yo en el juego que tengo para hacerles los tutoriales. La puedes encontrar con el nombre de “Consolas”.

Encuentra el código completo de este tutorial en mi repositorio de GitHub “Codigos_RenPy”. Accede al código desde el siguiente link :


¡Bieeeeeen! Como si estuviéramos en la cima del Monte Fuji o el Everest, clavamos la bandera en este punto para finalizar el post actual. Recuerda que si tienes dudas, no dudes ni un segundo en comentar o en comunicarte conmigo por Inbox (Telegram).


Mira el código de los posts anteriores en mi repositorio de GitHub!

Eres nuevo? Descarga el motor Ren’Py para que comiences a hacer tu propia Visual Novel!

  • Visita la web oficial de Ren’Py Presionando Aquí!
  • Link para copiar : https://renpy.org/

No has entendido algo sobre este post u otros de este mismo hilo? No dudes en comunicarte conmigo! Contactame mediante los comentarios o en mi Telegram personal!


¿Próximo post? Les enseñaré a obtener y utilizar los Searchpaths en Ren’Py, donde mezclaremos Python y Ren’Py nuevamente. Esto sirve para obtener las rutas donde se ubican los archivos de tu juego en el sistema. Añadido al siguiente post, añadiré código alternativo para el descargador que hicimos en este post.
¡Gracias por leer! ¡Ten un buen día, ve a picar código y conquista al mundo maldita sea! xD


Navega entre los posts de este hilo!

<< Ir al Post #17 | Ir al Post #19 >>

<< Eres nuevo? Click aquí para ir al Post #1 >>


CharlieFuu69 Creations! – ElectroBasicsYT


Ayuda a los autores

  • Tutorial
  • Programación | Programas, aplicaciones | Otros
6 Comentarios
  1. Juanjo
    Juanjo 3 meses

    Prolijo tu código, tabulado y comentado. Fácil de leer.

    1+
  2. Juani10
    Juani10 3 meses

    Muy buena idea lo del repositorio GitHub.

    1+
  3. Daniel01
    Daniel01 2 meses

    Se puede ver el código de las imagenes al detalle. Saludos

    1+

Contesta

CONTACTANOS

Esta es su red social de tecnología para compartir tus ideas y proyectos .Puedes enviarnos un correo si tienes dudas.Nos vemos

Enviando

Inicia Sesión con tu Usuario y Contraseña

o    

¿Olvidó sus datos?

Create Account