Anatomía de un proyecto de videojuego en Corona

El simulador de Corona tiene varias plantillas de proyecto disponibles para empezar a desarrollar videojuegos o aplicaciones. En esta entrada exploraremos los componentes que forman la plantilla de un videojuego y que cosas necesitamos conocer para poder manipularlas y así poder crear videojuegos increíbles.

Elementos de configuración de un nuevo proyecto.

Figura 1 – Crear nuevo proyecto

Para crear un nuevo proyecto de Corona tenemos 2 opciones, una es crear un nuevo proyecto desde la pantalla de Bienvenida de Corona (como vimos en esta entrada) o podemos hacerlo desde el menú File > New Project.

Figura 2 – Configuración inicial de un proyecto

En la ventana emergente vamos a encontrar lo siguiente:

  • Nombre del proyecto: Al colocarlo es el nombre de la carpeta donde se crearán todos los archivos (recomiendo usar un nombre sin espacios, si es mas de una palabra separarlo con un guión bajo)
  • Plantilla: En este ejemplo usaremos el de “Game”
  • Screen size: En general se recomienda usar un tamaño de pantalla que tenga una relación de 2:3 que es el tamaño base desde el cual evolucionaron los tamaños de pantalla en los dispositivos móviles. En lo personal suelo utilizar un tamaño de 800×1200 pixeles, de esta manera en las herramientas de diseño gráfico que tengo disponibles puedo simular un tamaño cómodo para trabajar los gráficos y organizar la distribución de los botones, menús, imágenes de fondo, animaciones, etc… pero mientras se respete la proporción antes mencionada puedes usar el tamaño que mas te acomode.
  • Orientación: Se refiere a la posición que tomará la pantalla para mostrar tu juego, en nuestro caso lo usaremos como sideways (dispositivo “acostado”).

Nota importante: Cuando se defina el tamaño de la pantalla asegúrate que los valores de ancho y alto sean los que corresponden al dispositivo como si lo vieras en posición Upright, cuando seleccionas la orientación el framework de Corona se encargará de ajustar internamente las dimensiones dependiendo la orientación final que selecciones.

El archivo config.lua

Una de las ventajas de usar el framework de Corona es que es multiplataforma, es decir, que una vez completado tu proyecto puedes publicarlo para dispositivos Android, iOS, escritorio, entre otros.

Para poder asegurar que las dimensiones de pantalla se ajustarán al tamaño del dispositivo en donde se esta ejecutando tu juego puedes ajustar el archivo de configuración (con el nombre config.lua) con la siguiente codificación que es muy recomendada en los foros de Corona.

local aspectRatio = display.pixelHeight / display.pixelWidth
local baseWidth = 800
local baseHeigth = 1200

application = {
	content = {
		width = aspectRatio > 1.5 and baseWidth or math.floor( baseHeigth / aspectRatio ),
		height = aspectRatio < 1.5 and baseHeigth or math.floor( baseWidth * aspectRatio ),
		scale = "letterBox",
		fps = 60,
		imageSuffix = {
			["@2x"] = 1.3,
		},
	},
}

Esta configuración te recomiendo la tengas guardada en algún lugar seguro pues así, en cada nuevo proyecto que vayas a crear, solo tendrías que reemplazar el archivo original que el simulador de Corona crea en el proyecto por este archivo de configuración.

El concepto de “escenas” y el archivo main

En muchos frameworks de videojuegos se denominan escenas a cada una de las pantallas que muestra un juego. Si ahora mismo tomas algún juego instalado en tu teléfono o tableta probablemente podrás ver una serie de pantallas como la presentación del logotipo de la empresa o equipo que hizo el juego, un menú principal, una pantalla que muestra los créditos del juego, otra que muestra una tienda para comprar mejoras, etc… Cada una de estas es conocida como escena de juego.

El framework de Corona también trabaja con este concepto y la plantilla básica crea para nosotros 2 escenas: menu y level1. Estas corresponden a la pantalla inicial que vemos y, al presionar el botón “play now” la pantalla con el ejemplo de física del framework pero ¿como es que el proyecto llega a estas escenas? Por medio del archivo main.

Figura 3 – escenas creadas por Corona

El archivo main.lua es el archivo más importante, es donde empezará la ejecución de tu proyecto por lo que siempre debe existir con ese nombre y su función es llevar el proyecto a la escena inicial que tu definas, en este caso lleva directamente a una escena de nombre menu.

-----------------------------------------------------------------------------------------
--
-- main.lua
--
-----------------------------------------------------------------------------------------

-- hide the status bar
display.setStatusBar( display.HiddenStatusBar )

-- include the Corona "composer" module
local composer = require "composer"

-- load menu screen
composer.gotoScene( "menu" )

Como puedes ver en el ejemplo anterior, el archivo main se apoya de una librería de nombre composer, que tiene un método de nombre gotoScene() que permite cambiar de una escena a otra usando como parámetro un String con el nombre de la escena pero… ¿Como sabemos cual es el nombre de la escena?

Figura 4 – Archivos de escena main y level1

El nombre de la escena corresponde al nombre del archivo que construye tu escena pero sin la extensión de archivo (en este caso la extensión es  .lua). ¿Recuerdas que mencioné que la plantilla básica de videojuego tiene 2 escenas con el nombre de menu y level1? Como puedes ver en la estructura de archivos que se crearon en el proyecto, hay un archivo de nombre menu.lua y otro de nombre level1.lua, estos son los archivos que construyen dichas escenas y son los nombres que hay que usar para cambiar de una escena a otra por medio de método gotoScene().

El ciclo de vida de una escena

Una escena para poder construirse requiere de la librería composer y del método newScene(). Esto deja los cimientos mas elementales para que podamos configurar los sprites, eventos y funciones de la escena del juego. Sin embargo, para tener un mejor control de lo que sucede en esta escena también necesitamos de una serie de funciones que nos permiten manipular la forma en que debe aparecer o desaparecer esta escena de pantalla, mejor conocido como ciclo de vida de escena que esta conformada por los siguientes estados:

[su_table]

create Es donde empieza la construcción de la escena, en esta función es donde debes asegurar hacer las configuraciones iniciales que requieras como el buscar información en una base de datos o inicializar variables y objetos.
show Es el momento donde la escena ya es visible para el jugador. Si estas usando efectos de transición de escenas como el fadeIn o fadeOut, es en esta función donde debes configurar que se muestre por ejemplo las imágenes de fondo, botones, textos, etc.

Tiene 2 fases, la fase will que indica que la escena aún no es visible pero que esta a punto de estarlo, y la fase did que es cuando la escena ya es visible en la pantalla.

hide Es el momento donde el programa sabe que la escena ya no será visible para el jugador. En este momento es cuando querrás detener alguna función que este ejecutándose de manera permanente o por ejemplo realizar alguna operación final antes de que la escena deje de estar disponible.

Tiene 2 fases, la fase will que indica que la escena esta visible pero esta a punto de dejar de serlo, y la fase did que indica que la escena ya no es visible en pantalla.

destroy Es el momento en que la escena ya no esta disponible para el jugador y ya no se puede interactuar con ella. En este momento es recomendable realizar operaciones de liberación de memoria.

[/su_table]

Me he tomado la libertad de crear este ejemplo con los elementos mínimos que debería contener un archivo de escena, lo puedes copiar y guardar en algún lado para que, a partir de esta plantilla de archivo, puedas agregar mas y mas escenas a tu juego.

--------------------------------------------------------------------
-- REQUIRED LIBRARIES
--------------------------------------------------------------------
local composer = require( "composer" )
local scene = composer.newScene()


-- "scene:create()"
function scene:create( event )
    local sceneGroup = self.view
    -- Initialize the scene here.
    -- Example: add display objects to "sceneGroup", add touch listeners, etc.
end


-- "scene:show()"
function scene:show( event )
    local sceneGroup = self.view
    local phase = event.phase
    if ( phase == "will" ) then
        -- Called when the scene is still off screen (but is about to come on screen).
    elseif ( phase == "did" ) then
        -- Called when the scene is now on screen.
        -- Insert code here to make the scene come alive.
        -- Example: start timers, begin animation, play audio, etc.
    end
end


-- "scene:hide()"
function scene:hide( event )

    local sceneGroup = self.view
    local phase = event.phase

    if ( phase == "will" ) then
        -- Called when the scene is on screen (but is about to go off screen).
        -- Insert code here to "pause" the scene.
        -- Example: stop timers, stop animation, stop audio, etc.
    elseif ( phase == "did" ) then
        -- Called immediately after scene goes off screen.
    end
end


-- "scene:destroy()"
function scene:destroy( event )
    local sceneGroup = self.view
    -- Called prior to the removal of scene's view ("sceneGroup").
    -- Insert code here to clean up the scene.
    -- Example: remove display objects, save state, etc.
    sceneGroup:removeSelf()
    sceneGroup = nil
end


-- -------------------------------------------------------------------------------

-- Listener setup
scene:addEventListener( "create", scene )
scene:addEventListener( "show", scene )
scene:addEventListener( "hide", scene )
scene:addEventListener( "destroy", scene )

-- -------------------------------------------------------------------------------

return scene

 

Estos son todos los aspectos importantes que definen la configuración de un proyecto de juego que nos provee el framework de Corona. Espero hayas disfrutado y aprendido muchas cosas de esta entrada y por favor siéntete libre de compartir esta información en tus redes sociales para que otras personas interesadas también puedan conocer algo nuevo y que les pueda ayudar en sus proyectos futuros. ¡Hasta la próxima!