Advertisement
  1. Code
  2. Corona SDK

Corona SDK: Crear un juego de obstáculos para helicópteros

Scroll to top
Read Time: 12 min

() translation by (you can also view the original English article)

En este tutorial, te mostraré cómo crear un juego de evasión de obstáculos usando el Corona SDK. Aprenderás más sobre los controles táctiles, la detección de colisiones y la física. El objetivo del juego es evitar tantos obstáculos como puedas para obtener la mayor puntuación. Empecemos.


1. Descripción de la aplicación

App OverviewApp OverviewApp Overview

Usando gráficos ya hechos, crearemos un juego entretenido usando el lenguaje de programación Lua y las APIs de Corona SDK El jugador podrá mover un helicóptero por la pantalla y deberá evitar los obstáculos que encuentre. Puedes modificar los parámetros en el código para personalizar el juego.


2. Dispositivo objetivo

Target DeviceTarget DeviceTarget Device

Lo primero que tenemos que hacer es seleccionar la plataforma en la que queremos ejecutar nuestra aplicación para poder elegir el tamaño de las imágenes que vamos a utilizar.

La plataforma iOS tiene los siguientes requisitos:

  • iPad 1/2/Mini: 1024px x 768px, 132 ppi
  • iPad Retina: 2048px x 1536px, 264 ppi
  • iPhone/iPod Touch: 320px x 480px, 163 ppi
  • iPhone/iPod Retina: 960px x 640px, 326 ppi
  • iPhone 5/iPod Touch: 1136px x 640px, 326 ppi

Dado que Android es una plataforma abierta, existen muchos dispositivos y resoluciones diferentes. Algunas de las características de pantalla más comunes son:

  • Asus Nexus 7 Tablet: 800px x 1280px, 216 ppi
  • Motorola Droid X: 854px x 480px, 228 ppi
  • Samsung Galaxy SIII: 720px x 1280px, 306 ppi

En este tutorial, nos centraremos en la plataforma iOS en términos de gráficos. En particular, desarrollaremos para el iPhone y el iPod Touch. Sin embargo, el código de este tutorial también se puede utilizar en tu objetivo de la plataforma Android.


3. Interface

InterfaceInterfaceInterface

Utilizaremos una interfaz de usuario sencilla que incluye múltiples formas, botones, mapas de bits, etc. Los gráficos que utilizaremos para este tutorial se encuentran en el proyecto incluido en este tutorial.


4. Export Graphics

Export GraphicsExport GraphicsExport Graphics

Dependiendo del dispositivo que hayas seleccionado, puede que tengas que convertir los gráficos a la resolución recomendada (ppi), lo que puedes hacer en tu editor de imágenes favorito. Yo he utilizado la opción Ajustar tamaño... del menú Herramientas de la aplicación Vista previa en OS X. Recuerda dar a las imágenes un nombre descriptivo y guardarlas en la carpeta del proyecto.


5. Configuración de la aplicación

Utilizaremos un archivo de configuración, config.lua, para hacer que la aplicación vaya a pantalla completa en todos los dispositivos. El archivo de configuración muestra el tamaño original de la pantalla y el método utilizado para escalar el contenido en caso de que la aplicación se ejecute en una resolución diferente.

1
application =
2
{
3
    content =
4
    {
5
        width = 320,
6
        height = 480,
7
        scale = "letterbox"
8
    },
9
}

6. main.lua

Vamos a escribir la aplicación real. Abre tu editor de Lua preferido. Cualquier editor de texto plano funcionará, pero se recomienda utilizar un editor de texto que tenga resaltado de sintaxis. Crea un nuevo archivo y guárdalo como main.lua en tu carpeta de proyecto.


7. Estructura del código

Estructuraremos nuestro código como si fuera una clase. Si estás familiarizado con ActionScript o Java, la estructura del proyecto te resultará familiar.

1
Necessary Classes
2
3
Variables and Constants
4
5
Declare Functions
6
7
    constructor (Main function)
8
9
    class methods (other functions)
10
11
call Main function

8. Ocultar la barra de estado

1
display.setStatusBar(display.HiddenStatusBar)

Este fragmento de código oculta la barra de estado. La barra de estado es la barra situada en la parte superior de la pantalla del dispositivo que muestra la hora, la señal y otros indicadores.


9. Importar Physics

Utilizaremos la biblioteca de física para manejar las colisiones. Importa la biblioteca utilizando el fragmento de código que se muestra a continuación.

1
-- Physics
2
3
local physics = require('physics')
4
physics.start()

10. Antecedentes

BackgroundBackgroundBackground

Un simple fondo para la interfaz de usuario de la aplicación. El siguiente fragmento de código dibuja el fondo en la pantalla.

1
-- Graphics
2
3
-- [Background]
4
5
local gameBg = display.newImage('gameBg.png')

11. Vista del título

Title ViewTitle ViewTitle View

Esta es la vista del título. Es la primera pantalla interactiva que aparece en nuestro juego. Estas variables almacenan sus componentes.

1
-- [Title View]
2
3
local title
4
local playBtn
5
local creditsBtn
6
local titleView

12. Vista de los créditos

Credits ViewCredits ViewCredits View

La vista de créditos muestra los créditos y el copyright de la aplicación. Esta variable se utiliza para almacenarla.

1
-- [CreditsView]
2
3
local creditsView

13. Mensaje de instrucciones

Instructions

Al principio del juego aparecerá un mensaje con instrucciones y desaparecerá después del primer toque.

1
-- Instructions
2
3
local ins

14. Helicóptero

Helicopter

Este es el gráfico del helicóptero. El jugador controlará el helicóptero mediante controles táctiles.

1
-- Helicopter
2
3
local helicopter

15. Bloques

Blocks

Los bloques son los obstáculos que el jugador debe evitar.

1
-- Blocks
2
3
local blocks = {}

16. Alerta

Alert

La alerta se muestra cuando el jugador pierde la pelota y el juego se acaba. Muestra un mensaje y termina el juego.

1
-- Alert
2
3
local alertView

17. Sonidos

Sounds

Para animar el juego, utilizaremos efectos de sonido. Los sonidos utilizados en el juego se obtuvieron de as3soundfxr. La música de fondo la encontré en playonloop.

1
-- Sounds
2
3
local bgMusic = audio.loadStream('POL-rocket-station-short.wav')
4
local explo = audio.loadSound('explo.wav')

18. Variables

El siguiente fragmento de código muestra las variables que utilizaremos. Lee los comentarios para entender para qué se utiliza cada variable.

1
-- Variables
2
3
local timerSrc --Blocks timer
4
local yPos = {90, 140, 180} --Possible positions for the blocks
5
local speed = 5 --Block speed
6
local speedTimer --Increases blocks speed
7
local up = false --Used to determine if helicopter is going up
8
local impulse = -60 --physics value to make helicopter go up

19. Declarar funciones

Declarar todas las funciones como local al principio.

1
-- Functions
2
3
local Main = {}
4
local startButtonListeners = {}
5
local showCredits = {}
6
local hideCredits = {}
7
local showGameView = {}
8
local gameListeners = {}
9
local createBlock = {}
10
local movePlayer = {}
11
local increaseSpeed = {}
12
local update = {}
13
local alert = {}

20. Constructor

A continuación, creamos la función que inicializará la lógica del juego.

1
function Main()
2
  -- code...
3
end

21. Añadir vista de título

Comenzamos colocando la vista de título en el escenario y llamamos a una función que añadirá escuchas de toque a los botones.

1
function Main()
2
  titleBg = display.newImage('titleBg.png')
3
  playBtn = display.newImage('playBtn.png', 220, 178)
4
  creditsBtn = display.newImage('creditsBtn.png', 204, 240)
5
  titleView = display.newGroup(titleBg, playBtn, creditsBtn)
6
7
  startButtonListeners('add')
8
end

22. oyentes del botón de inicio

La siguiente función añade los listeners necesarios a los botones del TitleView.

1
function startButtonListeners(action)
2
  if(action == 'add') then
3
    playBtn:addEventListener('tap', showGameView)
4
    creditsBtn:addEventListener('tap', showCredits)
5
  else
6
    playBtn:removeEventListener('tap', showGameView)
7
    creditsBtn:removeEventListener('tap', showCredits)
8
  end
9
end

23. Mostrar créditos

La pantalla de créditos se muestra cuando el usuario pulsa el botón sobre. Se añade un receptor de toques a la vista de créditos para descartarla cuando el usuario la pulse.

1
function showCredits:tap(e)
2
  playBtn.isVisible = false
3
  creditsBtn.isVisible = false
4
  creditsView = display.newImage('credits.png', -110, display.contentHeight-80)
5
  transition.to(creditsView, {time = 300, x = 55, onComplete = function() creditsView:addEventListener('tap', hideCredits) end})
6
end

24. Ocultar créditos

Cuando el usuario toca la vista de los créditos, se anima a salir del escenario y a eliminarlos.

1
function hideCredits:tap(e)
2
  playBtn.isVisible = true
3
  creditsBtn.isVisible = true
4
  transition.to(creditsView, {time = 300, y = display.contentHeight+creditsView.height, onComplete = function() creditsView:removeEventListener('tap', hideCredits) display.remove(creditsView) creditsView = nil end})
5
end

25. Mostrar la vista del juego

Cuando se pulsa el botón de jugar, la vista del título se anima fuera de la pantalla y se revela el juego. Hay una serie de partes móviles, así que vamos a ver con más detalle cada una de ellas.

1
function showGameView:tap(e)
2
  transition.to(titleView, {time = 300, x = -titleView.height, onComplete = function() startButtonListeners('rmv') display.remove(titleView) titleView = nil end})

26. Mensaje de instrucciones

El siguiente fragmento de código añade el mensaje de instrucciones.

1
ins = display.newImage('ins.png', 180, 270)
2
  transition.from(ins, {time = 200, alpha = 0.1, onComplete = function() timer.performWithDelay(2000, function() transition.to(ins, {time = 200, alpha = 0.1, onComplete = function() display.remove(ins) ins = nil end}) end) end})

27. Marcador TextField

El siguiente fragmento de código crea un campo de texto que muestra la puntuación actual del jugador en la parte superior derecha del escenario.

1
-- TextFields
2
3
  scoreTF = display.newText('0', 450, 5, 'Marker Felt', 14)
4
  scoreTF:setTextColor(255, 255, 255)

28. Helicóptero

A continuación, es el momento de añadir el gráfico del helicóptero al escenario, como se muestra a continuación.

1
-- Helicopter
2
3
  helicopter = display.newImage('helicopter.png', 23, 152)

29. Paredes

En el siguiente fragmento de código, utilizamos la API de gráficos de Corona para crear varias líneas que añadiremos a la simulación de física un poco más adelante en este tutorial. Se utilizarán para detectar colisiones con el helicóptero.

1
-- Walls
2
3
  local top = display.newRect(0, 60, 480, 1)
4
  top:setFillColor(34, 34, 34)
5
  local bottom = display.newRect(0, 260, 480, 1)
6
  bottom:setFillColor(34, 34, 34)
7
end

30. Física

A continuación, tenemos que añadir la física necesaria a cada objeto.

1
-- Add physics
2
3
  physics.addBody(helicopter)
4
  physics.addBody(top, 'static')
5
  physics.addBody(bottom, 'static')

31. Inicio del juego

Creamos un grupo para los bloques, invocamos la función gameListeners e iniciamos la música de fondo.

1
  blocks = display.newGroup()
2
  gameListeners('add')
3
  audio.play(bgMusic, {loops = -1, channel = 1})
4
end

32. Oyentes del juego

El siguiente fragmento de código puede parecer complejo, pero simplemente añade unas cuantas listeners para iniciar la lógica del juego.

1
function gameListeners(action)
2
  if(action == 'add') then
3
    gameBg:addEventListener('touch', movePlayer)
4
    Runtime:addEventListener('enterFrame', update)
5
    timerSrc = timer.performWithDelay(1300, createBlock, 0)
6
    speedTimer = timer.performWithDelay(5000, increaseSpeed, 5)
7
    helicopter:addEventListener('collision', onCollision)
8
  else
9
    gameBg:addEventListener('touch', movePlayer)
10
    Runtime:removeEventListener('enterFrame', update)
11
    timer.cancel(timerSrc)
12
    timerSrc = nil
13
    timer.cancel(speedTimer)
14
    speedTimer = nil
15
    helicopter:removeEventListener('collision', onCollision)
16
  end
17
end

33. Crear un bloque

Como su nombre indica, la función createBlock crea un bloque y lo dibuja en la pantalla. El objeto resultante se añade al motor de física para comprobar si hay colisiones.

1
function createBlock()
2
  local b
3
  local rnd = math.floor(math.random() * 4) + 1
4
  b = display.newImage('block.png', display.contentWidth, yPos[math.floor(math.random() * 3)+1])
5
  b.name = 'block'
6
  -- Block physics
7
  physics.addBody(b, 'kinematic')
8
  b.isSensor = true
9
  blocks:insert(b)
10
end

34. Función de desplazamiento

En la función movePlayer, actualizamos la variable up. Mientras su valor sea igual a true, la función de update mueve el helicóptero hacia arriba.

1
function movePlayer(e)
2
  if(e.phase == 'began') then
3
    up = true
4
  end
5
  if(e.phase == 'ended') then
6
    up = false
7
    impulse = -60
8
  end
9
end

35. Aumentar la velocidad

Para hacer el juego más interesante, un temporizador aumenta la velocidad cada cinco segundos. Se muestra un icono para avisar al jugador del cambio de velocidad.

1
function increaseSpeed()
2
  speed = speed + 2
3
  -- Icon
4
  local icon = display.newImage('speed.png', 204, 124)
5
  transition.from(icon, {time = 200, alpha = 0.1, onComplete = function() timer.performWithDelay(500, function() transition.to(icon, {time = 200, alpha = 0.1, onComplete = function() display.remove(icon) icon = nil end}) end) end})
6
end

36. Mover el helicóptero

La función update comprueba el valor de up y mueve el helicóptero hacia arriba si es igual a true.

1
function update(e)
2
  -- Move helicopter up
3
  if(up) then
4
    impulse = impulse - 3
5
    helicopter:setLinearVelocity(0, impulse)
6
  end

37. Mover bloques

A continuación, es el momento de mover los bloques. Utilizamos la variable speed para determinar cuántos píxeles deben moverse los bloques en cada fotograma.

1
-- Move Blocks
2
  if(blocks ~= nil)then
3
    for i = 1, blocks.numChildren do
4
      blocks[i].x = blocks[i].x - speed
5
    end
6
  end

38. Actualización de la puntuación

El algoritmo para actualizar la puntuación es sencillo. La puntuación se incrementa en uno cada fotograma mientras el helicóptero no se haya estrellado. Es sencillo. ¿No es así?

1
  -- Score
2
  scoreTF.text = tostring(tonumber(scoreTF.text) + 1)
3
end

39. Colisiones

La función onCollision verifica si el helicóptero ha colisionado con un bloque. Si se detecta una colisión, reproducimos un efecto de sonido, una explosión, eliminamos los gráficos y mostramos una alerta al jugador.

1
function onCollision(e)
2
  audio.play(explo)
3
  display.remove(helicopter)
4
  alert()
5
end

40. Alerta

La función alert crea una vista de alerta y la muestra al usuario. A continuación, el juego termina.

1
function alert()
2
  gameListeners('rmv')
3
  alert = display.newImage('alert.png', (display.contentWidth * 0.5) - 105, (display.contentHeight * 0.5) - 55)
4
  transition.from(alert, {time = 300, xScale = 0.5, yScale = 0.5})
5
end

41. Invocar la función Main

Para iniciar el juego, es necesario invocar la función Main. Con el resto del código en su lugar, lo hacemos aquí.

1
Main()

42. Pantalla de carga

Loading Screen

En la plataforma iOS, el archivo llamado Default.png se muestra mientras se lanza la aplicación. Añade esta imagen a la carpeta de fuentes de tu proyecto, será añadida automáticamente por el compilador de Corona.


43. Icono

Icon

Utilizando los gráficos que has creado antes, ahora puedes crear un bonito icono. Las dimensiones del icono para un iPhone sin retina son 57px x 57px, mientras que la versión con retina debe ser de 114px x 114px. El material gráfico para iTunes debe ser de 1024px x 1024px. Te sugiero que crees primero la ilustración de iTunes y luego crees las imágenes de menor tamaño reduciendo la ilustración de iTunes a las dimensiones correctas. No es necesario hacer que el icono de la aplicación sea brillante o añadir esquinas redondeadas, ya que el sistema operativo se encarga de ello por ti.


44. Pruebas en el simulador

TestingTestingTesting

Es hora de probar nuestra aplicación en el simulador. Abre el Simulador Corona, busca la carpeta de tu proyecto y haz clic en Abrir. Si todo funciona como se espera, estás listo para el paso final.


45. Construir un proyecto

BuildBuildBuild

En el Corona Simulator, ve a File > Build y selecciona el dispositivo de destino. Rellena los campos requeridos y haz clic en Build. Espera unos segundos y tu aplicación estará lista para ser probada en un dispositivo y/o para ser enviada para su distribución.


Conclusión

En este tutorial, hemos aprendido sobre las escuchas táctiles, la detección de colisiones, la física, así como algunas otras habilidades que pueden ser útiles en un amplio número de juegos. Experimenta con el resultado final e intenta modificar el juego para crear tu propia versión del mismo. Espero que te haya gustado este tutorial y te haya resultado útil. Gracias por leerlo.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.